-
Notifications
You must be signed in to change notification settings - Fork 142
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
fix(adblocker): inject scriplets with browser.contentScripts
on Firefox
#2074
base: main
Are you sure you want to change the base?
Conversation
Builds for commit 05fd0a5: |
Builds for commit 05fd0a5: |
Builds for commit ded4f50: |
ded4f50
to
d589cb3
Compare
Builds for commit d589cb3: |
Builds for commit 4ad49a1: |
Builds for commit 4ad49a1: |
@@ -196,6 +241,21 @@ async function injectScriptlets(scripts, tabId, frameId) { | |||
script.remove(); | |||
} | |||
|
|||
if (__PLATFORM__ === 'firefox') { | |||
if (scripts.length === 0) { | |||
contentScripts.unregister(hostname); |
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.
I'm wondering if this part of the code is necessary or how it should be best handled.
When the engine updates, it should automatically clear the content scripts (contentScripts.unregisterAll). There might be potential for race conditions, but in principle, it should eventually take care of unregistering.
Is the code here intended especially for pause (which won't trigger an engine reload)? If so, would be good to leave a comment explaining this.
Builds for commit b63b226: |
Tested version: #2074 (comment) Checked on:
Websites:
LGTM |
browser.contentScripts
on Firefox
b63b226
to
0eafaf4
Compare
0eafaf4
to
ac86ec3
Compare
Builds for commit ac86ec3: |
Builds for commit a3ec1b4: |
Builds for commit bcdaf85: |
src/background/adblocker.js
Outdated
@@ -224,6 +296,9 @@ function injectStyles(styles, tabId, frameId) { | |||
} | |||
|
|||
async function injectCosmetics(details, config) { | |||
const isBootstrap = config.bootstrap; | |||
const scriptletsOnly = Boolean(config.scriptletsOnly); |
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.
We are in control over the config, and undefined
is just fine, you don't need to convert it to Boolean.
src/background/adblocker.js
Outdated
@@ -237,6 +312,8 @@ async function injectCosmetics(details, config) { | |||
const domain = parsed.domain || ''; | |||
const hostname = parsed.hostname || ''; | |||
|
|||
if (scriptletsOnly && contentScripts.isRegistered(hostname)) return; |
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 scripletsOnly
is not what the name suggests - it is a flag for EXPERIMENTAL_SCRIPTLETS_INJECTION
- you can't use scripletsOnly
in Chrome if you would wish for example.
There is an unrelated bug in Firefox requiring the separation of injecting styles and scriptlets (styles must be injected not in onCommited
, as then we have permission for an issue in iframes). So as this function becomes harder to reason about, this is a moment to do so...
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.
not quite right, this block is just an optimization that prevent a matching if content scripts are already registered. scriptletsOnly
main role is to prevent style injection a bit below.
But yes, the condition should be improved
src/background/adblocker.js
Outdated
@@ -153,6 +158,12 @@ export const setup = asyncSetup('adblocker', [ | |||
OptionsObserver.addListener( | |||
'experimentalFilters', | |||
async (value, lastValue) => { | |||
if (__PLATFORM__ === 'firefox') { | |||
EXPERIMENTAL_SCRIPTLETS_INJECTION = value; |
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.
Please create another observer to separate logic. You are using the same option, but for another purpose.
Builds for commit b0198ba: |
WARNING: This has to be tested very carefully.
On Firefox, scriptlet injection run into timing issues which makes it impossible to inject certain scriptlets before page scripts.
Examples we try to fix are:
The only way to ensure the scriptlet is always executed before the page script is to use
browser.contentScripts
API which available on Firefox only.Open questions:
allFrames
safe? for example, can scriptlets from different hostnames be injected due toallFrames
?webRequest.onResponseStarted
?TODO: