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

Unified Diff: include.preload.js

Issue 5666188336037888: Issue 581 - Fixed element hiding/collapsing in anonymous frames on Chrome (Closed)
Patch Set: Created May 30, 2014, 11:32 a.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: include.preload.js
===================================================================
--- a/include.preload.js
+++ b/include.preload.js
@@ -17,108 +17,6 @@
var SELECTOR_GROUP_SIZE = 20;
-// use Shadow DOM if available to don't mess with web pages that
-// rely on the order of their own <style> tags. However
-// the <shadow> element is broken in some Chrome 32 builds (#309)
-//
-// also Chrome 31-33 crashes in some situations on some pages when using
-// ShadowDOM, e.g. when pressing tab key on Wikipedia and Facebook (#498)
-//
-// also we must not create the shadow root in the response callback passed
-// to sendMessage(), otherwise Chrome breaks some websites (#450)
-var shadow = null;
-if ("webkitCreateShadowRoot" in document.documentElement && !/\bChrome\/3[1-3]\b/.test(navigator.userAgent))
-{
- shadow = document.documentElement.webkitCreateShadowRoot();
- shadow.appendChild(document.createElement("shadow"));
-}
-
-// Sets the currently used CSS rules for elemhide filters
-function setElemhideCSSRules(selectors)
-{
- if (selectors.length == 0)
- return;
-
- var style = document.createElement("style");
- style.setAttribute("type", "text/css");
-
- if (shadow)
- {
- shadow.appendChild(style);
-
- try
- {
- document.querySelector("::content");
-
- for (var i = 0; i < selectors.length; i++)
- selectors[i] = "::content " + selectors[i];
- }
- catch (e)
- {
- for (var i = 0; i < selectors.length; i++)
- selectors[i] = "::-webkit-distributed(" + selectors[i] + ")";
- }
- }
- 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);
- }
-
- // 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++)
- {
- var selector = selectors.splice(0, SELECTOR_GROUP_SIZE).join(", ");
- style.sheet.insertRule(selector + " { display: none !important; }", i);
- }
-}
-
-var typeMap = {
- "img": "IMAGE",
- "input": "IMAGE",
- "audio": "MEDIA",
- "video": "MEDIA",
- "frame": "SUBDOCUMENT",
- "iframe": "SUBDOCUMENT"
-};
-
-function checkCollapse(event)
-{
- var target = event.target;
- var tag = target.localName;
- var expectedEvent = (tag == "iframe" || tag == "frame" ? "load" : "error");
- if (tag in typeMap && event.type == expectedEvent)
- {
- // This element failed loading, did we block it?
- var url = target.src;
- if (!url)
- return;
-
- ext.backgroundPage.sendMessage(
- {
- type: "should-collapse",
- url: url,
- mediatype: typeMap[tag]
- },
-
- function(response)
- {
- if (response && target.parentNode)
- {
- // <frame> cannot be removed, doing that will mess up the frameset
- if (tag == "frame")
- target.style.setProperty("visibility", "hidden", "important");
- else
- target.style.setProperty("display", "none", "important");
- }
- }
- );
- }
-}
-
// Converts relative to absolute URL
// e.g.: foo.swf on http://example.com/whatever/bar.html
// -> http://example.com/whatever/foo.swf
@@ -145,24 +43,162 @@
return base[0] + url;
}
-function init()
+var typeMap = {
+ "img": "IMAGE",
+ "input": "IMAGE",
+ "audio": "MEDIA",
+ "video": "MEDIA",
+ "frame": "SUBDOCUMENT",
+ "iframe": "SUBDOCUMENT"
+};
+
+function checkCollapse(element)
Wladimir Palant 2014/05/30 11:45:17 Please move this function and the typeMap declarat
Sebastian Noack 2014/05/30 12:31:11 Done.
{
- // Make sure this is really an HTML page, as Chrome runs these scripts on just about everything
- if (!(document.documentElement instanceof HTMLElement))
- return;
+ var tag = element.localName;
+ if (tag in typeMap)
+ {
+ // This element failed loading, did we block it?
+ var url = element.src;
+ if (!url)
+ return;
- document.addEventListener("error", checkCollapse, true);
- document.addEventListener("load", checkCollapse, true);
+ ext.backgroundPage.sendMessage(
+ {
+ type: "should-collapse",
+ url: url,
+ mediatype: typeMap[tag]
+ },
+ function(response)
+ {
+ if (response && element.parentNode)
+ {
+ // <frame> cannot be removed, doing that will mess up the frameset
+ if (tag == "frame")
+ element.style.setProperty("visibility", "hidden", "important");
+ else
+ element.style.setProperty("display", "none", "important");
+ }
+ }
+ );
+ }
+}
+
+function checkExcpetionKey()
Wladimir Palant 2014/05/30 11:45:17 Excpetion => Exception
Sebastian Noack 2014/05/30 12:31:11 Done.
+{
var attr = document.documentElement.getAttribute("data-adblockkey");
if (attr)
ext.backgroundPage.sendMessage({type: "add-key-exception", token: attr});
+}
+
+function init(document)
+{
+ // use Shadow DOM if available to don't mess with web pages that
+ // rely on the order of their own <style> tags. However
+ // the <shadow> element is broken in some Chrome 32 builds (#309)
+ //
+ // also Chrome 31-33 crashes in some situations on some pages when using
+ // ShadowDOM, e.g. when pressing tab key on Wikipedia and Facebook (#498)
+ //
+ // also we must not create the shadow root in the response callback passed
+ // to sendMessage(), otherwise Chrome breaks some websites (#450)
+ var shadow = null;
+ if ("webkitCreateShadowRoot" in document.documentElement && !/\bChrome\/3[1-3]\b/.test(navigator.userAgent))
+ {
+ shadow = document.documentElement.webkitCreateShadowRoot();
+ shadow.appendChild(document.createElement("shadow"));
+ }
+
+ // Sets the currently used CSS rules for elemhide filters
+ var setElemhideCSSRules = function(selectors)
+ {
+ if (selectors.length == 0)
+ return;
+
+ var style = document.createElement("style");
+ style.setAttribute("type", "text/css");
+
+ if (shadow)
+ {
+ shadow.appendChild(style);
+
+ try
+ {
+ document.querySelector("::content");
+
+ for (var i = 0; i < selectors.length; i++)
+ selectors[i] = "::content " + selectors[i];
+ }
+ catch (e)
+ {
+ for (var i = 0; i < selectors.length; i++)
+ selectors[i] = "::-webkit-distributed(" + selectors[i] + ")";
+ }
+ }
+ 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);
+ }
+
+ var setRules = function()
+ {
+ // The sheet property might not exist yet if the
+ // <style> element was created for a sub frame
+ if (!style.sheet)
+ {
+ setTimeout(setRules, 0);
+ return;
+ }
+
+ // 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++)
+ {
+ var selector = selectors.splice(0, SELECTOR_GROUP_SIZE).join(", ");
+ style.sheet.insertRule(selector + " { display: none !important; }", i);
+ }
+ };
+
+ setRules();
+ };
+
+ document.addEventListener("error", function(event)
+ {
+ checkCollapse(event.target);
+ }, true);
+
+ document.addEventListener("load", function(event)
+ {
+ if (/^i?frame$/.test(event.target.localName))
+ {
+ checkCollapse(event.target);
+
+ // Chrome doesn't run our content script on anonymous frames.
+ // So we have to apply element hiding and collapsing from the
+ // parent frame, when an anonymous sub frame loaded.
+ if (/^(javascript:|$)/.test(event.target.src) && /\bChrome\//.test(navigator.userAgent))
+ {
+ var contentDocument = event.target.contentDocument;
+
+ if (contentDocument.documentElement instanceof HTMLElement)
+ {
+ init(contentDocument);
+
+ for (tagName in typeMap)
+ Array.prototype.forEach.call(contentDocument.getElementsByTagName(tagName), checkCollapse);
+ }
+ }
+ }
+ }, true);
ext.backgroundPage.sendMessage({type: "get-selectors"}, setElemhideCSSRules);
}
-// In Chrome 18 the document might not be initialized yet
-if (document.documentElement)
- init();
-else
- window.setTimeout(init, 0);
+if (document.documentElement instanceof HTMLElement)
Wladimir Palant 2014/05/30 11:45:17 Why did you remove the failsafe? It was added back
Sebastian Noack 2014/05/30 12:31:11 I tested in Chrome 34 and Chrome 30, and it seems
+{
+ checkExcpetionKey();
+ init(document);
Wladimir Palant 2014/05/30 11:45:17 Why pass in the document which is a global variabl
Sebastian Noack 2014/05/30 12:31:11 It is not always called with the global document.
+}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld