From 8d6f96302292dbfdccf88966013ce8d67d64f475 Mon Sep 17 00:00:00 2001 From: hackademix Date: Tue, 24 Jul 2018 23:21:01 +0200 Subject: Work-around for serviceWorker loads bypassing webRequest. --- src/bg/RequestGuard.js | 21 +++++++++++++++----- src/content/content.js | 52 ++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 54 insertions(+), 19 deletions(-) diff --git a/src/bg/RequestGuard.js b/src/bg/RequestGuard.js index 6f507fe..8191f3e 100644 --- a/src/bg/RequestGuard.js +++ b/src/bg/RequestGuard.js @@ -72,6 +72,7 @@ var RequestGuard = (() => { }, initTab(tabId, records = this.newRecords()) { + if (tabId < 0) return; this.map.set(tabId, records); return records; }, @@ -109,6 +110,8 @@ var RequestGuard = (() => { }, record(request, what, optValue) { + let {tabId} = request; + if (tabId < 0) return; let records = this._record(request, what, optValue); if (records) { this.updateTab(request.tabId); @@ -118,6 +121,7 @@ var RequestGuard = (() => { _pendingTabs: new Set(), updateTab(tabId) { + if (tabId < 0) return; if (this._pendingTabs.size === 0) { window.setTimeout(() => { // clamp UI updates for (let tabId of this._pendingTabs) { @@ -217,7 +221,7 @@ var RequestGuard = (() => { case "pageshow": TabStatus.recordAll(sender.tab.id, message.seen); return true; - case "enable": + case "enable": { let {url, documentUrl, policyType} = message; let TAG = `<${policyType.toUpperCase()}>`; let origin = Sites.origin(url); @@ -258,10 +262,17 @@ var RequestGuard = (() => { ns.savePolicy(); } return true; - case "canScript": - let records = TabStatus.map.get(sender.tab.id); - debug("Records.noscriptFrames %o, canScript: %s", records && records.noscriptFrames, !(records && records.noscriptFrames[sender.frameId])); - return !(records && records.noscriptFrames[sender.frameId]); + } + case "canScript": { + let {frameId, url, tab} = sender; + let tabId = tab.id; + let records = TabStatus.map.get(tabId); + let noscriptFrames = records && records.noscriptFrames; + let canScript = !(noscriptFrames && noscriptFrames[sender.frameId]); + let shouldScript = ns.isEnforced(tabId) && ns.policy.can(url, "script"); + debug("Frame %s %s of %o, canScript: %s, shouldScript: %s", frameId, url, noscriptFrames, canScript, shouldScript); + return {canScript, shouldScript}; + } } }, diff --git a/src/content/content.js b/src/content/content.js index a183117..a2bb4d9 100644 --- a/src/content/content.js +++ b/src/content/content.js @@ -1,7 +1,9 @@ 'use strict'; // debug = () => {}; // XPI_ONLY - + +window.canScript = true; + function createHTMLElement(name) { return document.createElementNS("http://www.w3.org/1999/xhtml", name); } @@ -20,7 +22,6 @@ function probe() { var _ = browser.i18n.getMessage; -var canScript = true; var embeddingDocument = false; @@ -86,26 +87,49 @@ let notifyPage = () => { } var queryingCanScript = false; +var caps = {}; + async function init(oldPage = false) { if (queryingCanScript) return; + if (document.URL === "about:blank") { + return; + } queryingCanScript = true; - debug(`NoScript init() called in document %s, scripting=%s, content type %s readyState %s`, - document.URL, canScript, document.contentType, document.readyState); + + debug(`init() called in document %s, contentType %s readyState %s`, + document.URL, document.contentType, document.readyState); try { - canScript = document.URL === "about:blank" || await browser.runtime.sendMessage({type: "canScript"}); - if (oldPage && canScript) { - probe(); - setTimeout(() => init(), 100); - return; + let {canScript, shouldScript} = await browser.runtime.sendMessage({type: "canScript"}); + debug(`document %s, canScript=%s, shouldScript=%s, readyState %s`, document.URL, canScript, shouldScript, document.readyState); + if (canScript) { + if (oldPage) { + probe(); + setTimeout(() => init(), 100); + return; + } + if (!shouldScript) { + // Something wrong: scripts can run, permissions say they shouldn't. + // Was webRequest bypassed by caching/session restore/service workers? + let noCache = !!navigator.serviceWorker.controller; + if (noCache) { + for (let r of await navigator.serviceWorker.getRegistrations()) { + await r.unregister(); + } + } + debug("Reloading %s (%s)", document.URL, noCache ? "no cache" : "cached"); + location.reload(noCache); + return; + } } + window.canScript = canScript; init = () => {}; - debug("canScript:", canScript); } catch (e) { debug("Error querying canScript", e); - if (document.readyState !== "complete" && + if (!oldPage && /Receiving end does not exist/.test(e.message)) { - window.location.reload(false); + // probably startup and bg page not ready yet, hence no CSP: reload! + location.reload(false); } else { setTimeout(() => init(oldPage), 100); } @@ -126,8 +150,8 @@ async function init(oldPage = false) { } ); - debug(`Loading NoScript in document %s, scripting=%s, content type %s readyState %s`, - document.URL, canScript, document.contentType, document.readyState); + debug(`Loading NoScript in document %s, scripting=%s, readyState %s`, + document.URL, canScript, document.readyState); if (/application|video|audio/.test(document.contentType)) { debug("Embedding document detected"); -- cgit v1.2.3