| OLD | NEW | 
|---|
| 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-2016 Eyeo GmbH | 3  * Copyright (C) 2006-2016 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 var typeMap = { | 18 let typeMap = { | 
| 19   "img": "IMAGE", | 19   "img": "IMAGE", | 
| 20   "input": "IMAGE", | 20   "input": "IMAGE", | 
| 21   "picture": "IMAGE", | 21   "picture": "IMAGE", | 
| 22   "audio": "MEDIA", | 22   "audio": "MEDIA", | 
| 23   "video": "MEDIA", | 23   "video": "MEDIA", | 
| 24   "frame": "SUBDOCUMENT", | 24   "frame": "SUBDOCUMENT", | 
| 25   "iframe": "SUBDOCUMENT", | 25   "iframe": "SUBDOCUMENT", | 
| 26   "object": "OBJECT", | 26   "object": "OBJECT", | 
| 27   "embed": "OBJECT" | 27   "embed": "OBJECT" | 
| 28 }; | 28 }; | 
| 29 | 29 | 
| 30 function getURLsFromObjectElement(element) | 30 function getURLsFromObjectElement(element) | 
| 31 { | 31 { | 
| 32   var url = element.getAttribute("data"); | 32   let url = element.getAttribute("data"); | 
| 33   if (url) | 33   if (url) | 
| 34     return [url]; | 34     return [url]; | 
| 35 | 35 | 
| 36   for (var i = 0; i < element.children.length; i++) | 36   for (let child of element.children) | 
| 37   { | 37   { | 
| 38     var child = element.children[i]; |  | 
| 39     if (child.localName != "param") | 38     if (child.localName != "param") | 
| 40       continue; | 39       continue; | 
| 41 | 40 | 
| 42     var name = child.getAttribute("name"); | 41     let name = child.getAttribute("name"); | 
| 43     if (name != "movie"  && // Adobe Flash | 42     if (name != "movie"  && // Adobe Flash | 
| 44         name != "source" && // Silverlight | 43         name != "source" && // Silverlight | 
| 45         name != "src"    && // Real Media + Quicktime | 44         name != "src"    && // Real Media + Quicktime | 
| 46         name != "FileName") // Windows Media | 45         name != "FileName") // Windows Media | 
| 47       continue; | 46       continue; | 
| 48 | 47 | 
| 49     var value = child.getAttribute("value"); | 48     let value = child.getAttribute("value"); | 
| 50     if (!value) | 49     if (!value) | 
| 51       continue; | 50       continue; | 
| 52 | 51 | 
| 53     return [value]; | 52     return [value]; | 
| 54   } | 53   } | 
| 55 | 54 | 
| 56   return []; | 55   return []; | 
| 57 } | 56 } | 
| 58 | 57 | 
| 59 function getURLsFromAttributes(element) | 58 function getURLsFromAttributes(element) | 
| 60 { | 59 { | 
| 61   var urls = []; | 60   let urls = []; | 
| 62 | 61 | 
| 63   if (element.src) | 62   if (element.src) | 
| 64     urls.push(element.src); | 63     urls.push(element.src); | 
| 65 | 64 | 
| 66   if (element.srcset) | 65   if (element.srcset) | 
| 67   { | 66   { | 
| 68     var candidates = element.srcset.split(","); | 67     for (let candidate of element.srcset.split(",")) | 
| 69     for (var i = 0; i < candidates.length; i++) |  | 
| 70     { | 68     { | 
| 71       var url = candidates[i].trim().replace(/\s+\S+$/, ""); | 69       let url = candidate.trim().replace(/\s+\S+$/, ""); | 
| 72       if (url) | 70       if (url) | 
| 73         urls.push(url); | 71         urls.push(url); | 
| 74     } | 72     } | 
| 75   } | 73   } | 
| 76 | 74 | 
| 77   return urls; | 75   return urls; | 
| 78 } | 76 } | 
| 79 | 77 | 
| 80 function getURLsFromMediaElement(element) | 78 function getURLsFromMediaElement(element) | 
| 81 { | 79 { | 
| 82   var urls = getURLsFromAttributes(element); | 80   let urls = getURLsFromAttributes(element); | 
| 83 | 81 | 
| 84   for (var i = 0; i < element.children.length; i++) | 82   for (let child of element.children) | 
| 85   { |  | 
| 86     var child = element.children[i]; |  | 
| 87     if (child.localName == "source" || child.localName == "track") | 83     if (child.localName == "source" || child.localName == "track") | 
| 88       urls.push.apply(urls, getURLsFromAttributes(child)); | 84       urls.push.apply(urls, getURLsFromAttributes(child)); | 
| 89   } |  | 
| 90 | 85 | 
| 91   if (element.poster) | 86   if (element.poster) | 
| 92     urls.push(element.poster); | 87     urls.push(element.poster); | 
| 93 | 88 | 
| 94   return urls; | 89   return urls; | 
| 95 } | 90 } | 
| 96 | 91 | 
| 97 function getURLsFromElement(element) | 92 function getURLsFromElement(element) | 
| 98 { | 93 { | 
| 99   var urls; | 94   let urls; | 
| 100   switch (element.localName) | 95   switch (element.localName) | 
| 101   { | 96   { | 
| 102     case "object": | 97     case "object": | 
| 103       urls = getURLsFromObjectElement(element); | 98       urls = getURLsFromObjectElement(element); | 
| 104       break; | 99       break; | 
| 105 | 100 | 
| 106     case "video": | 101     case "video": | 
| 107     case "audio": | 102     case "audio": | 
| 108     case "picture": | 103     case "picture": | 
| 109       urls = getURLsFromMediaElement(element); | 104       urls = getURLsFromMediaElement(element); | 
| 110       break; | 105       break; | 
| 111 | 106 | 
| 112     default: | 107     default: | 
| 113       urls = getURLsFromAttributes(element); | 108       urls = getURLsFromAttributes(element); | 
| 114       break; | 109       break; | 
| 115   } | 110   } | 
| 116 | 111 | 
| 117   for (var i = 0; i < urls.length; i++) | 112   for (let i = 0; i < urls.length; i++) | 
| 118   { | 113   { | 
| 119     if (/^(?!https?:)[\w-]+:/i.test(urls[i])) | 114     if (/^(?!https?:)[\w-]+:/i.test(urls[i])) | 
| 120       urls.splice(i--, 1); | 115       urls.splice(i--, 1); | 
| 121   } | 116   } | 
| 122 | 117 | 
| 123   return urls; | 118   return urls; | 
| 124 } | 119 } | 
| 125 | 120 | 
| 126 function checkCollapse(element) | 121 function checkCollapse(element) | 
| 127 { | 122 { | 
| 128   var mediatype = typeMap[element.localName]; | 123   let mediatype = typeMap[element.localName]; | 
| 129   if (!mediatype) | 124   if (!mediatype) | 
| 130     return; | 125     return; | 
| 131 | 126 | 
| 132   var urls = getURLsFromElement(element); | 127   let urls = getURLsFromElement(element); | 
| 133   if (urls.length == 0) | 128   if (urls.length == 0) | 
| 134     return; | 129     return; | 
| 135 | 130 | 
| 136   ext.backgroundPage.sendMessage( | 131   ext.backgroundPage.sendMessage( | 
| 137     { | 132     { | 
| 138       type: "filters.collapse", | 133       type: "filters.collapse", | 
| 139       urls: urls, | 134       urls: urls, | 
| 140       mediatype: mediatype, | 135       mediatype: mediatype, | 
| 141       baseURL: document.location.href | 136       baseURL: document.location.href | 
| 142     }, | 137     }, | 
| 143 | 138 | 
| 144     function(collapse) | 139     collapse => | 
| 145     { | 140     { | 
| 146       function collapseElement() | 141       function collapseElement() | 
| 147       { | 142       { | 
| 148         var propertyName = "display"; | 143         let propertyName = "display"; | 
| 149         var propertyValue = "none"; | 144         let propertyValue = "none"; | 
| 150         if (element.localName == "frame") | 145         if (element.localName == "frame") | 
| 151         { | 146         { | 
| 152           propertyName = "visibility"; | 147           propertyName = "visibility"; | 
| 153           propertyValue = "hidden"; | 148           propertyValue = "hidden"; | 
| 154         } | 149         } | 
| 155 | 150 | 
| 156         if (element.style.getPropertyValue(propertyName) != propertyValue || | 151         if (element.style.getPropertyValue(propertyName) != propertyValue || | 
| 157             element.style.getPropertyPriority(propertyName) != "important") | 152             element.style.getPropertyPriority(propertyName) != "important") | 
| 158           element.style.setProperty(propertyName, propertyValue, "important"); | 153           element.style.setProperty(propertyName, propertyValue, "important"); | 
| 159       } | 154       } | 
| 160 | 155 | 
| 161       if (collapse) | 156       if (collapse) | 
| 162       { | 157       { | 
| 163         collapseElement(); | 158         collapseElement(); | 
| 164 | 159 | 
| 165         new MutationObserver(collapseElement).observe( | 160         new MutationObserver(collapseElement).observe( | 
| 166           element, { | 161           element, { | 
| 167             attributes: true, | 162             attributes: true, | 
| 168             attributeFilter: ["style"] | 163             attributeFilter: ["style"] | 
| 169           } | 164           } | 
| 170         ); | 165         ); | 
| 171       } | 166       } | 
| 172     } | 167     } | 
| 173   ); | 168   ); | 
| 174 } | 169 } | 
| 175 | 170 | 
| 176 function checkSitekey() | 171 function checkSitekey() | 
| 177 { | 172 { | 
| 178   var attr = document.documentElement.getAttribute("data-adblockkey"); | 173   let attr = document.documentElement.getAttribute("data-adblockkey"); | 
| 179   if (attr) | 174   if (attr) | 
| 180     ext.backgroundPage.sendMessage({type: "filters.addKey", token: attr}); | 175     ext.backgroundPage.sendMessage({type: "filters.addKey", token: attr}); | 
| 181 } | 176 } | 
| 182 | 177 | 
| 183 function getContentDocument(element) | 178 function getContentDocument(element) | 
| 184 { | 179 { | 
| 185   try | 180   try | 
| 186   { | 181   { | 
| 187     return element.contentDocument; | 182     return element.contentDocument; | 
| 188   } | 183   } | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
| 201 | 196 | 
| 202   this.observer = new MutationObserver(this.observe.bind(this)); | 197   this.observer = new MutationObserver(this.observe.bind(this)); | 
| 203   this.trace = this.trace.bind(this); | 198   this.trace = this.trace.bind(this); | 
| 204 | 199 | 
| 205   if (document.readyState == "loading") | 200   if (document.readyState == "loading") | 
| 206     document.addEventListener("DOMContentLoaded", this.trace); | 201     document.addEventListener("DOMContentLoaded", this.trace); | 
| 207   else | 202   else | 
| 208     this.trace(); | 203     this.trace(); | 
| 209 } | 204 } | 
| 210 ElementHidingTracer.prototype = { | 205 ElementHidingTracer.prototype = { | 
| 211   checkNodes: function(nodes) | 206   checkNodes: nodes => | 
| 212   { | 207   { | 
| 213     var matchedSelectors = []; | 208     let matchedSelectors = []; | 
| 214 | 209 | 
| 215     // Find all selectors that match any hidden element inside the given nodes. | 210     // Find all selectors that match any hidden element inside the given nodes. | 
| 216     for (var i = 0; i < this.selectors.length; i++) | 211     for (let selector of this.selectors) | 
| 217     { | 212     { | 
| 218       var selector = this.selectors[i]; | 213       for (let node of nodes) | 
|  | 214       { | 
|  | 215         let elements = node.querySelectorAll(selector); | 
|  | 216         let matched = false; | 
| 219 | 217 | 
| 220       for (var j = 0; j < nodes.length; j++) | 218         for (let element of elements) | 
| 221       { |  | 
| 222         var elements = nodes[j].querySelectorAll(selector); |  | 
| 223         var matched = false; |  | 
| 224 |  | 
| 225         for (var k = 0; k < elements.length; k++) |  | 
| 226         { | 219         { | 
| 227           // Only consider selectors that actually have an effect on the | 220           // Only consider selectors that actually have an effect on the | 
| 228           // computed styles, and aren't overridden by rules with higher | 221           // computed styles, and aren't overridden by rules with higher | 
| 229           // priority, or haven't been circumvented in a different way. | 222           // priority, or haven't been circumvented in a different way. | 
| 230           if (getComputedStyle(elements[k]).display == "none") | 223           if (getComputedStyle(element).display == "none") | 
| 231           { | 224           { | 
| 232             matchedSelectors.push(selector); | 225             matchedSelectors.push(selector); | 
| 233             matched = true; | 226             matched = true; | 
| 234             break; | 227             break; | 
| 235           } | 228           } | 
| 236         } | 229         } | 
| 237 | 230 | 
| 238         if (matched) | 231         if (matched) | 
| 239           break; | 232           break; | 
| 240       } | 233       } | 
| 241     } | 234     } | 
| 242 | 235 | 
| 243     if (matchedSelectors.length > 0) | 236     if (matchedSelectors.length > 0) | 
| 244       ext.backgroundPage.sendMessage({ | 237       ext.backgroundPage.sendMessage({ | 
| 245         type: "devtools.traceElemHide", | 238         type: "devtools.traceElemHide", | 
| 246         selectors: matchedSelectors | 239         selectors: matchedSelectors | 
| 247       }); | 240       }); | 
| 248   }, | 241   }, | 
| 249 | 242 | 
| 250   onTimeout: function() | 243   onTimeout: function() | 
| 251   { | 244   { | 
| 252     this.checkNodes(this.changedNodes); | 245     this.checkNodes(this.changedNodes); | 
| 253     this.changedNodes = []; | 246     this.changedNodes = []; | 
| 254     this.timeout = null; | 247     this.timeout = null; | 
| 255   }, | 248   }, | 
| 256 | 249 | 
| 257   observe: function(mutations) | 250   observe: function(mutations) | 
| 258   { | 251   { | 
| 259     // Forget previously changed nodes that are no longer in the DOM. | 252     // Forget previously changed nodes that are no longer in the DOM. | 
| 260     for (var i = 0; i < this.changedNodes.length; i++) | 253     for (let i = 0; i < this.changedNodes.length; i++) | 
| 261     { | 254     { | 
| 262       if (!document.contains(this.changedNodes[i])) | 255       if (!document.contains(this.changedNodes[i])) | 
| 263         this.changedNodes.splice(i--, 1); | 256         this.changedNodes.splice(i--, 1); | 
| 264     } | 257     } | 
| 265 | 258 | 
| 266     for (var j = 0; j < mutations.length; j++) | 259     for (let mutation of mutations) | 
| 267     { | 260     { | 
| 268       var mutation = mutations[j]; | 261       let node = mutation.target; | 
| 269       var node = mutation.target; |  | 
| 270 | 262 | 
| 271       // Ignore mutations of nodes that aren't in the DOM anymore. | 263       // Ignore mutations of nodes that aren't in the DOM anymore. | 
| 272       if (!document.contains(node)) | 264       if (!document.contains(node)) | 
| 273         continue; | 265         continue; | 
| 274 | 266 | 
| 275       // Since querySelectorAll() doesn't consider the root itself | 267       // Since querySelectorAll() doesn't consider the root itself | 
| 276       // and since CSS selectors can also match siblings, we have | 268       // and since CSS selectors can also match siblings, we have | 
| 277       // to consider the parent node for attribute mutations. | 269       // to consider the parent node for attribute mutations. | 
| 278       if (mutation.type == "attributes") | 270       if (mutation.type == "attributes") | 
| 279         node = node.parentNode; | 271         node = node.parentNode; | 
| 280 | 272 | 
| 281       var addNode = true; | 273       let addNode = true; | 
| 282       for (var k = 0; k < this.changedNodes.length; k++) | 274       for (let i = 0; i < this.changedNodes.length; i++) | 
| 283       { | 275       { | 
| 284         var previouslyChangedNode = this.changedNodes[k]; | 276         let previouslyChangedNode = this.changedNodes[i]; | 
| 285 | 277 | 
| 286         // If we are already going to check an ancestor of this node, | 278         // If we are already going to check an ancestor of this node, | 
| 287         // we can ignore this node, since it will be considered anyway | 279         // we can ignore this node, since it will be considered anyway | 
| 288         // when checking one of its ancestors. | 280         // when checking one of its ancestors. | 
| 289         if (previouslyChangedNode.contains(node)) | 281         if (previouslyChangedNode.contains(node)) | 
| 290         { | 282         { | 
| 291           addNode = false; | 283           addNode = false; | 
| 292           break; | 284           break; | 
| 293         } | 285         } | 
| 294 | 286 | 
| 295         // If this node is an ancestor of a node that previously changed, | 287         // If this node is an ancestor of a node that previously changed, | 
| 296         // we can ignore that node, since it will be considered anyway | 288         // we can ignore that node, since it will be considered anyway | 
| 297         // when checking one of its ancestors. | 289         // when checking one of its ancestors. | 
| 298         if (node.contains(previouslyChangedNode)) | 290         if (node.contains(previouslyChangedNode)) | 
| 299           this.changedNodes.splice(k--, 1); | 291           this.changedNodes.splice(i--, 1); | 
| 300       } | 292       } | 
| 301 | 293 | 
| 302       if (addNode) | 294       if (addNode) | 
| 303         this.changedNodes.push(node); | 295         this.changedNodes.push(node); | 
| 304     } | 296     } | 
| 305 | 297 | 
| 306     // Check only nodes whose descendants have changed, and not more often | 298     // Check only nodes whose descendants have changed, and not more often | 
| 307     // than once a second. Otherwise large pages with a lot of DOM mutations | 299     // than once a second. Otherwise large pages with a lot of DOM mutations | 
| 308     // (like YouTube) freeze when the devtools panel is active. | 300     // (like YouTube) freeze when the devtools panel is active. | 
| 309     if (this.timeout == null) | 301     if (this.timeout == null) | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 327   disconnect: function() | 319   disconnect: function() | 
| 328   { | 320   { | 
| 329     document.removeEventListener("DOMContentLoaded", this.trace); | 321     document.removeEventListener("DOMContentLoaded", this.trace); | 
| 330     this.observer.disconnect(); | 322     this.observer.disconnect(); | 
| 331     clearTimeout(this.timeout); | 323     clearTimeout(this.timeout); | 
| 332   } | 324   } | 
| 333 }; | 325 }; | 
| 334 | 326 | 
| 335 function runInPageContext(fn, arg) | 327 function runInPageContext(fn, arg) | 
| 336 { | 328 { | 
| 337   var script = document.createElement("script"); | 329   let script = document.createElement("script"); | 
| 338   script.type = "application/javascript"; | 330   script.type = "application/javascript"; | 
| 339   script.async = false; | 331   script.async = false; | 
| 340   script.textContent = "(" + fn + ")(" + JSON.stringify(arg) + ");"; | 332   script.textContent = "(" + fn + ")(" + JSON.stringify(arg) + ");"; | 
| 341   document.documentElement.appendChild(script); | 333   document.documentElement.appendChild(script); | 
| 342   document.documentElement.removeChild(script); | 334   document.documentElement.removeChild(script); | 
| 343 } | 335 } | 
| 344 | 336 | 
| 345 // Chrome doesn't allow us to intercept WebSockets[1], and therefore | 337 // Chrome doesn't allow us to intercept WebSockets[1], and therefore | 
| 346 // some ad networks are misusing them as a way to serve adverts and circumvent | 338 // some ad networks are misusing them as a way to serve adverts and circumvent | 
| 347 // us. As a workaround we wrap WebSocket, preventing blocked WebSocket | 339 // us. As a workaround we wrap WebSocket, preventing blocked WebSocket | 
| 348 // connections from being opened. | 340 // connections from being opened. | 
| 349 // [1] - https://bugs.chromium.org/p/chromium/issues/detail?id=129353 | 341 // [1] - https://bugs.chromium.org/p/chromium/issues/detail?id=129353 | 
| 350 function wrapWebSocket() | 342 function wrapWebSocket() | 
| 351 { | 343 { | 
| 352   var eventName = "abpws-" + Math.random().toString(36).substr(2); | 344   let eventName = "abpws-" + Math.random().toString(36).substr(2); | 
| 353 | 345 | 
| 354   document.addEventListener(eventName, function(event) | 346   document.addEventListener(eventName, event => | 
| 355   { | 347   { | 
| 356     ext.backgroundPage.sendMessage({ | 348     ext.backgroundPage.sendMessage({ | 
| 357       type: "request.websocket", | 349       type: "request.websocket", | 
| 358       url: event.detail.url | 350       url: event.detail.url | 
| 359     }, function (block) | 351     }, block => | 
| 360     { | 352     { | 
| 361       document.dispatchEvent( | 353       document.dispatchEvent( | 
| 362         new CustomEvent(eventName + "-" + event.detail.url, {detail: block}) | 354         new CustomEvent(eventName + "-" + event.detail.url, {detail: block}) | 
| 363       ); | 355       ); | 
| 364     }); | 356     }); | 
| 365   }); | 357   }); | 
| 366 | 358 | 
| 367   runInPageContext(function(eventName) | 359   runInPageContext(eventName => | 
| 368   { | 360   { | 
| 369     // As far as possible we must track everything we use that could be | 361     // As far as possible we must track everything we use that could be | 
| 370     // sabotaged by the website later in order to circumvent us. | 362     // sabotaged by the website later in order to circumvent us. | 
| 371     var RealWebSocket = WebSocket; | 363     let RealWebSocket = WebSocket; | 
| 372     var closeWebSocket = Function.prototype.call.bind(RealWebSocket.prototype.cl
     ose); | 364     let closeWebSocket = Function.prototype.call.bind(RealWebSocket.prototype.cl
     ose); | 
| 373     var addEventListener = document.addEventListener.bind(document); | 365     let addEventListener = document.addEventListener.bind(document); | 
| 374     var removeEventListener = document.removeEventListener.bind(document); | 366     let removeEventListener = document.removeEventListener.bind(document); | 
| 375     var dispatchEvent = document.dispatchEvent.bind(document); | 367     let dispatchEvent = document.dispatchEvent.bind(document); | 
| 376     var CustomEvent = window.CustomEvent; | 368     let CustomEvent = window.CustomEvent; | 
| 377 | 369 | 
| 378     function checkRequest(url, callback) | 370     function checkRequest(url, callback) | 
| 379     { | 371     { | 
| 380       var incomingEventName = eventName + "-" + url; | 372       let incomingEventName = eventName + "-" + url; | 
| 381       function listener(event) | 373       function listener(event) | 
| 382       { | 374       { | 
| 383         callback(event.detail); | 375         callback(event.detail); | 
| 384         removeEventListener(incomingEventName, listener); | 376         removeEventListener(incomingEventName, listener); | 
| 385       } | 377       } | 
| 386       addEventListener(incomingEventName, listener); | 378       addEventListener(incomingEventName, listener); | 
| 387 | 379 | 
| 388       dispatchEvent(new CustomEvent(eventName, { | 380       dispatchEvent(new CustomEvent(eventName, { | 
| 389         detail: {url: url} | 381         detail: {url: url} | 
| 390       })); | 382       })); | 
| 391     } | 383     } | 
| 392 | 384 | 
| 393     function WrappedWebSocket(url) | 385     function WrappedWebSocket(url) | 
| 394     { | 386     { | 
| 395       // Throw correct exceptions if the constructor is used improperly. | 387       // Throw correct exceptions if the constructor is used improperly. | 
| 396       if (!(this instanceof WrappedWebSocket)) return RealWebSocket(); | 388       if (!(this instanceof WrappedWebSocket)) return RealWebSocket(); | 
| 397       if (arguments.length < 1) return new RealWebSocket(); | 389       if (arguments.length < 1) return new RealWebSocket(); | 
| 398 | 390 | 
| 399       var websocket; | 391       let websocket; | 
| 400       if (arguments.length == 1) | 392       if (arguments.length == 1) | 
| 401         websocket = new RealWebSocket(url); | 393         websocket = new RealWebSocket(url); | 
| 402       else | 394       else | 
| 403         websocket = new RealWebSocket(url, arguments[1]); | 395         websocket = new RealWebSocket(url, arguments[1]); | 
| 404 | 396 | 
| 405       checkRequest(websocket.url, function(blocked) | 397       checkRequest(websocket.url, blocked => | 
| 406       { | 398       { | 
| 407         if (blocked) | 399         if (blocked) | 
| 408           closeWebSocket(websocket); | 400           closeWebSocket(websocket); | 
| 409       }); | 401       }); | 
| 410 | 402 | 
| 411       return websocket; | 403       return websocket; | 
| 412     } | 404     } | 
| 413     WrappedWebSocket.prototype = RealWebSocket.prototype; | 405     WrappedWebSocket.prototype = RealWebSocket.prototype; | 
| 414     WebSocket = WrappedWebSocket.bind(); | 406     WebSocket = WrappedWebSocket.bind(); | 
| 415     Object.defineProperties(WebSocket, { | 407     Object.defineProperties(WebSocket, { | 
| 416       CONNECTING: {value: RealWebSocket.CONNECTING, enumerable: true}, | 408       CONNECTING: {value: RealWebSocket.CONNECTING, enumerable: true}, | 
| 417       OPEN: {value: RealWebSocket.OPEN, enumerable: true}, | 409       OPEN: {value: RealWebSocket.OPEN, enumerable: true}, | 
| 418       CLOSING: {value: RealWebSocket.CLOSING, enumerable: true}, | 410       CLOSING: {value: RealWebSocket.CLOSING, enumerable: true}, | 
| 419       CLOSED: {value: RealWebSocket.CLOSED, enumerable: true}, | 411       CLOSED: {value: RealWebSocket.CLOSED, enumerable: true}, | 
| 420       prototype: {value: RealWebSocket.prototype} | 412       prototype: {value: RealWebSocket.prototype} | 
| 421     }); | 413     }); | 
| 422 | 414 | 
| 423     RealWebSocket.prototype.constructor = WebSocket; | 415     RealWebSocket.prototype.constructor = WebSocket; | 
| 424   }, eventName); | 416   }, eventName); | 
| 425 } | 417 } | 
| 426 | 418 | 
| 427 function ElemHide() | 419 function ElemHide() | 
| 428 { | 420 { | 
| 429   this.shadow = this.createShadowTree(); | 421   this.shadow = this.createShadowTree(); | 
| 430   this.style = null; | 422   this.style = null; | 
| 431   this.tracer = null; | 423   this.tracer = null; | 
| 432 | 424 | 
| 433   this.elemHideEmulation = new ElemHideEmulation( | 425   this.elemHideEmulation = new ElemHideEmulation( | 
| 434     window, | 426     window, | 
| 435     function(callback) | 427     callback => | 
| 436     { | 428     { | 
| 437       ext.backgroundPage.sendMessage({ | 429       ext.backgroundPage.sendMessage({ | 
| 438         type: "filters.get", | 430         type: "filters.get", | 
| 439         what: "elemhideemulation" | 431         what: "elemhideemulation" | 
| 440       }, callback); | 432       }, callback); | 
| 441     }, | 433     }, | 
| 442     this.addSelectors.bind(this) | 434     this.addSelectors.bind(this) | 
| 443   ); | 435   ); | 
| 444 } | 436 } | 
| 445 ElemHide.prototype = { | 437 ElemHide.prototype = { | 
| 446   selectorGroupSize: 200, | 438   selectorGroupSize: 200, | 
| 447 | 439 | 
| 448   createShadowTree: function() | 440   createShadowTree: () => | 
| 449   { | 441   { | 
| 450     // Use Shadow DOM if available as to not mess with with web pages that | 442     // Use Shadow DOM if available as to not mess with with web pages that | 
| 451     // rely on the order of their own <style> tags (#309). However, creating | 443     // rely on the order of their own <style> tags (#309). However, creating | 
| 452     // a shadow root breaks running CSS transitions. So we have to create | 444     // a shadow root breaks running CSS transitions. So we have to create | 
| 453     // the shadow root before transistions might start (#452). | 445     // the shadow root before transistions might start (#452). | 
| 454     if (!("createShadowRoot" in document.documentElement)) | 446     if (!("createShadowRoot" in document.documentElement)) | 
| 455       return null; | 447       return null; | 
| 456 | 448 | 
| 457     // Using shadow DOM causes issues on some Google websites, | 449     // Using shadow DOM causes issues on some Google websites, | 
| 458     // including Google Docs, Gmail and Blogger (#1770, #2602, #2687). | 450     // including Google Docs, Gmail and Blogger (#1770, #2602, #2687). | 
| 459     if (/\.(?:google|blogger)\.com$/.test(document.domain)) | 451     if (/\.(?:google|blogger)\.com$/.test(document.domain)) | 
| 460       return null; | 452       return null; | 
| 461 | 453 | 
| 462     // Finally since some users have both AdBlock and Adblock Plus installed we | 454     // Finally since some users have both AdBlock and Adblock Plus installed we | 
| 463     // have to consider how the two extensions interact. For example we want to | 455     // have to consider how the two extensions interact. For example we want to | 
| 464     // avoid creating the shadowRoot twice. | 456     // avoid creating the shadowRoot twice. | 
| 465     var shadow = document.documentElement.shadowRoot || | 457     let shadow = document.documentElement.shadowRoot || | 
| 466                  document.documentElement.createShadowRoot(); | 458                  document.documentElement.createShadowRoot(); | 
| 467     shadow.appendChild(document.createElement("shadow")); | 459     shadow.appendChild(document.createElement("shadow")); | 
| 468 | 460 | 
| 469     // Stop the website from messing with our shadow root (#4191, #4298). | 461     // Stop the website from messing with our shadow root (#4191, #4298). | 
| 470     if ("shadowRoot" in Element.prototype) | 462     if ("shadowRoot" in Element.prototype) | 
| 471     { | 463     { | 
| 472       runInPageContext(function() | 464       runInPageContext(() => | 
| 473       { | 465       { | 
| 474         var ourShadowRoot = document.documentElement.shadowRoot; | 466         let ourShadowRoot = document.documentElement.shadowRoot; | 
| 475         if (!ourShadowRoot) | 467         if (!ourShadowRoot) | 
| 476           return; | 468           return; | 
| 477         var desc = Object.getOwnPropertyDescriptor(Element.prototype, "shadowRoo
     t"); | 469         let desc = Object.getOwnPropertyDescriptor(Element.prototype, "shadowRoo
     t"); | 
| 478         var shadowRoot = Function.prototype.call.bind(desc.get); | 470         let shadowRoot = Function.prototype.call.bind(desc.get); | 
| 479 | 471 | 
| 480         Object.defineProperty(Element.prototype, "shadowRoot", { | 472         Object.defineProperty(Element.prototype, "shadowRoot", { | 
| 481           configurable: true, enumerable: true, get: function() | 473           configurable: true, enumerable: true, get: function() | 
| 482           { | 474           { | 
| 483             var shadow = shadowRoot(this); | 475             let shadow = shadowRoot(this); | 
| 484             return shadow == ourShadowRoot ? null : shadow; | 476             return shadow == ourShadowRoot ? null : shadow; | 
| 485           } | 477           } | 
| 486         }); | 478         }); | 
| 487       }, null); | 479       }, null); | 
| 488     } | 480     } | 
| 489 | 481 | 
| 490     return shadow; | 482     return shadow; | 
| 491   }, | 483   }, | 
| 492 | 484 | 
| 493   addSelectors: function(selectors) | 485   addSelectors: function(selectors) | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 511       // <style> element to the shadow DOM. | 503       // <style> element to the shadow DOM. | 
| 512       if (!this.style.sheet) | 504       if (!this.style.sheet) | 
| 513         return; | 505         return; | 
| 514     } | 506     } | 
| 515 | 507 | 
| 516     // If using shadow DOM, we have to add the ::content pseudo-element | 508     // If using shadow DOM, we have to add the ::content pseudo-element | 
| 517     // before each selector, in order to match elements within the | 509     // before each selector, in order to match elements within the | 
| 518     // insertion point. | 510     // insertion point. | 
| 519     if (this.shadow) | 511     if (this.shadow) | 
| 520     { | 512     { | 
| 521       var preparedSelectors = []; | 513       let preparedSelectors = []; | 
| 522       for (var i = 0; i < selectors.length; i++) | 514       for (let selector of selectors) | 
| 523       { | 515       { | 
| 524         var subSelectors = splitSelector(selectors[i]); | 516         let subSelectors = splitSelector(selector); | 
| 525         for (var j = 0; j < subSelectors.length; j++) | 517         for (let subSelector of subSelectors) | 
| 526           preparedSelectors.push("::content " + subSelectors[j]); | 518           preparedSelectors.push("::content " + subSelector); | 
| 527       } | 519       } | 
| 528       selectors = preparedSelectors; | 520       selectors = preparedSelectors; | 
| 529     } | 521     } | 
| 530 | 522 | 
| 531     // Safari only allows 8192 primitive selectors to be injected at once[1], we | 523     // Safari only allows 8192 primitive selectors to be injected at once[1], we | 
| 532     // therefore chunk the inserted selectors into groups of 200 to be safe. | 524     // therefore chunk the inserted selectors into groups of 200 to be safe. | 
| 533     // (Chrome also has a limit, larger... but we're not certain exactly what it | 525     // (Chrome also has a limit, larger... but we're not certain exactly what it | 
| 534     //  is! Edge apparently has no such limit.) | 526     //  is! Edge apparently has no such limit.) | 
| 535     // [1] - https://github.com/WebKit/webkit/blob/1cb2227f6b2a1035f7bdc46e5ab69
     debb75fc1de/Source/WebCore/css/RuleSet.h#L68 | 527     // [1] - https://github.com/WebKit/webkit/blob/1cb2227f6b2a1035f7bdc46e5ab69
     debb75fc1de/Source/WebCore/css/RuleSet.h#L68 | 
| 536     for (var i = 0; i < selectors.length; i += this.selectorGroupSize) | 528     for (let i = 0; i < selectors.length; i += this.selectorGroupSize) | 
| 537     { | 529     { | 
| 538       var selector = selectors.slice(i, i + this.selectorGroupSize).join(", "); | 530       let selector = selectors.slice(i, i + this.selectorGroupSize).join(", "); | 
| 539       this.style.sheet.insertRule(selector + "{display: none !important;}", | 531       this.style.sheet.insertRule(selector + "{display: none !important;}", | 
| 540                                   this.style.sheet.cssRules.length); | 532                                   this.style.sheet.cssRules.length); | 
| 541     } | 533     } | 
| 542   }, | 534   }, | 
| 543 | 535 | 
| 544   apply: function() | 536   apply: function() | 
| 545   { | 537   { | 
| 546     var selectors = null; | 538     let selectors = null; | 
| 547     var elemHideEmulationLoaded = false; | 539     let elemHideEmulationLoaded = false; | 
| 548 | 540 | 
| 549     var checkLoaded = function() | 541     let checkLoaded = function() | 
| 550     { | 542     { | 
| 551       if (!selectors || !elemHideEmulationLoaded) | 543       if (!selectors || !elemHideEmulationLoaded) | 
| 552         return; | 544         return; | 
| 553 | 545 | 
| 554       if (this.tracer) | 546       if (this.tracer) | 
| 555         this.tracer.disconnect(); | 547         this.tracer.disconnect(); | 
| 556       this.tracer = null; | 548       this.tracer = null; | 
| 557 | 549 | 
| 558       if (this.style && this.style.parentElement) | 550       if (this.style && this.style.parentElement) | 
| 559         this.style.parentElement.removeChild(this.style); | 551         this.style.parentElement.removeChild(this.style); | 
| 560       this.style = null; | 552       this.style = null; | 
| 561 | 553 | 
| 562       this.addSelectors(selectors.selectors); | 554       this.addSelectors(selectors.selectors); | 
| 563       this.elemHideEmulation.apply(); | 555       this.elemHideEmulation.apply(); | 
| 564 | 556 | 
| 565       if (selectors.trace) | 557       if (selectors.trace) | 
| 566         this.tracer = new ElementHidingTracer(selectors.selectors); | 558         this.tracer = new ElementHidingTracer(selectors.selectors); | 
| 567     }.bind(this); | 559     }.bind(this); | 
| 568 | 560 | 
| 569     ext.backgroundPage.sendMessage({type: "get-selectors"}, function(response) | 561     ext.backgroundPage.sendMessage({type: "get-selectors"}, response => | 
| 570     { | 562     { | 
| 571       selectors = response; | 563       selectors = response; | 
| 572       checkLoaded(); | 564       checkLoaded(); | 
| 573     }); | 565     }); | 
| 574 | 566 | 
| 575     this.elemHideEmulation.load(function() | 567     this.elemHideEmulation.load(() => | 
| 576     { | 568     { | 
| 577       elemHideEmulationLoaded = true; | 569       elemHideEmulationLoaded = true; | 
| 578       checkLoaded(); | 570       checkLoaded(); | 
| 579     }); | 571     }); | 
| 580   } | 572   } | 
| 581 }; | 573 }; | 
| 582 | 574 | 
| 583 if (document instanceof HTMLDocument) | 575 if (document instanceof HTMLDocument) | 
| 584 { | 576 { | 
| 585   checkSitekey(); | 577   checkSitekey(); | 
| 586   wrapWebSocket(); | 578   wrapWebSocket(); | 
| 587 | 579 | 
| 588   var elemhide = new ElemHide(); | 580   let elemhide = new ElemHide(); | 
| 589   elemhide.apply(); | 581   elemhide.apply(); | 
| 590 | 582 | 
| 591   document.addEventListener("error", function(event) | 583   document.addEventListener("error", event => | 
| 592   { | 584   { | 
| 593     checkCollapse(event.target); | 585     checkCollapse(event.target); | 
| 594   }, true); | 586   }, true); | 
| 595 | 587 | 
| 596   document.addEventListener("load", function(event) | 588   document.addEventListener("load", event => | 
| 597   { | 589   { | 
| 598     var element = event.target; | 590     let element = event.target; | 
| 599     if (/^i?frame$/.test(element.localName)) | 591     if (/^i?frame$/.test(element.localName)) | 
| 600       checkCollapse(element); | 592       checkCollapse(element); | 
| 601   }, true); | 593   }, true); | 
| 602 } | 594 } | 
| OLD | NEW | 
|---|