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

Unified Diff: lib/cssInjection.js

Issue 29717611: [on hold] Issue 6455 - Use tabs.removeCSS on Chromium Base URL: https://hg.adblockplus.org/adblockpluschrome/
Patch Set: Created March 8, 2018, 6 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 | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/cssInjection.js
===================================================================
--- a/lib/cssInjection.js
+++ b/lib/cssInjection.js
@@ -23,21 +23,17 @@
const {ElemHide} = require("elemHide");
const {ElemHideEmulation} = require("elemHideEmulation");
const {checkWhitelisted} = require("whitelisting");
const {extractHostFromFrame} = require("url");
const {port} = require("messaging");
const devtools = require("devtools");
const info = require("info");
-// Chromium's support for tabs.removeCSS is still a work in progress and the
-// API is likely to be different from Firefox's; for now we just don't use it
-// at all, even if it's available.
-// See https://crbug.com/608854
-const styleSheetRemovalSupported = info.platform == "gecko";
+const styleSheetRemovalSupported = "removeCSS" in browser.tabs;
const selectorGroupSize = 1024;
let userStyleSheetsSupported = true;
function* splitSelectors(selectors)
{
// Chromium's Blink engine supports only up to 8,192 simple selectors, and
@@ -112,31 +108,74 @@
if (!frame)
return false;
if (!frame.injectedStyleSheets)
frame.injectedStyleSheets = new Map();
let oldStyleSheet = frame.injectedStyleSheets.get(groupName);
+ // The behavior of tabs.insertCSS and tabs.removeCSS is different between
kzar 2018/03/19 18:42:49 Thanks for taking the time to write such a good co
+ // Firefox and Chromium. On Firefox, it is an error to inject a duplicate
+ // style sheet, whereas Chromium will happily inject the duplicate as a copy.
+ // tabs.removeCSS on Chromium will remove only the last injected copy.
+ //
// Ideally we would compare the old and new style sheets and skip this code
// if they're the same, but the old style sheet can be a leftover from a
// previous instance of the frame. We must add the new style sheet
// regardless.
-
- // Add the new style sheet first to keep previously hidden elements from
- // reappearing momentarily.
- if (styleSheet && !addStyleSheet(tabId, frameId, styleSheet))
- return false;
+ //
+ // We could simply remove the old style sheet first before we add the new
+ // one, but this may cause previously hidden elements to reappear
+ // momentarily. On the other hand, we cannot remove the old style sheet after
+ // we add the new one if they're exactly the same, because this would cause
+ // Firefox to remove its only copy; if we skip the removal, Chromium would
+ // end up with a duplicate copy!
+ //
+ // So: (1) we do not want to remove first to avoid flicker; (2) if the old
kzar 2018/03/19 18:42:49 I think this stanza can be removed.
+ // and new style sheets are identical, we do not want to remove on Firefox,
+ // but we do want to remove on Chromium.
+ //
+ // In order to resolve this conundrum without resorting to browser-specific
+ // code, we treat the different types of style sheets differently.
+ if (groupName == "standard")
kzar 2018/03/19 18:42:49 Perhaps the logic would be clearer something like
+ {
+ // Style sheets in the "standard" group are typically only added once and
kzar 2018/03/19 18:42:49 I think instead of saying 'the "standard" group' a
+ // never removed. In this case, it's OK to remove the old style sheet first
+ // and accept the flicker.
+ if (oldStyleSheet)
+ {
+ removeStyleSheet(tabId, frameId, oldStyleSheet);
- // Sometimes the old and new style sheets can be exactly the same. In such a
- // case, do not remove the "old" style sheet, because it is in fact the new
- // style sheet now.
- if (oldStyleSheet && oldStyleSheet != styleSheet)
- removeStyleSheet(tabId, frameId, oldStyleSheet);
+ // Delete the entry first, just in case style sheet injection below
+ // fails.
+ frame.injectedStyleSheets.delete(groupName);
+ }
+
+ if (styleSheet && !addStyleSheet(tabId, frameId, styleSheet))
+ return false;
+ }
+ else if (styleSheet != oldStyleSheet)
+ {
+ // Note that it is possible that the old and new style sheets are the same
+ // but the old one is really a leftover from a previous instance of the
+ // frame (i.e. it doesn't exist in the current instance of the frame). In
+ // this case we'll skip the addition of the new style sheet and ads will
+ // not get blocked. This would not be acceptable for style sheets in the
+ // "standard" group, but it's OK for other style sheets. Given the problems
+ // described above, this is the best tradeoff.
+
+ // Add the new style sheet first to keep previously hidden elements from
+ // reappearing momentarily.
+ if (styleSheet && !addStyleSheet(tabId, frameId, styleSheet))
+ return false;
+
+ if (oldStyleSheet)
+ removeStyleSheet(tabId, frameId, oldStyleSheet);
+ }
frame.injectedStyleSheets.set(groupName, styleSheet);
return true;
}
port.on("elemhide.getSelectors", (message, sender) =>
{
let selectors = [];
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld