Skip to content

Commit

Permalink
fix CSP by injecting styles using CSSOM
Browse files Browse the repository at this point in the history
This uses CSS Object Model (CSSOM) to modify stylesheets.
Changing stylesheets via CSSOM does not violate
Content-Security-Policy style-src 'none'.

CSSOM is still a working draft but the features been used should
be supported by all target browsers:
https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/styleSheets#Browser_compatibility
https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule#Browser_compatibility

Creating an empty style element does not violate CSP.

-webkit- prefix is not needed anymore for keyframe.
Inserting CSS rule @-webkit-keyframews throws a SyntaxError in IE11.

Done basic manual testing using samples in recent versions of:
- Chrome (Desktop & Mobile)
- Firefox
- Microsoft Edge
- IE 11

Fixes #5208 together with #5909

Live example: https://codepen.io/jelhan/pen/jXYymO

Please note the CSP meta tag definied in settings. You need to update SHA
hashes if you change any JavaScript in this Codepen as it violates CSP
otherwise.
  • Loading branch information
jelhan committed Jan 3, 2019
1 parent a8920f6 commit 4581859
Showing 1 changed file with 14 additions and 14 deletions.
28 changes: 14 additions & 14 deletions src/platforms/platform.dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -304,17 +304,19 @@ function removeResizeListener(node) {
}
}

function injectCSS(platform, css) {
// https://stackoverflow.com/q/3922139
var style = platform._style || document.createElement('style');
if (!platform._style) {
platform._style = style;
css = '/* Chart.js */\n' + css;
style.setAttribute('type', 'text/css');
document.getElementsByTagName('head')[0].appendChild(style);
function injectCSS(platform, cssRules) {
if (!platform._stylesheet) {
var styleElement = document.createElement('style');
styleElement.setAttribute('type', 'text/css');
document.getElementsByTagName('head')[0].appendChild(styleElement);

platform._stylesheet = styleElement.sheet;
}

style.appendChild(document.createTextNode(css));
cssRules.forEach(function(cssRule) {
// index is required for IE11
platform._stylesheet.insertRule(cssRule, 0);
});
}

module.exports = {
Expand All @@ -328,16 +330,14 @@ module.exports = {
initialize: function() {
var keyframes = 'from{opacity:0.99}to{opacity:1}';

injectCSS(this,
injectCSS(this, [
// DOM rendering detection
// https://davidwalsh.name/detect-node-insertion
'@-webkit-keyframes ' + CSS_RENDER_ANIMATION + '{' + keyframes + '}' +
'@keyframes ' + CSS_RENDER_ANIMATION + '{' + keyframes + '}' +
'@keyframes ' + CSS_RENDER_ANIMATION + '{' + keyframes + '}',
'.' + CSS_RENDER_MONITOR + '{' +
'-webkit-animation:' + CSS_RENDER_ANIMATION + ' 0.001s;' +
'animation:' + CSS_RENDER_ANIMATION + ' 0.001s;' +
'}'
);
]);
},

acquireContext: function(item, config) {
Expand Down

0 comments on commit 4581859

Please sign in to comment.