OLD | NEW |
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-2014 Eyeo GmbH | 3 * Copyright (C) 2006-2014 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 |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 processNode: function(wnd, node, contentType, location, collapse) | 155 processNode: function(wnd, node, contentType, location, collapse) |
156 { | 156 { |
157 let topWnd = wnd.top; | 157 let topWnd = wnd.top; |
158 if (!topWnd || !topWnd.location || !topWnd.location.href) | 158 if (!topWnd || !topWnd.location || !topWnd.location.href) |
159 return true; | 159 return true; |
160 | 160 |
161 let originWindow = Utils.getOriginWindow(wnd); | 161 let originWindow = Utils.getOriginWindow(wnd); |
162 let wndLocation = originWindow.location.href; | 162 let wndLocation = originWindow.location.href; |
163 let docDomain = getHostname(wndLocation); | 163 let docDomain = getHostname(wndLocation); |
164 let match = null; | 164 let match = null; |
| 165 let [sitekey, sitekeyWnd] = getSitekey(wnd); |
165 if (!match && Prefs.enabled) | 166 if (!match && Prefs.enabled) |
166 { | 167 { |
167 let testWnd = wnd; | 168 let testWnd = wnd; |
| 169 let testSitekey = sitekey; |
| 170 let testSitekeyWnd = sitekeyWnd; |
168 let parentWndLocation = getWindowLocation(testWnd); | 171 let parentWndLocation = getWindowLocation(testWnd); |
169 while (true) | 172 while (true) |
170 { | 173 { |
171 let testWndLocation = parentWndLocation; | 174 let testWndLocation = parentWndLocation; |
172 parentWndLocation = (testWnd == testWnd.parent ? testWndLocation : getWi
ndowLocation(testWnd.parent)); | 175 parentWndLocation = (testWnd == testWnd.parent ? testWndLocation : getWi
ndowLocation(testWnd.parent)); |
173 match = Policy.isWhitelisted(testWndLocation, parentWndLocation); | 176 match = Policy.isWhitelisted(testWndLocation, parentWndLocation, testSit
ekey); |
174 | |
175 if (!(match instanceof WhitelistFilter)) | |
176 { | |
177 let keydata = (testWnd.document && testWnd.document.documentElement ?
testWnd.document.documentElement.getAttribute("data-adblockkey") : null); | |
178 if (keydata && keydata.indexOf("_") >= 0) | |
179 { | |
180 let [key, signature] = keydata.split("_", 2); | |
181 let keyMatch = defaultMatcher.matchesByKey(testWndLocation, key.repl
ace(/=/g, ""), docDomain); | |
182 if (keyMatch && Utils.crypto) | |
183 { | |
184 // Website specifies a key that we know but is the signature valid
? | |
185 let uri = Services.io.newURI(testWndLocation, null, null); | |
186 let params = [ | |
187 uri.path.replace(/#.*/, ""), // REQUEST_URI | |
188 uri.asciiHost, // HTTP_HOST | |
189 Utils.httpProtocol.userAgent // HTTP_USER_AGENT | |
190 ]; | |
191 if (Utils.verifySignature(key, signature, params.join("\0"))) | |
192 match = keyMatch; | |
193 } | |
194 } | |
195 } | |
196 | 177 |
197 if (match instanceof WhitelistFilter) | 178 if (match instanceof WhitelistFilter) |
198 { | 179 { |
199 FilterStorage.increaseHitCount(match, wnd); | 180 FilterStorage.increaseHitCount(match, wnd); |
200 RequestNotifier.addNodeData(testWnd.document, topWnd, Policy.type.DOCU
MENT, getHostname(parentWndLocation), false, testWndLocation, match); | 181 RequestNotifier.addNodeData(testWnd.document, topWnd, Policy.type.DOCU
MENT, getHostname(parentWndLocation), false, testWndLocation, match); |
201 return true; | 182 return true; |
202 } | 183 } |
203 | 184 |
204 if (testWnd.parent == testWnd) | 185 if (testWnd.parent == testWnd) |
205 break; | 186 break; |
206 else | 187 |
207 testWnd = testWnd.parent; | 188 if (testWnd == testSitekeyWnd) |
| 189 [testSitekey, testSitekeyWnd] = getSitekey(testWnd.parent); |
| 190 testWnd = testWnd.parent; |
208 } | 191 } |
209 } | 192 } |
210 | 193 |
211 // Data loaded by plugins should be attached to the document | 194 // Data loaded by plugins should be attached to the document |
212 if (contentType == Policy.type.OBJECT_SUBREQUEST && node instanceof Ci.nsIDO
MElement) | 195 if (contentType == Policy.type.OBJECT_SUBREQUEST && node instanceof Ci.nsIDO
MElement) |
213 node = node.ownerDocument; | 196 node = node.ownerDocument; |
214 | 197 |
215 // Fix type for objects misrepresented as frames or images | 198 // Fix type for objects misrepresented as frames or images |
216 if (contentType != Policy.type.OBJECT && (node instanceof Ci.nsIDOMHTMLObjec
tElement || node instanceof Ci.nsIDOMHTMLEmbedElement)) | 199 if (contentType != Policy.type.OBJECT && (node instanceof Ci.nsIDOMHTMLObjec
tElement || node instanceof Ci.nsIDOMHTMLEmbedElement)) |
217 contentType = Policy.type.OBJECT; | 200 contentType = Policy.type.OBJECT; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 FilterStorage.increaseHitCount(exception, wnd); | 236 FilterStorage.increaseHitCount(exception, wnd); |
254 RequestNotifier.addNodeData(node, topWnd, contentType, docDomain, thirdP
arty, locationText, exception); | 237 RequestNotifier.addNodeData(node, topWnd, contentType, docDomain, thirdP
arty, locationText, exception); |
255 return true; | 238 return true; |
256 } | 239 } |
257 } | 240 } |
258 | 241 |
259 let thirdParty = (contentType == Policy.type.ELEMHIDE ? false : isThirdParty
(location, docDomain)); | 242 let thirdParty = (contentType == Policy.type.ELEMHIDE ? false : isThirdParty
(location, docDomain)); |
260 | 243 |
261 if (!match && Prefs.enabled) | 244 if (!match && Prefs.enabled) |
262 { | 245 { |
263 match = defaultMatcher.matchesAny(locationText, Policy.typeDescr[contentTy
pe] || "", docDomain, thirdParty); | 246 match = defaultMatcher.matchesAny(locationText, Policy.typeDescr[contentTy
pe] || "", docDomain, thirdParty, sitekey); |
264 if (match instanceof BlockingFilter && node.ownerDocument && !(contentType
in Policy.nonVisual)) | 247 if (match instanceof BlockingFilter && node.ownerDocument && !(contentType
in Policy.nonVisual)) |
265 { | 248 { |
266 let prefCollapse = (match.collapse != null ? match.collapse : !Prefs.fas
tcollapse); | 249 let prefCollapse = (match.collapse != null ? match.collapse : !Prefs.fas
tcollapse); |
267 if (collapse || prefCollapse) | 250 if (collapse || prefCollapse) |
268 schedulePostProcess(node); | 251 schedulePostProcess(node); |
269 } | 252 } |
270 | 253 |
271 // Track mouse events for objects | 254 // Track mouse events for objects |
272 if (!match && contentType == Policy.type.OBJECT && node.nodeType == Ci.nsI
DOMNode.ELEMENT_NODE) | 255 if (!match && contentType == Policy.type.OBJECT && node.nodeType == Ci.nsI
DOMNode.ELEMENT_NODE) |
273 { | 256 { |
(...skipping 17 matching lines...) Expand all Loading... |
291 */ | 274 */ |
292 isBlockableScheme: function(location) | 275 isBlockableScheme: function(location) |
293 { | 276 { |
294 return !(location.scheme in Policy.whitelistSchemes); | 277 return !(location.scheme in Policy.whitelistSchemes); |
295 }, | 278 }, |
296 | 279 |
297 /** | 280 /** |
298 * Checks whether a page is whitelisted. | 281 * Checks whether a page is whitelisted. |
299 * @param {String} url | 282 * @param {String} url |
300 * @param {String} [parentUrl] location of the parent page | 283 * @param {String} [parentUrl] location of the parent page |
| 284 * @param {String} [sitekey] public key provided on the page |
301 * @return {Filter} filter that matched the URL or null if not whitelisted | 285 * @return {Filter} filter that matched the URL or null if not whitelisted |
302 */ | 286 */ |
303 isWhitelisted: function(url, parentUrl) | 287 isWhitelisted: function(url, parentUrl, sitekey) |
304 { | 288 { |
305 if (!url) | 289 if (!url) |
306 return null; | 290 return null; |
307 | 291 |
308 // Do not apply exception rules to schemes on our whitelistschemes list. | 292 // Do not apply exception rules to schemes on our whitelistschemes list. |
309 let match = /^([\w\-]+):/.exec(url); | 293 let match = /^([\w\-]+):/.exec(url); |
310 if (match && match[1] in Policy.whitelistSchemes) | 294 if (match && match[1] in Policy.whitelistSchemes) |
311 return null; | 295 return null; |
312 | 296 |
313 if (!parentUrl) | 297 if (!parentUrl) |
314 parentUrl = url; | 298 parentUrl = url; |
315 | 299 |
316 // Ignore fragment identifier | 300 // Ignore fragment identifier |
317 let index = url.indexOf("#"); | 301 let index = url.indexOf("#"); |
318 if (index >= 0) | 302 if (index >= 0) |
319 url = url.substring(0, index); | 303 url = url.substring(0, index); |
320 | 304 |
321 let result = defaultMatcher.matchesAny(url, "DOCUMENT", getHostname(parentUr
l), false); | 305 let result = defaultMatcher.matchesAny(url, "DOCUMENT", getHostname(parentUr
l), false, sitekey); |
322 return (result instanceof WhitelistFilter ? result : null); | 306 return (result instanceof WhitelistFilter ? result : null); |
323 }, | 307 }, |
324 | 308 |
325 /** | 309 /** |
326 * Checks whether the page loaded in a window is whitelisted. | 310 * Checks whether the page loaded in a window is whitelisted for indication in
the UI. |
327 * @param wnd {nsIDOMWindow} | 311 * @param wnd {nsIDOMWindow} |
328 * @return {Filter} matching exception rule or null if not whitelisted | 312 * @return {Filter} matching exception rule or null if not whitelisted |
329 */ | 313 */ |
330 isWindowWhitelisted: function(wnd) | 314 isWindowWhitelisted: function(wnd) |
331 { | 315 { |
332 return Policy.isWhitelisted(getWindowLocation(wnd)); | 316 return Policy.isWhitelisted(getWindowLocation(wnd)); |
333 }, | 317 }, |
334 | 318 |
335 | |
336 /** | 319 /** |
337 * Asynchronously re-checks filters for given nodes. | 320 * Asynchronously re-checks filters for given nodes. |
338 */ | 321 */ |
339 refilterNodes: function(/**Node[]*/ nodes, /**RequestEntry*/ entry) | 322 refilterNodes: function(/**Node[]*/ nodes, /**RequestEntry*/ entry) |
340 { | 323 { |
341 // Ignore nodes that have been blocked already | 324 // Ignore nodes that have been blocked already |
342 if (entry.filter && !(entry.filter instanceof WhitelistFilter)) | 325 if (entry.filter && !(entry.filter instanceof WhitelistFilter)) |
343 return; | 326 return; |
344 | 327 |
345 for (let node of nodes) | 328 for (let node of nodes) |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
684 { | 667 { |
685 return Utils.unwrapURL(url).host; | 668 return Utils.unwrapURL(url).host; |
686 } | 669 } |
687 catch(e) | 670 catch(e) |
688 { | 671 { |
689 return null; | 672 return null; |
690 } | 673 } |
691 } | 674 } |
692 | 675 |
693 /** | 676 /** |
| 677 * Retrieves the sitekey of a window. |
| 678 */ |
| 679 function getSitekey(wnd) |
| 680 { |
| 681 let sitekey = null; |
| 682 |
| 683 while (true) |
| 684 { |
| 685 if (wnd.document && wnd.document.documentElement) |
| 686 { |
| 687 let keydata = wnd.document.documentElement.getAttribute("data-adblockkey")
; |
| 688 if (keydata && keydata.indexOf("_") >= 0) |
| 689 { |
| 690 let [key, signature] = keydata.split("_", 2); |
| 691 key = key.replace(/=/g, ""); |
| 692 |
| 693 // Website specifies a key but is the signature valid? |
| 694 let uri = Services.io.newURI(getWindowLocation(wnd), null, null); |
| 695 let host = uri.asciiHost; |
| 696 if (uri.port > 0) |
| 697 host += ":" + uri.port; |
| 698 let params = [ |
| 699 uri.path.replace(/#.*/, ""), // REQUEST_URI |
| 700 host, // HTTP_HOST |
| 701 Utils.httpProtocol.userAgent // HTTP_USER_AGENT |
| 702 ]; |
| 703 if (Utils.verifySignature(key, signature, params.join("\0"))) |
| 704 return [key, wnd]; |
| 705 } |
| 706 } |
| 707 |
| 708 if (wnd === wnd.parent) |
| 709 break; |
| 710 |
| 711 wnd = wnd.parent; |
| 712 } |
| 713 |
| 714 return [sitekey, wnd]; |
| 715 } |
| 716 |
| 717 /** |
694 * Retrieves the location of a window. | 718 * Retrieves the location of a window. |
695 * @param wnd {nsIDOMWindow} | 719 * @param wnd {nsIDOMWindow} |
696 * @return {String} window location or null on failure | 720 * @return {String} window location or null on failure |
697 */ | 721 */ |
698 function getWindowLocation(wnd) | 722 function getWindowLocation(wnd) |
699 { | 723 { |
700 if ("name" in wnd && wnd.name == "messagepane") | 724 if ("name" in wnd && wnd.name == "messagepane") |
701 { | 725 { |
702 // Thunderbird branch | 726 // Thunderbird branch |
703 try | 727 try |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
765 if (!wnd || wnd.closed) | 789 if (!wnd || wnd.closed) |
766 return; | 790 return; |
767 | 791 |
768 if (entry.type == Policy.type.OBJECT) | 792 if (entry.type == Policy.type.OBJECT) |
769 { | 793 { |
770 node.removeEventListener("mouseover", objectMouseEventHander, true); | 794 node.removeEventListener("mouseover", objectMouseEventHander, true); |
771 node.removeEventListener("mouseout", objectMouseEventHander, true); | 795 node.removeEventListener("mouseout", objectMouseEventHander, true); |
772 } | 796 } |
773 Policy.processNode(wnd, node, entry.type, Utils.makeURI(entry.location), true)
; | 797 Policy.processNode(wnd, node, entry.type, Utils.makeURI(entry.location), true)
; |
774 } | 798 } |
OLD | NEW |