Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 /* | 1 /* |
2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
3 * Copyright (C) 2006-2015 Eyeo GmbH | 3 * Copyright (C) 2006-2015 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 /** | 18 /** |
19 * @fileOverview Content policy implementation, responsible for blocking things. | 19 * @fileOverview Content policy implementation, responsible for blocking things. |
20 */ | 20 */ |
21 | 21 |
22 Cu.import("resource://gre/modules/XPCOMUtils.jsm"); | 22 "use strict"; |
23 Cu.import("resource://gre/modules/Services.jsm"); | 23 |
24 let {XPCOMUtils} = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {}); | |
25 let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); | |
24 | 26 |
25 let {Utils} = require("utils"); | 27 let {Utils} = require("utils"); |
26 let {Prefs} = require("prefs"); | 28 let {Prefs} = require("prefs"); |
27 let {FilterStorage} = require("filterStorage"); | 29 let {FilterStorage} = require("filterStorage"); |
28 let {BlockingFilter, WhitelistFilter, RegExpFilter} = require("filterClasses"); | 30 let {BlockingFilter, WhitelistFilter, RegExpFilter} = require("filterClasses"); |
29 let {defaultMatcher} = require("matcher"); | 31 let {defaultMatcher} = require("matcher"); |
30 let {objectMouseEventHander} = require("objectTabs"); | 32 let {objectMouseEventHander} = require("objectTabs"); |
31 let {RequestNotifier} = require("requestNotifier"); | 33 let {RequestNotifier} = require("requestNotifier"); |
32 let {ElemHide} = require("elemHide"); | 34 let {ElemHide} = require("elemHide"); |
33 | 35 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
79 localizedDescr: {}, | 81 localizedDescr: {}, |
80 | 82 |
81 /** | 83 /** |
82 * Lists the non-visual content types. | 84 * Lists the non-visual content types. |
83 * @type Object | 85 * @type Object |
84 */ | 86 */ |
85 nonVisual: {}, | 87 nonVisual: {}, |
86 | 88 |
87 /** | 89 /** |
88 * Map containing all schemes that should be ignored by content policy. | 90 * Map containing all schemes that should be ignored by content policy. |
89 * @type Object | 91 * @type Set |
90 */ | 92 */ |
91 whitelistSchemes: {}, | 93 whitelistSchemes: new Set(), |
92 | 94 |
93 /** | 95 /** |
94 * Called on module startup, initializes various exported properties. | 96 * Called on module startup, initializes various exported properties. |
95 */ | 97 */ |
96 init: function() | 98 init: function() |
97 { | 99 { |
98 // type constant by type description and type description by type constant | 100 // type constant by type description and type description by type constant |
99 let iface = Ci.nsIContentPolicy; | 101 let iface = Ci.nsIContentPolicy; |
100 for (let typeName of contentTypes) | 102 for (let typeName of contentTypes) |
101 { | 103 { |
(...skipping 25 matching lines...) Expand all Loading... | |
127 this.type.POPUP = 0xFFFE; | 129 this.type.POPUP = 0xFFFE; |
128 this.typeDescr[0xFFFE] = "POPUP"; | 130 this.typeDescr[0xFFFE] = "POPUP"; |
129 this.localizedDescr[0xFFFE] = Utils.getString("type_label_popup"); | 131 this.localizedDescr[0xFFFE] = Utils.getString("type_label_popup"); |
130 this.typeMask[0xFFFE] = RegExpFilter.typeMap.POPUP; | 132 this.typeMask[0xFFFE] = RegExpFilter.typeMap.POPUP; |
131 | 133 |
132 for (let type of nonVisualTypes) | 134 for (let type of nonVisualTypes) |
133 this.nonVisual[this.type[type]] = true; | 135 this.nonVisual[this.type[type]] = true; |
134 | 136 |
135 // whitelisted URL schemes | 137 // whitelisted URL schemes |
136 for (let scheme of Prefs.whitelistschemes.toLowerCase().split(" ")) | 138 for (let scheme of Prefs.whitelistschemes.toLowerCase().split(" ")) |
137 this.whitelistSchemes[scheme] = true; | 139 this.whitelistSchemes.add(scheme); |
138 | 140 |
139 // Generate class identifier used to collapse node and register correspondin g | 141 // Generate class identifier used to collapse node and register correspondin g |
140 // stylesheet. | 142 // stylesheet. |
141 let offset = "a".charCodeAt(0); | 143 let offset = "a".charCodeAt(0); |
142 for (let i = 0; i < 20; i++) | 144 for (let i = 0; i < 20; i++) |
143 collapsedClass += String.fromCharCode(offset + Math.random() * 26); | 145 collapsedClass += String.fromCharCode(offset + Math.random() * 26); |
144 | 146 |
145 let collapseStyle = Services.io.newURI("data:text/css," + | 147 let collapseStyle = Services.io.newURI("data:text/css," + |
146 encodeURIComponent("." + collapsedClass + | 148 encodeURIComponent("." + collapsedClass + |
147 "{-moz-binding: url(chrome://global/content/bindings/general.xml#foobarb azdummy) !important;}"), null, null); | 149 "{-moz-binding: url(chrome://global/content/bindings/general.xml#foobarb azdummy) !important;}"), null, null); |
148 Utils.styleService.loadAndRegisterSheet(collapseStyle, Ci.nsIStyleSheetServi ce.USER_SHEET); | 150 Utils.styleService.loadAndRegisterSheet(collapseStyle, Ci.nsIStyleSheetServi ce.USER_SHEET); |
149 onShutdown.add(function() | 151 onShutdown.add(() => |
150 { | 152 { |
151 Utils.styleService.unregisterSheet(collapseStyle, Ci.nsIStyleSheetService. USER_SHEET); | 153 Utils.styleService.unregisterSheet(collapseStyle, Ci.nsIStyleSheetService. USER_SHEET); |
152 }); | 154 }); |
153 }, | 155 }, |
154 | 156 |
155 /** | 157 /** |
156 * Checks whether a node should be blocked, hides it if necessary | 158 * Checks whether a node should be blocked, hides it if necessary |
157 * @param wnd {nsIDOMWindow} | 159 * @param wnd {nsIDOMWindow} |
158 * @param node {nsIDOMElement} | 160 * @param node {nsIDOMElement} |
159 * @param contentType {String} | 161 * @param contentType {String} |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
298 return !match || match instanceof WhitelistFilter; | 300 return !match || match instanceof WhitelistFilter; |
299 }, | 301 }, |
300 | 302 |
301 /** | 303 /** |
302 * Checks whether the location's scheme is blockable. | 304 * Checks whether the location's scheme is blockable. |
303 * @param location {nsIURI} | 305 * @param location {nsIURI} |
304 * @return {Boolean} | 306 * @return {Boolean} |
305 */ | 307 */ |
306 isBlockableScheme: function(location) | 308 isBlockableScheme: function(location) |
307 { | 309 { |
308 return !(location.scheme in Policy.whitelistSchemes); | 310 return !this.whitelistSchemes.has(location.scheme); |
309 }, | 311 }, |
310 | 312 |
311 /** | 313 /** |
312 * Checks whether a page is whitelisted. | 314 * Checks whether a page is whitelisted. |
313 * @param {String} url | 315 * @param {String} url |
314 * @param {String} [parentUrl] location of the parent page | 316 * @param {String} [parentUrl] location of the parent page |
315 * @param {String} [sitekey] public key provided on the page | 317 * @param {String} [sitekey] public key provided on the page |
316 * @return {Filter} filter that matched the URL or null if not whitelisted | 318 * @return {Filter} filter that matched the URL or null if not whitelisted |
317 */ | 319 */ |
318 isWhitelisted: function(url, parentUrl, sitekey) | 320 isWhitelisted: function(url, parentUrl, sitekey) |
319 { | 321 { |
320 if (!url) | 322 if (!url) |
321 return null; | 323 return null; |
322 | 324 |
323 // Do not apply exception rules to schemes on our whitelistschemes list. | 325 // Do not apply exception rules to schemes on our whitelistschemes list. |
324 let match = /^([\w\-]+):/.exec(url); | 326 let match = /^([\w\-]+):/.exec(url); |
325 if (match && match[1] in Policy.whitelistSchemes) | 327 if (match && this.whitelistSchemes.has(match[1])) |
326 return null; | 328 return null; |
327 | 329 |
328 if (!parentUrl) | 330 if (!parentUrl) |
329 parentUrl = url; | 331 parentUrl = url; |
330 | 332 |
331 // Ignore fragment identifier | 333 // Ignore fragment identifier |
332 let index = url.indexOf("#"); | 334 let index = url.indexOf("#"); |
333 if (index >= 0) | 335 if (index >= 0) |
334 url = url.substring(0, index); | 336 url = url.substring(0, index); |
335 | 337 |
336 let result = defaultMatcher.matchesAny(url, RegExpFilter.typeMap.DOCUMENT, g etHostname(parentUrl), false, sitekey); | 338 let result = defaultMatcher.matchesAny(url, RegExpFilter.typeMap.DOCUMENT, g etHostname(parentUrl), false, sitekey); |
337 return (result instanceof WhitelistFilter ? result : null); | 339 return (result instanceof WhitelistFilter ? result : null); |
338 }, | 340 }, |
339 | 341 |
340 /** | 342 /** |
341 * Checks whether the page loaded in a window is whitelisted for indication in the UI. | 343 * Checks whether the page loaded in a window is whitelisted for indication in the UI. |
342 * @param wnd {nsIDOMWindow} | 344 * @param wnd {nsIDOMWindow} |
343 * @return {Filter} matching exception rule or null if not whitelisted | 345 * @return {Filter} matching exception rule or null if not whitelisted |
344 */ | 346 */ |
345 isWindowWhitelisted: function(wnd) | 347 isWindowWhitelisted: function(wnd) |
346 { | 348 { |
347 return Policy.isWhitelisted(getWindowLocation(wnd)); | 349 return this.isWhitelisted(getWindowLocation(wnd)); |
348 }, | 350 }, |
349 | 351 |
350 /** | 352 /** |
351 * Asynchronously re-checks filters for given nodes. | 353 * Asynchronously re-checks filters for given nodes. |
352 * @param {Node[]} nodes | 354 * @param {Node[]} nodes |
353 * @param {RequestEntry} entry | 355 * @param {RequestEntry} entry |
354 */ | 356 */ |
355 refilterNodes: function(nodes, entry) | 357 refilterNodes: function(nodes, entry) |
356 { | 358 { |
357 // Ignore nodes that have been blocked already | 359 // Ignore nodes that have been blocked already |
(...skipping 24 matching lines...) Expand all Loading... | |
382 { | 384 { |
383 let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); | 385 let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); |
384 registrar.registerFactory(this.classID, this.classDescription, this.contract ID, this); | 386 registrar.registerFactory(this.classID, this.classDescription, this.contract ID, this); |
385 | 387 |
386 let catMan = Utils.categoryManager; | 388 let catMan = Utils.categoryManager; |
387 for (let category of this.xpcom_categories) | 389 for (let category of this.xpcom_categories) |
388 catMan.addCategoryEntry(category, this.contractID, this.contractID, false, true); | 390 catMan.addCategoryEntry(category, this.contractID, this.contractID, false, true); |
389 | 391 |
390 Services.obs.addObserver(this, "content-document-global-created", true); | 392 Services.obs.addObserver(this, "content-document-global-created", true); |
391 | 393 |
392 onShutdown.add(function() | 394 onShutdown.add(() => |
393 { | 395 { |
394 Services.obs.removeObserver(this, "content-document-global-created"); | 396 Services.obs.removeObserver(this, "content-document-global-created"); |
395 | 397 |
396 for (let category of this.xpcom_categories) | 398 for (let category of this.xpcom_categories) |
397 catMan.deleteCategoryEntry(category, this.contractID, false); | 399 catMan.deleteCategoryEntry(category, this.contractID, false); |
398 | 400 |
399 registrar.unregisterFactory(this.classID, this); | 401 registrar.unregisterFactory(this.classID, this); |
400 }.bind(this)); | 402 }); |
401 }, | 403 }, |
402 | 404 |
403 // | 405 // |
404 // nsISupports interface implementation | 406 // nsISupports interface implementation |
405 // | 407 // |
406 | 408 |
407 QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPolicy, Ci.nsIObserver, | 409 QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPolicy, Ci.nsIObserver, |
408 Ci.nsIChannelEventSink, Ci.nsIFactory, Ci.nsISupportsWeakReference]), | 410 Ci.nsIChannelEventSink, Ci.nsIFactory, Ci.nsISupportsWeakReference]), |
409 | 411 |
410 // | 412 // |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
458 let uri = additional || Utils.makeURI(subject.location.href); | 460 let uri = additional || Utils.makeURI(subject.location.href); |
459 if (!Policy.processNode(subject.opener, subject.opener.document, Policy. type.POPUP, uri, false)) | 461 if (!Policy.processNode(subject.opener, subject.opener.document, Policy. type.POPUP, uri, false)) |
460 { | 462 { |
461 subject.stop(); | 463 subject.stop(); |
462 Utils.runAsync(() => subject.close()); | 464 Utils.runAsync(() => subject.close()); |
463 } | 465 } |
464 else if (uri.spec == "about:blank") | 466 else if (uri.spec == "about:blank") |
465 { | 467 { |
466 // An about:blank pop-up most likely means that a load will be | 468 // An about:blank pop-up most likely means that a load will be |
467 // initiated asynchronously. Wait for that. | 469 // initiated asynchronously. Wait for that. |
468 Utils.runAsync(function() | 470 Utils.runAsync(() => |
469 { | 471 { |
470 let channel = subject.QueryInterface(Ci.nsIInterfaceRequestor) | 472 let channel = subject.QueryInterface(Ci.nsIInterfaceRequestor) |
471 .getInterface(Ci.nsIDocShell) | 473 .getInterface(Ci.nsIDocShell) |
472 .QueryInterface(Ci.nsIDocumentLoader) | 474 .QueryInterface(Ci.nsIDocumentLoader) |
473 .documentChannel; | 475 .documentChannel; |
474 if (channel) | 476 if (channel) |
475 this.observe(subject, topic, data, channel.URI); | 477 this.observe(subject, topic, data, channel.URI); |
476 }); | 478 }); |
477 } | 479 } |
478 break; | 480 break; |
479 } | 481 } |
480 } | 482 } |
481 }, | 483 }, |
482 | 484 |
483 // | 485 // |
484 // nsIChannelEventSink interface implementation | 486 // nsIChannelEventSink interface implementation |
485 // | 487 // |
486 | 488 |
487 asyncOnChannelRedirect: function(oldChannel, newChannel, flags, callback) | 489 asyncOnChannelRedirect: function(oldChannel, newChannel, flags, callback) |
488 { | 490 { |
489 let result = Cr.NS_OK; | 491 let result = Cr.NS_OK; |
490 try | 492 try |
491 { | 493 { |
492 // nsILoadInfo.contentPolicyType was introduced in Gecko 35, then | 494 // nsILoadInfo.contentPolicyType was introduced in Gecko 35, then |
493 // renamed to nsILoadInfo.externalContentPolicyType in Gecko 44. | 495 // renamed to nsILoadInfo.externalContentPolicyType in Gecko 44. |
494 let loadInfo = oldChannel.loadInfo; | 496 let loadInfo = oldChannel.loadInfo; |
495 let contentType = loadInfo.externalContentPolicyType || loadInfo.contentPo licyType; | 497 let contentType = ("externalContentPolicyType" in loadInfo ? |
498 loadInfo.externalContentPolicyType : loadInfo.contentPolicyType); | |
496 if (!contentType) | 499 if (!contentType) |
497 return; | 500 return; |
498 | 501 |
499 let wnd = Utils.getRequestWindow(newChannel); | 502 let wnd = Utils.getRequestWindow(newChannel); |
500 if (!wnd) | 503 if (!wnd) |
501 return; | 504 return; |
502 | 505 |
503 if (contentType == Ci.nsIContentPolicy.TYPE_DOCUMENT) | 506 if (contentType == Ci.nsIContentPolicy.TYPE_DOCUMENT) |
504 { | 507 { |
505 if (wnd.history.length <= 1 && wnd.opener) | 508 if (wnd.history.length <= 1 && wnd.opener) |
506 { | 509 { |
507 // Special treatment for pop-up windows. Note that we might not have | 510 // Special treatment for pop-up windows - this will close the window |
511 // rather than preventing the redirect. Note that we might not have | |
508 // seen the original channel yet because the redirect happened before | 512 // seen the original channel yet because the redirect happened before |
509 // the async code in observe() had a chance to run. | 513 // the async code in observe() had a chance to run. |
510 this.observe(wnd, "content-document-global-created", null, oldChannel. URI); | 514 this.observe(wnd, "content-document-global-created", null, oldChannel. URI); |
511 this.observe(wnd, "content-document-global-created", null, newChannel. URI); | 515 this.observe(wnd, "content-document-global-created", null, newChannel. URI); |
512 } | 516 } |
tschuster
2015/11/05 15:27:18
I think your comment about this patch set would he
Wladimir Palant
2015/11/05 15:51:59
Done.
| |
513 return; | 517 return; |
514 } | 518 } |
515 | 519 |
516 if (!Policy.processNode(wnd, wnd.document, contentType, newChannel.URI, fa lse)) | 520 if (!Policy.processNode(wnd, wnd.document, contentType, newChannel.URI, fa lse)) |
517 result = Cr.NS_BINDING_ABORTED; | 521 result = Cr.NS_BINDING_ABORTED; |
518 } | 522 } |
519 catch (e) | 523 catch (e) |
520 { | 524 { |
521 // We shouldn't throw exceptions here - this will prevent the redirect. | 525 // We shouldn't throw exceptions here - this will prevent the redirect. |
522 Cu.reportError(e); | 526 Cu.reportError(e); |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
725 if (!wnd || wnd.closed) | 729 if (!wnd || wnd.closed) |
726 return; | 730 return; |
727 | 731 |
728 if (entry.type == Policy.type.OBJECT) | 732 if (entry.type == Policy.type.OBJECT) |
729 { | 733 { |
730 node.removeEventListener("mouseover", objectMouseEventHander, true); | 734 node.removeEventListener("mouseover", objectMouseEventHander, true); |
731 node.removeEventListener("mouseout", objectMouseEventHander, true); | 735 node.removeEventListener("mouseout", objectMouseEventHander, true); |
732 } | 736 } |
733 Policy.processNode(wnd, node, entry.type, Utils.makeURI(entry.location), true) ; | 737 Policy.processNode(wnd, node, entry.type, Utils.makeURI(entry.location), true) ; |
734 } | 738 } |
LEFT | RIGHT |