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
Porting webcompat interventions injections from contentScripts to scripting API #320
Conversation
Thanks for your work here! We'll check it out as soon as we can. :) |
Thanks a lot! As a side note, in addition to the unit tests in this PR, here is an STR I used to verify the resiliency of the interventions content scripts registered from the extension background page after a process crash have triggered the background page to be destroyed (a similar STR can also be tried on Firefox for Android, but the extension process has to be enabled manually there):
I did also run |
@Rob--W would you mind to also take a look at this PR and provide feedback from your perspective? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, thanks! R+ with just a few nits/notes.
Also one question just in case we need to every worry about it: do the current ESRs support this as well, or should we avoid backporting this change if we ever update the interventions on ESR 102/115?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a step in the right direction: the positive aspect of this PR is that it ensures that injections continue to work even when the background unloads.
An issue is that the central management logic executes on each execution of run.js, and if the content script state exists from before the last background load, then there will be a registration error at https://searchfox.org/mozilla-central/rev/4e22b886bbd4c274f268c4a285ab7da00e95c99b/browser/extensions/webcompat/run.js#14-15
I think that it works just fine right now, other than logspam, but please confirm that.
Another nice-to-have (not required because it's pre-existing) is to register all content scripts with one registerContentScripts
call, because that is much more efficient than doing multiple calls - each registration results in a broadcast IPC to all content processes, which is not cheap at all.
I just pushed a few more changes that I had added locally but didn't push yet. Let's now merge this yet, I'm going to test this out locally explicitly and I want to double-check a couple more things around the AboutCompatBroker. |
@wisniewskit I double-checked in which version the scripting API was landed and what changes have been applied so far and left the following inline comment related to that:
|
@wisniewskit I have applied some more fixes, but there is still some more I want to double-check around the call to getRegisteredScripts and took some notes about some more things I want to test out manually locally a bit more, and so this is not yet to be merged. |
aedfc62
to
7caa3b2
Compare
src/lib/injections.js
Outdated
@@ -155,8 +203,8 @@ class Injections { | |||
} | |||
|
|||
async disableContentScripts(injection) { | |||
const contentScript = this._activeInjections.get(injection); | |||
await contentScript.unregister(); | |||
const scriptId = this._activeInjections.get(injection); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only purpose of _activeInjections
is to keep the handle around for unregistration. Since registration is now fully managed through the scripting
API by id, we can remove all traces of _activeInjections
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Rob--W if we port (or when we port, if we are not going to do that in this PR) the shims to the scripting API then we would still to tell from a getRegisteredContentScripts result which are the ones registered from Injections and which are registered from Shims and so I think we would still need to keep _activeInjections
If we want we could consider changing _activeInjections to be a Set of injection objects or injection ids instead of a Map if we want that.
src/lib/shims.js
Outdated
// NOTE: porting this call to scripting.registerContentScripts | ||
// would require Bug 1764572 to have been fixed in all Gecko | ||
// version where we would need to run the webcompat builtin, | ||
// otherwise the Firebase Shim would not be able to be registered |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If cookieStoreId support is causing that much hardship, then it can be removed. The Firebase shim is limited to PBM because it's only needed there.
The shim itself is already no-op when run in non-PBM (due to feature detection before overwriting). Due to the use of wrappedJSObject, in theory the page can void a global and trigger shimming. If we want to counter that, then we can modify
webcompat-addon/src/shims/firebase.js
Line 17 in 16f6e7b
(function () { |
if (navigator.serviceWorker) {
return; // SW available, not running in PBM.
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And actually, in hindsight this might be a good idea anyway, since if users disable serviceWorkers via about:config, this can keep the site working a bit better for them regardless of whether they're in PBM or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we can live without cookieStoreIds, then yeah we could port Shim to the scripting API and avoid the workaround added to avoid hitting Bug 1851173 (and the big inline comment added to explain why that workaround is there).
The gain for Shim may not be as the one for Injections, because it seems that the Shim may also depend from the background page covering other parts of the expected behavior for the shim (e.g. the parts covered by the webRequest listeners), and so even if the content script would still be injected while the background page may not be around (which would be the case if there are so many crashes that we would stop to reload the background page automatically and leave the user to choose if they want to try again) the shim may not still work if it also depends from what the background page was meant to cover.
@wisniewskit based on your deeper knowledge about what the shims are expected to be doing and how they collaborate with the background page to achieve that, do you think that there may be any chance that a shim content script without the background page running could misbehave?
would you mind to point me to a couple of cases that you think would be worth for me to test out explicitly and look into more deeply to get a better picture of this part and form a more informed opinion on my side about what we would expect to happen (vs. what should happen)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a side note, looking to the firebase.js shim, that one should still work fine without the background page, and so as I was expecting some shim do not depend from the background page still being around (and I could look for specific properties in the list of shims to determine which ones depends on the background page, e.g. I suspect that the ones with needsShimHelpers
or the ones redirecting urls may be part of the shims that depends also on the background page being running)
7caa3b2
to
3513cdd
Compare
@wisniewskit @Rob--W I applied the remaining few changes to cover the last round of comments, than I confirmed that I needed some more to cover a few details that got missed in the previous review passes:
@wisniewskit I've also run some more manual test on this version and I wrote down my STRs in the PR description in case you may also want to run a manual test locally. There is a scenario 3 related to write down the manual STRs to exercise the AboutCompatBroker part, if you have the STRs for that I may give that a try and write down Scenario 3 too. This should now be ready for the final (and hopefully last ;-)) pass from my perspective. @wisniewskit as a side note, as I think we may have mentioned you when we meet in Montreal, we didn't need this to land in 118, but we were aiming and hoping to get it vendored in the firefox-android repo in 119 (we may instead not strictly need it to be vendored in mozilla-central in the same timeframe, but I guess it may still be better to don't diverge the two), do you think that vendoring it in the firefox-android github repo can fit into the 119 timeframe? |
@wisniewskit hey, can you please take another look? Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, thanks! Could you rebase and bump the minor version number to 118.2.0? (https://phabricator.services.mozilla.com/D186793 just landed ahead of this) I think it's time to land this in the desktop/mobile nightlies and test it out.
d2a2632
to
70ccdcc
Compare
@wisniewskit thanks, I've just rebased and squashed the commits from this PR on the current repo tip, and added another commit which bumps the package and manifest versions to 118.2.0. |
I'm in the process of landing this now, via https://bugzilla.mozilla.org/show_bug.cgi?id=1853013 and mozilla-mobile/firefox-android#3624 |
This PR include a draft of the changes needed to port the webcompat interventions builtin addon from the contentScripts.register API method to the scripting.registerContentScripts API method.
The motivation behind it is that the content scripts dynamically registered using contentScripts.register are expected to be unregistered automatically if the background page is destroyed, while the ones registered through the scripting.registerContentScripts API are expected to stay registered even after the background page is destroyed.
While this PR does not aim to convert the persistent background page into an event page, it may still be interesting to consider it on its own, because it would still help to make the webcompat interventions to be more resilient to extension process shutdown/crashes, because the interventions content scripts will be stay registered even after the background page is gone due to an extension process shutdown/crash.
TODO Task list:
Manual Testing STR
npm run jake export-mc
as described in this repo README.md doc fileScenario 1: webcompat background page reloaded automatically after an extension process crash
Scenario 2: webcompat background page not running anymore due to extension process crashes exceeded threshold
extensions.background.disableRestartPersistentAfterCrash
totrue
to disable the autorestart of the persistent background pages after a crash (to simulate the condition of extension process crashes exceeding the threshold and the process not being restarted anymore)Scenario 3: webcompat injections and shims enabled/disabled from about:compat page