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; |
} |