From 1e3698679520737d4e0691ab989148db6c706abe Mon Sep 17 00:00:00 2001 From: hackademix Date: Thu, 13 Aug 2020 00:32:03 +0200 Subject: [PATCH] Work-arounds for edge cases in synchronous page loads bypassing webRequest (thanks skriptimaahinen). --- src/content/DocumentCSP.js | 7 ++++++- src/content/staticNS.js | 37 ++++++++++++------------------------- src/lib/SyncMessage.js | 3 ++- 3 files changed, 20 insertions(+), 27 deletions(-) diff --git a/src/content/DocumentCSP.js b/src/content/DocumentCSP.js index ed3348e..0e6b4a1 100644 --- a/src/content/DocumentCSP.js +++ b/src/content/DocumentCSP.js @@ -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 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; diff --git a/src/content/staticNS.js b/src/content/staticNS.js index af975b1..3310b21 100644 --- a/src/content/staticNS.js +++ b/src/content/staticNS.js @@ -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(); - 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); - } - } + if (syncLoad && !localPolicy) { + sessionStorage.setItem(localPolicyKey, JSON.stringify(policy)); + return; } } for (;;) { try { - policy = browser.runtime.sendSyncMessage( + browser.runtime.sendSyncMessage( {id: "fetchPolicy", url, contextUrl: url}, setup); break; diff --git a/src/lib/SyncMessage.js b/src/lib/SyncMessage.js index 9b295a4..a613483 100644 --- a/src/lib/SyncMessage.js +++ b/src/lib/SyncMessage.js @@ -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 };