Fix reload loops on broken file: HTML documents (thanks bernie for report).

This commit is contained in:
hackademix 2020-08-20 00:12:50 +02:00
parent a83cf372eb
commit affe284193
1 changed files with 54 additions and 23 deletions

View File

@ -68,37 +68,68 @@
let originalState = document.readyState; let originalState = document.readyState;
let syncLoad = UA.isMozilla && /^(?:ftp|file):/.test(url); let syncLoad = UA.isMozilla && /^(?:ftp|file):/.test(url);
let localPolicyKey; let localPolicy;
if (syncLoad && originalState !== "complete") { if (syncLoad && originalState !== "complete") {
localPolicyKey = `ns.policy.${url}|${browser.runtime.getURL("")}`; localPolicy = {
key: `[ns.policy.${url}|${browser.runtime.getURL("")}|${Math.floor(Date.now() / 10000)}]`,
let [name, localPolicy] = window.name.split(localPolicyKey); read(resetName = false) {
window.name = name; let [policy, name] =
if (localPolicy) { window.name.includes(this.key) ? window.name.split(this.key) : [null, window.name];
debug("Falling back to localPolicy", localPolicy); this.policy = policy ? (policy = JSON.parse(policy)) : null;
try { if (resetName) window.name = name;
this.setup(JSON.parse(localPolicy)); return {policy, name};
} catch(e) { },
error(e, "Falling back: could not setup local policy", localPolicy); write(policy = this.policy, name = window.name) {
localPolicyKey = null; if (name.includes(this.key)) {
this.setup(null); ({name} = this.read());
} }
let policyString = JSON.stringify(policy);
window.name = [policyString, name].join(this.key);
// verify
if (JSON.stringify(this.read(false).policy) !== policyString) {
throw new Error("Can't write localPolicy", policy, window.name);
}
}
}
try {
let {policy} = localPolicy.read(true);
if (policy) {
debug("Applying localPolicy", policy);
this.setup(policy);
let onBeforeUnload = e => {
// this fixes infinite reload loops if Firefox decides to reload the page immediately
// because it needs to be reparsed (e.g. broken / late charset declaration)
// see https://forums.informaction.com/viewtopic.php?p=102850
localPolicy.write(policy);
};
addEventListener("beforeunload", onBeforeUnload, false);
addEventListener("DOMContentLoaded", e => removeEventListener(onBeforeUnload, false), true);
return; return;
} else { }
} catch(e) {
error(e, "Falling back: could not setup local policy", localPolicy.policy);
this.setup(null);
return;
}
debug("Stopping synchronous load to fetch and apply localPolicy...");
addEventListener("beforescriptexecute", e => { addEventListener("beforescriptexecute", e => {
console.log("Blocking early script", e.target); console.log("Blocking early script", e.target);
e.preventDefault(); e.preventDefault();
}); });
stop(); stop();
} }
}
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 (syncLoad && originalState !== "complete") { if (localPolicy) {
window.name = [window.name, JSON.stringify(this.policy)].join(localPolicyKey); try {
localPolicy.write(policy);
location.reload(false); location.reload(false);
} catch (e) {
error(e, "Cannot write local policy, bailing out...")
}
return; return;
} }
} }