implement tabs.executeUserScript() or allow injecting user scripts in certain tabs
Categories
(WebExtensions :: General, enhancement, P3)
Tracking
(Not tracked)
People
(Reporter: robbendebiene, Unassigned)
References
Details
(Whiteboard: [wecg])
Updated•6 years ago
|
Updated•5 years ago
|
This is interesting for Firemonkey, too (without this it's not possible for a script manager to deactivate all scripts for just a tab temporarily):
https://github.com/erosman/support/issues/138#issuecomment-582540978
Reporter | ||
Comment 2•4 years ago
|
||
I might be overconfident with this, but I would like to give this a try in the near future.
The question is, would this functionality be accepted and what is the best way to integrate it?
Besides tabs.executeUserScript()
I could also imagine a tabId
property for the userScripts.register
method.
const registeredUserScript = await browser.userScripts.register({
tabId: 3
});
Comment 3•4 years ago
|
||
I'll defer to Luca on whether this is something that we'd accept.
The API has a design flaw (along with the contentScripts
API) where the script is unregistered upon unload of the background script (generally, the script that calls the API). We may redesign the API, and as a result this bug is probably not a good one to work on.
Comment 4•4 years ago
|
||
As Rob anticipated in comment 3, we expect these two APIs (userScripts
and contentScripts
) to be soon going through some redesign (related to the support for manifest_version: 3
extensions).
We (Rob and I) did briefly discussed about this issue with the rest of the team today and we all agree that it would be better to defer expanding the API (until the next quarter, at that point we should have already done the other necessary re-design and be a bit more free to evaluate enhancements to these APIs).
Nevertheless, we are quite happy about your contributions to the WebExtensions internals and we would really love to guide you on contributing this enhancement (once we don't have potentially conflicting changes that may make your experience less enjoyable and potentially blocking your contribution for too long) and so I didn't want to close this comment without also providing you my perspective about how we could expose this enhancement through the extension API (and so the notes that follows are not about the implementation details yet, but more about ideas around the API design part).
API Design ideas and notes
-
registering a (user or content) script that does only match some particular tab ids (and I guess that something similar for window ids or user context ids may also make sense) looks like an extended matching capability (and so it may also fit into Bug 1445909 enhancement request)
-
when content scripts and/or user scripts are registered, they are being sent to all the web child processes, and there is no 1-1 mapping between tab and child process (and that is the case right now with e10s and it will also be the case in the future with Fission):
- instead of registering a script (user or content) for a particular tab we may instead evaluating of extending the API exposed by the
script
objects that these two APIs return (which currently does only provide a singlescript.unregister
method) to allow the extension to change the matching properties (and maybe also other ones), something like:
- instead of registering a script (user or content) for a particular tab we may instead evaluating of extending the API exposed by the
const script = await browser.userScripts.register({...});
...
script.update({ includeTabIds: [...], ... })
- for an imperative way of injecting a userScript (instead of declarative as in rcontentScripts/userScripts.register), I was originally thinking to one of the following two alternatives (not something I discussed with the rest of the team to reach an agreement yet, just part of my own ideas about this particular enhancement request):
// Another method exposed on the script API object (this would allow the same script to be used to inject
// the same user script in other tabs).
const script = await browser.userScripts.register({... /* a script without any matching options yet */});
script.execute({tabIds: ...});
// or another tabs API method (which wouldn't allow to re-inject the same script again in some other tabs,
// we would be technically creating a new one):
browser.tabs.executeUserScript([optional tabId], {... /* user scripts options */});
Re: API Design ideas and notes
Few ideas for consideration (that have been discussed previously)
- Provide a per tab (tabId)
register
andunregister
method to inject|nuke contentScript|userScript without a need to refresh the tab.
The APIs already have the method but they are not acessible to the extension. - Add a break|abort method to
userScripts.onBeforeScript
to prevent userScript injection - Add Add
cssOrigin
to contentScripts API (Bug 1679997) Add a standard method for some forced workarounds inuserScripts.onBeforeScript
(e.g. process callback to defined functions)
💡It may be feasible to merge the 2 API into a single API browser.contentScripts.register
and instead add a flag, if it makes it easier to maintain in the long run. e.g.
browser.contentScripts.register({
matches: [hosts],
js: [{code}],
userScript: true,
runAt: 'document_idle'
});
Also ....
browser.tabs.executeScript([optional tabId], {
file: "/content-script.js",
userScript: true,
allFrames: true
});
Reporter | ||
Comment 6•4 years ago
|
||
All right, thanks for the detailed responses!
I'll wait for your starting signal :)
re Comment 5
I think the following would be better
browser.contentScripts.register({
matches: [hosts],
js: [{code}],
context: 'userScript', // defaults to 'content'
runAt: 'document_idle'
});
Comment 8•3 years ago
|
||
Please don't forget this issue. Users are waiting for a solution in multiple extensions that are currently blocked by Firefox.
Further consideration in future development of the API
A combined contentScripts/userScripts API would reduce browser load if both CSS & JS need to be injected.
Currently, a single contentScripts
registration is required to inject CSS & JS.
browser.contentScripts.register({
matches: [hosts],
css: [{code: css}],
js: [{code: js}],
});
However if the target is userScripts
, 2 almost identical registrations/processes have to be created.
browser.contentScripts.register({
matches: [hosts],
css: [{code: css}]
});
browser.userScripts.register.register({
matches: [hosts],
js: [{code: js}]
});
Updated•3 years ago
|
Updated•3 years ago
|
Comment 10•1 year ago
|
||
Moving this enhacement request to a seealso for Bug 1875475, the userScripts API this bug was originally reported for is deprecated in MV3 and meant to be replaced by the API tracked by Bug 1875475.
Based on a quick look to the Google Chrome API reference for the MV3 userScripts API, it doesn't seem this enhancement request is already covered by the API as is, and so instead of wontfixing it (along with Bug 1595853) I'm linking it as a seealso to the bug tracking the new API to be considered for the new MV3 API.
Comment 11•1 year ago
|
||
The ability to execute on demand in the new userScripts API is covered by the feature request at https://github.com/w3c/webextensions/issues/477
Description
•