From 7514aa20f959cd997e328cf8d15121d602a5c4fc Mon Sep 17 00:00:00 2001 From: hackademix Date: Sat, 8 Sep 2018 11:50:40 +0200 Subject: Saner message dispatching. --- src/bg/RequestGuard.js | 1 + src/bg/main.js | 23 ++++++++++++----------- src/content/content.js | 3 +-- src/lib/Messages.js | 28 +++++++++++++++++++--------- src/lib/restricted.js | 4 +++- 5 files changed, 36 insertions(+), 23 deletions(-) diff --git a/src/bg/RequestGuard.js b/src/bg/RequestGuard.js index 947a7c1..e507806 100644 --- a/src/bg/RequestGuard.js +++ b/src/bg/RequestGuard.js @@ -394,6 +394,7 @@ var RequestGuard = (() => { let blockedURI = report['blocked-uri']; if (blockedURI && blockedURI !== 'self') { let r = fakeRequestFromCSP(report, request); + if (r.url === 'inline') r.url = request.documentURI; Content.reportTo(r, false, policyTypesMap[r.type]); TabStatus.record(r, "blocked"); } else if (report["violated-directive"] === "script-src" && /; script-src 'none'/.test(report["original-policy"])) { diff --git a/src/bg/main.js b/src/bg/main.js index 9976f8f..376a981 100644 --- a/src/bg/main.js +++ b/src/bg/main.js @@ -24,7 +24,7 @@ async function init() { await Defaults.init(); - + let policyData = (await Storage.get("sync", "policy")).policy; if (policyData && policyData.DEFAULT) { ns.policy = new Policy(policyData); @@ -116,7 +116,7 @@ await Settings.update(settings); toggleCtxMenuItem(); }, - + async broadcastSettings({ tabId = -1 }) { @@ -140,12 +140,12 @@ async importSettings({data}) { return await Settings.import(data); }, - + async fetchChildPolicy({url, contextUrl}, sender) { - return ChildPolicies.getForDocument(ns.policy, + return ChildPolicies.getForDocument(ns.policy, url || sender.url, contextUrl || sender.tab.url); }, - + async openStandalonePopup() { let win = await browser.windows.getLastFocused(); let [tab] = (await browser.tabs.query({ @@ -184,10 +184,10 @@ if (this.running) return; this.running = true; - deferWebTraffic(init(), + deferWebTraffic(init(), async () => { Commands.install(); - + this.devMode = (await browser.management.getSelf()).installType === "development"; if (this.local.debug) { if (this.devMode) { @@ -231,16 +231,17 @@ }, async collectSeen(tabId) { - try { let seen = Array.from(await Messages.send("collect", {}, {tabId, frameId: 0})); debug("Collected seen", seen); return seen; } catch (e) { - // probably a page where content scripts cannot run, let's open the options instead - error(e, "Cannot collect noscript activity data"); + await include("/lib/restricted.js"); + if (!isRestrictedURL((await browser.tabs.get(tabId)).url)) { + // probably a page where content scripts cannot run, let's open the options instead + error(e, "Cannot collect noscript activity data"); + } } - return null; }, }; diff --git a/src/content/content.js b/src/content/content.js index 3709bd1..c501282 100644 --- a/src/content/content.js +++ b/src/content/content.js @@ -51,8 +51,7 @@ var notifyPage = async () => { if (!("canScript" in ns)) { let childPolicy = await Messages.send("fetchChildPolicy", {url: document.URL}); if (!childPolicy) { - debug(`No answer to fetchChildPolicy message. Still initializing?`); - setTimeout(notifyPage, 300); + debug(`No answer to fetchChildPolicy message. This should not be happening.`); return; } ns.config.CURRENT = childPolicy.CURRENT; diff --git a/src/lib/Messages.js b/src/lib/Messages.js index b8977cf..8152555 100644 --- a/src/lib/Messages.js +++ b/src/lib/Messages.js @@ -3,10 +3,11 @@ let handlers = new Set(); let dispatch = async (msg, sender) => { - let {_messageName} = msg; + let {__meta} = msg; + let {name} = __meta; let answers = []; for (let h of handlers) { - let f = h[_messageName]; + let f = h[name]; if (typeof f === "function") { answers.push(f(msg, sender)); } @@ -16,8 +17,17 @@ answers.length === 1 ? answers.pop(): Promise.all(answers) ); } - console.debug("Warning: no handler for message %s", _messageName); - return undefined; + let context = typeof window === "object" && window.location || null; + let originalSender = __meta.originalSender || sender; + console.debug("Warning: no handler for message %o in context %s", msg, context); + if (originalSender.tab && originalSender.tab.id) { + // if we're receiving a message from content, there might be another + // Messages instance in a different context (e.g. background page vs + // options page vs browser action) capable of processing it, and we've + // just "steal" it. Let's rebroadcast. + return await Messages.send(name, msg, {originalSender}); + } + throw new Error(`No handler registered for message "${name}" in context ${context}`); }; var Messages = { @@ -35,12 +45,12 @@ browser.runtime.onMessage.removeListener(dispatch); } }, - async send(name, args = {}, toContent = null) { - args._messageName = name; - if (toContent && "tabId" in toContent) { + async send(name, args = {}, recipientInfo = null) { + args.__meta = {name, recipientInfo}; + if (recipientInfo && "tabId" in recipientInfo) { let opts; - if ("frameId" in toContent) opts = {frameId: toContent.frameId}; - return await browser.tabs.sendMessage(toContent.tabId, args, opts); + if ("frameId" in recipientInfo) opts = {frameId: recipientInfo.frameId}; + return await browser.tabs.sendMessage(recipientInfo.tabId, args, opts); } return await browser.runtime.sendMessage(args); } diff --git a/src/lib/restricted.js b/src/lib/restricted.js index 6415221..b9bddae 100644 --- a/src/lib/restricted.js +++ b/src/lib/restricted.js @@ -21,7 +21,9 @@ function isRestrictedURL(u) { try { if (typeof u === "string") u = new URL(u); - return u.protocol === "https:" && domains.includes(tld.normalize(u.hostname || "")); + let {protocol, hostname} = u; + return (!/^(?:https?|file|data):$/.test(protocol)) + || protocol === "https:" && hostname && domains.includes(tld.normalize(hostname)); } catch (e) { return false; } -- cgit v1.2.3