Skip to content

Proposal: RegisteredContentScript.tabIds and RegisteredContentScript.excludeTabIds properties to filter injection #539

Closed

Description

@hackademix

(As discussed in #103)

Use Case

Some time-critical features can be provided only by document_start registered content scripts which run before any page script has a chance to: scripting.executeScript() is useless for this, bacause it doesn't provide reliable time guarantees.

However users may want to turn such features on/off on certain tabs only, e.g. in order to be sure a multi-site workflow like an e-commerce check-out/payment one are not disrupted by the extension. That's the case of the Disable all restrictions for this tab NoScript command, for instance.

Proposal

The above use case would be served if script registration could be filtered by tabId.

Therefore, in addition to the RegisteredContentScript properties already specified, we propose to add:

  • tabIds Optional
    an array of number. If defined, limits the injection to the tabs whose IDs are included in the array, after all the other requirements are met. If defined as an empty array, no injection will occur1 . If persistAcrossSessions is true or undefined, a "TypeError: tabIds can't be defined for persistent content scripts." exception will be thrown (in other words, persistAcrossSessions MUST be set to false).

  • excludeTabIds Optional
    an array of number. Tabs whose IDs are contained in this array will be excluded from injection, even if all the other requirements are met. This property won't be persisted even if persistAcrossSession is true or undefined, i.e. the registered content script will survive across sessions restarts and updates but, after those, will be injected in every tab and if retrieved via scripting.getRegisteredContentScripts() will have excludeTabIds undefined. 2

If any of these two parametersThis filter could only be specified for non-persistent script registration, and would throw TypeError otherwise)

Footnotes

  1. even if this might seem just a fancy expensive way to disable the RegisteredContentScript, it can be argued that it's the least surprising and most consistent API. Alternatively, passing an empty array could throw as an invalid type. The worst, to be avoided at all costs to prevent bugs, would be an empty tabIds array falling back to match any tab. ↩

  2. the different behavior regarding persistence between tabIds and excludeTabIds provides a reliable mechanism to both turn off persistent features and add temporary features on certain tabs only. ↩

Activity

  1. added
    proposalProposal for a change or new feature
    enhancementEnhancement or change to an existing feature
    neutral: safariNot opposed or supportive from Safari
    and removed on Feb 29, 2024
  2. hackademix commented on Feb 29, 2024

    @hackademix
    Author

    Better clarified the use case and proposed behavior regarding persistence in the main issue description, as a follow up of today's meeting discussion.

  3. self-assigned this
    on Apr 11, 2024
  4. oliverdunk commented on Apr 18, 2024

    @oliverdunk
    Member

    Hey @hackademix, thanks for opening this issue! I think you mentioned you had some workarounds for this in MV2 - would you be able to share what those are and how well they work?

    We discussed this a bit on the Chrome side. We have no concerns about the capability, but are also concerned that this doesn't feel like the right sort of thing to be adding to this API. A better solution seems like being able to set global and per-tab parameters for content scripts, that you could then access synchronously from inside them. This is something we've discussed in the past and would still like to look at in the future.

    Going to remove our follow-up label for now but definitely open to continuing the conversation.

  5. added and removed
    follow-up: chromeNeeds a response from a Chrome representative
    on Apr 18, 2024
  6. removed their assignment
    on Apr 18, 2024
  7. hackademix commented on Apr 18, 2024

    @hackademix
    Author

    Hey @oliverdunk, thank you for looking into this.

    I believe the work-around you might have heard me alluding to is (https://github.com/hackademix/nscl/blob/main/service/DocStartInjection.js]this DocStartInjection NSCL module), which I don't think easily translates to the MV3 world because:

    1. It depends on a combined use of browser.contentScripts.register() on Firefox and browser.tab.executeScript() on Chromium, carefully timed and/or brute forced from both webNavigation and webRequest listeners.
    2. It relies on belters and suspenders, based even on syncrhonous XHR, to reliably handle some edge cases such as file:/// URLs

    Therefore I really hope you reconsider the opposed:chrome label you've just attached to this issue, or otherwise finally act ASAP on your parametrized content scripts proposal, because we've been talking about this for more than 3 years now but for some reason we're still stuck here. Thanks again!

  8. added and removed
    neutral: safariNot opposed or supportive from Safari
    on Apr 18, 2024
  9. dotproto commented on Apr 8, 2026

    @dotproto
    Member

    2026 London F2F Triage

    Consensus view as that it doesn't make sense to use tabIds as a primitive for modifying content scripts. Recognize that there's utility in addressing the use case of disabling an extension on a given tab, but don't think this is the right approach to do so.

    See also #793

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementEnhancement or change to an existing featureopposed: chromeOpposed by Chromeopposed: safariOpposed by SafariproposalProposal for a change or new featuresupportive: firefoxSupportive from Firefox

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions