Skip to content

Commit 4302246

Browse files
committed
More reliable handling of edge startup cases.
1 parent 81b3851 commit 4302246

5 files changed

Lines changed: 116 additions & 36 deletions

File tree

src/bg/RequestGuard.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ var RequestGuard = (() => {
357357
// called for main_frame, sub_frame and object
358358
debug("onHeadersReceived", request);
359359
let {url, documentUrl, statusCode, tabId, responseHeaders} = request;
360-
if (statusCode >= 300 && statusCode < 400) return;
360+
//if (statusCode >= 300 && statusCode < 400) return;
361361

362362
try {
363363
let header, blocker;
@@ -421,6 +421,9 @@ var RequestGuard = (() => {
421421
await RequestUtil.executeOnStart(request, {
422422
file: "content/media.js"
423423
});
424+
} else if (request.frameId === 0 && !TabStatus.map.has(tabId)) {
425+
debug("No TabStatus data yet for noscriptFrame", tabId);
426+
TabStatus.record(request, "noscriptFrame", true);
424427
}
425428
}
426429

@@ -442,6 +445,7 @@ var RequestGuard = (() => {
442445
},
443446

444447
onResponseStarted(request) {
448+
debug("onResponseStarted", request);
445449
if (request.type === "main_frame") {
446450
TabStatus.initTab(request.tabId);
447451
}
@@ -477,7 +481,7 @@ var RequestGuard = (() => {
477481
let type = report["violated-directive"].split("-", 1)[0]; // e.g. script-src 'none' => script
478482
if (type === "frame") type = "sub_frame";
479483
let url = report['blocked-uri'];
480-
if (url === 'self') url = request.documentUrl;
484+
if (!url || url === 'self') url = request.documentUrl;
481485
return Object.assign({}, request, {
482486
url,
483487
type,
@@ -490,11 +494,12 @@ var RequestGuard = (() => {
490494
const report = JSON.parse(decoder.decode(request.requestBody.raw[0].bytes))['csp-report'];
491495
let csp = report["original-policy"]
492496
debug("CSP report", report);
493-
if (report['blocked-uri'] !== 'self') {
497+
let blockedURI = report['blocked-uri'];
498+
if (blockedURI && blockedURI !== 'self') {
494499
let r = fakeRequestFromCSP(report, request);
495500
Content.reportTo(r, false, policyTypesMap[r.type]);
496501
TabStatus.record(r, "blocked");
497-
} else if (report["violated-directive"] === "script-src 'none'") {
502+
} else if (report["violated-directive"] === "script-src" && /; script-src 'none'/.test(report["original-policy"])) {
498503
let r = fakeRequestFromCSP(report, request);
499504
TabStatus.record(r, "noscriptFrame", true);
500505
}

src/bg/deferWebTraffic.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
function deferWebTraffic(promiseToWaitFor, next) {
2+
debug("deferWebTraffic on %o", promiseToWaitFor);
3+
let seenTabs = new Set();
4+
function checkNavigation(nav) {
5+
if (nav.url.startsWith("http")) {
6+
let seen = seenTabs.has(nav.tabId);
7+
debug(`%s navigation %o`, seen ? "seen" : "unseen", nav);
8+
if (!seen) {
9+
reloadTab(tabId);
10+
}
11+
}
12+
}
13+
browser.webNavigation.onCommitted.addListener(checkNavigation);
14+
function reloadTab(tabId) {
15+
seenTabs.add(tabId);
16+
try {
17+
// browser.tabs.update(tabId, {url: documentUrl});
18+
browser.tabs.executeScript(tabId, {
19+
runAt: "document_start",
20+
code: "window.location.reload(false)"
21+
});
22+
debug("Reloading tab", tabId);
23+
} catch (e) {
24+
error(e, "Can't reload tab", tabId);
25+
}
26+
}
27+
28+
async function waitFor(request) {
29+
let {type, documentUrl, url, tabId, frameId} = request;
30+
if (!seenTabs.has(tabId)) {
31+
if (type === "main_frame") {
32+
seenTabs.add(tabId);
33+
} else if (documentUrl) {
34+
if (frameId !== 0) {
35+
documentUrl = request.frameAncestors.pop().url;
36+
}
37+
reloadTab(tabId);
38+
}
39+
}
40+
debug("Deferring ", url, type);
41+
try {
42+
await promiseToWaitFor;
43+
} catch (e) {
44+
error(e);
45+
}
46+
debug("Green light to ", url, type);
47+
}
48+
49+
function spyTabs(request) {
50+
debug("Spying request %o", request);
51+
52+
}
53+
browser.webRequest.onHeadersReceived.addListener(spyTabs, {
54+
urls: ["<all_urls>"],
55+
types: ["main_frame"],
56+
}, ["blocking", "responseHeaders"]);
57+
browser.webRequest.onBeforeRequest.addListener(waitFor, {
58+
urls: ["<all_urls>"]
59+
}, ["blocking"]);
60+
61+
(async () => {
62+
await promiseToWaitFor;
63+
browser.webNavigation.onCommitted.removeListener(checkNavigation);
64+
browser.webRequest.onBeforeRequest.removeListener(waitFor);
65+
browser.webRequest.onHeadersReceived.removeListener(spyTabs);
66+
if (next) next();
67+
})();
68+
}

src/bg/main.js

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -194,38 +194,27 @@
194194
return this.policy.enforced && (tabId === -1 || !this.unrestrictedTabs.has(tabId));
195195
},
196196

197-
async start() {
197+
start() {
198198
if (this.running) return;
199199
this.running = true;
200200

201-
let initializing = init();
202-
let wr = browser.webRequest;
203-
let waitForPolicy = async r => {
204-
try {
205-
await initializing;
206-
} catch (e) {
207-
error(e);
208-
}
209-
}
210-
wr.onBeforeRequest.addListener(waitForPolicy, {
211-
urls: ["<all_urls>"]
212-
}, ["blocking"]);
213-
await initializing;
214-
wr.onBeforeRequest.removeListener(waitForPolicy);
201+
deferWebTraffic(init(),
202+
async () => {
215203

216-
await include("/bg/Settings.js");
217-
MessageHandler.listen();
204+
await include("/bg/Settings.js");
205+
MessageHandler.listen();
218206

219-
log("STARTED");
207+
log("STARTED");
220208

221-
this.devMode = (await browser.management.getSelf()).installType === "development";
222-
if (this.local.debug) {
223-
if (this.devMode) {
224-
include("/test/run.js");
225-
}
226-
} else {
227-
debug = () => {}; // suppress verbosity
228-
}
209+
this.devMode = (await browser.management.getSelf()).installType === "development";
210+
if (this.local.debug) {
211+
if (this.devMode) {
212+
include("/test/run.js");
213+
}
214+
} else {
215+
debug = () => {}; // suppress verbosity
216+
}
217+
});
229218
},
230219

231220
stop() {

src/content/content.js

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@ function createHTMLElement(name) {
66
return document.createElementNS("http://www.w3.org/1999/xhtml", name);
77
}
88

9+
function probe() {
10+
try {
11+
debug("Probing execution...");
12+
let s = document.createElement("script");
13+
s.textContent=";";
14+
document.documentElement.appendChild(s);
15+
s.remove();
16+
} catch(e) {
17+
debug(e);
18+
}
19+
}
20+
921
var _ = browser.i18n.getMessage;
1022

1123
var canScript = true;
@@ -62,8 +74,9 @@ if (document.readyState !== "complete") {
6274
init();
6375
};
6476
addEventListener("pageshow", pageshown);
65-
} else init();
66-
77+
} else {
78+
init(true);
79+
}
6780
let notifyPage = () => {
6881
if (document.readyState === "complete") {
6982
browser.runtime.sendMessage({type: "pageshow", seen, canScript});
@@ -73,24 +86,28 @@ let notifyPage = () => {
7386
}
7487

7588
var queryingCanScript = false;
76-
async function init() {
89+
async function init(oldPage = false) {
7790
if (queryingCanScript) return;
7891
queryingCanScript = true;
7992
debug(`NoScript init() called in document %s, scripting=%s, content type %s readyState %s`,
8093
document.URL, canScript, document.contentType, document.readyState);
8194

8295
try {
83-
canScript = await browser.runtime.sendMessage({type: "canScript"});
96+
canScript = document.URL === "about:blank" || await browser.runtime.sendMessage({type: "canScript"});
97+
if (oldPage && canScript) {
98+
probe();
99+
setTimeout(() => init(), 100);
100+
return;
101+
}
84102
init = () => {};
85103
debug("canScript:", canScript);
86104
} catch (e) {
87105
debug("Error querying canScript", e);
88106
if (document.readyState !== "complete" &&
89-
document.URL !== "about:blank" &&
90107
/Receiving end does not exist/.test(e.message)) {
91108
window.location.reload(false);
92109
} else {
93-
setTimeout(() => init(), 100);
110+
setTimeout(() => init(oldPage), 100);
94111
}
95112
return;
96113
} finally {

src/manifest.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"common/Storage.js",
4848
"ui/Prompts.js",
4949
"xss/XSS.js",
50+
"bg/deferWebTraffic.js",
5051
"bg/main.js"
5152
]
5253
},

0 commit comments

Comments
 (0)