| 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 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 * Set of content types that aren't associated with a visual document area | 64 * Set of content types that aren't associated with a visual document area |
| 65 * @type Set | 65 * @type Set |
| 66 */ | 66 */ |
| 67 nonVisualTypes: new Set([ | 67 nonVisualTypes: new Set([ |
| 68 "SCRIPT", "STYLESHEET", "XMLHTTPREQUEST", "OBJECT_SUBREQUEST", "FONT", | 68 "SCRIPT", "STYLESHEET", "XMLHTTPREQUEST", "OBJECT_SUBREQUEST", "FONT", |
| 69 "ELEMHIDE", "POPUP", "GENERICHIDE", "GENERICBLOCK" | 69 "ELEMHIDE", "POPUP", "GENERICHIDE", "GENERICBLOCK" |
| 70 ]), | 70 ]), |
| 71 | 71 |
| 72 /** | 72 /** |
| 73 * Map containing all schemes that should be ignored by content policy. | 73 * Map containing all schemes that should be ignored by content policy. |
| 74 * @type Object | 74 * @type Set |
| 75 */ | 75 */ |
| 76 whitelistSchemes: new Set(), | 76 whitelistSchemes: new Set(), |
| 77 | 77 |
| 78 /** | 78 /** |
| 79 * Called on module startup, initializes various exported properties. | 79 * Called on module startup, initializes various exported properties. |
| 80 */ | 80 */ |
| 81 init: function() | 81 init: function() |
| 82 { | 82 { |
| 83 // Populate types map | 83 // Populate types map |
| 84 let iface = Ci.nsIContentPolicy; | 84 let iface = Ci.nsIContentPolicy; |
| 85 for (let name in iface) | 85 for (let name in iface) |
| 86 if (name.indexOf("TYPE_") == 0 && name != "TYPE_DATAREQUEST") | 86 if (name.indexOf("TYPE_") == 0 && name != "TYPE_DATAREQUEST") |
| 87 types.set(iface[name], name.substr(5)); | 87 types.set(iface[name], name.substr(5)); |
| 88 | 88 |
| 89 // whitelisted URL schemes | 89 // whitelisted URL schemes |
| 90 for (let scheme of Prefs.whitelistschemes.toLowerCase().split(" ")) | 90 for (let scheme of Prefs.whitelistschemes.toLowerCase().split(" ")) |
| 91 this.whitelistSchemes.add(scheme); | 91 this.whitelistSchemes.add(scheme); |
| 92 | 92 |
| 93 // Generate class identifier used to collapse node and register correspondin
g | 93 // Generate class identifier used to collapse node and register correspondin
g |
| 94 // stylesheet. | 94 // stylesheet. |
| 95 let offset = "a".charCodeAt(0); | 95 let offset = "a".charCodeAt(0); |
| 96 for (let i = 0; i < 20; i++) | 96 for (let i = 0; i < 20; i++) |
| 97 collapsedClass += String.fromCharCode(offset + Math.random() * 26); | 97 collapsedClass += String.fromCharCode(offset + Math.random() * 26); |
| 98 | 98 |
| 99 let collapseStyle = Services.io.newURI("data:text/css," + | 99 let collapseStyle = Services.io.newURI("data:text/css," + |
| 100 encodeURIComponent("." + collapsedClass + | 100 encodeURIComponent("." + collapsedClass + |
| 101 "{-moz-binding: url(chrome://global/content/bindings/general.xml#foobarb
azdummy) !important;}"), null, null); | 101 "{-moz-binding: url(chrome://global/content/bindings/general.xml#foobarb
azdummy) !important;}"), null, null); |
| 102 Utils.styleService.loadAndRegisterSheet(collapseStyle, Ci.nsIStyleSheetServi
ce.USER_SHEET); | 102 Utils.styleService.loadAndRegisterSheet(collapseStyle, Ci.nsIStyleSheetServi
ce.USER_SHEET); |
| 103 onShutdown.add(function() | 103 onShutdown.add(() => |
| 104 { | 104 { |
| 105 Utils.styleService.unregisterSheet(collapseStyle, Ci.nsIStyleSheetService.
USER_SHEET); | 105 Utils.styleService.unregisterSheet(collapseStyle, Ci.nsIStyleSheetService.
USER_SHEET); |
| 106 }); | 106 }); |
| 107 }, | 107 }, |
| 108 | 108 |
| 109 /** | 109 /** |
| 110 * Checks whether a node should be blocked, hides it if necessary | 110 * Checks whether a node should be blocked, hides it if necessary |
| 111 * @param wnd {nsIDOMWindow} | 111 * @param wnd {nsIDOMWindow} |
| 112 * @param node {nsIDOMElement} | 112 * @param node {nsIDOMElement} |
| 113 * @param contentType {String} | 113 * @param contentType {String} |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 return !match || match instanceof WhitelistFilter; | 246 return !match || match instanceof WhitelistFilter; |
| 247 }, | 247 }, |
| 248 | 248 |
| 249 /** | 249 /** |
| 250 * Checks whether the location's scheme is blockable. | 250 * Checks whether the location's scheme is blockable. |
| 251 * @param location {nsIURI} | 251 * @param location {nsIURI} |
| 252 * @return {Boolean} | 252 * @return {Boolean} |
| 253 */ | 253 */ |
| 254 isBlockableScheme: function(location) | 254 isBlockableScheme: function(location) |
| 255 { | 255 { |
| 256 return !Policy.whitelistSchemes.has(location.scheme); | 256 return !this.whitelistSchemes.has(location.scheme); |
| 257 }, | 257 }, |
| 258 | 258 |
| 259 /** | 259 /** |
| 260 * Checks whether a page is whitelisted. | 260 * Checks whether a page is whitelisted. |
| 261 * @param {String} url | 261 * @param {String} url |
| 262 * @param {String} [parentUrl] location of the parent page | 262 * @param {String} [parentUrl] location of the parent page |
| 263 * @param {String} [sitekey] public key provided on the page | 263 * @param {String} [sitekey] public key provided on the page |
| 264 * @return {Filter} filter that matched the URL or null if not whitelisted | 264 * @return {Filter} filter that matched the URL or null if not whitelisted |
| 265 */ | 265 */ |
| 266 isWhitelisted: function(url, parentUrl, sitekey) | 266 isWhitelisted: function(url, parentUrl, sitekey) |
| 267 { | 267 { |
| 268 if (!url) | 268 if (!url) |
| 269 return null; | 269 return null; |
| 270 | 270 |
| 271 // Do not apply exception rules to schemes on our whitelistschemes list. | 271 // Do not apply exception rules to schemes on our whitelistschemes list. |
| 272 let match = /^([\w\-]+):/.exec(url); | 272 let match = /^([\w\-]+):/.exec(url); |
| 273 if (match && Policy.whitelistSchemes.has(match[1])) | 273 if (match && this.whitelistSchemes.has(match[1])) |
| 274 return null; | 274 return null; |
| 275 | 275 |
| 276 if (!parentUrl) | 276 if (!parentUrl) |
| 277 parentUrl = url; | 277 parentUrl = url; |
| 278 | 278 |
| 279 // Ignore fragment identifier | 279 // Ignore fragment identifier |
| 280 let index = url.indexOf("#"); | 280 let index = url.indexOf("#"); |
| 281 if (index >= 0) | 281 if (index >= 0) |
| 282 url = url.substring(0, index); | 282 url = url.substring(0, index); |
| 283 | 283 |
| 284 let result = defaultMatcher.matchesAny(url, RegExpFilter.typeMap.DOCUMENT, g
etHostname(parentUrl), false, sitekey); | 284 let result = defaultMatcher.matchesAny(url, RegExpFilter.typeMap.DOCUMENT, g
etHostname(parentUrl), false, sitekey); |
| 285 return (result instanceof WhitelistFilter ? result : null); | 285 return (result instanceof WhitelistFilter ? result : null); |
| 286 }, | 286 }, |
| 287 | 287 |
| 288 /** | 288 /** |
| 289 * Checks whether the page loaded in a window is whitelisted for indication in
the UI. | 289 * Checks whether the page loaded in a window is whitelisted for indication in
the UI. |
| 290 * @param wnd {nsIDOMWindow} | 290 * @param wnd {nsIDOMWindow} |
| 291 * @return {Filter} matching exception rule or null if not whitelisted | 291 * @return {Filter} matching exception rule or null if not whitelisted |
| 292 */ | 292 */ |
| 293 isWindowWhitelisted: function(wnd) | 293 isWindowWhitelisted: function(wnd) |
| 294 { | 294 { |
| 295 return Policy.isWhitelisted(getWindowLocation(wnd)); | 295 return this.isWhitelisted(getWindowLocation(wnd)); |
| 296 }, | 296 }, |
| 297 | 297 |
| 298 /** | 298 /** |
| 299 * Asynchronously re-checks filters for given nodes. | 299 * Asynchronously re-checks filters for given nodes. |
| 300 * @param {Node[]} nodes | 300 * @param {Node[]} nodes |
| 301 * @param {RequestEntry} entry | 301 * @param {RequestEntry} entry |
| 302 */ | 302 */ |
| 303 refilterNodes: function(nodes, entry) | 303 refilterNodes: function(nodes, entry) |
| 304 { | 304 { |
| 305 // Ignore nodes that have been blocked already | 305 // Ignore nodes that have been blocked already |
| (...skipping 24 matching lines...) Expand all Loading... |
| 330 { | 330 { |
| 331 let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); | 331 let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); |
| 332 registrar.registerFactory(this.classID, this.classDescription, this.contract
ID, this); | 332 registrar.registerFactory(this.classID, this.classDescription, this.contract
ID, this); |
| 333 | 333 |
| 334 let catMan = Utils.categoryManager; | 334 let catMan = Utils.categoryManager; |
| 335 for (let category of this.xpcom_categories) | 335 for (let category of this.xpcom_categories) |
| 336 catMan.addCategoryEntry(category, this.contractID, this.contractID, false,
true); | 336 catMan.addCategoryEntry(category, this.contractID, this.contractID, false,
true); |
| 337 | 337 |
| 338 Services.obs.addObserver(this, "content-document-global-created", true); | 338 Services.obs.addObserver(this, "content-document-global-created", true); |
| 339 | 339 |
| 340 onShutdown.add(function() | 340 onShutdown.add(() => |
| 341 { | 341 { |
| 342 Services.obs.removeObserver(this, "content-document-global-created"); | 342 Services.obs.removeObserver(this, "content-document-global-created"); |
| 343 | 343 |
| 344 for (let category of this.xpcom_categories) | 344 for (let category of this.xpcom_categories) |
| 345 catMan.deleteCategoryEntry(category, this.contractID, false); | 345 catMan.deleteCategoryEntry(category, this.contractID, false); |
| 346 | 346 |
| 347 registrar.unregisterFactory(this.classID, this); | 347 registrar.unregisterFactory(this.classID, this); |
| 348 }.bind(this)); | 348 }); |
| 349 }, | 349 }, |
| 350 | 350 |
| 351 // | 351 // |
| 352 // nsISupports interface implementation | 352 // nsISupports interface implementation |
| 353 // | 353 // |
| 354 | 354 |
| 355 QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPolicy, Ci.nsIObserver, | 355 QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPolicy, Ci.nsIObserver, |
| 356 Ci.nsIChannelEventSink, Ci.nsIFactory, Ci.nsISupportsWeakReference]), | 356 Ci.nsIChannelEventSink, Ci.nsIFactory, Ci.nsISupportsWeakReference]), |
| 357 | 357 |
| 358 // | 358 // |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 let uri = additional || subject.location.href; | 402 let uri = additional || subject.location.href; |
| 403 if (!Policy.processNode(subject.opener, subject.opener.document, "POPUP"
, uri, false)) | 403 if (!Policy.processNode(subject.opener, subject.opener.document, "POPUP"
, uri, false)) |
| 404 { | 404 { |
| 405 subject.stop(); | 405 subject.stop(); |
| 406 Utils.runAsync(() => subject.close()); | 406 Utils.runAsync(() => subject.close()); |
| 407 } | 407 } |
| 408 else if (uri == "about:blank") | 408 else if (uri == "about:blank") |
| 409 { | 409 { |
| 410 // An about:blank pop-up most likely means that a load will be | 410 // An about:blank pop-up most likely means that a load will be |
| 411 // initiated asynchronously. Wait for that. | 411 // initiated asynchronously. Wait for that. |
| 412 Utils.runAsync(function() | 412 Utils.runAsync(() => |
| 413 { | 413 { |
| 414 let channel = subject.QueryInterface(Ci.nsIInterfaceRequestor) | 414 let channel = subject.QueryInterface(Ci.nsIInterfaceRequestor) |
| 415 .getInterface(Ci.nsIDocShell) | 415 .getInterface(Ci.nsIDocShell) |
| 416 .QueryInterface(Ci.nsIDocumentLoader) | 416 .QueryInterface(Ci.nsIDocumentLoader) |
| 417 .documentChannel; | 417 .documentChannel; |
| 418 if (channel) | 418 if (channel) |
| 419 this.observe(subject, topic, data, channel.URI.spec); | 419 this.observe(subject, topic, data, channel.URI.spec); |
| 420 }); | 420 }); |
| 421 } | 421 } |
| 422 break; | 422 break; |
| 423 } | 423 } |
| 424 } | 424 } |
| 425 }, | 425 }, |
| 426 | 426 |
| 427 // | 427 // |
| 428 // nsIChannelEventSink interface implementation | 428 // nsIChannelEventSink interface implementation |
| 429 // | 429 // |
| 430 | 430 |
| 431 asyncOnChannelRedirect: function(oldChannel, newChannel, flags, callback) | 431 asyncOnChannelRedirect: function(oldChannel, newChannel, flags, callback) |
| 432 { | 432 { |
| 433 let result = Cr.NS_OK; | 433 let result = Cr.NS_OK; |
| 434 try | 434 try |
| 435 { | 435 { |
| 436 // nsILoadInfo.contentPolicyType was introduced in Gecko 35, then | 436 // nsILoadInfo.contentPolicyType was introduced in Gecko 35, then |
| 437 // renamed to nsILoadInfo.externalContentPolicyType in Gecko 44. | 437 // renamed to nsILoadInfo.externalContentPolicyType in Gecko 44. |
| 438 let loadInfo = oldChannel.loadInfo; | 438 let loadInfo = oldChannel.loadInfo; |
| 439 let contentType = loadInfo.externalContentPolicyType || loadInfo.contentPo
licyType; | 439 let contentType = ("externalContentPolicyType" in loadInfo ? |
| 440 loadInfo.externalContentPolicyType : loadInfo.contentPolicyType); |
| 440 if (!contentType) | 441 if (!contentType) |
| 441 return; | 442 return; |
| 442 | 443 |
| 443 let wnd = Utils.getRequestWindow(newChannel); | 444 let wnd = Utils.getRequestWindow(newChannel); |
| 444 if (!wnd) | 445 if (!wnd) |
| 445 return; | 446 return; |
| 446 | 447 |
| 447 if (contentType == Ci.nsIContentPolicy.TYPE_DOCUMENT) | 448 if (contentType == Ci.nsIContentPolicy.TYPE_DOCUMENT) |
| 448 { | 449 { |
| 449 if (wnd.history.length <= 1 && wnd.opener) | 450 if (wnd.history.length <= 1 && wnd.opener) |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 670 if (!wnd || wnd.closed) | 671 if (!wnd || wnd.closed) |
| 671 return; | 672 return; |
| 672 | 673 |
| 673 if (entry.type == "OBJECT") | 674 if (entry.type == "OBJECT") |
| 674 { | 675 { |
| 675 node.removeEventListener("mouseover", objectMouseEventHander, true); | 676 node.removeEventListener("mouseover", objectMouseEventHander, true); |
| 676 node.removeEventListener("mouseout", objectMouseEventHander, true); | 677 node.removeEventListener("mouseout", objectMouseEventHander, true); |
| 677 } | 678 } |
| 678 Policy.processNode(wnd, node, entry.type, entry.location, true); | 679 Policy.processNode(wnd, node, entry.type, entry.location, true); |
| 679 } | 680 } |
| LEFT | RIGHT |