| 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); | 
| } | 
|  |