Index: lib/cssInjection.js |
=================================================================== |
--- a/lib/cssInjection.js |
+++ b/lib/cssInjection.js |
@@ -25,33 +25,74 @@ |
const {checkWhitelisted} = require("whitelisting"); |
const {extractHostFromFrame} = require("url"); |
const {port} = require("messaging"); |
const devtools = require("devtools"); |
const userStyleSheetsSupported = "extensionTypes" in browser && |
"CSSOrigin" in browser.extensionTypes; |
-function hideElements(tabId, frameId, selectors) |
+function addStyleSheet(tabId, frameId, styleSheet) |
{ |
browser.tabs.insertCSS(tabId, { |
- code: selectors.join(", ") + "{display: none !important;}", |
+ code: styleSheet, |
cssOrigin: "user", |
frameId, |
matchAboutBlank: true, |
runAt: "document_start" |
}); |
} |
-port.on("elemhide.getSelectors", (msg, sender) => |
+function removeStyleSheet(tabId, frameId, styleSheet) |
+{ |
+ browser.tabs.removeCSS(tabId, { |
+ code: styleSheet, |
+ cssOrigin: "user", |
+ frameId, |
+ matchAboutBlank: true |
+ }); |
+} |
+ |
+function updateFrameStyles(tabId, frameId, selectors, groupName) |
+{ |
+ let styleSheet = null; |
+ if (selectors.length > 0) |
+ styleSheet = selectors.join(", ") + "{display: none !important;}"; |
+ |
+ let frame = ext.getFrame(tabId, frameId); |
+ if (!frame.injectedStyleSheets) |
+ frame.injectedStyleSheets = new Map(); |
+ |
+ let oldStyleSheet = frame.injectedStyleSheets.get(groupName); |
+ |
+ // 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); |
+ |
+ // 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); |
+ |
+ frame.injectedStyleSheets.set(groupName, styleSheet); |
+} |
+ |
+port.on("elemhide.getSelectors", (message, sender) => |
{ |
let selectors = []; |
let emulatedPatterns = []; |
let trace = devtools && devtools.hasPanel(sender.page); |
- let inject = !userStyleSheetsSupported; |
+ let inline = !userStyleSheetsSupported; |
if (!checkWhitelisted(sender.page, sender.frame, |
RegExpFilter.typeMap.DOCUMENT | |
RegExpFilter.typeMap.ELEMHIDE)) |
{ |
let hostname = extractHostFromFrame(sender.frame); |
let specificOnly = checkWhitelisted(sender.page, sender.frame, |
RegExpFilter.typeMap.GENERICHIDE); |
@@ -60,22 +101,23 @@ |
hostname, |
specificOnly ? ElemHide.SPECIFIC_ONLY : ElemHide.ALL_MATCHING |
); |
for (let filter of ElemHideEmulation.getRulesForDomain(hostname)) |
emulatedPatterns.push({selector: filter.selector, text: filter.text}); |
} |
- if (!inject && selectors.length > 0) |
- hideElements(sender.page.id, sender.frame.id, selectors); |
+ if (!inline) |
+ updateFrameStyles(sender.page.id, sender.frame.id, selectors); |
- let response = {trace, inject, emulatedPatterns}; |
- if (trace || inject) |
+ let response = {trace, inline, emulatedPatterns}; |
+ if (trace || inline) |
response.selectors = selectors; |
return response; |
}); |
-port.on("elemhide.injectSelectors", (msg, sender) => |
+port.on("elemhide.injectSelectors", (message, sender) => |
{ |
- hideElements(sender.page.id, sender.frame.id, msg.selectors); |
+ updateFrameStyles(sender.page.id, sender.frame.id, message.selectors, |
+ message.groupName); |
}); |