Work-around for conflict with extensions inserting elements into content pages' DOM early.

This commit is contained in:
hackademix 2020-08-02 13:27:12 +02:00
parent 7af5194ef5
commit 762b0122ce
1 changed files with 20 additions and 11 deletions

View File

@ -195,10 +195,17 @@
let uuid = () => (Math.random() * Date.now()).toString(16); let uuid = () => (Math.random() * Date.now()).toString(16);
let docUrl = document.URL; let docUrl = document.URL;
browser.runtime.sendSyncMessage = (msg, callback) => { browser.runtime.sendSyncMessage = (msg, callback) => {
// we interrogate the canScript() callback to know whether the caller
// wants scripts deferred by sendSyncMessage to be eventually executed:
// - undefined -> too soon to tell, suspend
// - true -> go on and execute
// - false -> block
let canScript; let canScript;
if (callback && typeof callback === "object") { if (callback && typeof callback === "object") {
({canScript, callback} = callback); ({canScript, callback} = callback);
} else { }
if (typeof canScript !== "function") {
// if no canScript() callback was passed, default to execute scripts
canScript = () => true; canScript = () => true;
} }
@ -213,9 +220,10 @@
if (MOZILLA) { if (MOZILLA) {
// In order to cope with inconsistencies in XHR synchronicity, // In order to cope with inconsistencies in XHR synchronicity,
// allowing DOM element to be inserted and script to be executed // allowing scripts to be executed (especially with synchronous loads
// (seen with file:// and ftp:// loads) we additionally suspend on // or when other extensions manipulate the DOM early) we additionally
// Mutation notifications and beforescriptexecute events // suspend on beforescriptexecute events
let suspendURL = url + "&suspend=true"; let suspendURL = url + "&suspend=true";
let suspended = false; let suspended = false;
let suspend = () => { let suspend = () => {
@ -230,20 +238,21 @@
} }
suspended = false; suspended = false;
}; };
let domSuspender = new MutationObserver(records => {
suspend();
});
domSuspender.observe(document.documentElement, {childList: true});
let onBeforeScript = e => { let onBeforeScript = e => {
while(typeof canScript() === "undefined") {
suspend(); suspend();
if (!canScript()) e.preventDefault(); }
if (!canScript()) {
console.debug("sendSyncMessage blocked a script element", e.target);
e.preventDefault();
}
}; };
addEventListener("beforescriptexecute", onBeforeScript, true); addEventListener("beforescriptexecute", onBeforeScript, true);
let finalize = () => { let finalize = () => {
removeEventListener("beforescriptexecute", onBeforeScript, true); removeEventListener("beforescriptexecute", onBeforeScript, true);
domSuspender.disconnect();
}; };
// on Firefox we first need to send an async message telling the // on Firefox we first need to send an async message telling the