Index: include.preload.js |
=================================================================== |
--- a/include.preload.js |
+++ b/include.preload.js |
@@ -180,6 +180,9 @@ |
function init(document) |
{ |
+ var shadow = null; |
+ var style = null; |
+ |
// Use Shadow DOM if available to don't mess with web pages that rely on |
// the order of their own <style> tags (#309). |
// |
@@ -188,57 +191,58 @@ |
// |
// Also, we can't use shadow DOM on Google Docs, since it breaks printing |
// there (#1770). |
- var shadow = null; |
if ("createShadowRoot" in document.documentElement && document.domain != "docs.google.com") |
{ |
shadow = document.documentElement.createShadowRoot(); |
shadow.appendChild(document.createElement("shadow")); |
} |
- // Sets the currently used CSS rules for elemhide filters |
- var setElemhideCSSRules = function(selectors) |
+ var hideElements = function(selectors) |
{ |
- if (selectors.length == 0) |
- return; |
- |
- var style = document.createElement("style"); |
- style.setAttribute("type", "text/css"); |
- |
- if (shadow) |
+ // 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. |
+ if (!style || !style.sheet) |
{ |
- shadow.appendChild(style); |
- selectors = convertSelectorsForShadowDOM(selectors); |
- } |
- else |
- { |
- // Try to insert the style into the <head> tag, inserting directly under the |
- // document root breaks dev tools functionality: |
- // http://code.google.com/p/chromium/issues/detail?id=178109 |
- (document.head || document.documentElement).appendChild(style); |
+ style = document.createElement("style"); |
+ (shadow || document.head || document.documentElement).appendChild(style); |
} |
- var setRules = function() |
+ // 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 (style.sheet) |
{ |
- // The sheet property might not exist yet if the |
- // <style> element was created for a sub frame |
- if (!style.sheet) |
- { |
- setTimeout(setRules, 0); |
- return; |
- } |
+ // If using shadow DOM, we have to add the ::content pseudo-element |
+ // before each selector, in order to match elements within the |
+ // insertion point. |
+ if (shadow) |
+ selectors = convertSelectorsForShadowDOM(selectors); |
- // WebKit apparently chokes when the selector list in a CSS rule is huge. |
- // So we split the elemhide selectors into groups. |
- for (var i = 0; selectors.length > 0; i++) |
+ // WebKit (and Blink?) apparently chokes when the selector list in a |
+ // CSS rule is huge. So we split the elemhide selectors into groups. |
+ while (selectors.length > 0) |
{ |
var selector = selectors.splice(0, SELECTOR_GROUP_SIZE).join(", "); |
- style.sheet.insertRule(selector + " { display: none !important; }", i); |
+ |
+ style.sheet.insertRule( |
+ selector + " { display: none !important; }", |
+ style.sheet.cssRules.length |
+ ); |
} |
- }; |
+ } |
+ }; |
- setRules(); |
- reinjectRulesWhenRemoved(document, style); |
- }; |
+ ext.backgroundPage.sendMessage({type: "get-selectors"}, function(selectors) |
+ { |
+ if (selectors.length > 0) |
+ { |
+ hideElements(selectors); |
+ reinjectRulesWhenRemoved(document, style); |
+ } |
+ }); |
document.addEventListener("error", function(event) |
{ |
@@ -265,11 +269,11 @@ |
} |
}, true); |
- ext.backgroundPage.sendMessage({type: "get-selectors"}, setElemhideCSSRules); |
+ return hideElements; |
} |
if (document instanceof HTMLDocument) |
{ |
checkSitekey(); |
- init(document); |
+ window.hideElements = init(document); |
} |