Skip to content

Commit

Permalink
Support injecting scriptlet in MAIN or ISOLATED world
Browse files Browse the repository at this point in the history
This reflects the _world_ of the MV3 scripting API:
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/ExecutionWorld

MAIN: page's world
ISOLATED: extension's content script world

Some scriptlets are best executed in either world, so this
commit allows to pick in which world a scriptlet should execute
(default to MAIN).

For instance, the new sed.js scriptlet will now execute in
the ISOLATED world.
  • Loading branch information
gorhill committed May 23, 2023
1 parent 9f465f5 commit 1a863a8
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 79 deletions.
10 changes: 3 additions & 7 deletions assets/resources/scriptlets.js
Expand Up @@ -2218,6 +2218,7 @@ builtinScriptlets.push({
name: 'sed.js',
requiresTrust: true,
fn: sed,
world: 'ISOLATED',
dependencies: [
'pattern-to-regex.fn',
'run-at.fn',
Expand All @@ -2229,7 +2230,6 @@ function sed(
pattern = '',
replacement = ''
) {
if ( document.documentElement === null ) { return; }
const reNodeName = patternToRegex(nodeName, 'i');
const rePattern = patternToRegex(pattern, 'gms');
const extraArgs = new Map(
Expand Down Expand Up @@ -2274,22 +2274,18 @@ function sed(
}
};
const observer = new MutationObserver(handleMutations);
observer.observe(document.documentElement, { childList: true, subtree: true });
{
observer.observe(document, { childList: true, subtree: true });
if ( document.documentElement ) {
const treeWalker = document.createTreeWalker(
document.documentElement,
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT
);
const currentScriptNode = document.currentScript;
const currentTextNode = currentScriptNode.firstChild;
let count = 0;
for (;;) {
const node = treeWalker.nextNode();
count += 1;
if ( node === null ) { break; }
if ( reNodeName.test(node.nodeName) === false ) { continue; }
if ( node === currentScriptNode ) { continue; }
if ( node === currentTextNode ) { continue; }
if ( handleNode(node) ) { continue; }
stop(); break;
}
Expand Down
2 changes: 1 addition & 1 deletion platform/firefox/vapi-background-ext.js
Expand Up @@ -315,7 +315,7 @@ vAPI.scriptletsInjector = ((doc, details) => {
script = doc.createElement('script');
script.async = false;
script.src = url;
(doc.head || doc.documentElement).appendChild(script);
doc.append(script);
self.uBO_scriptletsInjected = details.filters;
} catch (ex) {
}
Expand Down
6 changes: 3 additions & 3 deletions src/js/contentscript.js
Expand Up @@ -1324,9 +1324,9 @@ vAPI.DOMFilterer = class {
// https://github.com/gorhill/uBlock/blob/master/assets/ublock/resources.txt
if ( scriptletDetails && typeof self.uBO_scriptletsInjected !== 'string' ) {
self.uBO_scriptletsInjected = scriptletDetails.filters;
if ( scriptletDetails.scriptlets ) {
vAPI.injectScriptlet(document, scriptletDetails.scriptlets);
vAPI.injectedScripts = scriptletDetails.scriptlets;
if ( scriptletDetails.mainWorld ) {
vAPI.injectScriptlet(document, scriptletDetails.mainWorld);
vAPI.injectedScripts = scriptletDetails.mainWorld;
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/js/redirect-engine.js
Expand Up @@ -87,6 +87,7 @@ class RedirectEntry {
this.warURL = undefined;
this.params = undefined;
this.requiresTrust = false;
this.world = 'MAIN';
this.dependencies = [];
}

Expand Down Expand Up @@ -157,6 +158,7 @@ class RedirectEntry {
r.requiresTrust = details.requiresTrust === true;
r.warURL = details.warURL !== undefined && details.warURL || undefined;
r.params = details.params !== undefined && details.params || undefined;
r.world = details.world || 'MAIN';
if ( Array.isArray(details.dependencies) ) {
r.dependencies.push(...details.dependencies);
}
Expand Down Expand Up @@ -227,6 +229,7 @@ class RedirectEngine {
if ( entry.mime.startsWith(mime) === false ) { return; }
return {
js: entry.toContent(),
world: entry.world,
dependencies: entry.dependencies.slice(),
};
}
Expand Down Expand Up @@ -320,6 +323,7 @@ class RedirectEngine {
data: fn.toString(),
dependencies: scriptlet.dependencies,
requiresTrust: scriptlet.requiresTrust === true,
world: scriptlet.world || 'MAIN',
});
this.resources.set(name, entry);
if ( Array.isArray(aliases) === false ) { continue; }
Expand Down

3 comments on commit 1a863a8

@uBlock-user
Copy link
Contributor

@uBlock-user uBlock-user commented on 1a863a8 May 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm seeing ads on intermittent refresh at https://www.youtube.com/watch?v=p6qZdzimIFA(could be NSFW) after updating to the latest dev build on Nightly and Firefox. Could it be because of this commit ?

@gorhill
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing change for all scriptlets other than sed.

@uBlock-user
Copy link
Contributor

@uBlock-user uBlock-user commented on 1a863a8 May 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, I don't see the ads on that video appearing even once after I downgrade to two days old build 1.49.3b16, very strange occurrence....

Edit: fixed with 9134c11

Please sign in to comment.