18

The following code throws an error in the Firefox Console at the line with the continue.

SecurityError: The operation is insecure.
if( !sheet.cssRules ) { continue; }

However does not in Chrome and IE 11... Can someone explain the -why- of this? (And also how to re-work to make it safe.) I assume this is a cross-domain issue, but I'm stuck as how to re-work the code properly.

var bgColor = getStyleRuleValue('background-color', 'bg_selector');

function getStyleRuleValue(style, selector, sheet) {
  var sheets = typeof sheet !== 'undefined' ? [sheet] : document.styleSheets;
  for (var i = 0, l = sheets.length; i < l; i++) {
    var sheet = sheets[i];
    if( !sheet.cssRules ) { continue; }
    for (var j = 0, k = sheet.cssRules.length; j < k; j++) {
      var rule = sheet.cssRules[j];
      if (rule.selectorText && rule.selectorText.split(',').indexOf(selector) !== -1) 
         return rule.style[style];            
     }
   }
  return null;
 }
jchwebdev
  • 5,034
  • 5
  • 21
  • 30
  • [X] SecurityError: The operation is insecure. if( !sheet.cssRules ) { continue; } – jchwebdev Feb 08 '14 at 18:35
  • How is that insecure? Are you passing in a CrossSite stylesheet? Smells Buggy, I'd file with Firefox. – jeremyjjbrown Feb 08 '14 at 18:37
  • 1
    It's a Wordpress site so, yes, some of the stylesheets are going to be from other domains---like Google for example. I'm obviously not advanced enough to understand why this is an issue in the above code. – jchwebdev Feb 08 '14 at 18:39
  • I think maybe FF doesn't like the fact the sheet comes from elsewhere and you are evaluating it with javascript. Imagine, `if( !sheet.cssRules ){do bad stuff with the contents of sheet...} If you remove the negation and only execute the block if true does that help? Or, maybe remove the check and make sure you only have css rules in those files. – jeremyjjbrown Feb 08 '14 at 18:49
  • 1
    This is an old question, but adding a new style element https://stackoverflow.com/a/29833756/4621141 worked for me in bypassing this Firefox restriction – flen Dec 06 '17 at 02:37

2 Answers2

22

To circumvent the SecurityError in Firefox when attempting to access the cssRules attribute, you must use a try/catch statement. The following should work:

// Example call to process_stylesheet() with StyleSheet object.
process_stylesheet(window.document.styleSheets[0]);

function process_stylesheet(ss) {
  // cssRules respects same-origin policy, as per
  // https://code.google.com/p/chromium/issues/detail?id=49001#c10.
  try {
    // In Chrome, if stylesheet originates from a different domain,
    // ss.cssRules simply won't exist. I believe the same is true for IE, but
    // I haven't tested it.
    //
    // In Firefox, if stylesheet originates from a different domain, trying
    // to access ss.cssRules will throw a SecurityError. Hence, we must use
    // try/catch to detect this condition in Firefox.
    if(!ss.cssRules)
      return;
  } catch(e) {
    // Rethrow exception if it's not a SecurityError. Note that SecurityError
    // exception is specific to Firefox.
    if(e.name !== 'SecurityError')
      throw e;
    return;
  }

  // ss.cssRules is available, so proceed with desired operations.
  for(var i = 0; i < ss.cssRules.length; i++) {
    var rule = ss.cssRules[i];
    // Do something with rule
  }
}
Jeff W.
  • 355
  • 3
  • 8
  • 4
    yeah, but then how do you modify the style? – Michael Sep 28 '17 at 23:15
  • For anyone else getting this error in Firefox try running in safe mode. In my case it was one of my extensions causing this error. – jjrabbit Mar 09 '19 at 12:21
  • In my case I started getting this only after I added a link to a google font. The stylesheet was outside my domain so it threw the error. – Mike Aug 13 '19 at 17:17
0

I had the same issue with Firefox. Try this instead.

function getStyle(styleName, className) {

    for (var i=0;i<document.styleSheets.length;i++) {
        var s = document.styleSheets[i];

        var classes = s.rules || s.cssRules
        for(var x=0;x<classes.length;x++) {
            if(classes[x].selectorText==className) {
                return classes[x].style[styleName] ? classes[x].style[styleName] : classes[x].style.getPropertyValue(styleName);
            }
        }
    }
}
Cliff F
  • 381
  • 6
  • 14