Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: include.preload.js

Issue 29350213: Issue 4364 - Drop support for Chrome 29-40 and remove legacy code (Closed)
Patch Set: Created Aug. 25, 2016, 3:09 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/ext/background.js ('k') | metadata.chrome » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 try 189 try
190 { 190 {
191 return element.contentDocument; 191 return element.contentDocument;
192 } 192 }
193 catch (e) 193 catch (e)
194 { 194 {
195 return null; 195 return null;
196 } 196 }
197 } 197 }
198 198
199 function ElementHidingTracer(document, selectors) 199 function ElementHidingTracer(selectors)
200 { 200 {
201 this.document = document;
202 this.selectors = selectors; 201 this.selectors = selectors;
203 202
204 this.changedNodes = []; 203 this.changedNodes = [];
205 this.timeout = null; 204 this.timeout = null;
206 205
207 this.observer = new MutationObserver(this.observe.bind(this)); 206 this.observer = new MutationObserver(this.observe.bind(this));
208 this.trace = this.trace.bind(this); 207 this.trace = this.trace.bind(this);
209 208
210 if (document.readyState == "loading") 209 if (document.readyState == "loading")
211 document.addEventListener("DOMContentLoaded", this.trace); 210 document.addEventListener("DOMContentLoaded", this.trace);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 this.checkNodes(this.changedNodes); 256 this.checkNodes(this.changedNodes);
258 this.changedNodes = []; 257 this.changedNodes = [];
259 this.timeout = null; 258 this.timeout = null;
260 }, 259 },
261 260
262 observe: function(mutations) 261 observe: function(mutations)
263 { 262 {
264 // Forget previously changed nodes that are no longer in the DOM. 263 // Forget previously changed nodes that are no longer in the DOM.
265 for (var i = 0; i < this.changedNodes.length; i++) 264 for (var i = 0; i < this.changedNodes.length; i++)
266 { 265 {
267 if (!this.document.contains(this.changedNodes[i])) 266 if (!document.contains(this.changedNodes[i]))
268 this.changedNodes.splice(i--, 1); 267 this.changedNodes.splice(i--, 1);
269 } 268 }
270 269
271 for (var j = 0; j < mutations.length; j++) 270 for (var j = 0; j < mutations.length; j++)
272 { 271 {
273 var mutation = mutations[j]; 272 var mutation = mutations[j];
274 var node = mutation.target; 273 var node = mutation.target;
275 274
276 // Ignore mutations of nodes that aren't in the DOM anymore. 275 // Ignore mutations of nodes that aren't in the DOM anymore.
277 if (!this.document.contains(node)) 276 if (!document.contains(node))
278 continue; 277 continue;
279 278
280 // Since querySelectorAll() doesn't consider the root itself 279 // Since querySelectorAll() doesn't consider the root itself
281 // and since CSS selectors can also match siblings, we have 280 // and since CSS selectors can also match siblings, we have
282 // to consider the parent node for attribute mutations. 281 // to consider the parent node for attribute mutations.
283 if (mutation.type == "attributes") 282 if (mutation.type == "attributes")
284 node = node.parentNode; 283 node = node.parentNode;
285 284
286 var addNode = true; 285 var addNode = true;
287 for (var k = 0; k < this.changedNodes.length; k++) 286 for (var k = 0; k < this.changedNodes.length; k++)
(...skipping 22 matching lines...) Expand all
310 309
311 // Check only nodes whose descendants have changed, and not more often 310 // Check only nodes whose descendants have changed, and not more often
312 // than once a second. Otherwise large pages with a lot of DOM mutations 311 // than once a second. Otherwise large pages with a lot of DOM mutations
313 // (like YouTube) freeze when the devtools panel is active. 312 // (like YouTube) freeze when the devtools panel is active.
314 if (this.timeout == null) 313 if (this.timeout == null)
315 this.timeout = setTimeout(this.onTimeout.bind(this), 1000); 314 this.timeout = setTimeout(this.onTimeout.bind(this), 1000);
316 }, 315 },
317 316
318 trace: function() 317 trace: function()
319 { 318 {
320 this.checkNodes([this.document]); 319 this.checkNodes([document]);
321 320
322 this.observer.observe( 321 this.observer.observe(
323 this.document, 322 document,
324 { 323 {
325 childList: true, 324 childList: true,
326 attributes: true, 325 attributes: true,
327 subtree: true 326 subtree: true
328 } 327 }
329 ); 328 );
330 }, 329 },
331 330
332 disconnect: function() 331 disconnect: function()
333 { 332 {
334 this.document.removeEventListener("DOMContentLoaded", this.trace); 333 document.removeEventListener("DOMContentLoaded", this.trace);
335 this.observer.disconnect(); 334 this.observer.disconnect();
336 clearTimeout(this.timeout); 335 clearTimeout(this.timeout);
337 } 336 }
338 }; 337 };
339 338
340 function runInDocument(document, fn, arg) 339 function runInDocument(fn, arg)
341 { 340 {
342 var script = document.createElement("script"); 341 var script = document.createElement("script");
343 script.type = "application/javascript"; 342 script.type = "application/javascript";
344 script.async = false; 343 script.async = false;
345 script.textContent = "(" + fn + ")(" + JSON.stringify(arg) + ");"; 344 script.textContent = "(" + fn + ")(" + JSON.stringify(arg) + ");";
346 document.documentElement.appendChild(script); 345 document.documentElement.appendChild(script);
347 document.documentElement.removeChild(script); 346 document.documentElement.removeChild(script);
348 } 347 }
349 348
350 // Neither Chrome[1] nor Safari allow us to intercept WebSockets, and therefore 349 // Neither Chrome[1] nor Safari allow us to intercept WebSockets, and therefore
351 // some ad networks are misusing them as a way to serve adverts and circumvent 350 // some ad networks are misusing them as a way to serve adverts and circumvent
352 // us. As a workaround we wrap WebSocket, preventing blocked WebSocket 351 // us. As a workaround we wrap WebSocket, preventing blocked WebSocket
353 // connections from being opened. 352 // connections from being opened.
354 // [1] - https://bugs.chromium.org/p/chromium/issues/detail?id=129353 353 // [1] - https://bugs.chromium.org/p/chromium/issues/detail?id=129353
355 function wrapWebSocket(document) 354 function wrapWebSocket()
356 { 355 {
357 if (typeof WebSocket == "undefined") 356 if (typeof WebSocket == "undefined")
358 return; 357 return;
359 358
360 var eventName = "abpws-" + Math.random().toString(36).substr(2); 359 var eventName = "abpws-" + Math.random().toString(36).substr(2);
361 360
362 document.addEventListener(eventName, function(event) 361 document.addEventListener(eventName, function(event)
363 { 362 {
364 ext.backgroundPage.sendMessage({ 363 ext.backgroundPage.sendMessage({
365 type: "request.websocket", 364 type: "request.websocket",
366 url: event.detail.url 365 url: event.detail.url
367 }, function (block) 366 }, function (block)
368 { 367 {
369 document.dispatchEvent( 368 document.dispatchEvent(
370 new CustomEvent(eventName + "-" + event.detail.url, {detail: block}) 369 new CustomEvent(eventName + "-" + event.detail.url, {detail: block})
371 ); 370 );
372 }); 371 });
373 }); 372 });
374 373
375 runInDocument(document, function(eventName) 374 runInDocument(function(eventName)
376 { 375 {
377 // As far as possible we must track everything we use that could be 376 // As far as possible we must track everything we use that could be
378 // sabotaged by the website later in order to circumvent us. 377 // sabotaged by the website later in order to circumvent us.
379 var RealWebSocket = WebSocket; 378 var RealWebSocket = WebSocket;
380 var closeWebSocket = Function.prototype.call.bind(RealWebSocket.prototype.cl ose); 379 var closeWebSocket = Function.prototype.call.bind(RealWebSocket.prototype.cl ose);
381 var addEventListener = document.addEventListener.bind(document); 380 var addEventListener = document.addEventListener.bind(document);
382 var removeEventListener = document.removeEventListener.bind(document); 381 var removeEventListener = document.removeEventListener.bind(document);
383 var dispatchEvent = document.dispatchEvent.bind(document); 382 var dispatchEvent = document.dispatchEvent.bind(document);
384 var CustomEvent = window.CustomEvent; 383 var CustomEvent = window.CustomEvent;
385 384
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 OPEN: {value: RealWebSocket.OPEN, enumerable: true}, 424 OPEN: {value: RealWebSocket.OPEN, enumerable: true},
426 CLOSING: {value: RealWebSocket.CLOSING, enumerable: true}, 425 CLOSING: {value: RealWebSocket.CLOSING, enumerable: true},
427 CLOSED: {value: RealWebSocket.CLOSED, enumerable: true}, 426 CLOSED: {value: RealWebSocket.CLOSED, enumerable: true},
428 prototype: {value: RealWebSocket.prototype} 427 prototype: {value: RealWebSocket.prototype}
429 }); 428 });
430 429
431 RealWebSocket.prototype.constructor = WebSocket; 430 RealWebSocket.prototype.constructor = WebSocket;
432 }, eventName); 431 }, eventName);
433 } 432 }
434 433
435 function init(document) 434 function init()
436 { 435 {
437 var shadow = null; 436 var shadow = null;
438 var style = null; 437 var style = null;
439 var observer = null; 438 var observer = null;
440 var tracer = null; 439 var tracer = null;
441 440
442 wrapWebSocket(document); 441 wrapWebSocket();
443 442
444 function getPropertyFilters(callback) 443 function getPropertyFilters(callback)
445 { 444 {
446 ext.backgroundPage.sendMessage({ 445 ext.backgroundPage.sendMessage({
447 type: "filters.get", 446 type: "filters.get",
448 what: "cssproperties" 447 what: "cssproperties"
449 }, callback); 448 }, callback);
450 } 449 }
451 var propertyFilters = new CSSPropertyFilters(window, getPropertyFilters, 450 var propertyFilters = new CSSPropertyFilters(window, getPropertyFilters,
452 addElemHideSelectors); 451 addElemHideSelectors);
453 452
454 // Use Shadow DOM if available to don't mess with web pages that rely on 453 // Use Shadow DOM if available to don't mess with web pages that rely on
455 // the order of their own <style> tags (#309). 454 // the order of their own <style> tags (#309).
456 // 455 //
457 // However, creating a shadow root breaks running CSS transitions. So we 456 // However, creating a shadow root breaks running CSS transitions. So we
458 // have to create the shadow root before transistions might start (#452). 457 // have to create the shadow root before transistions might start (#452).
459 // 458 //
460 // Also, using shadow DOM causes issues on some Google websites, 459 // Also, using shadow DOM causes issues on some Google websites,
461 // including Google Docs, Gmail and Blogger (#1770, #2602, #2687). 460 // including Google Docs, Gmail and Blogger (#1770, #2602, #2687).
462 if ("createShadowRoot" in document.documentElement && 461 if ("createShadowRoot" in document.documentElement &&
463 !/\.(?:google|blogger)\.com$/.test(document.domain)) 462 !/\.(?:google|blogger)\.com$/.test(document.domain))
464 { 463 {
465 shadow = document.documentElement.createShadowRoot(); 464 shadow = document.documentElement.createShadowRoot();
466 shadow.appendChild(document.createElement("shadow")); 465 shadow.appendChild(document.createElement("shadow"));
467 466
468 // Stop the website from messing with our shadowRoot 467 // Stop the website from messing with our shadowRoot
469 if ("shadowRoot" in Element.prototype) 468 if ("shadowRoot" in Element.prototype)
470 { 469 {
471 runInDocument(document, function() 470 runInDocument(function()
472 { 471 {
473 var ourShadowRoot = document.documentElement.shadowRoot; 472 var ourShadowRoot = document.documentElement.shadowRoot;
474 var desc = Object.getOwnPropertyDescriptor(Element.prototype, "shadowRoo t"); 473 var desc = Object.getOwnPropertyDescriptor(Element.prototype, "shadowRoo t");
475 var shadowRoot = Function.prototype.call.bind(desc.get); 474 var shadowRoot = Function.prototype.call.bind(desc.get);
476 475
477 Object.defineProperty(Element.prototype, "shadowRoot", { 476 Object.defineProperty(Element.prototype, "shadowRoot", {
478 configurable: true, enumerable: true, get: function() 477 configurable: true, enumerable: true, get: function()
479 { 478 {
480 var shadow = shadowRoot(this); 479 var shadow = shadowRoot(this);
481 return shadow == ourShadowRoot ? null : shadow; 480 return shadow == ourShadowRoot ? null : shadow;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 tracer = null; 552 tracer = null;
554 553
555 if (style && style.parentElement) 554 if (style && style.parentElement)
556 style.parentElement.removeChild(style); 555 style.parentElement.removeChild(style);
557 style = null; 556 style = null;
558 557
559 addElemHideSelectors(selectors.selectors); 558 addElemHideSelectors(selectors.selectors);
560 propertyFilters.apply(); 559 propertyFilters.apply();
561 560
562 if (selectors.trace) 561 if (selectors.trace)
563 tracer = new ElementHidingTracer(document, selectors.selectors); 562 tracer = new ElementHidingTracer(selectors.selectors);
564 }; 563 };
565 564
566 ext.backgroundPage.sendMessage({type: "get-selectors"}, function(response) 565 ext.backgroundPage.sendMessage({type: "get-selectors"}, function(response)
567 { 566 {
568 selectors = response; 567 selectors = response;
569 checkLoaded(); 568 checkLoaded();
570 }); 569 });
571 570
572 propertyFilters.load(function() 571 propertyFilters.load(function()
573 { 572 {
574 CSSPropertyFiltersLoaded = true; 573 CSSPropertyFiltersLoaded = true;
575 checkLoaded(); 574 checkLoaded();
576 }); 575 });
577 }; 576 };
578 577
579 updateStylesheet(); 578 updateStylesheet();
580 579
581 document.addEventListener("error", function(event) 580 document.addEventListener("error", function(event)
582 { 581 {
583 checkCollapse(event.target); 582 checkCollapse(event.target);
584 }, true); 583 }, true);
585 584
586 document.addEventListener("load", function(event) 585 document.addEventListener("load", function(event)
587 { 586 {
588 var element = event.target; 587 var element = event.target;
589
590 if (/^i?frame$/.test(element.localName)) 588 if (/^i?frame$/.test(element.localName))
591 checkCollapse(element); 589 checkCollapse(element);
592
593 if (/\bChrome\//.test(navigator.userAgent))
594 {
595 var contentDocument = getContentDocument(element);
596 if (contentDocument)
597 {
598 var contentWindow = contentDocument.defaultView;
599 if (contentDocument instanceof contentWindow.HTMLDocument)
600 {
601 // Prior to Chrome 37, content scripts cannot run in
602 // dynamically created frames. Also on Chrome 37-40
603 // document_start content scripts (like this one) don't
604 // run either in those frames due to https://crbug.com/416907.
605 // So we have to apply element hiding from the parent frame.
606 if (!("init" in contentWindow))
607 init(contentDocument);
608 }
609 }
610 }
611 }, true); 590 }, true);
612 591
613 return updateStylesheet; 592 return updateStylesheet;
614 } 593 }
615 594
616 if (document instanceof HTMLDocument) 595 if (document instanceof HTMLDocument)
617 { 596 {
618 checkSitekey(); 597 checkSitekey();
619 window.updateStylesheet = init(document); 598 window.updateStylesheet = init();
620 } 599 }
OLDNEW
« no previous file with comments | « chrome/ext/background.js ('k') | metadata.chrome » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld