| Index: webrequest.js |
| =================================================================== |
| --- a/webrequest.js |
| +++ b/webrequest.js |
| @@ -17,15 +17,11 @@ |
| var FilterNotifier = require("filterNotifier").FilterNotifier; |
| -chrome.webRequest.onBeforeRequest.addListener(onBeforeRequest, {urls: ["http://*/*", "https://*/*"]}, ["blocking"]); |
| -chrome.webRequest.onHeadersReceived.addListener(onHeadersReceived, {urls: ["http://*/*", "https://*/*"]}, ["responseHeaders"]); |
| -chrome.tabs.onRemoved.addListener(forgetTab); |
| - |
| var onFilterChangeTimeout = null; |
| function onFilterChange() |
| { |
| onFilterChangeTimeout = null; |
| - chrome.webRequest.handlerBehaviorChanged(); |
| + ext.webRequest.handlerBehaviorChanged(); |
| } |
| var importantNotifications = { |
| @@ -50,135 +46,72 @@ |
| } |
| }); |
| -var frames = {}; |
| +var frames = new TabMap(); |
| -function onBeforeRequest(details) |
| +function onBeforeRequest(url, type, tab, frameId, parentFrameId) |
| { |
| - if (details.tabId == -1) |
| - return {}; |
| - |
| - var type = details.type; |
| + if (!tab) |
| + return true; |
| // Assume that the first request belongs to the top frame. Chrome may give the |
| // top frame the type "object" instead of "main_frame". |
| // https://code.google.com/p/chromium/issues/detail?id=281711 |
| - if (details.frameId == 0 && !(details.tabId in frames) && type == "object") |
| + if (frameId == 0 && !frames.has(tab) && type == "object") |
| type = "main_frame"; |
| if (type == "main_frame" || type == "sub_frame") |
| - recordFrame(details.tabId, details.frameId, details.parentFrameId, details.url); |
| + { |
| + recordFrame(tab, frameId, parentFrameId, url); |
| - if (type == "main_frame") |
| - return {}; |
| + if (type == "main_frame") |
| + return true; |
| - // Type names match Mozilla's with main_frame and sub_frame being the only exceptions. |
| - if (type == "sub_frame") |
| - type = "SUBDOCUMENT"; |
| - else |
| - type = type.toUpperCase(); |
| + type = "subdocument"; |
| + frameId = parentFrameId; |
| + } |
| - var frame = (type != "SUBDOCUMENT" ? details.frameId : details.parentFrameId); |
| - var filter = checkRequest(type, details.tabId, details.url, frame); |
| - FilterNotifier.triggerListeners("filter.hitCount", filter, 0, 0, details.tabId); |
| - if (filter instanceof BlockingFilter) |
| - return {cancel: true}; |
| - else |
| - return {}; |
| + var filter = checkRequest(type.toUpperCase(), tab, url, frameId); |
| + FilterNotifier.triggerListeners("filter.hitCount", filter, 0, 0, tab); |
| + return !(filter instanceof BlockingFilter); |
| } |
| -function onHeadersReceived(details) |
| +function recordFrame(tab, frameId, parentFrameId, url) |
| { |
| - if (details.tabId == -1) |
| - return; |
| + var framesOfTab = frames.get(tab); |
| - var type = details.type; |
| - if (type != "main_frame" && type != "sub_frame") |
| - return; |
| + if (!framesOfTab) |
| + frames.set(tab, (framesOfTab = {})); |
| - var url = getFrameUrl(details.tabId, details.frameId); |
| - if (url != details.url) |
| - return; |
| + framesOfTab[frameId] = {url: url, parent: parentFrameId}; |
| +} |
| - var key = null; |
| - var signature = null; |
| - for (var i = 0; i < details.responseHeaders.length; i++) |
| +function getFrameData(tab, frameId) |
| +{ |
| + var framesOfTab = frames.get(tab); |
| + |
| + if (framesOfTab) |
| { |
| - var header = details.responseHeaders[i]; |
| - if (header.name.toLowerCase() == "x-adblock-key" && header.value) |
| - { |
| - var index = header.value.indexOf("_"); |
| - if (index >= 0) |
| - { |
| - var key = header.value.substr(0, index); |
| - var signature = header.value.substr(index + 1); |
| - break; |
| - } |
| - } |
| - } |
| - if (!key) |
| - return; |
| + if (frameId in framesOfTab) |
| + return framesOfTab[frameId]; |
| - 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; |
| + // We don't know anything about javascript: or data: frames, use top frame |
| + if (frameId != -1) |
| + return framesOfTab[0]; |
| } |
| } |
| -function recordFrame(tabId, frameId, parentFrameId, frameUrl) |
| +function getFrameUrl(tab, frameId) |
| { |
| - if (!(tabId in frames)) |
| - frames[tabId] = {}; |
| - frames[tabId][frameId] = {url: frameUrl, parent: parentFrameId}; |
| -} |
| - |
| -function getFrameData(tabId, frameId) |
| -{ |
| - if (tabId in frames && frameId in frames[tabId]) |
| - return frames[tabId][frameId]; |
| - else if (frameId > 0 && tabId in frames && 0 in frames[tabId]) |
| - { |
| - // We don't know anything about javascript: or data: frames, use top frame |
| - return frames[tabId][0]; |
| - } |
| - return null; |
| -} |
| - |
| -function getFrameUrl(tabId, frameId) |
| -{ |
| - var frameData = getFrameData(tabId, frameId); |
| + var frameData = getFrameData(tab, frameId); |
| return (frameData ? frameData.url : null); |
| } |
| -function forgetTab(tabId) |
| +function checkRequest(type, tab, url, frameId) |
| { |
| - delete frames[tabId]; |
| -} |
| - |
| -function checkRequest(type, tabId, url, frameId) |
| -{ |
| - if (isFrameWhitelisted(tabId, frameId)) |
| + if (isFrameWhitelisted(tab, frameId)) |
| return false; |
| - var documentUrl = getFrameUrl(tabId, frameId); |
| + var documentUrl = getFrameUrl(tab, frameId); |
| if (!documentUrl) |
| return false; |
| @@ -188,17 +121,17 @@ |
| return defaultMatcher.matchesAny(url, type, documentHost, thirdParty); |
| } |
| -function isFrameWhitelisted(tabId, frameId, type) |
| +function isFrameWhitelisted(tab, frameId, type) |
| { |
| var parent = frameId; |
| - var parentData = getFrameData(tabId, parent); |
| + var parentData = getFrameData(tab, parent); |
| while (parentData) |
| { |
| var frame = parent; |
| var frameData = parentData; |
| parent = frameData.parent; |
| - parentData = getFrameData(tabId, parent); |
| + parentData = getFrameData(tab, parent); |
| var frameUrl = frameData.url; |
| var parentUrl = (parentData ? parentData.url : frameUrl); |
| @@ -207,3 +140,68 @@ |
| } |
| return false; |
| } |
| + |
| +ext.webRequest.onBeforeRequest.addListener(onBeforeRequest, ["http://*/*", "https://*/*"]); |
| + |
| +if (require("info").platform == "chromium") |
| +{ |
| + function onHeadersReceived(details) |
| + { |
| + if (details.tabId == -1) |
| + return; |
| + |
| + var type = details.type; |
| + if (type != "main_frame" && type != "sub_frame") |
| + return; |
| + |
| + var tab = new Tab({id: details.tabId}); |
| + var url = getFrameUrl(tab, details.frameId); |
| + if (url != details.url) |
| + return; |
| + |
| + var key = null; |
| + var signature = null; |
| + for (var i = 0; i < details.responseHeaders.length; i++) |
| + { |
| + var header = details.responseHeaders[i]; |
| + if (header.name.toLowerCase() == "x-adblock-key" && header.value) |
| + { |
| + var index = header.value.indexOf("_"); |
| + if (index >= 0) |
| + { |
| + key = header.value.substr(0, index); |
| + signature = header.value.substr(index + 1); |
| + break; |
| + } |
| + } |
| + } |
| + if (!key) |
| + return; |
| + |
| + var parentUrl = null; |
| + if (type == "sub_frame") |
| + parentUrl = getFrameUrl(tab, 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.get(tab)[details.frameId].keyException = true; |
| + } |
| + } |
| + |
| + chrome.webRequest.onHeadersReceived.addListener(onHeadersReceived, {urls: ["http://*/*", "https://*/*"]}, ["responseHeaders"]); |
| +} |