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

Unified Diff: include.postload.js

Issue 5225119261655040: Issue 1282 - Don't generate filters conflicting with existing exception rules (Closed)
Patch Set: Created Dec. 15, 2014, 2:47 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 | « background.js ('k') | include.preload.js » ('j') | include.preload.js » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: include.postload.js
===================================================================
--- a/include.postload.js
+++ b/include.postload.js
@@ -267,24 +267,6 @@
return getURLsFromAttributes(element);
}
-function isBlockable(element)
-{
- if (element.id)
- return true;
- if (element.classList.length > 0)
- return true;
- if (getURLsFromElement(element).length > 0)
- return true;
-
- // We only generate filters based on the "style" attribute,
- // if this is the only way we can generate a filter, and
- // only if there are at least two CSS properties defined.
- if (/:.+:/.test(getOriginalStyle(element)))
- return true;
-
- return false;
-}
-
// Gets the absolute position of an element by walking up the DOM tree,
// adding up offsets.
// I hope there's a better way because it just seems absolutely stupid
@@ -301,14 +283,9 @@
}
// Adds an overlay to an element, which is probably a Flash object
-function addElementOverlay(elt) {
+function addElementOverlay(elt, callback) {
// If this element is enclosed in an object tag, we prefer to block that instead
if(!elt)
- return null;
-
- // If element doesn't have at least one of class name, ID or URL, give up
- // because we don't know how to construct a filter rule for it
- if(!isBlockable(elt))
return;
// If the element isn't rendered (since its or one of its ancestor's
@@ -316,23 +293,30 @@
if (!elt.offsetParent)
return;
- var thisStyle = getComputedStyle(elt, null);
- var overlay = document.createElement('div');
- overlay.prisoner = elt;
- overlay.className = "__adblockplus__overlay";
- overlay.setAttribute('style', 'opacity:0.4; background-color:#ffffff; display:inline-box; ' + 'width:' + thisStyle.width + '; height:' + thisStyle.height + '; position:absolute; overflow:hidden; -webkit-box-sizing:border-box;');
- var pos = getAbsolutePosition(elt);
- overlay.style.left = pos[0] + "px";
- overlay.style.top = pos[1] + "px";
+ generateFilters(elt, function(filters)
+ {
+ if (filters.length == 0)
+ return;
- if (thisStyle.position != "static")
- overlay.style.zIndex = thisStyle.zIndex;
- else
- overlay.style.zIndex = getComputedStyle(elt.offsetParent).zIndex;
+ var thisStyle = getComputedStyle(elt, null);
+ var overlay = document.createElement('div');
+ overlay.prisoner = elt;
+ overlay.className = "__adblockplus__overlay";
+ overlay.setAttribute('style', 'opacity:0.4; background-color:#ffffff; display:inline-box; ' + 'width:' + thisStyle.width + '; height:' + thisStyle.height + '; position:absolute; overflow:hidden; -webkit-box-sizing:border-box;');
+ var pos = getAbsolutePosition(elt);
+ overlay.style.left = pos[0] + "px";
+ overlay.style.top = pos[1] + "px";
- // elt.parentNode.appendChild(overlay, elt);
- document.body.appendChild(overlay);
- return overlay;
+ if (thisStyle.position != "static")
+ overlay.style.zIndex = thisStyle.zIndex;
+ else
+ overlay.style.zIndex = getComputedStyle(elt.offsetParent).zIndex;
+
+ document.body.appendChild(overlay);
+
+ if (callback)
+ callback(overlay);
+ });
}
// Show dialog asking user whether she wants to add the proposed filters derived
@@ -443,31 +427,50 @@
clickHide_mouseClick(ev);
}
+function getBlockableElementOrAncestor(element, callback)
+{
+ if (element && element != document.documentElement
+ && element != document.body)
+ {
+ generateFilters(element, function(filters)
+ {
+ if (filters.length > 0)
+ callback(element);
+ else
+ getBlockableElementOrAncestor(element.parentElement, callback);
+ });
+ }
+ else
+ {
+ callback(null);
+ }
+}
+
// Hovering over an element so highlight it
function clickHide_mouseOver(e)
{
if (clickHide_activated == false)
return;
- var target = e.target;
- while (target.parentNode && !isBlockable(target))
- target = target.parentNode;
- if (target == document.documentElement || target == document.body)
- target = null;
+ getBlockableElementOrAncestor(e.target, function(element)
+ {
+ if (currentElement)
+ unhighlightElement(currentElement);
- if (target && target instanceof HTMLElement)
- {
- currentElement = target;
+ if (element)
+ {
+ highlightElement(element, "#d6d84b", "#f8fa47");
+ element.addEventListener("contextmenu", clickHide_elementClickHandler, true);
+ }
- highlightElement(target, "#d6d84b", "#f8fa47");
- target.addEventListener("contextmenu", clickHide_elementClickHandler, true);
- }
+ currentElement = element;
+ });
}
// No longer hovering over this element so unhighlight it
function clickHide_mouseOut(e)
{
- if (!clickHide_activated || !currentElement)
+ if (!clickHide_activated || currentElement != e.target)
return;
unhighlightElement(currentElement);
@@ -494,6 +497,108 @@
}
}
+function generateFilters(element, callback)
+{
+ function addStyleAttributeFilter(filters, selectors)
+ {
+ var style = getOriginalStyle(element);
+ if (style && filters.length == 0)
+ {
+ ext.backgroundPage.sendMessage(
+ {
+ type: "get-filters-from-selectors",
+ selectors: [escapeCSS(element.localName) + '[style=' + quote(style) + ']']
+ },
+
+ function(response)
+ {
+ callback(filters.concat(response.filters), selectors.concat(response.selectors));
+ }
+ );
+ }
+ else
+ callback(filters, selectors);
+ }
+
+ function addElemHideFilter(filters, selectors)
+ {
+ if (selectors.length > 0)
+ {
+ ext.backgroundPage.sendMessage(
+ {
+ type: "get-filters-from-selectors",
+ selectors: selectors
+ },
+
+ function(response)
+ {
+ addStyleAttributeFilter(filters.concat(response.filters), response.selectors);
+ }
+ );
+ }
+ else
+ addStyleAttributeFilter(filters, selectors);
+ }
+
+ var filters = [];
+ var selectors = [];
+
+ if (element.id)
+ selectors.push("#" + escapeCSS(element.id));
+
+ if (element.classList.length > 0)
+ {
+ var selector = "";
+
+ for (var i = 0; i < element.classList.length; i++)
+ selector += "." + escapeCSS(element.classList[i]);
+
+ selectors.push(selector);
+ }
+
+ var urls = getURLsFromElement(element);
+ if (urls.length > 0)
+ {
+ ext.backgroundPage.sendMessage(
+ {
+ type: "check-whitelisted-urls",
+ mediatype: typeMap[element.localName],
+ urls: urls
+ },
+
+ function(whitelisted)
+ {
+ for (var i = 0; i < urls.length; i++)
+ {
+ var url = urls[i];
+
+ if (!whitelisted[url] && /^https?:/i.test(url))
+ {
+ var filter = url.replace(/^[\w\-]+:\/+(?:www\.)?/, "||");
+
+ if (filters.indexOf(filter) == -1)
+ filters.push(filter);
+
+ continue;
+ }
+
+ if (url == element.src)
+ {
+ var selector = escapeCSS(element.localName) + '[src=' + quote(element.getAttribute("src")) + ']';
+
+ if (selectors.indexOf(selector) == -1)
+ selectors.push(selector);
+ }
+ }
+
+ addElemHideFilter(filters, selectors);
+ }
+ );
+ }
+ else
+ addElemHideFilter(filters, selectors);
+}
+
// When the user clicks, the currentElement is the one we want.
// We should have ABP rules ready for when the
// popup asks for them.
@@ -506,66 +611,17 @@
if (currentElement.classList.contains("__adblockplus__overlay"))
elt = currentElement.prisoner;
- clickHideFilters = new Array();
- selectorList = new Array();
+ generateFilters(elt, function(filters, selectors)
+ {
+ clickHide_showDialog(e.clientX, e.clientY, filters);
- var addSelector = function(selector)
- {
- if (selectorList.indexOf(selector) != -1)
- return;
+ // Highlight the elements specified by selector in yellow
+ if (selectors.length > 0)
+ highlightElements(selectors.join(","));
- clickHideFilters.push(document.domain + "##" + selector);
- selectorList.push(selector);
- };
-
- if (elt.id)
- addSelector("#" + escapeCSS(elt.id));
-
- if (elt.classList.length > 0)
- {
- var selector = "";
-
- for (var i = 0; i < elt.classList.length; i++)
- selector += "." + escapeCSS(elt.classList[i]);
-
- addSelector(selector);
- }
-
- var urls = getURLsFromElement(elt);
- for (var i = 0; i < urls.length; i++)
- {
- var url = urls[i];
-
- if (/^https?:/i.test(url))
- {
- var filter = url.replace(/^[\w\-]+:\/+(?:www\.)?/, "||");
-
- if (clickHideFilters.indexOf(filter) == -1)
- clickHideFilters.push(filter);
-
- continue;
- }
-
- if (url == elt.src)
- addSelector(escapeCSS(elt.localName) + '[src=' + quote(elt.getAttribute("src")) + ']');
- }
-
- // as last resort, create a filter based on inline styles
- if (clickHideFilters.length == 0)
- {
- var style = getOriginalStyle(elt);
- if (style)
- addSelector(escapeCSS(elt.localName) + '[style=' + quote(style) + ']');
- }
-
- // Show popup
- clickHide_showDialog(e.clientX, e.clientY, clickHideFilters);
-
- // Highlight the elements specified by selector in yellow
- if (selectorList.length > 0)
- highlightElements(selectorList.join(","));
- // Now, actually highlight the element the user clicked on in red
- highlightElement(currentElement, "#fd1708", "#f6a1b5");
+ // Now, actually highlight the element the user clicked on in red
+ highlightElement(currentElement, "#fd1708", "#f6a1b5");
+ });
// Make sure the browser doesn't handle this click
e.preventDefault();
@@ -692,9 +748,14 @@
case "clickhide-new-filter":
if(lastRightClickEvent)
{
- clickHide_activated = true;
- currentElement = addElementOverlay(lastRightClickEvent.target);
- clickHide_mouseClick(lastRightClickEvent);
+ var event = lastRightClickEvent;
+
+ addElementOverlay(event.target, function(overlay)
+ {
+ clickHide_activated = true;
+ currentElement = overlay;
+ clickHide_mouseClick(event);
+ });
}
break;
case "clickhide-init":
« no previous file with comments | « background.js ('k') | include.preload.js » ('j') | include.preload.js » ('J')

Powered by Google App Engine
This is Rietveld