| Index: webrequest.js |
| =================================================================== |
| --- a/webrequest.js |
| +++ b/webrequest.js |
| @@ -1,16 +1,16 @@ |
| /* |
| * This Source Code is subject to the terms of the Mozilla Public License |
| * version 2.0 (the "License"). You can obtain a copy of the License at |
| * http://mozilla.org/MPL/2.0/. |
| */ |
| chrome.webRequest.onBeforeRequest.addListener(onBeforeRequest, {urls: ["http://*/*", "https://*/*"]}, ["blocking"]); |
| -chrome.webRequest.onBeforeSendHeaders.addListener(onBeforeSendHeaders, {urls: ["http://*/*", "https://*/*"]}, ["requestHeaders", "blocking"]); |
| +chrome.webRequest.onHeadersReceived.addListener(onHeadersReceived, {urls: ["http://*/*", "https://*/*"]}, ["responseHeaders"]); |
| chrome.tabs.onRemoved.addListener(forgetTab); |
| var frames = {}; |
| function onBeforeRequest(details) |
| { |
| if (details.tabId == -1) |
| return {}; |
| @@ -41,29 +41,71 @@ function onBeforeRequest(details) |
| return {redirectUrl: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg=="}; |
| else |
| return {cancel: true}; |
| } |
| else |
| return {}; |
| } |
| -function onBeforeSendHeaders(details) |
| +function onHeadersReceived(details) |
| { |
| - var match = defaultMatcher.matchesAny(details.url, "DONOTTRACK", null, false); |
| - if (match && match instanceof BlockingFilter) |
| + if (details.tabId == -1) |
| + return; |
| + |
| + var type = details.type; |
| + if (type != "main_frame" && type != "sub_frame") |
| + return; |
| + |
| + var url = getFrameUrl(details.tabId, details.frameId); |
| + if (url != details.url) |
| + return; |
| + |
| + var key = null; |
| + var signature = null; |
| + for (var i = 0; i < details.responseHeaders.length; i++) |
| { |
| - var headers = details.requestHeaders || []; |
| - if (!headers.some(function(header) { header.name == "DNT";})) |
| + var header = details.responseHeaders[i]; |
| + if (header.name.toLowerCase() == "x-adblock-key" && header.value) |
| { |
| - headers.push({name: "DNT", value: "1"}); |
| - return {requestHeaders: headers}; |
| + var index = header.value.indexOf("_"); |
| + if (index >= 0) |
| + { |
| + var key = header.value.substr(0, index); |
| + var signature = header.value.substr(index + 1); |
| + break; |
| + } |
| } |
| } |
| - return null; |
| + if (!key) |
| + return; |
| + |
| + var parentUrl = null; |
| + if (type == "sub_frame") |
| + parentUrl = getFrameUrl(details.tabId, details.parentFrameId); |
| + if (!parentUrl) |
| + parentUrl = url; |
| + var docDomain = extractHostFromURL(parentUrl); |
| + var keyMatch = defaultMatcher.matchesByKey(url, key.replace(/=/g, ""), docDomain); |
| + if (keyMatch) |
| + { |
| + // Website specifies a key that we know but is the signature valid? |
| + var uri = new URI(url); |
| + var host = uri.asciiHost; |
| + if (uri.port > 0) |
| + host += ":" + uri.port; |
| + |
| + var params = [ |
| + uri.path.replace(/#.*/, ""), // REQUEST_URI |
| + host, // HTTP_HOST |
| + window.navigator.userAgent // HTTP_USER_AGENT |
| + ]; |
| + if (verifySignature(key, signature, params.join("\0"))) |
| + frames[details.tabId][details.frameId].keyException = true; |
| + } |
| } |
| function recordFrame(tabId, frameId, parentFrameId, frameUrl) |
| { |
| if (!(tabId in frames)) |
| frames[tabId] = {}; |
| frames[tabId][frameId] = {url: frameUrl, parent: parentFrameId}; |
| } |
| @@ -105,12 +147,14 @@ function checkRequest(type, tabId, url, |
| function isFrameWhitelisted(tabId, frameId, type) |
| { |
| var parent = frameId; |
| while (parent != -1) |
| { |
| var parentUrl = getFrameUrl(tabId, parent); |
| if (parentUrl && isWhitelisted(parentUrl, type)) |
| return true; |
| + if (parentUrl && "keyException" in frames[tabId][frameId]) |
| + return true; |
| parent = getFrameParent(tabId, parent); |
| } |
| return false; |
| } |