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 chartjs#5208 together with chartjs#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 2, 2019
1 parent a8920f6 commit cb2db07
Showing 1 changed file with 14 additions and 13 deletions.
27 changes: 14 additions & 13 deletions src/platforms/platform.dom.js
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,15 @@ 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 cb2db07

Please sign in to comment.