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

Side by Side Diff: include.preload.js

Issue 29723558: Issue 6482 - Use ES6 classes (Closed) Base URL: https://hg.adblockplus.org/adblockpluschrome/
Patch Set: Created March 15, 2018, 7:46 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
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-present eyeo GmbH 3 * Copyright (C) 2006-present 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 17 matching lines...) Expand all
28 ["input", "IMAGE"], 28 ["input", "IMAGE"],
29 ["picture", "IMAGE"], 29 ["picture", "IMAGE"],
30 ["audio", "MEDIA"], 30 ["audio", "MEDIA"],
31 ["video", "MEDIA"], 31 ["video", "MEDIA"],
32 ["frame", "SUBDOCUMENT"], 32 ["frame", "SUBDOCUMENT"],
33 ["iframe", "SUBDOCUMENT"], 33 ["iframe", "SUBDOCUMENT"],
34 ["object", "OBJECT"], 34 ["object", "OBJECT"],
35 ["embed", "OBJECT"] 35 ["embed", "OBJECT"]
36 ]); 36 ]);
37 37
38 const selectorGroupSize = 1024;
Manish Jethani 2018/03/15 07:54:10 There's no reason for this to be a member of ElemH
39
38 function getURLsFromObjectElement(element) 40 function getURLsFromObjectElement(element)
39 { 41 {
40 let url = element.getAttribute("data"); 42 let url = element.getAttribute("data");
41 if (url) 43 if (url)
42 return [url]; 44 return [url];
43 45
44 for (let child of element.children) 46 for (let child of element.children)
45 { 47 {
46 if (child.localName != "param") 48 if (child.localName != "param")
47 continue; 49 continue;
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 ); 185 );
184 } 186 }
185 187
186 function checkSitekey() 188 function checkSitekey()
187 { 189 {
188 let attr = document.documentElement.getAttribute("data-adblockkey"); 190 let attr = document.documentElement.getAttribute("data-adblockkey");
189 if (attr) 191 if (attr)
190 browser.runtime.sendMessage({type: "filters.addKey", token: attr}); 192 browser.runtime.sendMessage({type: "filters.addKey", token: attr});
191 } 193 }
192 194
193 function ElementHidingTracer() 195 class ElementHidingTracer
194 { 196 {
195 this.selectors = []; 197 constructor()
196 this.changedNodes = []; 198 {
197 this.timeout = null; 199 this.selectors = [];
198 this.observer = new MutationObserver(this.observe.bind(this)); 200 this.changedNodes = [];
199 this.trace = this.trace.bind(this); 201 this.timeout = null;
202 this.observer = new MutationObserver(this.observe.bind(this));
203 this.trace = this.trace.bind(this);
200 204
201 if (document.readyState == "loading") 205 if (document.readyState == "loading")
202 document.addEventListener("DOMContentLoaded", this.trace); 206 document.addEventListener("DOMContentLoaded", this.trace);
203 else 207 else
204 this.trace(); 208 this.trace();
205 } 209 }
206 ElementHidingTracer.prototype = { 210
207 addSelectors(selectors, filters) 211 addSelectors(selectors, filters)
208 { 212 {
209 let pairs = selectors.map((sel, i) => [sel, filters && filters[i]]); 213 let pairs = selectors.map((sel, i) => [sel, filters && filters[i]]);
210 214
211 if (document.readyState != "loading") 215 if (document.readyState != "loading")
212 this.checkNodes([document], pairs); 216 this.checkNodes([document], pairs);
213 217
214 this.selectors.push(...pairs); 218 this.selectors.push(...pairs);
215 }, 219 }
216 220
217 checkNodes(nodes, pairs) 221 checkNodes(nodes, pairs)
218 { 222 {
219 let selectors = []; 223 let selectors = [];
220 let filters = []; 224 let filters = [];
221 225
222 for (let [selector, filter] of pairs) 226 for (let [selector, filter] of pairs)
223 { 227 {
224 nodes: for (let node of nodes) 228 nodes: for (let node of nodes)
225 { 229 {
(...skipping 20 matching lines...) Expand all
246 } 250 }
247 } 251 }
248 252
249 if (selectors.length > 0 || filters.length > 0) 253 if (selectors.length > 0 || filters.length > 0)
250 { 254 {
251 browser.runtime.sendMessage({ 255 browser.runtime.sendMessage({
252 type: "devtools.traceElemHide", 256 type: "devtools.traceElemHide",
253 selectors, filters 257 selectors, filters
254 }); 258 });
255 } 259 }
256 }, 260 }
257 261
258 onTimeout() 262 onTimeout()
259 { 263 {
260 this.checkNodes(this.changedNodes, this.selectors); 264 this.checkNodes(this.changedNodes, this.selectors);
261 this.changedNodes = []; 265 this.changedNodes = [];
262 this.timeout = null; 266 this.timeout = null;
263 }, 267 }
264 268
265 observe(mutations) 269 observe(mutations)
266 { 270 {
267 // Forget previously changed nodes that are no longer in the DOM. 271 // Forget previously changed nodes that are no longer in the DOM.
268 for (let i = 0; i < this.changedNodes.length; i++) 272 for (let i = 0; i < this.changedNodes.length; i++)
269 { 273 {
270 if (!document.contains(this.changedNodes[i])) 274 if (!document.contains(this.changedNodes[i]))
271 this.changedNodes.splice(i--, 1); 275 this.changedNodes.splice(i--, 1);
272 } 276 }
273 277
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 312
309 if (addNode) 313 if (addNode)
310 this.changedNodes.push(node); 314 this.changedNodes.push(node);
311 } 315 }
312 316
313 // Check only nodes whose descendants have changed, and not more often 317 // Check only nodes whose descendants have changed, and not more often
314 // than once a second. Otherwise large pages with a lot of DOM mutations 318 // than once a second. Otherwise large pages with a lot of DOM mutations
315 // (like YouTube) freeze when the devtools panel is active. 319 // (like YouTube) freeze when the devtools panel is active.
316 if (this.timeout == null) 320 if (this.timeout == null)
317 this.timeout = setTimeout(this.onTimeout.bind(this), 1000); 321 this.timeout = setTimeout(this.onTimeout.bind(this), 1000);
318 }, 322 }
319 323
320 trace() 324 trace()
321 { 325 {
322 this.checkNodes([document], this.selectors); 326 this.checkNodes([document], this.selectors);
323 327
324 this.observer.observe( 328 this.observer.observe(
325 document, 329 document,
326 { 330 {
327 childList: true, 331 childList: true,
328 attributes: true, 332 attributes: true,
329 subtree: true 333 subtree: true
330 } 334 }
331 ); 335 );
332 }, 336 }
333 337
334 disconnect() 338 disconnect()
335 { 339 {
336 document.removeEventListener("DOMContentLoaded", this.trace); 340 document.removeEventListener("DOMContentLoaded", this.trace);
337 this.observer.disconnect(); 341 this.observer.disconnect();
338 clearTimeout(this.timeout); 342 clearTimeout(this.timeout);
339 } 343 }
340 }; 344 }
341 345
342 function ElemHide() 346 class ElemHide
343 { 347 {
344 this.shadow = this.createShadowTree(); 348 constructor()
345 this.styles = new Map(); 349 {
346 this.tracer = null; 350 this.shadow = this.createShadowTree();
347 this.inline = true; 351 this.styles = new Map();
348 this.inlineEmulated = true; 352 this.tracer = null;
353 this.inline = true;
354 this.inlineEmulated = true;
349 355
350 this.elemHideEmulation = new ElemHideEmulation( 356 this.elemHideEmulation = new ElemHideEmulation(
351 this.addSelectors.bind(this), 357 this.addSelectors.bind(this),
352 this.hideElements.bind(this) 358 this.hideElements.bind(this)
353 ); 359 );
354 } 360 }
355 ElemHide.prototype = {
356 selectorGroupSize: 1024,
357 361
358 createShadowTree() 362 createShadowTree()
359 { 363 {
360 // Use Shadow DOM if available as to not mess with with web pages that 364 // Use Shadow DOM if available as to not mess with with web pages that
361 // rely on the order of their own <style> tags (#309). However, creating 365 // rely on the order of their own <style> tags (#309). However, creating
362 // a shadow root breaks running CSS transitions. So we have to create 366 // a shadow root breaks running CSS transitions. So we have to create
363 // the shadow root before transistions might start (#452). 367 // the shadow root before transistions might start (#452).
364 if (!("createShadowRoot" in document.documentElement)) 368 if (!("createShadowRoot" in document.documentElement))
365 return null; 369 return null;
366 370
367 // Both Firefox and Chrome 66+ support user style sheets, so we can avoid 371 // Both Firefox and Chrome 66+ support user style sheets, so we can avoid
368 // creating an unnecessary shadow root on these platforms. 372 // creating an unnecessary shadow root on these platforms.
369 let match = /\bChrome\/(\d+)/.exec(navigator.userAgent); 373 let match = /\bChrome\/(\d+)/.exec(navigator.userAgent);
370 if (!match || match[1] >= 66) 374 if (!match || match[1] >= 66)
371 return null; 375 return null;
372 376
373 // Using shadow DOM causes issues on some Google websites, 377 // Using shadow DOM causes issues on some Google websites,
374 // including Google Docs, Gmail and Blogger (#1770, #2602, #2687). 378 // including Google Docs, Gmail and Blogger (#1770, #2602, #2687).
375 if (/\.(?:google|blogger)\.com$/.test(document.domain)) 379 if (/\.(?:google|blogger)\.com$/.test(document.domain))
376 return null; 380 return null;
377 381
378 // Finally since some users have both AdBlock and Adblock Plus installed we 382 // Finally since some users have both AdBlock and Adblock Plus installed we
379 // have to consider how the two extensions interact. For example we want to 383 // have to consider how the two extensions interact. For example we want to
380 // avoid creating the shadowRoot twice. 384 // avoid creating the shadowRoot twice.
381 let shadow = document.documentElement.shadowRoot || 385 let shadow = document.documentElement.shadowRoot ||
382 document.documentElement.createShadowRoot(); 386 document.documentElement.createShadowRoot();
383 shadow.appendChild(document.createElement("content")); 387 shadow.appendChild(document.createElement("content"));
384 388
385 return shadow; 389 return shadow;
386 }, 390 }
387 391
388 addSelectorsInline(selectors, groupName) 392 addSelectorsInline(selectors, groupName)
389 { 393 {
390 let style = this.styles.get(groupName); 394 let style = this.styles.get(groupName);
391 395
392 if (style) 396 if (style)
393 { 397 {
394 while (style.sheet.cssRules.length > 0) 398 while (style.sheet.cssRules.length > 0)
395 style.sheet.deleteRule(0); 399 style.sheet.deleteRule(0);
396 } 400 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 // even fewer compound selectors, in a rule. The exact number of selectors 444 // even fewer compound selectors, in a rule. The exact number of selectors
441 // that would work depends on their sizes (e.g. "#foo .bar" has a 445 // that would work depends on their sizes (e.g. "#foo .bar" has a
442 // size of 2). Since we don't know the sizes of the selectors here, we 446 // size of 2). Since we don't know the sizes of the selectors here, we
443 // simply split them into groups of 1,024, based on the reasonable 447 // simply split them into groups of 1,024, based on the reasonable
444 // assumption that the average selector won't have a size greater than 8. 448 // assumption that the average selector won't have a size greater than 8.
445 // The alternative would be to calculate the sizes of the selectors and 449 // The alternative would be to calculate the sizes of the selectors and
446 // divide them up accordingly, but this approach is more efficient and has 450 // divide them up accordingly, but this approach is more efficient and has
447 // worked well in practice. In theory this could still lead to some 451 // worked well in practice. In theory this could still lead to some
448 // selectors not working on Chromium, but it is highly unlikely. 452 // selectors not working on Chromium, but it is highly unlikely.
449 // See issue #6298 and https://crbug.com/804179 453 // See issue #6298 and https://crbug.com/804179
450 for (let i = 0; i < preparedSelectors.length; i += this.selectorGroupSize) 454 for (let i = 0; i < preparedSelectors.length; i += selectorGroupSize)
451 { 455 {
452 let selector = preparedSelectors.slice( 456 let selector = preparedSelectors.slice(
453 i, i + this.selectorGroupSize 457 i, i + selectorGroupSize
454 ).join(", "); 458 ).join(", ");
455 style.sheet.insertRule(selector + "{display: none !important;}", 459 style.sheet.insertRule(selector + "{display: none !important;}",
456 style.sheet.cssRules.length); 460 style.sheet.cssRules.length);
457 } 461 }
458 }, 462 }
459 463
460 addSelectors(selectors, filters) 464 addSelectors(selectors, filters)
461 { 465 {
462 if (this.inline || this.inlineEmulated) 466 if (this.inline || this.inlineEmulated)
463 { 467 {
464 // Insert the style rules inline if we have been instructed by the 468 // Insert the style rules inline if we have been instructed by the
465 // background page to do so. This is usually the case, except on platforms 469 // background page to do so. This is usually the case, except on platforms
466 // that do support user stylesheets via the browser.tabs.insertCSS API 470 // that do support user stylesheets via the browser.tabs.insertCSS API
467 // (Firefox 53 onwards for now and possibly Chrome in the near future). 471 // (Firefox 53 onwards for now and possibly Chrome in the near future).
468 // Once all supported platforms have implemented this API, we can remove 472 // Once all supported platforms have implemented this API, we can remove
469 // the code below. See issue #5090. 473 // the code below. See issue #5090.
470 // Related Chrome and Firefox issues: 474 // Related Chrome and Firefox issues:
471 // https://bugs.chromium.org/p/chromium/issues/detail?id=632009 475 // https://bugs.chromium.org/p/chromium/issues/detail?id=632009
472 // https://bugzilla.mozilla.org/show_bug.cgi?id=1310026 476 // https://bugzilla.mozilla.org/show_bug.cgi?id=1310026
473 this.addSelectorsInline(selectors, "emulated"); 477 this.addSelectorsInline(selectors, "emulated");
474 } 478 }
475 else 479 else
476 { 480 {
477 browser.runtime.sendMessage({ 481 browser.runtime.sendMessage({
478 type: "elemhide.injectSelectors", 482 type: "elemhide.injectSelectors",
479 selectors, 483 selectors,
480 groupName: "emulated" 484 groupName: "emulated"
481 }); 485 });
482 } 486 }
483 487
484 if (this.tracer) 488 if (this.tracer)
485 this.tracer.addSelectors(selectors, filters); 489 this.tracer.addSelectors(selectors, filters);
486 }, 490 }
487 491
488 hideElements(elements, filters) 492 hideElements(elements, filters)
489 { 493 {
490 for (let element of elements) 494 for (let element of elements)
491 hideElement(element); 495 hideElement(element);
492 496
493 if (this.tracer) 497 if (this.tracer)
494 { 498 {
495 browser.runtime.sendMessage({ 499 browser.runtime.sendMessage({
496 type: "devtools.traceElemHide", 500 type: "devtools.traceElemHide",
497 selectors: [], 501 selectors: [],
498 filters 502 filters
499 }); 503 });
500 } 504 }
501 }, 505 }
502 506
503 apply() 507 apply()
504 { 508 {
505 browser.runtime.sendMessage({type: "elemhide.getSelectors"}, response => 509 browser.runtime.sendMessage({type: "elemhide.getSelectors"}, response =>
506 { 510 {
507 if (this.tracer) 511 if (this.tracer)
508 this.tracer.disconnect(); 512 this.tracer.disconnect();
509 this.tracer = null; 513 this.tracer = null;
510 514
511 if (response.trace) 515 if (response.trace)
512 this.tracer = new ElementHidingTracer(); 516 this.tracer = new ElementHidingTracer();
513 517
514 this.inline = response.inline; 518 this.inline = response.inline;
515 this.inlineEmulated = !!response.inlineEmulated; 519 this.inlineEmulated = !!response.inlineEmulated;
516 520
517 if (this.inline) 521 if (this.inline)
518 this.addSelectorsInline(response.selectors, "standard"); 522 this.addSelectorsInline(response.selectors, "standard");
519 523
520 if (this.tracer) 524 if (this.tracer)
521 this.tracer.addSelectors(response.selectors); 525 this.tracer.addSelectors(response.selectors);
522 526
523 // Prefer CSS selectors for -abp-has and -abp-contains unless the 527 // Prefer CSS selectors for -abp-has and -abp-contains unless the
524 // background page has asked us to use inline styles. 528 // background page has asked us to use inline styles.
525 this.elemHideEmulation.useInlineStyles = this.inline || 529 this.elemHideEmulation.useInlineStyles = this.inline ||
526 this.inlineEmulated; 530 this.inlineEmulated;
527 531
528 this.elemHideEmulation.apply(response.emulatedPatterns); 532 this.elemHideEmulation.apply(response.emulatedPatterns);
529 }); 533 });
530 } 534 }
531 }; 535 }
532 536
533 if (document instanceof HTMLDocument) 537 if (document instanceof HTMLDocument)
534 { 538 {
535 checkSitekey(); 539 checkSitekey();
536 540
537 elemhide = new ElemHide(); 541 elemhide = new ElemHide();
538 elemhide.apply(); 542 elemhide.apply();
539 543
540 document.addEventListener("error", event => 544 document.addEventListener("error", event =>
541 { 545 {
542 checkCollapse(event.target); 546 checkCollapse(event.target);
543 }, true); 547 }, true);
544 548
545 document.addEventListener("load", event => 549 document.addEventListener("load", event =>
546 { 550 {
547 let element = event.target; 551 let element = event.target;
548 if (/^i?frame$/.test(element.localName)) 552 if (/^i?frame$/.test(element.localName))
549 checkCollapse(element); 553 checkCollapse(element);
550 }, true); 554 }, true);
551 } 555 }
552 556
553 window.checkCollapse = checkCollapse; 557 window.checkCollapse = checkCollapse;
554 window.elemhide = elemhide; 558 window.elemhide = elemhide;
555 window.typeMap = typeMap; 559 window.typeMap = typeMap;
556 window.getURLsFromElement = getURLsFromElement; 560 window.getURLsFromElement = getURLsFromElement;
OLDNEW

Powered by Google App Engine
This is Rietveld