| 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 injectJS(f) | 
 |  354 { | 
 |  355   var args = JSON.stringify(Array.prototype.slice.call(arguments, 1)); | 
 |  356   args = args.substring(1, args.length - 1); | 
 |  357   var codeString = "(" + f.toString() + ")(" + args + ");"; | 
 |  358  | 
 |  359   var script = document.createElement("script"); | 
 |  360   script.async = false; | 
 |  361   script.textContent = codeString; | 
 |  362   document.documentElement.appendChild(script); | 
 |  363   document.documentElement.removeChild(script); | 
 |  364 } | 
 |  365  | 
|  352 function protectStyleSheet(document, style) |  366 function protectStyleSheet(document, style) | 
|  353 { |  367 { | 
|  354   var id = Math.random().toString(36).substr(2) |  | 
|  355   style.id = id; |  368   style.id = id; | 
|  356  |  369  | 
|  357   var code = [ |  370   var protector = function(id) | 
|  358     "(function()", |  371   { | 
|  359     "{", |  372     var style = document.getElementById(id) || | 
|  360     '  var style = document.getElementById("' + id + '") ||', |  373                 document.documentElement.shadowRoot.getElementById(id); | 
|  361     '              document.documentElement.shadowRoot.getElementById("' + id + 
     '");', |  374     style.removeAttribute("id"); | 
|  362     '  style.removeAttribute("id");' |  | 
|  363   ]; |  | 
|  364  |  375  | 
|  365   var disableables = ["style", "style.sheet"]; |  376     var i; | 
|  366   for (var i = 0; i < disableables.length; i++) |  377     var disableables = [style, style.sheet]; | 
 |  378     for (i = 0; i < disableables.length; i += 1) | 
 |  379       Object.defineProperty(disableables[i], "disabled", | 
 |  380                             {value: false, enumerable: true}); | 
 |  381  | 
 |  382     var methods = ["deleteRule", "removeRule"]; | 
 |  383     for (i = 0; i < methods.length; i += 1) | 
 |  384     { | 
 |  385       if (methods[i] in CSSStyleSheet.prototype) | 
 |  386       { | 
 |  387         (function(method) | 
 |  388         { | 
 |  389           var original = CSSStyleSheet.prototype[method]; | 
 |  390           CSSStyleSheet.prototype[method] = function(index) | 
 |  391           { | 
 |  392             if (this != style.sheet) | 
 |  393               original.call(this, index); | 
 |  394           }; | 
 |  395         }(methods[i])); | 
 |  396       } | 
 |  397     } | 
 |  398   }; | 
 |  399  | 
 |  400   injectJS(protector, id); | 
 |  401 } | 
 |  402  | 
 |  403 // Neither Chrome[1] nor Safari allow us to intercept WebSockets, and therefore | 
 |  404 // some ad networks are misusing them as a way to serve adverts and circumvent | 
 |  405 // us. As a workaround we wrap WebSocket, preventing blocked WebSocket | 
 |  406 // connections from being opened. | 
 |  407 // [1] - https://bugs.chromium.org/p/chromium/issues/detail?id=129353 | 
 |  408 function wrapWebSocket() | 
 |  409 { | 
 |  410   if (typeof WebSocket == "undefined") | 
 |  411     return; | 
 |  412  | 
 |  413   var eventName = "abpws-" + id; | 
 |  414  | 
 |  415   document.addEventListener(eventName, function(event) | 
|  367   { |  416   { | 
|  368     code.push("  Object.defineProperty(" + disableables[i] + ', "disabled", ' |  417     ext.backgroundPage.sendMessage({ | 
|  369                                          + "{value: false, enumerable: true});")
     ; |  418       type: "websocket-request", | 
 |  419       url: event.detail.url | 
 |  420     }, function (block) | 
 |  421     { | 
 |  422       document.dispatchEvent( | 
 |  423         new CustomEvent(eventName + "-" + event.detail.url, {detail: block}) | 
 |  424       ); | 
 |  425     }); | 
 |  426   }); | 
 |  427  | 
 |  428   function wrapper(eventName) | 
 |  429   { | 
 |  430     // As far as possible we must track everything we use that could be | 
 |  431     // sabotaged by the website later in order to circumvent us. | 
 |  432     var RealWebSocket = WebSocket; | 
 |  433     var closeWebSocket = RealWebSocket.prototype.close; | 
 |  434     var document = window.document; | 
 |  435     var addEventListener = document.addEventListener; | 
 |  436     var removeEventListener = document.removeEventListener; | 
 |  437     var dispatchEvent = document.dispatchEvent; | 
 |  438     var CustomEvent = window.CustomEvent; | 
 |  439     var boundCall = Function.prototype.call.bind(Function.prototype.call); | 
 |  440     var toString = Function.prototype.toString; | 
 |  441  | 
 |  442     function checkRequest(url, protocols, callback) | 
 |  443     { | 
 |  444       var incomingEventName = eventName + "-" + url; | 
 |  445       function listener(event) | 
 |  446       { | 
 |  447         callback(event.detail); | 
 |  448         boundCall(removeEventListener, document, incomingEventName, listener); | 
 |  449       } | 
 |  450       boundCall(addEventListener, document, incomingEventName, listener); | 
 |  451  | 
 |  452       boundCall(dispatchEvent, document, new CustomEvent(eventName, { | 
 |  453         detail: {url: url, protocols: protocols} | 
 |  454       })); | 
 |  455     } | 
 |  456  | 
 |  457     function wrappedToString() | 
 |  458     { | 
 |  459       if (this === WebSocket) | 
 |  460         return boundCall(toString, RealWebSocket); | 
 |  461       if (this === wrappedToString) | 
 |  462         return boundCall(toString, toString); | 
 |  463       return boundCall(toString, this); | 
 |  464     }; | 
 |  465     Function.prototype.toString = wrappedToString; | 
 |  466  | 
 |  467     WebSocket = function(url, protocols) | 
 |  468     { | 
 |  469       var websocket = new RealWebSocket(url, protocols); | 
 |  470  | 
 |  471       checkRequest(url, protocols, function(blocked) | 
 |  472       { | 
 |  473         if (blocked) | 
 |  474           boundCall(closeWebSocket, websocket); | 
 |  475       }); | 
 |  476  | 
 |  477       return websocket; | 
 |  478     }; | 
 |  479     Object.defineProperties(WebSocket, { | 
 |  480       CONNECTING: {value: 0, enumerable: true}, | 
 |  481       OPEN: {value: 1, enumerable: true}, | 
 |  482       CLOSING: {value: 2, enumerable: true}, | 
 |  483       CLOSED: {value: 3, enumerable: true} | 
 |  484     }); | 
 |  485     WebSocket.prototype = RealWebSocket.prototype; | 
 |  486     RealWebSocket.prototype.constructor = WebSocket; | 
|  370   } |  487   } | 
|  371  |  488  | 
|  372   var methods = ["deleteRule", "removeRule"]; |  489   injectJS(wrapper, eventName); | 
|  373   for (var j = 0; j < methods.length; j++) |  | 
|  374   { |  | 
|  375     var method = methods[j]; |  | 
|  376     if (method in CSSStyleSheet.prototype) |  | 
|  377     { |  | 
|  378       var origin = "CSSStyleSheet.prototype." + method; |  | 
|  379       code.push("  var " + method + " = " + origin + ";", |  | 
|  380                 "  " + origin + " = function(index)", |  | 
|  381                 "  {", |  | 
|  382                 "    if (this != style.sheet)", |  | 
|  383                 "      " + method + ".call(this, index);", |  | 
|  384                 "  }"); |  | 
|  385     } |  | 
|  386   } |  | 
|  387  |  | 
|  388   code.push("})();"); |  | 
|  389  |  | 
|  390   var script = document.createElement("script"); |  | 
|  391   script.async = false; |  | 
|  392   script.textContent = code.join("\n"); |  | 
|  393   document.documentElement.appendChild(script); |  | 
|  394   document.documentElement.removeChild(script); |  | 
|  395 } |  490 } | 
|  396  |  491  | 
|  397 function init(document) |  492 function init(document) | 
|  398 { |  493 { | 
|  399   var shadow = null; |  494   var shadow = null; | 
|  400   var style = null; |  495   var style = null; | 
|  401   var observer = null; |  496   var observer = null; | 
|  402   var tracer = null; |  497   var tracer = null; | 
|  403  |  498  | 
 |  499   wrapWebSocket(); | 
 |  500  | 
|  404   function getPropertyFilters(callback) |  501   function getPropertyFilters(callback) | 
|  405   { |  502   { | 
|  406     ext.backgroundPage.sendMessage({ |  503     ext.backgroundPage.sendMessage({ | 
|  407       type: "filters.get", |  504       type: "filters.get", | 
|  408       what: "cssproperties" |  505       what: "cssproperties" | 
|  409     }, callback); |  506     }, callback); | 
|  410   } |  507   } | 
|  411   var propertyFilters = new CSSPropertyFilters(window, getPropertyFilters, |  508   var propertyFilters = new CSSPropertyFilters(window, getPropertyFilters, | 
|  412                                                addElemHideSelectors); |  509                                                addElemHideSelectors); | 
|  413  |  510  | 
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  564   }, true); |  661   }, true); | 
|  565  |  662  | 
|  566   return updateStylesheet; |  663   return updateStylesheet; | 
|  567 } |  664 } | 
|  568  |  665  | 
|  569 if (document instanceof HTMLDocument) |  666 if (document instanceof HTMLDocument) | 
|  570 { |  667 { | 
|  571   checkSitekey(); |  668   checkSitekey(); | 
|  572   window.updateStylesheet = init(document); |  669   window.updateStylesheet = init(document); | 
|  573 } |  670 } | 
| OLD | NEW |