-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
API for extensions to exclusion/deny list their content scripts #653
Comments
Regarding your specific requests:
You can't unload JavaScript once it's been run. CSS code is already unloaded in Firefox and Safari in this case (I think not in Chrome)
That already happens. You will receive the tab URL if you have permission to access the website. See the output of |
Thanks for you answer. That looks like a decent solution for allow list scenarios. Unfortunately I'm more interested into the blocklist/exclusion scenario. I would also prefer if this could be leveraged with the browsers host permission like your approach does. In fact the idea has been raised some time ago for Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=1745823
I'm not sure to which extend this is true. At least in Firefox if I remove/uninstall an extension the content script seems to be removed. This may be possible due to their X-Ray vision, but that is beyond my knowledge.
You are right. My apologies. My tests case had an error. |
So far there is now way to do this via browser functionality, or dynamic content script registration. See also w3c/webextensions#653
As discussed in the meeting, it is infeasible to undo the injection in existing tabs. While browsers may be able to partially clean up the script, it is impossible to undo the DOM changes that a content script might have done. Cleaning up logic would therefore be the responsibility of an extension. Without this part, the most that we could read in this issue is the ability to customize excludeMatches of content scripts in manifest.json (so you aren't forced to use About the other parts of the request: Browsers are currently inconsistent in whether scripts run in existing tabs. There is a feature request to control injection behavior at:
Note: even without first-class support for disabling content scripts, it may be possible to implement "skip content script functionality" if there is a way to customize parameters for content scripts (previously referred to as "globalParams"), e.g. as described at #536 (comment) |
I think that in practice this can be implemented in two ways:
I think the latter closely matches what has been asked here. I have two proposed APIs. Block list (preferred)browser.scripting.blockContentScripts({
matches: ['https://example.com/*']
}) This would disable all content scripts on the specified matches. The request could be undone via an browser.scripting.unblockContentScripts({
ids: ['previously-specified-block-id']
}) This would work as an additional "block list" over the existing content scripts.
|
An additional solution would be for the browser to expose the block-list and let the user deal with it directly. This would work similarly to how browsers block the execution of scripts on specific pages (like the respective extension stores, etc) For example in Safari it might extend the existing host list: |
Thanks for the update.
How about allow setting the "content_scripts": [
{
"id": "my_special_cs",
"matches": ["<all_urls>"],
"run_at": "document_start",
"js": [
"script.js"
],
}
], Then allow updating it via scripting.updateContentScripts({
id: "my_special_cs",
excludeMatches: [...]
}); If the developer wants to know which sites are currently blocked: const [script] = await scripting.getRegisteredContentScripts({
ids: ["my_special_cs"]
});
script.excludeMatches; I have to admit though that this whole concept of persistently updating the manifest content scripts is probably undesirable as it becomes less and less clear what the manifest is actually doing after multiple calls to |
@fregante Safari will offer to configure any open tab in a "Currently Open Websites" section, so you can block/allow sites individually. Allowing input of a pattern is likely too advanced for most users. |
We discussed this during an in-person meeting at TPAC. There was general alignment that this is a use case we want to support and have seen developers solve in various ways. That said, there are some limitations to what we can do. For example, uninjecting a script isn't possible because there is no way to revert any changes it may have made to a page. The main path forward we saw was adding a way to specify that you would like scripts to inject in certain conditions even if a page is already loaded. That matches the request in #617 so we're going to continue discussion there, and I'm going to close this in favor of that issue. |
I’m really confused about the progression of this issue. I don’t see anyone suggesting the “unloading” of scripts. What was suggested here was a way to disable scripts that are declared in the manifest. #617 is completely unrelated to that. |
The request to unload is part of the feature request ("and also unloading it when it becomes excluded"), and you already called out before that this is not possible. During the meeting where this was discussed, I also said that unloading is not possible.
#617 relates to the remaining part of the feature request, "inject into existing tabs". The request there is for a manifest key, but any such content script specific feature would likely be ported to dynamically registered content scripts. Note: when this issue was discussed first (https://github.com/w3c/webextensions/blob/main/_minutes/2024-07-18-wecg.md#meeting-notes), I noted that a way to support this would be to enable statically registered scripts to be updated. This idea resonated with some. If one is interested in having this idea pursued, please create a new issue focused on that specific solution/feature. |
Basic Use Case: Users often want an exclusion/allow list functionality to disable add-ons on certain URLs.
Goal:
tabs
permission as self-deactivation is not a main feature of an add-on. It is kinda contradictory that content script disabling requires loosening the permissions.Attempts:
Block the content script injection:
Approach:
scripting.registerContentScripts()
seems like a wonderful fit for this, because it provides theexcludeMatches
functionality wherefore no knowledge about the tab urls has to be exposed.browser.storage
.scripting.registerContentScripts()
(orscripting.updateContentScripts()
) with the exclusions asexcludeMatches
to register the content script.Problems:
scripting.registerContentScripts()
does not inject the script into already existing tabs. Any workaround viascripting.executeScript()
requires thetabs
permission because it should only be called for tabs whose url is not listed in the exclusions.excludeMatches
(viascripting.updateContentScripts()
) does not remove/disable already injected content scripts.Drawbacks:
Block the code inside the content script:
Approach:
content_scripts
manifest keybrowser.storage
.Problems:
window.location.href
to background page and then back to all frames) or using the privacy unfriendlypostMessage
API.The browser action icon either requires passing the url from the content script to the background script since it does not have access to the tab url without thetabs
permission, or some other messaging.Drawbacks:
Conclusion:
So far only the latter approach really works, but for a seemingly simple functionality as whitelisting/blacklisting it is cumbersome to implement. Also it feels wrong to rely on content script code while the goal is to avoid any content script injection.
Possible solutions:
scripting.registerContentScripts()
to inject into existing tabs and also unloading it when it becomes excluded viaexcludeMatches
.Related requests:
Provide the tab url regardless of theEdit: This is already the case.tabs
permission if the add-on has host permissions for the respective tab. This would still require the content script to be injected at all times but at least require less implementation overhead for the background script code.The text was updated successfully, but these errors were encountered: