sendSyncMessage support for multiple suspension requests (should fix extension script injection issues).

This commit is contained in:
hackademix 2020-08-08 09:27:15 +02:00
parent d56eb371a9
commit a977563b88
1 changed files with 14 additions and 26 deletions

View File

@ -62,6 +62,12 @@
if (!wrapper.unsuspend) { if (!wrapper.unsuspend) {
wrapper.unsuspend = resolve; wrapper.unsuspend = resolve;
return; return;
} else {
let {unsuspend} = wrapper;
wrapper.unsuspend = () => {
unsuspend();
resolve();
}
} }
} }
resolve(); resolve();
@ -225,10 +231,10 @@
// suspend on beforescriptexecute events // suspend on beforescriptexecute events
let suspendURL = url + "&suspend=true"; let suspendURL = url + "&suspend=true";
let suspended = false; let suspended = 0;
let suspend = () => { let suspend = () => {
if (suspended) return; suspended++;
suspended = true; console.debug("Suspended, count:", suspended)
try { try {
let r = new XMLHttpRequest(); let r = new XMLHttpRequest();
r.open("GET", suspendURL, false); r.open("GET", suspendURL, false);
@ -236,46 +242,28 @@
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
suspended = false; suspended--;
}; console.debug("Unsuspended, count: ", suspended);
let deferred = [];
let runDeferred = () => {
let current = deferred;
deferred = []; // prevent reentrant calls
for (let ds of current) {
console.debug("sendSyncMessage running deferred", ds)
let replacement = document.createElement("script");
for (let a of ds.attributes) {
replacement.setAttribute(a.name, a.value);
}
replacement.textContent = ds.textContent;
ds.replaceWith(replacement);
}
}; };
let onBeforeScript = e => { let onBeforeScript = e => {
if(typeof canScript() === "undefined") { if(typeof canScript() === "undefined") {
suspend(); suspend();
} }
let allowed = canScript(); let allowed = canScript();
let script = e.target;
if (typeof allowed === "undefined") { if (typeof allowed === "undefined") {
console.debug("sendSyncMessage deferring", script); console.error("sendSyncMessage: script unsuspended before canScript() is defined!", e.target);
deferred.push(script);
} }
if (!allowed) { if (!allowed) {
console.debug("sendSyncMessage blocked", script); console.debug("sendSyncMessage blocked a script element", e.target);
e.preventDefault(); e.preventDefault();
return;
} }
runDeferred();
console.debug("sendSyncMessage allowed", script);
}; };
addEventListener("beforescriptexecute", onBeforeScript, true); addEventListener("beforescriptexecute", onBeforeScript, true);
let finalize = () => { let finalize = () => {
removeEventListener("beforescriptexecute", onBeforeScript, true); removeEventListener("beforescriptexecute", onBeforeScript, true);
runDeferred();
}; };
// on Firefox we first need to send an async message telling the // on Firefox we first need to send an async message telling the