Simpler and more reliable safety net to ensure CSP headers are injected last among WebExtensions.

This commit is contained in:
hackademix 2018-08-20 23:45:33 +02:00
parent f7fcdb37a3
commit dc4ab14c92
1 changed files with 40 additions and 23 deletions

View File

@ -453,7 +453,10 @@ var RequestGuard = (() => {
} }
} }
if (header) return {responseHeaders}; if (header) {
pending.cspHeader = header;
return {responseHeaders};
}
} catch (e) { } catch (e) {
error(e, "Error in onHeadersReceived", request); error(e, "Error in onHeadersReceived", request);
} }
@ -462,7 +465,7 @@ var RequestGuard = (() => {
onResponseStarted(request) { onResponseStarted(request) {
debug("onResponseStarted", request); debug("onResponseStarted", request);
let {url, tabId, frameId, type} = request; let {requestId, url, tabId, frameId, type} = request;
if (type === "main_frame") { if (type === "main_frame") {
TabStatus.initTab(tabId); TabStatus.initTab(tabId);
} }
@ -471,7 +474,7 @@ var RequestGuard = (() => {
); );
debug("%s scriptBlocked=%s setting noscriptFrame on ", url, scriptBlocked, tabId, frameId); debug("%s scriptBlocked=%s setting noscriptFrame on ", url, scriptBlocked, tabId, frameId);
TabStatus.record(request, "noscriptFrame", scriptBlocked); TabStatus.record(request, "noscriptFrame", scriptBlocked);
let pending = pendingRequests.get(request.requestId); let pending = pendingRequests.get(requestId);
if (pending) { if (pending) {
pending.scriptBlocked = scriptBlocked; pending.scriptBlocked = scriptBlocked;
if (!(pending.headersProcessed && if (!(pending.headersProcessed &&
@ -550,29 +553,43 @@ var RequestGuard = (() => {
async start() { async start() {
let wr = browser.webRequest; let wr = browser.webRequest;
let listen = (what, ...args) => wr[what].addListener(listeners[what], ...args); let listen = (what, ...args) => wr[what].addListener(listeners[what], ...args);
let listenLast = (what, ...args) => new LastListener(wr[what], listeners[what], ...args).install();
let allUrls = ["<all_urls>"]; let allUrls = ["<all_urls>"];
let docTypes = ["main_frame", "sub_frame", "object"]; let docTypes = ["main_frame", "sub_frame", "object"];
listen("onBeforeRequest", let filterDocs = {urls: allUrls, types: docTypes};
{urls: allUrls, types: allTypes}, let filterAll = {urls: allUrls, types: allTypes};
["blocking"]
); listen("onBeforeRequest", filterAll, ["blocking"]);
listenLast("onHeadersReceived",
{urls: allUrls, types: docTypes}, listen("onHeadersReceived", filterDocs, ["blocking", "responseHeaders"]);
["blocking", "responseHeaders"]
); (listeners.onHeadersReceivedLast = new LastListener(wr.onHeadersReceived, request => {
listen("onResponseStarted", let {requestId, responseHeaders} = request;
{urls: allUrls, types: docTypes}, let pending = pendingRequests.get(request.requestId);
["responseHeaders"] if (pending && pending.headersProcessed) {
); let {cspHeader} = pending;
listen("onCompleted", if (cspHeader) {
{urls: allUrls, types: allTypes}, debug("Safety net: injecting again %o in %o", cspHeader, request);
); for (let h of responseHeaders) {
listen("onErrorOccurred", if (h.name === cspHeader.name) {
{urls: allUrls, types: allTypes}, h.value = cspHeader.value;
); cspHeader = null;
break;
}
}
if (cspHeader) responseHeaders.push(cspHeader);
return {responseHeaders};
}
} else {
debug("[WARNING] onHeadersReceived not called (yet?)", request);
}
return null;
}, filterDocs, ["blocking", "responseHeaders"])).install();
listen("onResponseStarted", filterDocs, ["responseHeaders"]);
listen("onCompleted", filterAll);
listen("onErrorOccurred", filterAll);
wr.onBeforeRequest.addListener(onViolationReport, wr.onBeforeRequest.addListener(onViolationReport,