4

I'm writing a web extension for use in Firefox, Edge, and Chrome, using only universal code (the only difference being the top level namespace browser vs chrome), using the following permissions in the manifest:

"permissions": [
  "*://*/*",
  "activeTab",
  "storage",
  "webRequest"
]

(The domain wildcarding is because this needs to kick in for http and https pages)

I also have a single background script main.js:

var namespace = false;

if (typeof browser !== "undefined" && browser.browserAction) {
    namespace = browser;
}
else if (typeof chrome !== "undefined" && chrome.browserAction) {
    namespace = chrome;
}

if (namespace) {
    namespace.browserAction.onClicked.addListener(e => {
        namespace.tabs.executeScript({
            file: `start.js`
        });
    });
} else {
    throw new Error("This browser does not support the webextension 'browser' or 'chrome' namespace.");
}

And then a slew of content_script entries that lead up to start.js:

"content_scripts": [
  {
    "matches": [ "*://*/*" ],
    "js": [
      "vendor/base64.js",
      "vendor/codemirror.js",
      "vendor/html-beautify.js",
      "vendor/md5.min.js",
      "vendor/mode/css/css.js",
      "vendor/mode/htmlmixed/htmlmixed.js",
      "vendor/mode/javascript/javascript.js",
      "vendor/mode/xml/xml.js",
      "utilities.js",
      "modal.js",
      "listening.js",
      "editor.js",
      "publisher.js",
      "help.js",
      "pagemixer.js"
    ],
    "css": [
      "vendor/codemirror.css",
      "pagemix.css"
    ]
  }
]

With this setup, Firefox lets me aggregate the current tab's applied document styles, by using:

getPageStyle() {
  let css = [];
  Array.from(document.styleSheets).forEach(s => {
    Array.from(s.cssRules).forEach(r => {
      css.push(r.cssText);
    });
  });
  return css.join('\n');
}

However, in Chrome this throws a CORS error:

Uncaught DOMException: Failed to read the 'cssRules' property from 'CSSStyleSheet': Cannot access rules

As far as I can tell, my permissions say that my web extension should be running with local-to-the-current-page permissions "anywhere" and so CORS should not be getting the way here: how do I set up this extension with full DOM and CSSOM access for Chrome?

(From what I can find, Cannot access cssRules from local css file in Chrome 64 describes the "why" in general, but web extensions are supposed to run same-origin as the page, so this should work without additional permissions, yet it doesn't)

Mike 'Pomax' Kamermans
  • 49,297
  • 16
  • 112
  • 153
  • Assuming you're trying to access that "local file", i.e. `file://` URL, try using `""` instead of `"*://*/*"` (the latter doesn't include file:// scheme), and make sure to enable file access in the details of your extension on chrome://extensions page. – wOxxOm Sep 10 '18 at 19:59
  • I am not trying to access anything by `file://`, this is running on any normal page in the browser on http or https, and the extension needs to aggregate the current document CSS so that it can pack it off and send it over to a github repo. – Mike 'Pomax' Kamermans Sep 10 '18 at 20:09
  • I think cssRules CORS circumvention for extensions wasn't implemented. Try submitting a feature request on https://crbug.com. – wOxxOm Sep 11 '18 at 04:25
  • Did you ever solve this? – kyw Feb 24 '21 at 12:42

1 Answers1

-1

Add the following part on your manifest.json.

"web_accessible_resources": [ "vendor/*.js", "*.js", "vendor/*.css", "*.css", ],

Found the solution on https://developer.chrome.com/extensions/manifest/web_accessible_resources

Abdulla
  • 485
  • 6
  • 16
  • that is already the case - amended the post to make that clear. But that alone will _not_ give you access to `cssRules` on the active tab's `document.styleSheets`. – Mike 'Pomax' Kamermans Sep 10 '18 at 20:08