How to enable/disable manifest.json CSS content script from Chrome Extension's options page?

2.6k Views Asked by At

Is there any way to disable/enable a CSS content script from a browserAction or pageAction icon? I'm talking about the kind of script that runs a CSS content script, as defined in the manifest, on a specific set of matched pages. So, if the manifest includes:

"content_scripts": [
  {
    "matches": [ "*://*.somewhere.com/*" ],
    "css": ["somewhere.css"]
  }
]

which would inject somewhere.css on somewhere.com. Is there any way to write a browserAction or pageAction options popup that could fully enable or disable the CSS content script?

I know that I could write a JavaScript content script that listens to such an options popup and then adds/subtracts CSS rules and/or classes to the page. But I want this CSS inserted before the page is rendered and as far as I can tell the only way to do that is with a CSS content script.

But, is there a way to fully enable or disable the extension—which only has a CSS content script—from the popup? I can't see a way to do this.

2

There are 2 best solutions below

5
On

No, unfortunately, there is no way to turn off injection of a manifest.json content_script (either CSS or JavaScript). The specified code will be injected in all matching URLs.

In order to have complete control over injecting, or not injecting, you will need to perform the injection via tabs.insertCSS() and/or tabs.executeScript. Injecting, or not injecting, scripts and CSS with these methods is fully under the control of the JavaScript in your extension. It is certainly possible to get similar functionality using these methods to what you obtain with manifest.json content_script entries, but with more control and complexity.

Depending on what, exactly, you are wanting to do, a more appropriate way to accomplish it may be to use a chrome.declarativeContent onPageChanged rule which includes a RequestContentScript action. However, there are mixed indications as to this being actually supported on stable builds of Chrome. In addition, it does not have the capability to provide a runAt property. Thus, it may not be suitable for what you are doing.

0
On

You can't change the content of manifest.json, once you specify content_scripts in there, they'll always be loaded.

If you need more flexibility when injecting content scripts, you have to use the new contentScripts.register() Firefox API and its Chrome polyfill to register and unregister scripts.

The API however requires a page reload to inject and remove the CSS. You can use the instant chrome.tabs.insertCSS instead, but you still can't remove the CSS without a reload.


Additionally, I wrote 2 modules to help with the whole process: add/remove domains + inject CSS or JS


Note: DO NOT use chrome.declarativeContent because it's basically unused and unsupported, and it specifically breaks with CSS