| 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 | 
|---|