Skip to content

Commit 15e832d

Browse files
committed
Mind potential race condition when dynamically registering scriptlets
In Firefox, scriptlets are dynamically registered as content scripts to ensure they execute in a timely manner. The race condition could lead to scriptlet injection failing at browser launch time in Firefox when the setting "Suspend network activity until all filter lists are loaded" had been disabled[1], even after forcing a page reload. Causing the filter lists to reload would make the issue go away. [1] Default is enabled in Firefox and it is strongly advised to NOT change this.
1 parent 3d2f70a commit 15e832d

File tree

1 file changed

+8
-4
lines changed

1 file changed

+8
-4
lines changed

src/js/scriptlet-filtering.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import µb from './background.js';
3838
/******************************************************************************/
3939

4040
const contentScriptRegisterer = {
41+
id: 1,
4142
hostnameToDetails: new Map(),
4243
register(hostname, code) {
4344
if ( browser.contentScripts === undefined ) { return false; }
@@ -47,22 +48,25 @@ const contentScriptRegisterer = {
4748
if ( code === details.code ) {
4849
return details.handle instanceof Promise === false;
4950
}
50-
details.handle.unregister();
51+
this.unregisterHandle(details.handle);
5152
this.hostnameToDetails.delete(hostname);
5253
}
54+
const id = this.id++;
5355
const promise = browser.contentScripts.register({
5456
js: [ { code } ],
5557
allFrames: true,
5658
matches: [ `*://*.${hostname}/*` ],
5759
matchAboutBlank: true,
5860
runAt: 'document_start',
5961
}).then(handle => {
60-
this.hostnameToDetails.set(hostname, { handle, code });
61-
return handle;
62+
const details = this.hostnameToDetails.get(hostname);
63+
if ( details === undefined ) { return; }
64+
if ( details.id !== id ) { return; }
65+
details.handle = handle;
6266
}).catch(( ) => {
6367
this.hostnameToDetails.delete(hostname);
6468
});
65-
this.hostnameToDetails.set(hostname, { handle: promise, code });
69+
this.hostnameToDetails.set(hostname, { id, handle: promise, code });
6670
return false;
6771
},
6872
unregister(hostname) {

0 commit comments

Comments
 (0)