未捕获的DOMException:无法从'CSSStyleSheet'读取'rules'属性

Bra*_*nan 3 javascript css google-chrome cors cssom

在Code.org的App Lab编辑器中,我们最近开始在Chrome 64中看到此错误:

Uncaught DOMException: Failed to read the 'rules' property from 'CSSStyleSheet'
Run Code Online (Sandbox Code Playgroud)

此函数中引发错误,旨在检测浏览器是否正在使用CSS媒体查询styleSheets[i].cssRules.

/**
 * IE9 throws an exception when trying to access the media field of a stylesheet
 */
export function browserSupportsCssMedia() {
  var styleSheets = document.styleSheets;
  for (var i = 0; i < styleSheets.length; i++) {
    var rules = styleSheets[i].cssRules || styleSheets[i].rules;
    try {
      if (rules.length > 0) {
        // see if we can access media
        rules[0].media;
      }
    } catch (e) {
      return false;
    }
  }
  return true;
}
Run Code Online (Sandbox Code Playgroud)

在Windows,OSX,Ubuntu和ChromeOS上已经出现了这个问题.在Chrome版本64.0.3282.167和64.0.3282.186上.但是,我们也看到这个问题不会发生在完全相同的Chrome版本和平台上 - 而且我们似乎无法在隐身窗口中重现此问题.

这个错误的根本原因是什么?

Bra*_*nan 11

对于Web开发人员来说,这是一个很好的故事和新的"问题",所以我只需要分享:

Chrome 64.0.3282.0(2018年1月发布,完整更改列表)引入了对样式表安全规则的更改.我很恼火,因为在完整提交列表中没有详细记录的任何更改日志中我找不到此更改.

在Chromium中提交a4ebe08描述如下:

更新CSSStyleSheet的行为以匹配安全性来源的规范

规格在这里:https: //www.w3.org/TR/cssom-1/#the-cssstylesheet-interface

更新:如果样式表不可访问,以下方法现在抛出SecurityError:

  • cssRules()/ rules()
  • insertRule()
  • deleteRule()

此提交是针对错误安全性的修复:关于CSS和链接元素的不一致的CORS实现.链接的W3C规范详细描述了CSS对象模型的使用需要同源访问.

所有这一切,为什么这个问题出现在App Lab中?我们不应该遇到任何CORS问题,因为我们只从我们自己的来源加载样式表:

Chrome网络标签显示受影响页面中请求的所有CSS

最后的线索是我们无法在私人标签中重现此问题.我们开始关注Chrome扩展程序,并意识到一些受影响的用户启用了Loom Video Recorder扩展,这似乎将自己的CSS注入到页面中.由于我们的(天真)函数正在迭代所有加载的样式表,因此它试图访问由扩展注入的样式表,从而导致CORS错误.

也就是说,Chrome中的这一变化仍有一些悬而未决的问题和争论:

  • 这篇关于原始安全漏洞的评论抱怨说,现在唯一可以检测到无法从JavaScript访问样式表的方法是使用try/catch.
  • 1月23日开放的Chromium bug(即使使用Access-Control-Allow-Origin:*,document.styleSheets.cssRules为null)表明新的安全规则可能存在实施问题,从而破坏了某些变通方法.
  • 正在实施的规范似乎相当稳定,但它仍然具有"工作草案"状态,因此谁知道它将落在哪里以及其他浏览器将实现什么.

为了解决我们的问题,我们只是撕掉了整个功能. 我们不再支持IE9了,我们知道所有支持的浏览器都能正确处理媒体查询.

相关(但不完全重复)的问题: