Closed Bug 1447361 Opened 6 years ago Closed 6 years ago

userScripts API or manifest key to disable/unregister content scripts

Categories

(WebExtensions :: General, enhancement)

59 Branch
enhancement
Not set
normal

Tracking

(Not tracked)

RESOLVED WONTFIX

People

(Reporter: robwu, Unassigned)

References

Details

(Whiteboard: [design-decision-denied])

The userScripts.register API has arrived in Firefox 59 (bug 1332273), which allows extension authors to register new content scripts. This is part of a greater efforts to make it easier to develop user script managers (bug 1437098).

For interoperability with other browsers, and for backwards-compatibility with versions of Firefox that do not support the desired userScripts API, it is necessary that an extension can opt in to disable some or all content scripts that are declared in manifest.json.

The most flexible way to provide this functionality is to add a new method, something like this:

browser.userScripts.unregister({
   manifest_content_script_index: 1,
});

A potential disadvantage of the above is that the API is not declarative, so until the background page has finished loading, the browser doesn't know whether a content script should be disabled. This problem would disappear if the background page is guaranteed to finish loading before other parts of the browser start to load (e.g. by bug 1378459).

If the API approach is not viable, then an alternative is to extend the content_scripts[*] API with a key to disable content scripts:

{
    ...
    "content_scripts": [{
        "js": [...],
        "matches": [ ... ],
        "disabled_by_default": true, // <-- New
    }],
    ...
}

The above boolean is quite blunt: If the browser recognizes it, then the content script would be disabled. So any browser that recognizes the key should support a userScripts API that is at least as powerful as the content_scripts key in manifest.json.
In both Firefox (48+) and Chrome, unrecognized keys in the content_scripts[*] dictionary are ignored, so this alternative proposal would be backwards-compatible.


An open question is whether the disabled scripts have a special status (so they can be enabled again with low cost), or whether they completely disappear from memory (i.e. to register them again, the userScripts API need to be used).
I don't understand the need for this.  If an extension wants to switch from content_scripts in the manifest to user scripts, then they can just do that in an upgrade.  We don't need cross-browser interop here, and backwards compatibility is not an issue (just declare min/max-version in the manifest, let AMO present the correct version to the user).
My direct motivation for opening this feature request is that I was reviewing an add-on that injects a content script in every page for some optional feature (requiring document_start, so tabs.executeScript is not an option). Ideally, this content script should be optional, and that is possible through the userScripts API.

Currently, an extension author has the following choices:
- Run content script on all websites via manifest.json
- Use userScripts API and drop support for Firefox<59 (including ESR 52) and other browsers.
- Use userScripts API and have separate builds for other browsers.
  (AMO only shows the latest version, resulting in a more complicated installation flow of Fx<59 users)

From the extension author's perspective, there is little cost associated with the first option.
The cost of switching to the userScripts API is substantial, and the only benefit is that content scripts are not unnecessarily inserted.



If there was a way to disable manifest-declared content scripts, then an extension author can use code like below to provide the best experience to users of the latest Firefox version, and gracefully fall back to a slightly worse situation for other users:

if ( browser.userScripts && ... ) {
  browser.userScripts.unregister( ... );
  if ( await isOptionalFeatureEnabled() ) {
    browser.userScripts.register( ... );
  }
}
Whiteboard: design-decision-needed
Depends on: 1450388
No longer depends on: webextensions-startup
Hi Rob, this has been added to the agenda for the WebExtensions APIs triage on May 29, 2018. Anyone who is interested in this bug is welcome to join the meeting. :) 

Here’s a quick overview of what to expect at the triage: 

* We normally spend 5 minutes per bug
* The more information in the bug, the better
* The goal of the triage is to give a general thumbs up or thumbs down on a proposal; we won't be going deep into implementation details

Relevant Links: 

* Wiki for the meeting: https://wiki.mozilla.org/WebExtensions/Triage#Next_Meeting
* Meeting agenda: https://docs.google.com/document/d/1Y_oYPldTT_kQOOouyJbC-8y3ASIizScLKFRhQfsDQWI/edit#heading=h.v63i1wz9d1pc
* Vision doc for WebExtensions: https://wiki.mozilla.org/WebExtensions/Vision
Status: NEW → RESOLVED
Closed: 6 years ago
Resolution: --- → WONTFIX
Whiteboard: design-decision-needed → [design-decision-denied]
> (In reply to Rob Wu [:robwu] from comment #2)

You could also check for browser name and version, or use a separate manifest.json. You can filter out a JSON file with jq to delete values you don't want in transformed files. jq is widely available, you could integrate that in the build process. See https://github.com/Smile4ever/firefoxaddons/blob/master/Neat%20URL-webext/build.sh
Product: Toolkit → WebExtensions
You need to log in before you can comment on or make changes to this bug.