| Index: lib/requestBlocker.js |
| =================================================================== |
| --- a/lib/requestBlocker.js |
| +++ b/lib/requestBlocker.js |
| @@ -73,20 +73,54 @@ |
| yield "CSP"; |
| }()); |
| -function onBeforeRequestAsync(tabId, url, type, docDomain, |
| - thirdParty, sitekey, |
| - specificOnly, filter) |
| +function getRelatedTabIds(details) |
| { |
| - let tabIds = tabId != -1 ? [tabId] : []; |
| + // This is the common case, the request is associated with a single tab. |
| + // If tabId is -1, its not (e.g. the request was sent by |
| + // a Service/Shared Worker) and we have to identify the related tabs. |
| + if (details.tabId != -1) |
| + return Promise.resolve([details.tabId]); |
| - if (filter) |
| - FilterNotifier.emit("filter.hitCount", filter, 0, 0, tabIds); |
| + // Firefox >=48 provides "originUrl" indicating the URL of the tab |
| + // that caused this request. In case of Service/Shared Worker, |
| + // this is URL of the tab that caused the worker to be spawned. |
| + if (details.originUrl) |
|
kzar
2018/04/03 12:49:30
Nit: Please use braces since the body spans multip
Sebastian Noack
2018/04/04 01:04:45
No longer relevant (the block has only one line no
|
| + return browser.tabs.query({url: details.originUrl}).then( |
| + tabs => tabs.map(tab => tab.id) |
| + ); |
| - devtools.logRequest( |
| - tabIds, url, type, docDomain, |
| - thirdParty, sitekey, |
| - specificOnly, filter |
| - ); |
| + // Chromium >=63 provides "intiator" which is equivalent to "originUrl" on |
| + // Firefox except that its not a full URL but just an origin (proto + host). |
| + // So we have to find each tab with an URL of the same origin. |
| + if (details.initiator) |
| + return browser.tabs.query({}).then(tabs => |
|
kzar
2018/04/03 12:49:30
Couldn't we pass something like `details.initiator
Sebastian Noack
2018/04/04 01:04:45
In fact we can. I wasn't aware that tab.query() ac
kzar
2018/04/05 10:31:51
Cool, I assumed I was wrong somehow :p. This looks
|
| + { |
| + let tabIds = []; |
| + for (let tab of tabs) |
| + { |
| + if (new URL(tab.url).origin == details.initiator) |
| + tabIds.push(tab.id); |
|
kzar
2018/04/03 12:49:30
Wouldn't this mean we sometimes log a request for
Sebastian Noack
2018/04/04 01:04:45
This usually means that the request was sent by a
kzar
2018/04/05 10:31:51
Acknowledged.
|
| + } |
| + return tabIds; |
| + }); |
| + |
| + return Promise.resolve([]); |
| +} |
| + |
| +function logRequest(details, url, type, docDomain, thirdParty, |
| + sitekey, specificOnly, filter) |
| +{ |
| + getRelatedTabIds(details).then(tabIds => |
| + { |
| + if (filter) |
| + FilterNotifier.emit("filter.hitCount", filter, 0, 0, tabIds); |
| + |
| + devtools.logRequest( |
| + tabIds, url, type, docDomain, |
| + thirdParty, sitekey, |
| + specificOnly, filter |
| + ); |
| + }); |
| } |
| browser.webRequest.onBeforeRequest.addListener(details => |
| @@ -105,55 +139,57 @@ |
| url.protocol != "ws:" && url.protocol != "wss:") |
| return; |
| - // Firefox (only) allows to intercept requests sent by the browser |
| - // and other extensions. We don't want to block these. |
| + let originUrl = null; |
| if (details.originUrl) |
| { |
| - let originUrl = new URL(details.originUrl); |
| + originUrl = new URL(details.originUrl); |
| + |
| + // Firefox (only) allows to intercept requests sent by the browser |
| + // and other extensions. We don't want to block these. |
| if (originUrl.protocol == "chrome:" || |
| originUrl.protocol == "moz-extension:") |
| return; |
| } |
| - |
| - let frame = ext.getFrame( |
| - details.tabId, |
| - // We are looking for the frame that contains the element which |
| - // has triggered this request. For most requests (e.g. images) we |
| - // can just use the request's frame ID, but for subdocument requests |
| - // (e.g. iframes) we must instead use the request's parent frame ID. |
| - details.type == "sub_frame" ? details.parentFrameId : details.frameId |
| - ); |
| + // Fallback to "initiator" on Chrome >=63. It doesn't include the |
| + // path (unlike "originUrl" on Firefox), but is still good enough |
| + // (in case the tab/frame is unknown) for the $domain filter option |
| + // and most document exception rules which only match the domain part. |
| + else if (details.initiator) |
| + originUrl = new URL(details.initiator); |
| - let docDomain = null; |
| - let sitekey = null; |
| - let thirdParty = false; |
| - let specificOnly = false; |
| - |
| - if (frame) |
| + let page = null; |
| + let frame = null; |
| + if (details.tabId != -1) |
| { |
| - let page = new ext.Page({id: details.tabId}); |
| + page = new ext.Page({id: details.tabId}); |
| + frame = ext.getFrame( |
| + details.tabId, |
| + // We are looking for the frame that contains the element which |
| + // has triggered this request. For most requests (e.g. images) we |
| + // can just use the request's frame ID, but for subdocument requests |
| + // (e.g. iframes) we must instead use the request's parent frame ID. |
| + details.type == "sub_frame" ? details.parentFrameId : details.frameId |
| + ); |
| + } |
| - if (checkWhitelisted(page, frame)) |
| - return; |
| - |
| - docDomain = extractHostFromFrame(frame); |
| - sitekey = getKey(page, frame); |
| - thirdParty = isThirdParty(url, docDomain); |
| - specificOnly = !!checkWhitelisted(page, frame, |
| - RegExpFilter.typeMap.GENERICBLOCK); |
| - } |
| + if (checkWhitelisted(page, frame, originUrl)) |
| + return; |
| let urlString = stringifyURL(url); |
| let type = resourceTypes.get(details.type) || "OTHER"; |
| + let docDomain = extractHostFromFrame(frame, originUrl); |
| + let thirdParty = isThirdParty(url, docDomain); |
| + let sitekey = getKey(page, frame, originUrl); |
| + let specificOnly = !!checkWhitelisted(page, frame, originUrl, |
| + RegExpFilter.typeMap.GENERICBLOCK); |
| + |
| let filter = defaultMatcher.matchesAny( |
| urlString, RegExpFilter.typeMap[type], |
| docDomain, thirdParty, sitekey, specificOnly |
| ); |
| - setTimeout(onBeforeRequestAsync, 0, details.tabId, urlString, |
| - type, docDomain, |
| - thirdParty, sitekey, |
| - specificOnly, filter); |
| + logRequest(details, urlString, type, docDomain, |
| + thirdParty, sitekey, specificOnly, filter); |
| if (filter instanceof BlockingFilter) |
| return {cancel: true}; |
| @@ -170,7 +206,7 @@ |
| let blocked = false; |
| let specificOnly = checkWhitelisted( |
| - sender.page, sender.frame, |
| + sender.page, sender.frame, null, |
| RegExpFilter.typeMap.GENERICBLOCK |
| ); |