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

Side by Side Diff: include.preload.js

Issue 29670575: Issue 5899 - Use CSS attribute selectors for collapsing media elements (Closed) Base URL: https://hg.adblockplus.org/adblockpluschrome/
Patch Set: Check for "collapsing" group name Created March 2, 2018, 11:08 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
« no previous file with comments | « no previous file | lib/cssInjection.js » ('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-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 let collapsingSelectors = new Set();
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 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 123
122 for (let i = 0; i < urls.length; i++) 124 for (let i = 0; i < urls.length; i++)
123 { 125 {
124 if (/^(?!https?:)[\w-]+:/i.test(urls[i])) 126 if (/^(?!https?:)[\w-]+:/i.test(urls[i]))
125 urls.splice(i--, 1); 127 urls.splice(i--, 1);
126 } 128 }
127 129
128 return urls; 130 return urls;
129 } 131 }
130 132
133 function isCollapsibleMediaElement(element, mediatype)
134 {
135 if (mediatype != "MEDIA")
136 return false;
137
138 if (!element.getAttribute("src"))
139 return false;
140
141 for (let child of element.children)
142 {
143 // If the <video> or <audio> element contains any <source> or <track>
144 // children, we cannot address it in CSS by the source URL; in that case we
145 // don't "collapse" it using a CSS selector but rather hide it directly by
146 // setting the style="..." attribute.
147 if (["source", "track"].includes(child.localName))
kzar 2018/04/18 14:56:13 Nit: It seems kinda wasteful to create the array,
Manish Jethani 2018/04/19 21:57:20 Done.
148 return false;
149 }
150
151 return true;
152 }
153
154 function collapseMediaElement(element, srcValue)
155 {
156 if (!srcValue)
157 return;
158
159 let selector = element.localName + "[src=" + CSS.escape(srcValue) + "]";
160
161 // Adding selectors is expensive so do it only if we really have a new
162 // selector.
163 if (!collapsingSelectors.has(selector))
164 {
165 collapsingSelectors.add(selector);
166 elemhide.addSelectors([selector], null, "collapsing", true);
167 }
168 }
169
131 function hideElement(element) 170 function hideElement(element)
132 { 171 {
133 function doHide() 172 function doHide()
134 { 173 {
135 let propertyName = "display"; 174 let propertyName = "display";
136 let propertyValue = "none"; 175 let propertyValue = "none";
137 if (element.localName == "frame") 176 if (element.localName == "frame")
138 { 177 {
139 propertyName = "visibility"; 178 propertyName = "visibility";
140 propertyValue = "hidden"; 179 propertyValue = "hidden";
(...skipping 17 matching lines...) Expand all
158 function checkCollapse(element) 197 function checkCollapse(element)
159 { 198 {
160 let mediatype = typeMap.get(element.localName); 199 let mediatype = typeMap.get(element.localName);
161 if (!mediatype) 200 if (!mediatype)
162 return; 201 return;
163 202
164 let urls = getURLsFromElement(element); 203 let urls = getURLsFromElement(element);
165 if (urls.length == 0) 204 if (urls.length == 0)
166 return; 205 return;
167 206
207 let collapsibleMediaElement = isCollapsibleMediaElement(element, mediatype);
208
209 // Save the value of the src attribute because it can change between now and
210 // when we get the response from the background page.
211 let srcValue = collapsibleMediaElement ? element.getAttribute("src") : null;
212
168 browser.runtime.sendMessage( 213 browser.runtime.sendMessage(
169 { 214 {
170 type: "filters.collapse", 215 type: "filters.collapse",
171 urls, 216 urls,
172 mediatype, 217 mediatype,
173 baseURL: document.location.href 218 baseURL: document.location.href
174 }, 219 },
175
176 collapse => 220 collapse =>
177 { 221 {
178 if (collapse) 222 if (collapse)
179 { 223 {
180 hideElement(element); 224 if (collapsibleMediaElement)
225 collapseMediaElement(element, srcValue);
226 else
227 hideElement(element);
181 } 228 }
182 } 229 }
183 ); 230 );
184 } 231 }
185 232
186 function checkSitekey() 233 function checkSitekey()
187 { 234 {
188 let attr = document.documentElement.getAttribute("data-adblockkey"); 235 let attr = document.documentElement.getAttribute("data-adblockkey");
189 if (attr) 236 if (attr)
190 browser.runtime.sendMessage({type: "filters.addKey", token: attr}); 237 browser.runtime.sendMessage({type: "filters.addKey", token: attr});
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 // Finally since some users have both AdBlock and Adblock Plus installed we 420 // Finally since some users have both AdBlock and Adblock Plus installed we
374 // have to consider how the two extensions interact. For example we want to 421 // have to consider how the two extensions interact. For example we want to
375 // avoid creating the shadowRoot twice. 422 // avoid creating the shadowRoot twice.
376 let shadow = document.documentElement.shadowRoot || 423 let shadow = document.documentElement.shadowRoot ||
377 document.documentElement.createShadowRoot(); 424 document.documentElement.createShadowRoot();
378 shadow.appendChild(document.createElement("shadow")); 425 shadow.appendChild(document.createElement("shadow"));
379 426
380 return shadow; 427 return shadow;
381 }, 428 },
382 429
383 addSelectorsInline(selectors, groupName) 430 addSelectorsInline(selectors, groupName, appendOnly = false)
384 { 431 {
385 let style = this.styles.get(groupName); 432 let style = this.styles.get(groupName);
386 433
387 if (style) 434 if (style && !appendOnly)
388 { 435 {
389 while (style.sheet.cssRules.length > 0) 436 while (style.sheet.cssRules.length > 0)
390 style.sheet.deleteRule(0); 437 style.sheet.deleteRule(0);
391 } 438 }
392 439
393 if (selectors.length == 0) 440 if (selectors.length == 0)
394 return; 441 return;
395 442
396 if (!style) 443 if (!style)
397 { 444 {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 for (let i = 0; i < preparedSelectors.length; i += this.selectorGroupSize) 492 for (let i = 0; i < preparedSelectors.length; i += this.selectorGroupSize)
446 { 493 {
447 let selector = preparedSelectors.slice( 494 let selector = preparedSelectors.slice(
448 i, i + this.selectorGroupSize 495 i, i + this.selectorGroupSize
449 ).join(", "); 496 ).join(", ");
450 style.sheet.insertRule(selector + "{display: none !important;}", 497 style.sheet.insertRule(selector + "{display: none !important;}",
451 style.sheet.cssRules.length); 498 style.sheet.cssRules.length);
452 } 499 }
453 }, 500 },
454 501
455 addSelectors(selectors, filters) 502 addSelectors(selectors, filters, groupName = "emulated", appendOnly = false)
456 { 503 {
457 if (this.inline || this.inlineEmulated) 504 if (this.inline || this.inlineEmulated)
458 { 505 {
459 // Insert the style rules inline if we have been instructed by the 506 // Insert the style rules inline if we have been instructed by the
460 // background page to do so. This is usually the case, except on platforms 507 // background page to do so. This is usually the case, except on platforms
461 // that do support user stylesheets via the browser.tabs.insertCSS API 508 // that do support user stylesheets via the browser.tabs.insertCSS API
462 // (Firefox 53 onwards for now and possibly Chrome in the near future). 509 // (Firefox 53 onwards for now and possibly Chrome in the near future).
463 // Once all supported platforms have implemented this API, we can remove 510 // Once all supported platforms have implemented this API, we can remove
464 // the code below. See issue #5090. 511 // the code below. See issue #5090.
465 // Related Chrome and Firefox issues: 512 // Related Chrome and Firefox issues:
466 // https://bugs.chromium.org/p/chromium/issues/detail?id=632009 513 // https://bugs.chromium.org/p/chromium/issues/detail?id=632009
467 // https://bugzilla.mozilla.org/show_bug.cgi?id=1310026 514 // https://bugzilla.mozilla.org/show_bug.cgi?id=1310026
468 this.addSelectorsInline(selectors, "emulated"); 515 this.addSelectorsInline(selectors, groupName, appendOnly);
469 } 516 }
470 else 517 else
471 { 518 {
472 browser.runtime.sendMessage({ 519 browser.runtime.sendMessage({
473 type: "elemhide.injectSelectors", 520 type: "elemhide.injectSelectors",
474 selectors, 521 selectors,
475 groupName: "emulated" 522 groupName,
523 appendOnly
476 }); 524 });
477 } 525 }
478 526
479 if (this.tracer) 527 // Only trace selectors that are based directly on hiding filters
528 // (i.e. leave out collapsing selectors).
529 if (this.tracer && groupName != "collapsing")
480 this.tracer.addSelectors(selectors, filters); 530 this.tracer.addSelectors(selectors, filters);
481 }, 531 },
482 532
483 hideElements(elements, filters) 533 hideElements(elements, filters)
484 { 534 {
485 for (let element of elements) 535 for (let element of elements)
486 hideElement(element); 536 hideElement(element);
487 537
488 if (this.tracer) 538 if (this.tracer)
489 { 539 {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
537 let element = event.target; 587 let element = event.target;
538 if (/^i?frame$/.test(element.localName)) 588 if (/^i?frame$/.test(element.localName))
539 checkCollapse(element); 589 checkCollapse(element);
540 }, true); 590 }, true);
541 } 591 }
542 592
543 window.checkCollapse = checkCollapse; 593 window.checkCollapse = checkCollapse;
544 window.elemhide = elemhide; 594 window.elemhide = elemhide;
545 window.typeMap = typeMap; 595 window.typeMap = typeMap;
546 window.getURLsFromElement = getURLsFromElement; 596 window.getURLsFromElement = getURLsFromElement;
OLDNEW
« no previous file with comments | « no previous file | lib/cssInjection.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld