Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: webrequest.js

Issue 16067002: Added Safari Support (Closed)
Patch Set: Created Nov. 9, 2013, 6:45 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« safari/content.js ('K') | « utils.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <http://adblockplus.org/>, 2 * This file is part of Adblock Plus <http://adblockplus.org/>,
3 * Copyright (C) 2006-2013 Eyeo GmbH 3 * Copyright (C) 2006-2013 Eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 var FilterNotifier = require("filterNotifier").FilterNotifier; 18 var FilterNotifier = require("filterNotifier").FilterNotifier;
19 19
20 chrome.webRequest.onBeforeRequest.addListener(onBeforeRequest, {urls: ["http://* /*", "https://*/*"]}, ["blocking"]);
21 chrome.webRequest.onHeadersReceived.addListener(onHeadersReceived, {urls: ["http ://*/*", "https://*/*"]}, ["responseHeaders"]);
22 chrome.tabs.onRemoved.addListener(forgetTab);
23
24 var onFilterChangeTimeout = null; 20 var onFilterChangeTimeout = null;
25 function onFilterChange() 21 function onFilterChange()
26 { 22 {
27 onFilterChangeTimeout = null; 23 onFilterChangeTimeout = null;
28 chrome.webRequest.handlerBehaviorChanged(); 24 ext.webRequest.handlerBehaviorChanged();
29 } 25 }
30 26
31 var importantNotifications = { 27 var importantNotifications = {
32 'filter.added': true, 28 'filter.added': true,
33 'filter.removed': true, 29 'filter.removed': true,
34 'filter.disabled': true, 30 'filter.disabled': true,
35 'subscription.added': true, 31 'subscription.added': true,
36 'subscription.removed': true, 32 'subscription.removed': true,
37 'subscription.disabled': true, 33 'subscription.disabled': true,
38 'subscription.updated': true, 34 'subscription.updated': true,
39 'load': true 35 'load': true
40 }; 36 };
41 37
42 FilterNotifier.addListener(function(action) 38 FilterNotifier.addListener(function(action)
43 { 39 {
44 if (action in importantNotifications) 40 if (action in importantNotifications)
45 { 41 {
46 // Execute delayed to prevent multiple executions in a quick succession 42 // Execute delayed to prevent multiple executions in a quick succession
47 if (onFilterChangeTimeout != null) 43 if (onFilterChangeTimeout != null)
48 window.clearTimeout(onFilterChangeTimeout); 44 window.clearTimeout(onFilterChangeTimeout);
49 onFilterChangeTimeout = window.setTimeout(onFilterChange, 2000); 45 onFilterChangeTimeout = window.setTimeout(onFilterChange, 2000);
50 } 46 }
51 }); 47 });
52 48
53 var frames = {}; 49 var frames = new TabMap();
54 50
55 function onBeforeRequest(details) 51 function onBeforeRequest(url, type, tab, frameId, parentFrameId)
56 { 52 {
57 if (details.tabId == -1) 53 if (!tab)
58 return {}; 54 return true;
59
60 var type = details.type;
61 55
62 // Assume that the first request belongs to the top frame. Chrome may give the 56 // Assume that the first request belongs to the top frame. Chrome may give the
63 // top frame the type "object" instead of "main_frame". 57 // top frame the type "object" instead of "main_frame".
64 // https://code.google.com/p/chromium/issues/detail?id=281711 58 // https://code.google.com/p/chromium/issues/detail?id=281711
65 if (details.frameId == 0 && !(details.tabId in frames) && type == "object") 59 if (frameId == 0 && !frames.has(tab) && type == "object")
66 type = "main_frame"; 60 type = "main_frame";
67 61
68 if (type == "main_frame" || type == "sub_frame") 62 if (type == "main_frame" || type == "sub_frame")
69 recordFrame(details.tabId, details.frameId, details.parentFrameId, details.u rl); 63 {
64 recordFrame(tab, frameId, parentFrameId, url);
70 65
71 if (type == "main_frame") 66 if (type == "main_frame")
72 return {}; 67 return true;
73 68
74 // Type names match Mozilla's with main_frame and sub_frame being the only exc eptions. 69 type = "subdocument";
75 if (type == "sub_frame") 70 frameId = parentFrameId;
76 type = "SUBDOCUMENT"; 71 }
77 else
78 type = type.toUpperCase();
79 72
80 var frame = (type != "SUBDOCUMENT" ? details.frameId : details.parentFrameId); 73 var filter = checkRequest(type.toUpperCase(), tab, url, frameId);
81 var filter = checkRequest(type, details.tabId, details.url, frame); 74 FilterNotifier.triggerListeners("filter.hitCount", filter, 0, 0, tab);
82 FilterNotifier.triggerListeners("filter.hitCount", filter, 0, 0, details.tabId ); 75 return !(filter instanceof BlockingFilter);
83 if (filter instanceof BlockingFilter)
84 return {cancel: true};
85 else
86 return {};
87 } 76 }
88 77
89 function onHeadersReceived(details) 78 function recordFrame(tab, frameId, parentFrameId, url)
90 { 79 {
91 if (details.tabId == -1) 80 var framesOfTab = frames.get(tab);
92 return;
93 81
94 var type = details.type; 82 if (!framesOfTab)
95 if (type != "main_frame" && type != "sub_frame") 83 frames.set(tab, (framesOfTab = {}));
96 return;
97 84
98 var url = getFrameUrl(details.tabId, details.frameId); 85 framesOfTab[frameId] = {url: url, parent: parentFrameId};
99 if (url != details.url) 86 }
100 return;
101 87
102 var key = null; 88 function getFrameData(tab, frameId)
103 var signature = null; 89 {
104 for (var i = 0; i < details.responseHeaders.length; i++) 90 var framesOfTab = frames.get(tab);
91
92 if (framesOfTab)
105 { 93 {
106 var header = details.responseHeaders[i]; 94 if (frameId in framesOfTab)
107 if (header.name.toLowerCase() == "x-adblock-key" && header.value) 95 return framesOfTab[frameId];
108 {
109 var index = header.value.indexOf("_");
110 if (index >= 0)
111 {
112 var key = header.value.substr(0, index);
113 var signature = header.value.substr(index + 1);
114 break;
115 }
116 }
117 }
118 if (!key)
119 return;
120 96
121 var parentUrl = null; 97 // We don't know anything about javascript: or data: frames, use top frame
122 if (type == "sub_frame") 98 if (frameId != -1)
123 parentUrl = getFrameUrl(details.tabId, details.parentFrameId); 99 return framesOfTab[0];
124 if (!parentUrl)
125 parentUrl = url;
126 var docDomain = extractHostFromURL(parentUrl);
127 var keyMatch = defaultMatcher.matchesByKey(url, key.replace(/=/g, ""), docDoma in);
128 if (keyMatch)
129 {
130 // Website specifies a key that we know but is the signature valid?
131 var uri = new URI(url);
132 var host = uri.asciiHost;
133 if (uri.port > 0)
134 host += ":" + uri.port;
135
136 var params = [
137 uri.path.replace(/#.*/, ""), // REQUEST_URI
138 host, // HTTP_HOST
139 window.navigator.userAgent // HTTP_USER_AGENT
140 ];
141 if (verifySignature(key, signature, params.join("\0")))
142 frames[details.tabId][details.frameId].keyException = true;
143 } 100 }
144 } 101 }
145 102
146 function recordFrame(tabId, frameId, parentFrameId, frameUrl) 103 function getFrameUrl(tab, frameId)
147 { 104 {
148 if (!(tabId in frames)) 105 var frameData = getFrameData(tab, frameId);
149 frames[tabId] = {};
150 frames[tabId][frameId] = {url: frameUrl, parent: parentFrameId};
151 }
152
153 function getFrameData(tabId, frameId)
154 {
155 if (tabId in frames && frameId in frames[tabId])
156 return frames[tabId][frameId];
157 else if (frameId > 0 && tabId in frames && 0 in frames[tabId])
158 {
159 // We don't know anything about javascript: or data: frames, use top frame
160 return frames[tabId][0];
161 }
162 return null;
163 }
164
165 function getFrameUrl(tabId, frameId)
166 {
167 var frameData = getFrameData(tabId, frameId);
168 return (frameData ? frameData.url : null); 106 return (frameData ? frameData.url : null);
169 } 107 }
170 108
171 function forgetTab(tabId) 109 function checkRequest(type, tab, url, frameId)
172 { 110 {
173 delete frames[tabId]; 111 if (isFrameWhitelisted(tab, frameId))
174 }
175
176 function checkRequest(type, tabId, url, frameId)
177 {
178 if (isFrameWhitelisted(tabId, frameId))
179 return false; 112 return false;
180 113
181 var documentUrl = getFrameUrl(tabId, frameId); 114 var documentUrl = getFrameUrl(tab, frameId);
182 if (!documentUrl) 115 if (!documentUrl)
183 return false; 116 return false;
184 117
185 var requestHost = extractHostFromURL(url); 118 var requestHost = extractHostFromURL(url);
186 var documentHost = extractHostFromURL(documentUrl); 119 var documentHost = extractHostFromURL(documentUrl);
187 var thirdParty = isThirdParty(requestHost, documentHost); 120 var thirdParty = isThirdParty(requestHost, documentHost);
188 return defaultMatcher.matchesAny(url, type, documentHost, thirdParty); 121 return defaultMatcher.matchesAny(url, type, documentHost, thirdParty);
189 } 122 }
190 123
191 function isFrameWhitelisted(tabId, frameId, type) 124 function isFrameWhitelisted(tab, frameId, type)
192 { 125 {
193 var parent = frameId; 126 var parent = frameId;
194 var parentData = getFrameData(tabId, parent); 127 var parentData = getFrameData(tab, parent);
195 while (parentData) 128 while (parentData)
196 { 129 {
197 var frame = parent; 130 var frame = parent;
198 var frameData = parentData; 131 var frameData = parentData;
199 132
200 parent = frameData.parent; 133 parent = frameData.parent;
201 parentData = getFrameData(tabId, parent); 134 parentData = getFrameData(tab, parent);
202 135
203 var frameUrl = frameData.url; 136 var frameUrl = frameData.url;
204 var parentUrl = (parentData ? parentData.url : frameUrl); 137 var parentUrl = (parentData ? parentData.url : frameUrl);
205 if ("keyException" in frameData || isWhitelisted(frameUrl, parentUrl, type)) 138 if ("keyException" in frameData || isWhitelisted(frameUrl, parentUrl, type))
206 return true; 139 return true;
207 } 140 }
208 return false; 141 return false;
209 } 142 }
143
144 ext.webRequest.onBeforeRequest.addListener(onBeforeRequest, ["http://*/*", "http s://*/*"]);
145
146 if ('chrome' in window)
Felix Dahlke 2013/11/10 01:07:00 We normally use ".
147 {
148 function onHeadersReceived(details)
149 {
150 if (details.tabId == -1)
151 return;
152
153 var type = details.type;
154 if (type != "main_frame" && type != "sub_frame")
155 return;
156
157 var tab = new Tab({id: details.tabId});
158 var url = getFrameUrl(tab, details.frameId);
159 if (url != details.url)
160 return;
161
162 var key = null;
163 var signature = null;
164 for (var i = 0; i < details.responseHeaders.length; i++)
165 {
166 var header = details.responseHeaders[i];
167 if (header.name.toLowerCase() == "x-adblock-key" && header.value)
168 {
169 var index = header.value.indexOf("_");
170 if (index >= 0)
171 {
172 var key = header.value.substr(0, index);
Felix Dahlke 2013/11/10 01:07:00 key and signature are already declared above. I kn
173 var signature = header.value.substr(index + 1);
174 break;
175 }
176 }
177 }
178 if (!key)
179 return;
180
181 var parentUrl = null;
182 if (type == "sub_frame")
183 parentUrl = getFrameUrl(tab, details.parentFrameId);
184 if (!parentUrl)
185 parentUrl = url;
186 var docDomain = extractHostFromURL(parentUrl);
187 var keyMatch = defaultMatcher.matchesByKey(url, key.replace(/=/g, ""), docDo main);
188 if (keyMatch)
189 {
190 // Website specifies a key that we know but is the signature valid?
191 var uri = new URI(url);
192 var host = uri.asciiHost;
193 if (uri.port > 0)
194 host += ":" + uri.port;
195
196 var params = [
197 uri.path.replace(/#.*/, ""), // REQUEST_URI
198 host, // HTTP_HOST
199 window.navigator.userAgent // HTTP_USER_AGENT
200 ];
201 if (verifySignature(key, signature, params.join("\0")))
202 frames.get(tab)[details.frameId].keyException = true;
203 }
204 }
205
206 chrome.webRequest.onHeadersReceived.addListener(onHeadersReceived, {urls: ["ht tp://*/*", "https://*/*"]}, ["responseHeaders"]);
207 }
OLDNEW
« safari/content.js ('K') | « utils.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld