| 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 MutationObserver = window.MutationObserver || window.WebKitMutationObserver; |   18 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver; | 
|   19 var SELECTOR_GROUP_SIZE = 200; |   19 var SELECTOR_GROUP_SIZE = 200; | 
 |   20 var id = Math.random().toString(36).substr(2); | 
|   20  |   21  | 
|   21 var typeMap = { |   22 var typeMap = { | 
|   22   "img": "IMAGE", |   23   "img": "IMAGE", | 
|   23   "input": "IMAGE", |   24   "input": "IMAGE", | 
|   24   "picture": "IMAGE", |   25   "picture": "IMAGE", | 
|   25   "audio": "MEDIA", |   26   "audio": "MEDIA", | 
|   26   "video": "MEDIA", |   27   "video": "MEDIA", | 
|   27   "frame": "SUBDOCUMENT", |   28   "frame": "SUBDOCUMENT", | 
|   28   "iframe": "SUBDOCUMENT", |   29   "iframe": "SUBDOCUMENT", | 
|   29   "object": "OBJECT", |   30   "object": "OBJECT", | 
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  342   var observer = new MutationObserver(function() |  343   var observer = new MutationObserver(function() | 
|  343   { |  344   { | 
|  344     if (style.parentNode != parentNode) |  345     if (style.parentNode != parentNode) | 
|  345       parentNode.appendChild(style); |  346       parentNode.appendChild(style); | 
|  346   }); |  347   }); | 
|  347  |  348  | 
|  348   observer.observe(parentNode, {childList: true}); |  349   observer.observe(parentNode, {childList: true}); | 
|  349   return observer; |  350   return observer; | 
|  350 } |  351 } | 
|  351  |  352  | 
 |  353 function runInPage(fn, arg) | 
 |  354 { | 
 |  355   var script = document.createElement("script"); | 
 |  356   script.type = "application/javascript"; | 
 |  357   script.async = false; | 
 |  358   script.textContent = "(" + fn + ")(" + JSON.stringify(arg) + ");"; | 
 |  359   document.documentElement.appendChild(script); | 
 |  360   document.documentElement.removeChild(script); | 
 |  361 } | 
 |  362  | 
|  352 function protectStyleSheet(document, style) |  363 function protectStyleSheet(document, style) | 
|  353 { |  364 { | 
|  354   var id = Math.random().toString(36).substr(2) |  | 
|  355   style.id = id; |  365   style.id = id; | 
|  356  |  366  | 
|  357   var code = [ |  367   runInPage(function(id) | 
|  358     "(function()", |  368   { | 
|  359     "{", |  369     var style = document.getElementById(id) || | 
|  360     '  var style = document.getElementById("' + id + '") ||', |  370                 document.documentElement.shadowRoot.getElementById(id); | 
|  361     '              document.documentElement.shadowRoot.getElementById("' + id + 
     '");', |  371     style.removeAttribute("id"); | 
|  362     '  style.removeAttribute("id");' |  | 
|  363   ]; |  | 
|  364  |  372  | 
|  365   var disableables = ["style", "style.sheet"]; |  373     var disableables = [style, style.sheet]; | 
|  366   for (var i = 0; i < disableables.length; i++) |  374     for (var i = 0; i < disableables.length; i++) | 
 |  375       Object.defineProperty(disableables[i], "disabled", | 
 |  376                             {value: false, enumerable: true}); | 
 |  377  | 
 |  378     ["deleteRule", "removeRule"].forEach(function(method) | 
 |  379     { | 
 |  380       var original = CSSStyleSheet.prototype[method]; | 
 |  381       CSSStyleSheet.prototype[method] = function(index) | 
 |  382       { | 
 |  383         if (this != style.sheet) | 
 |  384           original.call(this, index); | 
 |  385       }; | 
 |  386     }); | 
 |  387   }, id); | 
 |  388 } | 
 |  389  | 
 |  390 // Neither Chrome[1] nor Safari allow us to intercept WebSockets, and therefore | 
 |  391 // some ad networks are misusing them as a way to serve adverts and circumvent | 
 |  392 // us. As a workaround we wrap WebSocket, preventing blocked WebSocket | 
 |  393 // connections from being opened. | 
 |  394 // [1] - https://bugs.chromium.org/p/chromium/issues/detail?id=129353 | 
 |  395 function wrapWebSocket() | 
 |  396 { | 
 |  397   if (typeof WebSocket == "undefined") | 
 |  398     return; | 
 |  399  | 
 |  400   var eventName = "abpws-" + id; | 
 |  401  | 
 |  402   document.addEventListener(eventName, function(event) | 
|  367   { |  403   { | 
|  368     code.push("  Object.defineProperty(" + disableables[i] + ', "disabled", ' |  404     ext.backgroundPage.sendMessage({ | 
|  369                                          + "{value: false, enumerable: true});")
     ; |  405       type: "websocket-request", | 
|  370   } |  406       url: event.detail.url | 
 |  407     }, function (block) | 
 |  408     { | 
 |  409       document.dispatchEvent( | 
 |  410         new CustomEvent(eventName + "-" + event.detail.url, {detail: block}) | 
 |  411       ); | 
 |  412     }); | 
 |  413   }); | 
|  371  |  414  | 
|  372   var methods = ["deleteRule", "removeRule"]; |  415   runInPage(function(eventName) | 
|  373   for (var j = 0; j < methods.length; j++) |  | 
|  374   { |  416   { | 
|  375     var method = methods[j]; |  417     // As far as possible we must track everything we use that could be | 
|  376     if (method in CSSStyleSheet.prototype) |  418     // sabotaged by the website later in order to circumvent us. | 
 |  419     var RealWebSocket = WebSocket; | 
 |  420     var closeWebSocket = Function.prototype.call.bind(RealWebSocket.prototype.cl
     ose); | 
 |  421     var addEventListener = document.addEventListener.bind(document); | 
 |  422     var removeEventListener = document.removeEventListener.bind(document); | 
 |  423     var dispatchEvent = document.dispatchEvent.bind(document); | 
 |  424     var CustomEvent = window.CustomEvent; | 
 |  425  | 
 |  426     function checkRequest(url, callback) | 
|  377     { |  427     { | 
|  378       var origin = "CSSStyleSheet.prototype." + method; |  428       var incomingEventName = eventName + "-" + url; | 
|  379       code.push("  var " + method + " = " + origin + ";", |  429       function listener(event) | 
|  380                 "  " + origin + " = function(index)", |  430       { | 
|  381                 "  {", |  431         callback(event.detail); | 
|  382                 "    if (this != style.sheet)", |  432         removeEventListener(incomingEventName, listener); | 
|  383                 "      " + method + ".call(this, index);", |  433       } | 
|  384                 "  }"); |  434       addEventListener(incomingEventName, listener); | 
 |  435  | 
 |  436       dispatchEvent(new CustomEvent(eventName, { | 
 |  437         detail: {url: url} | 
 |  438       })); | 
|  385     } |  439     } | 
|  386   } |  | 
|  387  |  440  | 
|  388   code.push("})();"); |  441     WebSocket = function WrappedWebSocket(url, protocols) | 
 |  442     { | 
 |  443       // Throw correct exceptions if the constructor is used improperly. | 
 |  444       if (!(this instanceof WrappedWebSocket)) return RealWebSocket(); | 
 |  445       if (arguments.length < 1) return new RealWebSocket(); | 
|  389  |  446  | 
|  390   var script = document.createElement("script"); |  447       var websocket = new RealWebSocket(url, protocols); | 
|  391   script.async = false; |  448  | 
|  392   script.textContent = code.join("\n"); |  449       checkRequest(websocket.url, function(blocked) | 
|  393   document.documentElement.appendChild(script); |  450       { | 
|  394   document.documentElement.removeChild(script); |  451         if (blocked) | 
 |  452           closeWebSocket(websocket); | 
 |  453       }); | 
 |  454  | 
 |  455       return websocket; | 
 |  456     }.bind(); | 
 |  457  | 
 |  458     var properties = Object.getOwnPropertyNames(RealWebSocket); | 
 |  459     for (var i = 0; i < properties.length; i++) | 
 |  460     { | 
 |  461       var name = properties[i]; | 
 |  462       var desc = Object.getOwnPropertyDescriptor(RealWebSocket, name); | 
 |  463       Object.defineProperty(WebSocket, name, desc); | 
 |  464     } | 
 |  465  | 
 |  466     RealWebSocket.prototype.constructor = WebSocket; | 
 |  467   }, eventName); | 
|  395 } |  468 } | 
|  396  |  469  | 
|  397 function init(document) |  470 function init(document) | 
|  398 { |  471 { | 
|  399   var shadow = null; |  472   var shadow = null; | 
|  400   var style = null; |  473   var style = null; | 
|  401   var observer = null; |  474   var observer = null; | 
|  402   var tracer = null; |  475   var tracer = null; | 
|  403  |  476  | 
 |  477   wrapWebSocket(); | 
 |  478  | 
|  404   function getPropertyFilters(callback) |  479   function getPropertyFilters(callback) | 
|  405   { |  480   { | 
|  406     ext.backgroundPage.sendMessage({ |  481     ext.backgroundPage.sendMessage({ | 
|  407       type: "filters.get", |  482       type: "filters.get", | 
|  408       what: "cssproperties" |  483       what: "cssproperties" | 
|  409     }, callback); |  484     }, callback); | 
|  410   } |  485   } | 
|  411   var propertyFilters = new CSSPropertyFilters(window, getPropertyFilters, |  486   var propertyFilters = new CSSPropertyFilters(window, getPropertyFilters, | 
|  412                                                addElemHideSelectors); |  487                                                addElemHideSelectors); | 
|  413  |  488  | 
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  564   }, true); |  639   }, true); | 
|  565  |  640  | 
|  566   return updateStylesheet; |  641   return updateStylesheet; | 
|  567 } |  642 } | 
|  568  |  643  | 
|  569 if (document instanceof HTMLDocument) |  644 if (document instanceof HTMLDocument) | 
|  570 { |  645 { | 
|  571   checkSitekey(); |  646   checkSitekey(); | 
|  572   window.updateStylesheet = init(document); |  647   window.updateStylesheet = init(document); | 
|  573 } |  648 } | 
| OLD | NEW |