Skip to content

Commit

Permalink
Best effort to run webRequest.onHeaderReceived listener last (issue #6)
Browse files Browse the repository at this point in the history
  • Loading branch information
hackademix committed Aug 7, 2018
1 parent 2250d51 commit 8caa253
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 6 deletions.
30 changes: 24 additions & 6 deletions src/bg/RequestGuard.js
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,14 @@ var RequestGuard = (() => {

onHeadersReceived(request) {
// called for main_frame, sub_frame and object

// check for duplicate calls
let pending = pendingRequests.get(request.requestId);
if (pending && pending.headersProcessed) {
debug("[WARNING] already processed ", request);
}
pending.headersProcessed = true;

debug("onHeadersReceived", request);
let {url, documentUrl, statusCode, tabId, responseHeaders} = request;

Expand Down Expand Up @@ -478,7 +486,12 @@ var RequestGuard = (() => {
debug("%s scriptBlocked=%s setting noscriptFrame on ", request.url, scriptBlocked, request.tabId, request.frameId);
TabStatus.record(request, "noscriptFrame", scriptBlocked);
let pending = pendingRequests.get(request.requestId);
if (pending) pending.scriptBlocked = scriptBlocked;
if (pending) {
pending.scriptBlocked = scriptBlocked;
if (!pending.headersProcessed) {
debug("[WARNING] onHeadersReceived could not process", request);
}
}
},

onCompleted(request) {
Expand Down Expand Up @@ -533,20 +546,21 @@ var RequestGuard = (() => {
}
return ABORT;
}

const RequestGuard = {
async start() {
let wr = browser.webRequest;
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 docTypes = ["main_frame", "sub_frame", "object"];

listen("onBeforeRequest",
{urls: allUrls, types: allTypes},
["blocking"]
);
listen("onHeadersReceived",
listenLast("onHeadersReceived",
{urls: allUrls, types: docTypes},
["blocking", "responseHeaders"]
);
Expand All @@ -570,8 +584,12 @@ var RequestGuard = (() => {

stop() {
let wr = browser.webRequest;
for (let [name, listener] of Object.entries(this.listeners)) {
wr[name].removeListener(listener);
for (let [name, listener] of Object.entries(listeners)) {
if (typeof listener === "function") {
wr[name].removeListener(listener);
} else if (listener instanceof LastListener) {
listener.uninstall();
}
}
wr.onBeforeRequest.removeListener(onViolationReport);
}
Expand Down
50 changes: 50 additions & 0 deletions src/lib/LastListener.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* Wrapper around listeners on various WebExtensions
* APIs (e.g. webRequest.on*), as a best effort to
* let them run last by removing and re-adding them
* on each call (swapping 2 copies because
* addListener() calls are asynchronous).
* Note: we rely on implementation details Like
* listeners being called in addition order; also,
* clients should ensure they're not called twice for
* the same event, if that's important.
}
*/

class LastListener {
constructor(observed, listener, ...extras) {
this.observed = observed;
this.listener = listener;
this.extras = extras;
let ww = this._wrapped = [listener, listener].map(l => {
let w = (...args) => {
if (this.observed.hasListener(w._other)) {
this.observed.removeListener(w._other);
if (this.last === w) return this.defaultResult;
} else if (this.installed) {
this.observed.addListener(w._other, ...this.extras);
this.last = w._other;
}
return this.installed ? this.listener(...args)
: this.defaultResult;
}
return w;
});

ww[0]._other = ww[1];
ww[1]._other = ww[0];
this.installed = false;
this.defaultResult = null;
}

install() {
if (this.installed) return;
this.observed.addListener(this._wrapped[0], ...this.extras);
this.installed = true;
}

uninstall() {
this.installed = false;
for (let l of this._wrapped) this.observed.removeListener(l);
}
}
1 change: 1 addition & 0 deletions src/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"lib/punycode.js",
"lib/tld.js",
"lib/ResponseMetaData.js",
"lib/LastListener.js",
"common/Policy.js",
"common/locale.js",
"common/Entities.js",
Expand Down

0 comments on commit 8caa253

Please sign in to comment.