Work-arounds for edge cases in synchronous page loads bypassing webRequest (thanks skriptimaahinen).
This commit is contained in:
parent
d4c2ab2c05
commit
1e36986795
|
@ -1,5 +1,4 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
class DocumentCSP {
|
class DocumentCSP {
|
||||||
constructor(document) {
|
constructor(document) {
|
||||||
this.document = document;
|
this.document = document;
|
||||||
|
@ -33,6 +32,9 @@ class DocumentCSP {
|
||||||
meta.setAttribute("http-equiv", header.name);
|
meta.setAttribute("http-equiv", header.name);
|
||||||
meta.setAttribute("content", header.value);
|
meta.setAttribute("content", header.value);
|
||||||
let root = document.documentElement;
|
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 {head} = document;
|
||||||
let parent = head ||
|
let parent = head ||
|
||||||
(root instanceof HTMLElement
|
(root instanceof HTMLElement
|
||||||
|
@ -44,6 +46,9 @@ class DocumentCSP {
|
||||||
debug(`Failsafe <meta> CSP inserted in %s: "%s"`, document.URL, header.value);
|
debug(`Failsafe <meta> CSP inserted in %s: "%s"`, document.URL, header.value);
|
||||||
meta.remove();
|
meta.remove();
|
||||||
if (!head) parent.remove();
|
if (!head) parent.remove();
|
||||||
|
for (let a of rootAttrs) {
|
||||||
|
root.setAttributeNodeNS(a);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error(e, "Error inserting CSP %s in %s", document.URL, header && header.value);
|
error(e, "Error inserting CSP %s in %s", document.URL, header && header.value);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -66,10 +66,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
let originalState = document.readyState;
|
let originalState = document.readyState;
|
||||||
let blockedScripts = [];
|
let syncLoad = UA.isMozilla && /^(?:ftp|file):/.test(url);
|
||||||
let localPolicyKey, localPolicy;
|
let localPolicyKey, localPolicy;
|
||||||
if (UA.isMozilla && /^(?:ftp|file):/.test(url)) {
|
if (syncLoad) {
|
||||||
|
|
||||||
localPolicyKey = `ns.policy.${url}|${browser.runtime.getURL("")}`;
|
localPolicyKey = `ns.policy.${url}|${browser.runtime.getURL("")}`;
|
||||||
let localPolicy = sessionStorage.getItem(localPolicyKey);
|
let localPolicy = sessionStorage.getItem(localPolicyKey);
|
||||||
sessionStorage.removeItem(localPolicyKey);
|
sessionStorage.removeItem(localPolicyKey);
|
||||||
|
@ -81,39 +80,27 @@
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
error(e, "Could not setup local policy", localPolicy);
|
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 => {
|
let setup = policy => {
|
||||||
debug("Fetched %o, readyState %s", policy, document.readyState); // DEV_ONLY
|
debug("Fetched %o, readyState %s", policy, document.readyState); // DEV_ONLY
|
||||||
this.setup(policy);
|
this.setup(policy);
|
||||||
if (this.canScript && blockedScripts.length && originalState === "loading") {
|
if (syncLoad && !localPolicy) {
|
||||||
log("Running suspended scripts which are permitted by %s policy.", url);
|
sessionStorage.setItem(localPolicyKey, JSON.stringify(policy));
|
||||||
// something went wrong, e.g. with session restore.
|
return;
|
||||||
if (url.startsWith("file:") && !localPolicy) {
|
|
||||||
stop();
|
|
||||||
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 (;;) {
|
for (;;) {
|
||||||
try {
|
try {
|
||||||
policy = browser.runtime.sendSyncMessage(
|
browser.runtime.sendSyncMessage(
|
||||||
{id: "fetchPolicy", url, contextUrl: url},
|
{id: "fetchPolicy", url, contextUrl: url},
|
||||||
setup);
|
setup);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -221,6 +221,7 @@
|
||||||
// or when other extensions manipulate the DOM early) we additionally
|
// or when other extensions manipulate the DOM early) we additionally
|
||||||
// suspend on beforescriptexecute events
|
// suspend on beforescriptexecute events
|
||||||
|
|
||||||
|
let startTime = Date.now(); // DEV_ONLY
|
||||||
let suspendURL = url + "&suspend=true";
|
let suspendURL = url + "&suspend=true";
|
||||||
let suspended = 0;
|
let suspended = 0;
|
||||||
let suspendedId = 0;
|
let suspendedId = 0;
|
||||||
|
@ -236,7 +237,7 @@
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
suspended--;
|
suspended--;
|
||||||
console.debug("sendSyncMessage resume #%s/%s", id, suspended);
|
console.debug("sendSyncMessage resume #%s/%s - %sms", id, suspended, Date.now() - startTime); // DEV_ONLY
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue