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

Unified Diff: include.preload.js

Issue 29575739: Issue 5864 - Remove previous style sheet before adding one (Closed) Base URL: https://hg.adblockplus.org/adblockpluschrome/
Patch Set: Create style sheet in include.preload.js Created Oct. 14, 2017, 11:36 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
@@ -337,20 +337,21 @@
this.observer.disconnect();
clearTimeout(this.timeout);
}
};
function ElemHide()
{
this.shadow = this.createShadowTree();
- this.style = null;
+ this.styles = new Map();
this.tracer = null;
- this.inject = true;
+ this.inline = true;
this.emulatedPatterns = null;
+ this.injectedStyleSheet = null;
this.elemHideEmulation = new ElemHideEmulation(
this.addSelectors.bind(this),
this.hideElements.bind(this)
);
}
ElemHide.prototype = {
selectorGroupSize: 200,
@@ -374,34 +375,69 @@
// avoid creating the shadowRoot twice.
let shadow = document.documentElement.shadowRoot ||
document.documentElement.createShadowRoot();
shadow.appendChild(document.createElement("shadow"));
return shadow;
},
- injectSelectors(selectors, filters)
+ createRule(selectors)
+ {
+ if (selectors.length == 0)
+ return null;
Sebastian Noack 2017/10/17 22:00:38 .sheet.insertRule() fails if we return null here.
Manish Jethani 2017/10/17 22:14:27 Yes, but we have the following code earlier in add
Sebastian Noack 2017/10/18 00:53:06 So this check is redundant here. It seems in the o
Manish Jethani 2017/10/18 01:48:37 We still need that check for this line of code in
Manish Jethani 2017/10/18 01:49:56 I mean the initial value of "this.injectedStyleShe
+
+ return selectors.join(", ") + "{display: none !important;}";
+ },
+
+ injectStyleSheet(styleSheet)
{
- if (!this.style)
+ if (styleSheet == this.injectedStyleSheet)
+ return;
+
+ chrome.runtime.sendMessage({
+ type: "elemhide.injectStyleSheet",
+ styleSheet,
+ oldStyleSheet: this.injectedStyleSheet
+ });
+
+ this.injectedStyleSheet = styleSheet;
+ },
+
+ addSelectorsInline(selectors, filters, groupName)
+ {
+ let style = this.styles.get(groupName);
+
+ if (style)
+ {
+ while (style.sheet.cssRules.length > 0)
+ style.sheet.deleteRule(0);
+ }
+
+ if (selectors.length == 0)
+ return;
+
+ if (!style)
{
// Create <style> element lazily, only if we add styles. Add it to
// the shadow DOM if possible. Otherwise fallback to the <head> or
// <html> element. If we have injected a style element before that
// has been removed (the sheet property is null), create a new one.
- this.style = document.createElement("style");
+ style = document.createElement("style");
(this.shadow || document.head ||
- document.documentElement).appendChild(this.style);
+ document.documentElement).appendChild(style);
// It can happen that the frame already navigated to a different
// document while we were waiting for the background page to respond.
// In that case the sheet property will stay null, after addind the
// <style> element to the shadow DOM.
- if (!this.style.sheet)
+ if (!style.sheet)
return;
+
+ this.styles.set(groupName, style);
}
// If using shadow DOM, we have to add the ::content pseudo-element
// before each selector, in order to match elements within the
// insertion point.
let preparedSelectors = [];
if (this.shadow)
{
@@ -419,48 +455,41 @@
// Safari only allows 8192 primitive selectors to be injected at once[1], we
// therefore chunk the inserted selectors into groups of 200 to be safe.
// (Chrome also has a limit, larger... but we're not certain exactly what it
// is! Edge apparently has no such limit.)
// [1] - https://github.com/WebKit/webkit/blob/1cb2227f6b2a1035f7bdc46e5ab69debb75fc1de/Source/WebCore/css/RuleSet.h#L68
for (let i = 0; i < preparedSelectors.length; i += this.selectorGroupSize)
{
- let selector = preparedSelectors.slice(
- i, i + this.selectorGroupSize
- ).join(", ");
- this.style.sheet.insertRule(selector + "{display: none !important;}",
- this.style.sheet.cssRules.length);
+ style.sheet.insertRule(
+ this.createRule(preparedSelectors.slice(i, i + this.selectorGroupSize)),
+ style.sheet.cssRules.length
+ );
}
},
addSelectors(selectors, filters)
{
- if (selectors.length == 0)
- return;
-
- if (this.inject)
+ if (this.inline)
{
// 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 chrome.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.injectSelectors(selectors, filters);
+ this.addSelectorsInline(selectors, filters, "emulated");
}
else
{
- chrome.runtime.sendMessage({
- type: "elemhide.injectSelectors",
- selectors
- });
+ this.injectStyleSheet(this.createRule(selectors));
}
if (this.tracer)
this.tracer.addSelectors(selectors, filters);
},
hideElements(elements, filters)
{
@@ -480,28 +509,25 @@
apply()
{
chrome.runtime.sendMessage({type: "elemhide.getSelectors"}, response =>
{
if (this.tracer)
this.tracer.disconnect();
this.tracer = null;
- if (this.style && this.style.parentElement)
- this.style.parentElement.removeChild(this.style);
- this.style = null;
Sebastian Noack 2017/10/17 22:00:38 What if the "Block element" dialog (from the brows
Manish Jethani 2017/10/17 22:14:27 No, now the removal of the previous style sheet is
Sebastian Noack 2017/10/18 00:53:07 Doesn't that cause ElemHideEmulation when adding s
Manish Jethani 2017/10/18 01:48:37 ElemHideEmulation styles are in this.styles.get("e
-
if (response.trace)
this.tracer = new ElementHidingTracer();
- this.inject = response.inject;
+ this.inline = response.inline;
- if (this.inject)
- this.addSelectors(response.selectors);
- else if (this.tracer)
+ if (this.inline)
+ this.addSelectorsInline(response.selectors);
+
+ if (this.tracer)
this.tracer.addSelectors(response.selectors);
this.elemHideEmulation.apply(response.emulatedPatterns);
});
}
};
if (document instanceof HTMLDocument)
« 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