Work-arounds for edge cases in synchronous page loads bypassing webRequest (thanks skriptimaahinen).

This commit is contained in:
hackademix 2020-08-13 00:32:03 +02:00
parent d4c2ab2c05
commit 1e36986795
3 changed files with 20 additions and 27 deletions

View File

@ -1,5 +1,4 @@
'use strict';
class DocumentCSP {
constructor(document) {
this.document = document;
@ -33,6 +32,9 @@ class DocumentCSP {
meta.setAttribute("http-equiv", header.name);
meta.setAttribute("content", header.value);
let root = document.documentElement;
let rootAttrs = [...root.attributes].filter(a => a.name.toLowerCase().startsWith("on"));
for (let a of rootAttrs) root.removeAttributeNode(a);
let {head} = document;
let parent = head ||
(root instanceof HTMLElement
@ -44,6 +46,9 @@ class DocumentCSP {
debug(`Failsafe <meta> CSP inserted in %s: "%s"`, document.URL, header.value);
meta.remove();
if (!head) parent.remove();
for (let a of rootAttrs) {
root.setAttributeNodeNS(a);
}
} catch (e) {
error(e, "Error inserting CSP %s in %s", document.URL, header && header.value);
return false;

View File

@ -66,10 +66,9 @@
}
let originalState = document.readyState;
let blockedScripts = [];
let syncLoad = UA.isMozilla && /^(?:ftp|file):/.test(url);
let localPolicyKey, localPolicy;
if (UA.isMozilla && /^(?:ftp|file):/.test(url)) {
if (syncLoad) {
localPolicyKey = `ns.policy.${url}|${browser.runtime.getURL("")}`;
let localPolicy = sessionStorage.getItem(localPolicyKey);
sessionStorage.removeItem(localPolicyKey);
@ -81,39 +80,27 @@
} catch(e) {
error(e, "Could not setup local policy", localPolicy);
}
} else {
addEventListener("beforescriptexecute", e => {
console.log("Blocking early script", e.target);
e.preventDefault();
});
stop();
}
}
let policy = null;
let setup = policy => {
debug("Fetched %o, readyState %s", policy, document.readyState); // DEV_ONLY
this.setup(policy);
if (this.canScript && blockedScripts.length && originalState === "loading") {
log("Running suspended scripts which are permitted by %s policy.", url);
// something went wrong, e.g. with session restore.
if (url.startsWith("file:") && !localPolicy) {
stop();
if (syncLoad && !localPolicy) {
sessionStorage.setItem(localPolicyKey, JSON.stringify(policy));
location.reload(false);
return;
}
for (let s of blockedScripts) {
// reinsert the script:
// just s.cloneNode(true) doesn't work, the script wouldn't run,
// let's clone it the hard way...
try {
s.replaceWith(document.createRange().createContextualFragment(s.outerHTML));
} catch (e) {
error(e);
}
}
}
}
for (;;) {
try {
policy = browser.runtime.sendSyncMessage(
browser.runtime.sendSyncMessage(
{id: "fetchPolicy", url, contextUrl: url},
setup);
break;

View File

@ -221,6 +221,7 @@
// or when other extensions manipulate the DOM early) we additionally
// suspend on beforescriptexecute events
let startTime = Date.now(); // DEV_ONLY
let suspendURL = url + "&suspend=true";
let suspended = 0;
let suspendedId = 0;
@ -236,7 +237,7 @@
console.error(e);
}
suspended--;
console.debug("sendSyncMessage resume #%s/%s", id, suspended);
console.debug("sendSyncMessage resume #%s/%s - %sms", id, suspended, Date.now() - startTime); // DEV_ONLY
};