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

Unified 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: Compare child name directly Created April 19, 2018, 9:56 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | lib/cssInjection.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: include.preload.js
===================================================================
--- a/include.preload.js
+++ b/include.preload.js
@@ -31,16 +31,18 @@
["audio", "MEDIA"],
["video", "MEDIA"],
["frame", "SUBDOCUMENT"],
["iframe", "SUBDOCUMENT"],
["object", "OBJECT"],
["embed", "OBJECT"]
]);
+let collapsingSelectors = new Set();
+
function getURLsFromObjectElement(element)
{
let url = element.getAttribute("data");
if (url)
return [url];
for (let child of element.children)
{
@@ -124,16 +126,53 @@
{
if (/^(?!https?:)[\w-]+:/i.test(urls[i]))
urls.splice(i--, 1);
}
return urls;
}
+function isCollapsibleMediaElement(element, mediatype)
+{
+ if (mediatype != "MEDIA")
+ return false;
+
+ if (!element.getAttribute("src"))
+ return false;
+
+ for (let child of element.children)
+ {
+ // If the <video> or <audio> element contains any <source> or <track>
+ // children, we cannot address it in CSS by the source URL; in that case we
+ // don't "collapse" it using a CSS selector but rather hide it directly by
+ // setting the style="..." attribute.
+ if (child.localName == "source" || child.localName == "track")
+ return false;
+ }
+
+ return true;
+}
+
+function collapseMediaElement(element, srcValue)
+{
+ if (!srcValue)
+ return;
+
+ let selector = element.localName + "[src=" + CSS.escape(srcValue) + "]";
+
+ // Adding selectors is expensive so do it only if we really have a new
+ // selector.
+ if (!collapsingSelectors.has(selector))
+ {
+ collapsingSelectors.add(selector);
+ elemhide.addSelectors([selector], null, "collapsing", true);
+ }
+}
+
function hideElement(element)
{
function doHide()
{
let propertyName = "display";
let propertyValue = "none";
if (element.localName == "frame")
{
@@ -161,29 +200,37 @@
let mediatype = typeMap.get(element.localName);
if (!mediatype)
return;
let urls = getURLsFromElement(element);
if (urls.length == 0)
return;
+ let collapsibleMediaElement = isCollapsibleMediaElement(element, mediatype);
+
+ // Save the value of the src attribute because it can change between now and
+ // when we get the response from the background page.
+ let srcValue = collapsibleMediaElement ? element.getAttribute("src") : null;
+
browser.runtime.sendMessage(
{
type: "filters.collapse",
urls,
mediatype,
baseURL: document.location.href
},
-
collapse =>
{
if (collapse)
{
- hideElement(element);
+ if (collapsibleMediaElement)
+ collapseMediaElement(element, srcValue);
+ else
+ hideElement(element);
}
}
);
}
function checkSitekey()
{
let attr = document.documentElement.getAttribute("data-adblockkey");
@@ -381,21 +428,21 @@
// avoid creating the shadowRoot twice.
let shadow = document.documentElement.shadowRoot ||
document.documentElement.createShadowRoot();
shadow.appendChild(document.createElement("content"));
return shadow;
},
- addSelectorsInline(selectors, groupName)
+ addSelectorsInline(selectors, groupName, appendOnly = false)
{
let style = this.styles.get(groupName);
- if (style)
+ if (style && !appendOnly)
{
while (style.sheet.cssRules.length > 0)
style.sheet.deleteRule(0);
}
if (selectors.length == 0)
return;
@@ -453,41 +500,44 @@
let selector = preparedSelectors.slice(
i, i + this.selectorGroupSize
).join(", ");
style.sheet.insertRule(selector + "{display: none !important;}",
style.sheet.cssRules.length);
}
},
- addSelectors(selectors, filters)
+ addSelectors(selectors, filters, groupName = "emulated", appendOnly = false)
{
if (this.inline || this.inlineEmulated)
{
// Insert the style rules inline if we have been instructed by the
// background page to do so. This is usually the case, except on platforms
// that do support user stylesheets via the browser.tabs.insertCSS API
// (Firefox 53 onwards for now and possibly Chrome in the near future).
// Once all supported platforms have implemented this API, we can remove
// the code below. See issue #5090.
// Related Chrome and Firefox issues:
// https://bugs.chromium.org/p/chromium/issues/detail?id=632009
// https://bugzilla.mozilla.org/show_bug.cgi?id=1310026
- this.addSelectorsInline(selectors, "emulated");
+ this.addSelectorsInline(selectors, groupName, appendOnly);
}
else
{
browser.runtime.sendMessage({
type: "elemhide.injectSelectors",
selectors,
- groupName: "emulated"
+ groupName,
+ appendOnly
});
}
- if (this.tracer)
+ // Only trace selectors that are based directly on hiding filters
+ // (i.e. leave out collapsing selectors).
+ if (this.tracer && groupName != "collapsing")
this.tracer.addSelectors(selectors, filters);
},
hideElements(elements, filters)
{
for (let element of elements)
hideElement(element);
« 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