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

Delta Between Two Patch Sets: include.preload.js

Issue 29401596: Issue 5094 - Implement support for :has() in chrome extension (Closed) Base URL: https://hg.adblockplus.org/adblockpluschrome/
Left Patch Set: Remove no longer needed code. Created April 7, 2017, 3:50 p.m.
Right Patch Set: Update dependencies to the latest. Created June 19, 2017, 2:12 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « dependencies ('k') | lib/filterValidation.js » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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-2017 eyeo GmbH 3 * Copyright (C) 2006-2017 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 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 { 122 {
123 if (/^(?!https?:)[\w-]+:/i.test(urls[i])) 123 if (/^(?!https?:)[\w-]+:/i.test(urls[i]))
124 urls.splice(i--, 1); 124 urls.splice(i--, 1);
125 } 125 }
126 126
127 return urls; 127 return urls;
128 } 128 }
129 129
130 function hideElement(element) 130 function hideElement(element)
131 { 131 {
132 function doHide(element) 132 function doHide(el)
133 { 133 {
134 let propertyName = "display"; 134 let propertyName = "display";
135 let propertyValue = "none"; 135 let propertyValue = "none";
136 if (element.localName == "frame") 136 if (el.localName == "frame")
137 { 137 {
138 propertyName = "visibility"; 138 propertyName = "visibility";
139 propertyValue = "hidden"; 139 propertyValue = "hidden";
140 } 140 }
141 141
142 if (element.style.getPropertyValue(propertyName) != propertyValue || 142 if (el.style.getPropertyValue(propertyName) != propertyValue ||
143 element.style.getPropertyPriority(propertyName) != "important") 143 el.style.getPropertyPriority(propertyName) != "important")
144 element.style.setProperty(propertyName, propertyValue, "important"); 144 el.style.setProperty(propertyName, propertyValue, "important");
145 } 145 }
146 146
147 doHide(element); 147 doHide(element);
148 148
149 new MutationObserver(doHide).observe( 149 new MutationObserver(doHide).observe(
150 element, { 150 element, {
151 attributes: true, 151 attributes: true,
152 attributeFilter: ["style"] 152 attributeFilter: ["style"]
153 } 153 }
154 ); 154 );
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 }, 331 },
332 332
333 disconnect() 333 disconnect()
334 { 334 {
335 document.removeEventListener("DOMContentLoaded", this.trace); 335 document.removeEventListener("DOMContentLoaded", this.trace);
336 this.observer.disconnect(); 336 this.observer.disconnect();
337 clearTimeout(this.timeout); 337 clearTimeout(this.timeout);
338 } 338 }
339 }; 339 };
340 340
341 function runInPageContext(fn, arg)
342 {
343 let script = document.createElement("script");
344 script.type = "application/javascript";
345 script.async = false;
346 script.textContent = "(" + fn + ")(" + JSON.stringify(arg) + ");";
347 document.documentElement.appendChild(script);
348 document.documentElement.removeChild(script);
349 }
350
351 // Before Chrome 58 the webRequest API didn't allow us to intercept
352 // WebSockets[1], and therefore some ad networks are misusing them as a way to
353 // serve adverts and circumvent us. As a workaround we wrap WebSocket,
354 // preventing blocked WebSocket connections from being opened.
355 // [1] - https://bugs.chromium.org/p/chromium/issues/detail?id=129353
356 function wrapWebSocket()
357 {
358 let randomEventName = "abpws-" + Math.random().toString(36).substr(2);
359
360 document.addEventListener(randomEventName, event =>
361 {
362 ext.backgroundPage.sendMessage({
363 type: "request.websocket",
364 url: event.detail.url
365 }, block =>
366 {
367 document.dispatchEvent(new CustomEvent(
368 randomEventName + "-" + event.detail.url, {detail: block}
369 ));
370 });
371 });
372
373 runInPageContext(eventName =>
374 {
375 // As far as possible we must track everything we use that could be
376 // sabotaged by the website later in order to circumvent us.
377 let RealWebSocket = WebSocket;
378 let RealCustomEvent = window.CustomEvent;
379 let closeWebSocket = Function.prototype.call.bind(
380 RealWebSocket.prototype.close
381 );
382 let addEventListener = document.addEventListener.bind(document);
383 let removeEventListener = document.removeEventListener.bind(document);
384 let dispatchEvent = document.dispatchEvent.bind(document);
385
386 function checkRequest(url, callback)
387 {
388 let incomingEventName = eventName + "-" + url;
389 function listener(event)
390 {
391 callback(event.detail);
392 removeEventListener(incomingEventName, listener);
393 }
394 addEventListener(incomingEventName, listener);
395
396 dispatchEvent(new RealCustomEvent(eventName, {detail: {url}}));
397 }
398
399 function WrappedWebSocket(url, ...args)
400 {
401 // Throw correct exceptions if the constructor is used improperly.
402 if (!(this instanceof WrappedWebSocket)) return RealWebSocket();
403 if (arguments.length < 1) return new RealWebSocket();
404
405 let websocket = new RealWebSocket(url, ...args);
406
407 checkRequest(websocket.url, blocked =>
408 {
409 if (blocked)
410 closeWebSocket(websocket);
411 });
412
413 return websocket;
414 }
415 WrappedWebSocket.prototype = RealWebSocket.prototype;
416 window.WebSocket = WrappedWebSocket.bind();
417 Object.defineProperties(WebSocket, {
418 CONNECTING: {value: RealWebSocket.CONNECTING, enumerable: true},
419 OPEN: {value: RealWebSocket.OPEN, enumerable: true},
420 CLOSING: {value: RealWebSocket.CLOSING, enumerable: true},
421 CLOSED: {value: RealWebSocket.CLOSED, enumerable: true},
422 prototype: {value: RealWebSocket.prototype}
423 });
424
425 RealWebSocket.prototype.constructor = WebSocket;
426 }, randomEventName);
427 }
428
429 function ElemHide() 341 function ElemHide()
430 { 342 {
431 this.shadow = this.createShadowTree(); 343 this.shadow = this.createShadowTree();
432 this.style = null; 344 this.style = null;
433 this.tracer = null; 345 this.tracer = null;
434 346
435 this.elemHideEmulation = new ElemHideEmulation( 347 this.elemHideEmulation = new ElemHideEmulation(
436 window, 348 window,
437 callback => 349 callback =>
438 { 350 {
(...skipping 23 matching lines...) Expand all
462 if (/\.(?:google|blogger)\.com$/.test(document.domain)) 374 if (/\.(?:google|blogger)\.com$/.test(document.domain))
463 return null; 375 return null;
464 376
465 // Finally since some users have both AdBlock and Adblock Plus installed we 377 // Finally since some users have both AdBlock and Adblock Plus installed we
466 // have to consider how the two extensions interact. For example we want to 378 // have to consider how the two extensions interact. For example we want to
467 // avoid creating the shadowRoot twice. 379 // avoid creating the shadowRoot twice.
468 let shadow = document.documentElement.shadowRoot || 380 let shadow = document.documentElement.shadowRoot ||
469 document.documentElement.createShadowRoot(); 381 document.documentElement.createShadowRoot();
470 shadow.appendChild(document.createElement("shadow")); 382 shadow.appendChild(document.createElement("shadow"));
471 383
472 // Stop the website from messing with our shadow root (#4191, #4298).
473 if ("shadowRoot" in Element.prototype)
474 {
475 runInPageContext(() =>
476 {
477 let ourShadowRoot = document.documentElement.shadowRoot;
478 if (!ourShadowRoot)
479 return;
480 let desc = Object.getOwnPropertyDescriptor(Element.prototype,
481 "shadowRoot");
482 let shadowRoot = Function.prototype.call.bind(desc.get);
483
484 Object.defineProperty(Element.prototype, "shadowRoot", {
485 configurable: true, enumerable: true, get()
486 {
487 let thisShadow = shadowRoot(this);
488 return thisShadow == ourShadowRoot ? null : thisShadow;
489 }
490 });
491 }, null);
492 }
493
494 return shadow; 384 return shadow;
495 }, 385 },
496 386
497 addSelectors(selectors, filters) 387 addSelectors(selectors, filters)
498 { 388 {
499 if (selectors.length == 0) 389 if (selectors.length == 0)
500 return; 390 return;
501 391
502 if (!this.style) 392 if (!this.style)
503 { 393 {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 if (this.tracer) 442 if (this.tracer)
553 this.tracer.addSelectors(selectors, filters); 443 this.tracer.addSelectors(selectors, filters);
554 }, 444 },
555 445
556 hideElements(elements, filters) 446 hideElements(elements, filters)
557 { 447 {
558 for (let element of elements) 448 for (let element of elements)
559 hideElement(element); 449 hideElement(element);
560 450
561 if (this.tracer) 451 if (this.tracer)
452 {
562 ext.backgroundPage.sendMessage({ 453 ext.backgroundPage.sendMessage({
563 type: "devtools.traceElemHide", 454 type: "devtools.traceElemHide",
564 selectors: [], 455 selectors: [],
565 filters 456 filters
566 }); 457 });
458 }
567 }, 459 },
568 460
569 apply() 461 apply()
570 { 462 {
571 ext.backgroundPage.sendMessage({type: "get-selectors"}, response => 463 ext.backgroundPage.sendMessage({type: "get-selectors"}, response =>
572 { 464 {
573 if (this.tracer) 465 if (this.tracer)
574 this.tracer.disconnect(); 466 this.tracer.disconnect();
575 this.tracer = null; 467 this.tracer = null;
576 468
577 if (this.style && this.style.parentElement) 469 if (this.style && this.style.parentElement)
578 this.style.parentElement.removeChild(this.style); 470 this.style.parentElement.removeChild(this.style);
579 this.style = null; 471 this.style = null;
580 472
581 if (response.trace) 473 if (response.trace)
582 this.tracer = new ElementHidingTracer(); 474 this.tracer = new ElementHidingTracer();
583 475
584 this.addSelectors(response.selectors); 476 this.addSelectors(response.selectors);
585 this.elemHideEmulation.apply(); 477 this.elemHideEmulation.apply();
586 }); 478 });
587 } 479 }
588 }; 480 };
589 481
590 if (document instanceof HTMLDocument) 482 if (document instanceof HTMLDocument)
591 { 483 {
592 checkSitekey(); 484 checkSitekey();
593 wrapWebSocket();
594 485
595 elemhide = new ElemHide(); 486 elemhide = new ElemHide();
596 elemhide.apply(); 487 elemhide.apply();
597 488
598 document.addEventListener("error", event => 489 document.addEventListener("error", event =>
599 { 490 {
600 checkCollapse(event.target); 491 checkCollapse(event.target);
601 }, true); 492 }, true);
602 493
603 document.addEventListener("load", event => 494 document.addEventListener("load", event =>
604 { 495 {
605 let element = event.target; 496 let element = event.target;
606 if (/^i?frame$/.test(element.localName)) 497 if (/^i?frame$/.test(element.localName))
607 checkCollapse(element); 498 checkCollapse(element);
608 }, true); 499 }, true);
609 } 500 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld