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; |
168 let parentWndLocation = getWindowLocation(testWnd); | 169 let parentWndLocation = getWindowLocation(testWnd); |
169 while (true) | 170 while (true) |
170 { | 171 { |
171 let testWndLocation = parentWndLocation; | 172 let testWndLocation = parentWndLocation; |
172 parentWndLocation = (testWnd == testWnd.parent ? testWndLocation : getWi
ndowLocation(testWnd.parent)); | 173 parentWndLocation = (testWnd == testWnd.parent ? testWndLocation : getWi
ndowLocation(testWnd.parent)); |
173 match = Policy.isWhitelisted(testWndLocation, parentWndLocation); | 174 match = Policy.isWhitelisted(testWndLocation, parentWndLocation, sitekey
); |
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 | 175 |
197 if (match instanceof WhitelistFilter) | 176 if (match instanceof WhitelistFilter) |
198 { | 177 { |
199 FilterStorage.increaseHitCount(match, wnd); | 178 FilterStorage.increaseHitCount(match, wnd); |
200 RequestNotifier.addNodeData(testWnd.document, topWnd, Policy.type.DOCU
MENT, getHostname(parentWndLocation), false, testWndLocation, match); | 179 RequestNotifier.addNodeData(testWnd.document, topWnd, Policy.type.DOCU
MENT, getHostname(parentWndLocation), false, testWndLocation, match); |
201 return true; | 180 return true; |
202 } | 181 } |
203 | 182 |
204 if (testWnd.parent == testWnd) | 183 if (testWnd.parent == testWnd) |
205 break; | 184 break; |
206 else | 185 else |
| 186 { |
| 187 if (testWnd == sitekeyWnd) |
| 188 [sitekey, sitekeyWnd] = getSitekey(testWnd.parent); |
207 testWnd = testWnd.parent; | 189 testWnd = testWnd.parent; |
| 190 } |
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 16 matching lines...) Expand all Loading... |
290 * @return {Boolean} | 273 * @return {Boolean} |
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} (optional) parentUrl location of the parent page |
| 284 * @param {String} (optional) 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. |
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 let url = getWindowLocation(wnd); |
| 317 let parentUrl = (wnd.parent) ? getWindowLocation(wnd.parent) : url; |
| 318 let [sitekey, sitekeyWnd] = getSitekey(wnd); |
| 319 return Policy.isWhitelisted(url, parentUrl, sitekey); |
333 }, | 320 }, |
334 | 321 |
335 | |
336 /** | 322 /** |
337 * Asynchronously re-checks filters for given nodes. | 323 * Asynchronously re-checks filters for given nodes. |
338 */ | 324 */ |
339 refilterNodes: function(/**Node[]*/ nodes, /**RequestEntry*/ entry) | 325 refilterNodes: function(/**Node[]*/ nodes, /**RequestEntry*/ entry) |
340 { | 326 { |
341 // Ignore nodes that have been blocked already | 327 // Ignore nodes that have been blocked already |
342 if (entry.filter && !(entry.filter instanceof WhitelistFilter)) | 328 if (entry.filter && !(entry.filter instanceof WhitelistFilter)) |
343 return; | 329 return; |
344 | 330 |
345 for (let node of nodes) | 331 for (let node of nodes) |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
684 { | 670 { |
685 return Utils.unwrapURL(url).host; | 671 return Utils.unwrapURL(url).host; |
686 } | 672 } |
687 catch(e) | 673 catch(e) |
688 { | 674 { |
689 return null; | 675 return null; |
690 } | 676 } |
691 } | 677 } |
692 | 678 |
693 /** | 679 /** |
| 680 * Retrieves the sitekey of a window. |
| 681 */ |
| 682 function getSitekey(wnd) |
| 683 { |
| 684 let sitekey = null; |
| 685 |
| 686 if (Utils.crypto) |
| 687 { |
| 688 while (wnd) |
| 689 { |
| 690 if (wnd.document && wnd.document.documentElement) |
| 691 { |
| 692 let foundKey = wnd.document.documentElement.getAttribute("data-adblockke
y"); |
| 693 if (foundKey && foundKey.indexOf("_") > - 1) |
| 694 { |
| 695 let [key, signature] = foundKey.split("_", 2); |
| 696 |
| 697 // Website specifies a key but is the signature valid? |
| 698 let uri = Services.io.newURI(getWindowLocation(wnd), null, null); |
| 699 let host = uri.asciiHost; |
| 700 if (uri.port > 0) |
| 701 host += ":" + uri.port; |
| 702 let params = [ |
| 703 uri.path.replace(/#.*/, ""), // REQUEST_URI |
| 704 host, // HTTP_HOST |
| 705 Utils.httpProtocol.userAgent // HTTP_USER_AGENT |
| 706 ]; |
| 707 if (Utils.verifySignature(key, signature, params.join("\0"))) |
| 708 sitekey = foundKey; |
| 709 } |
| 710 break; |
| 711 } |
| 712 |
| 713 if (wnd === wnd.top) |
| 714 break; |
| 715 |
| 716 wnd = wnd.parent; |
| 717 } |
| 718 } |
| 719 |
| 720 return [sitekey, wnd]; |
| 721 } |
| 722 |
| 723 /** |
694 * Retrieves the location of a window. | 724 * Retrieves the location of a window. |
695 * @param wnd {nsIDOMWindow} | 725 * @param wnd {nsIDOMWindow} |
696 * @return {String} window location or null on failure | 726 * @return {String} window location or null on failure |
697 */ | 727 */ |
698 function getWindowLocation(wnd) | 728 function getWindowLocation(wnd) |
699 { | 729 { |
700 if ("name" in wnd && wnd.name == "messagepane") | 730 if ("name" in wnd && wnd.name == "messagepane") |
701 { | 731 { |
702 // Thunderbird branch | 732 // Thunderbird branch |
703 try | 733 try |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
765 if (!wnd || wnd.closed) | 795 if (!wnd || wnd.closed) |
766 return; | 796 return; |
767 | 797 |
768 if (entry.type == Policy.type.OBJECT) | 798 if (entry.type == Policy.type.OBJECT) |
769 { | 799 { |
770 node.removeEventListener("mouseover", objectMouseEventHander, true); | 800 node.removeEventListener("mouseover", objectMouseEventHander, true); |
771 node.removeEventListener("mouseout", objectMouseEventHander, true); | 801 node.removeEventListener("mouseout", objectMouseEventHander, true); |
772 } | 802 } |
773 Policy.processNode(wnd, node, entry.type, Utils.makeURI(entry.location), true)
; | 803 Policy.processNode(wnd, node, entry.type, Utils.makeURI(entry.location), true)
; |
774 } | 804 } |
OLD | NEW |