Left: | ||
Right: |
OLD | NEW |
---|---|
1 /* | 1 /* |
2 * This file is part of Adblock Plus <http://adblockplus.org/>, | 2 * This file is part of Adblock Plus <http://adblockplus.org/>, |
3 * Copyright (C) 2006-2014 Eyeo GmbH | 3 * Copyright (C) 2006-2014 Eyeo GmbH |
4 * | 4 * |
5 * Adblock Plus is free software: you can redistribute it and/or modify | 5 * Adblock Plus is free software: you can redistribute it and/or modify |
6 * it under the terms of the GNU General Public License version 3 as | 6 * it under the terms of the GNU General Public License version 3 as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
8 * | 8 * |
9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 30 matching lines...) Expand all Loading... | |
41 function quote(value) | 41 function quote(value) |
42 { | 42 { |
43 return '"' + value.replace(/["\\\{\}\x00-\x1F\x7F]/g, escapeChar) + '"'; | 43 return '"' + value.replace(/["\\\{\}\x00-\x1F\x7F]/g, escapeChar) + '"'; |
44 } | 44 } |
45 | 45 |
46 function escapeCSS(s) | 46 function escapeCSS(s) |
47 { | 47 { |
48 return s.replace(/^[\d\-]|[^\w\-\u0080-\uFFFF]/g, escapeChar); | 48 return s.replace(/^[\d\-]|[^\w\-\u0080-\uFFFF]/g, escapeChar); |
49 } | 49 } |
50 | 50 |
51 function supportsShadowRoot(element) | |
52 { | |
53 if (!("createShadowRoot" in element)) | |
54 return false; | |
55 | |
56 // There are some elements (e.g. <textarea>), which don't | |
57 // support author created shadow roots and throw an exception. | |
58 var clone = element.cloneNode(false); | |
59 try | |
60 { | |
61 clone.createShadowRoot(); | |
62 } | |
63 catch (e) | |
64 { | |
65 return false; | |
66 } | |
67 | |
68 // There are some elements (e.g. <input>), which support | |
69 // author created shadow roots, but ignore insertion points. | |
70 var child = document.createTextNode(""); | |
71 clone.appendChild(child); | |
72 | |
73 var shadow = document.createElement("shadow"); | |
74 clone.shadowRoot.appendChild(shadow); | |
75 | |
76 return shadow.getDistributedNodes()[0] == child; | |
77 } | |
78 | |
79 function getOriginalStyle(element) | |
80 { | |
81 if ("_originalStyle" in element) | |
82 return element._originalStyle; | |
83 | |
84 return element.getAttribute("style"); | |
85 } | |
86 | |
87 function highlightElement(element, shadowColor, backgroundColor) | 51 function highlightElement(element, shadowColor, backgroundColor) |
88 { | 52 { |
89 unhighlightElement(element); | 53 unhighlightElement(element); |
90 | 54 |
91 var originalBoxShadowPriority = element.style.getPropertyPriority("box-shadow" ); | 55 var highlightWithOverlay = function() |
92 var originalBackgroundColorPriority = element.style.getPropertyPriority("backg round-color"); | |
93 | |
94 var boxShadow = "inset 0px 0px 5px " + shadowColor; | |
95 | |
96 var highlightWithShadowDOM = function() | |
97 { | 56 { |
98 var style = document.createElement("style"); | 57 highlightElement(overlay, shadowColor, backgroundColor); |
99 style.textContent = ":host {" + | 58 overlay.style.pointerEvents = "none"; |
100 "box-shadow:" + boxShadow + " !important;" + | |
101 "background-color:" + backgroundColor + " !important;" + | |
102 "}"; | |
103 | |
104 var root = element.createShadowRoot(); | |
105 root.appendChild(document.createElement("shadow")); | |
106 root.appendChild(style); | |
107 | 59 |
108 element._unhighlight = function() | 60 element._unhighlight = function() |
kzar
2015/01/13 11:04:24
Could this cause a memory leak as _unhighlight fun
Sebastian Noack
2015/01/13 13:03:53
It is actually removed, see unhighlightElement().
| |
109 { | 61 { |
110 root.removeChild(style); | 62 overlay.parentNode.removeChild(overlay); |
111 }; | 63 }; |
112 }; | 64 }; |
113 | 65 |
114 var highlightWithStyleAttribute = function() | 66 var highlightWithStyleAttribute = function() |
115 { | 67 { |
116 var originalBoxShadow = element.style.getPropertyValue("box-shadow"); | 68 var originalBoxShadow = element.style.getPropertyValue ("box -shadow"); |
kzar
2015/01/13 11:04:24
Why extra spacing before opening bracket? (Maybe i
Sebastian Noack
2015/01/13 13:03:53
I find it more readable, when similar code is alig
| |
117 var originalBackgroundColor = element.style.getPropertyValue("background-col or"); | 69 var originalBoxShadowPriority = element.style.getPropertyPriority("box -shadow"); |
70 var originalBackgroundColor = element.style.getPropertyValue ("bac kground-color"); | |
71 var originalBackgroundColorPriority = element.style.getPropertyPriority("bac kground-color"); | |
118 | 72 |
119 element._originalStyle = getOriginalStyle(element); | 73 element.style.setProperty("box-shadow", "inset 0px 0px 5px " + shadowColor, "important"); |
120 | |
121 element.style.setProperty("box-shadow", boxShadow, "important"); | |
122 element.style.setProperty("background-color", backgroundColor, "important"); | 74 element.style.setProperty("background-color", backgroundColor, "important"); |
123 | 75 |
124 element._unhighlight = function() | 76 element._unhighlight = function() |
125 { | 77 { |
126 this.style.removeProperty("box-shadow"); | 78 this.style.removeProperty("box-shadow"); |
127 this.style.setProperty( | 79 this.style.setProperty( |
128 "box-shadow", | 80 "box-shadow", |
129 originalBoxShadow, | 81 originalBoxShadow, |
130 originalBoxShadowPriority | 82 originalBoxShadowPriority |
131 ); | 83 ); |
132 | 84 |
133 this.style.removeProperty("background-color"); | 85 this.style.removeProperty("background-color"); |
134 this.style.setProperty( | 86 this.style.setProperty( |
135 "background-color", | 87 "background-color", |
136 originalBackgroundColor, | 88 originalBackgroundColor, |
137 originalBackgroundColorPriority | 89 originalBackgroundColorPriority |
138 ); | 90 ); |
139 }; | 91 }; |
140 }; | 92 }; |
141 | 93 |
142 // Use shadow DOM if posibble to avoid side effects when the | 94 var overlay; |
kzar
2015/01/13 11:04:24
Seems confusing to me that overlay is declared her
Sebastian Noack
2015/01/13 13:03:53
I moved the declaration into highlightWithOverlay(
| |
143 // web page updates style while highlighted. However, if the | 95 if (!("prisoner" in element) && (overlay = addElementOverlay(element))) |
kzar
2015/01/13 11:04:24
Could you add a comment before this if statement e
Sebastian Noack
2015/01/13 13:03:53
We only highlight elements with style attributes i
| |
144 // element has important styles we can't override them with shadow DOM. | 96 highlightWithOverlay(); |
145 if (supportsShadowRoot(element) && originalBoxShadowPriority != "importa nt" && | |
146 originalBackgroundColorPriority != "importa nt") | |
147 highlightWithShadowDOM(); | |
148 else | 97 else |
149 highlightWithStyleAttribute(); | 98 highlightWithStyleAttribute(); |
150 } | 99 } |
151 | 100 |
152 | 101 |
153 function unhighlightElement(element) | 102 function unhighlightElement(element) |
154 { | 103 { |
155 if ("_unhighlight" in element) | 104 if ("_unhighlight" in element) |
156 { | 105 { |
157 element._unhighlight(); | 106 element._unhighlight(); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
272 if (element.id) | 221 if (element.id) |
273 return true; | 222 return true; |
274 if (element.classList.length > 0) | 223 if (element.classList.length > 0) |
275 return true; | 224 return true; |
276 if (getURLsFromElement(element).length > 0) | 225 if (getURLsFromElement(element).length > 0) |
277 return true; | 226 return true; |
278 | 227 |
279 // We only generate filters based on the "style" attribute, | 228 // We only generate filters based on the "style" attribute, |
280 // if this is the only way we can generate a filter, and | 229 // if this is the only way we can generate a filter, and |
281 // only if there are at least two CSS properties defined. | 230 // only if there are at least two CSS properties defined. |
282 if (/:.+:/.test(getOriginalStyle(element))) | 231 if (/:.+:/.test(element.getAttribute("style"))) |
283 return true; | 232 return true; |
284 | 233 |
285 return false; | 234 return false; |
286 } | 235 } |
287 | 236 |
288 // Gets the absolute position of an element by walking up the DOM tree, | 237 // Gets the absolute position of an element by walking up the DOM tree, |
289 // adding up offsets. | 238 // adding up offsets. |
290 // I hope there's a better way because it just seems absolutely stupid | 239 // I hope there's a better way because it just seems absolutely stupid |
291 // that the DOM wouldn't have a direct way to get this, given that it | 240 // that the DOM wouldn't have a direct way to get this, given that it |
292 // has hundreds and hundreds of other methods that do random junk. | 241 // has hundreds and hundreds of other methods that do random junk. |
293 function getAbsolutePosition(elt) { | 242 function getAbsolutePosition(elt) { |
294 var l = 0; | 243 var l = 0; |
295 var t = 0; | 244 var t = 0; |
296 for(; elt; elt = elt.offsetParent) { | 245 for(; elt; elt = elt.offsetParent) { |
297 l += elt.offsetLeft; | 246 l += elt.offsetLeft; |
298 t += elt.offsetTop; | 247 t += elt.offsetTop; |
299 } | 248 } |
300 return [l, t]; | 249 return [l, t]; |
301 } | 250 } |
302 | 251 |
303 // Adds an overlay to an element, which is probably a Flash object | 252 // Adds an overlay to an element, which is probably a Flash object |
304 function addElementOverlay(elt) { | 253 function addElementOverlay(elt) { |
305 // If this element is enclosed in an object tag, we prefer to block that inste ad | |
306 if(!elt) | |
307 return null; | |
308 | |
309 // If element doesn't have at least one of class name, ID or URL, give up | |
310 // because we don't know how to construct a filter rule for it | |
311 if(!isBlockable(elt)) | |
312 return; | |
313 | |
314 // If the element isn't rendered (since its or one of its ancestor's | 254 // If the element isn't rendered (since its or one of its ancestor's |
315 // "display" property is "none"), the overlay wouldn't match the element. | 255 // "display" property is "none"), the overlay wouldn't match the element. |
316 if (!elt.offsetParent) | 256 if (!elt.offsetParent) |
317 return; | 257 return; |
318 | 258 |
319 var thisStyle = getComputedStyle(elt, null); | 259 var thisStyle = getComputedStyle(elt, null); |
320 var overlay = document.createElement('div'); | 260 var overlay = document.createElement('div'); |
321 overlay.prisoner = elt; | 261 overlay.prisoner = elt; |
322 overlay.className = "__adblockplus__overlay"; | 262 overlay.className = "__adblockplus__overlay"; |
323 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;'); | 263 overlay.setAttribute('style', 'opacity:0.4; display:inline-box; position:absol ute; overflow:hidden; box-sizing:border-box;'); |
kzar
2015/01/13 11:04:24
Are these changes relevant to the issue?
kzar
2015/01/13 13:26:34
What about these changes?
Sebastian Noack
2015/01/13 13:36:11
Kinda; it already prior to my changes here, it wer
| |
324 var pos = getAbsolutePosition(elt); | 264 var pos = getAbsolutePosition(elt); |
265 overlay.style.width = elt.offsetWidth + "px"; | |
266 overlay.style.height = elt.offsetHeight + "px"; | |
325 overlay.style.left = pos[0] + "px"; | 267 overlay.style.left = pos[0] + "px"; |
326 overlay.style.top = pos[1] + "px"; | 268 overlay.style.top = pos[1] + "px"; |
327 | 269 |
328 if (thisStyle.position != "static") | 270 if (thisStyle.position != "static") |
329 overlay.style.zIndex = thisStyle.zIndex; | 271 overlay.style.zIndex = thisStyle.zIndex; |
330 else | 272 else |
331 overlay.style.zIndex = getComputedStyle(elt.offsetParent).zIndex; | 273 overlay.style.zIndex = getComputedStyle(elt.offsetParent).zIndex; |
332 | 274 |
333 // elt.parentNode.appendChild(overlay, elt); | 275 // elt.parentNode.appendChild(overlay, elt); |
334 document.body.appendChild(overlay); | 276 document.body.appendChild(overlay); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
373 | 315 |
374 // Turn on the choose element to create filter thing | 316 // Turn on the choose element to create filter thing |
375 function clickHide_activate() { | 317 function clickHide_activate() { |
376 if(document == null) | 318 if(document == null) |
377 return; | 319 return; |
378 | 320 |
379 // If we are already selecting, abort now | 321 // If we are already selecting, abort now |
380 if (clickHide_activated || clickHideFiltersDialog) | 322 if (clickHide_activated || clickHideFiltersDialog) |
381 clickHide_deactivate(); | 323 clickHide_deactivate(); |
382 | 324 |
383 // Add overlays for elements with URLs so user can easily click them | 325 // Add overlays for blockable elements that don't emit mouse events that they can still be selected |
384 var elts = document.querySelectorAll('object,embed,img,iframe,video,audio,pict ure'); | 326 var elts = document.querySelectorAll('object,embed,iframe'); |
385 for(var i=0; i<elts.length; i++) | 327 for(var i=0; i<elts.length; i++) |
386 addElementOverlay(elts[i]); | 328 { |
329 var element = elts[i]; | |
330 if (isBlockable(element)) | |
331 addElementOverlay(element); | |
332 } | |
387 | 333 |
388 clickHide_activated = true; | 334 clickHide_activated = true; |
389 document.addEventListener("mouseover", clickHide_mouseOver, true); | 335 document.addEventListener("mouseover", clickHide_mouseOver, true); |
390 document.addEventListener("mouseout", clickHide_mouseOut, true); | 336 document.addEventListener("mouseout", clickHide_mouseOut, true); |
391 document.addEventListener("click", clickHide_mouseClick, true); | 337 document.addEventListener("click", clickHide_mouseClick, true); |
392 document.addEventListener("keydown", clickHide_keyDown, true); | 338 document.addEventListener("keydown", clickHide_keyDown, true); |
393 } | 339 } |
394 | 340 |
395 // Called when user has clicked on something and we are waiting for confirmation | 341 // Called when user has clicked on something and we are waiting for confirmation |
396 // on whether the user actually wants these filters | 342 // on whether the user actually wants these filters |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
546 continue; | 492 continue; |
547 } | 493 } |
548 | 494 |
549 if (url == elt.src) | 495 if (url == elt.src) |
550 addSelector(escapeCSS(elt.localName) + '[src=' + quote(elt.getAttribute("s rc")) + ']'); | 496 addSelector(escapeCSS(elt.localName) + '[src=' + quote(elt.getAttribute("s rc")) + ']'); |
551 } | 497 } |
552 | 498 |
553 // as last resort, create a filter based on inline styles | 499 // as last resort, create a filter based on inline styles |
554 if (clickHideFilters.length == 0) | 500 if (clickHideFilters.length == 0) |
555 { | 501 { |
556 var style = getOriginalStyle(elt); | 502 var style = elt.getAttribute("style"); |
557 if (style) | 503 if (style) |
558 addSelector(escapeCSS(elt.localName) + '[style=' + quote(style) + ']'); | 504 addSelector(escapeCSS(elt.localName) + '[style=' + quote(style) + ']'); |
559 } | 505 } |
560 | 506 |
561 // Show popup | 507 // Show popup |
562 clickHide_showDialog(e.clientX, e.clientY, clickHideFilters); | 508 clickHide_showDialog(e.clientX, e.clientY, clickHideFilters); |
563 | 509 |
564 // Highlight the elements specified by selector in yellow | 510 // Highlight the elements specified by selector in yellow |
565 if (selectorList.length > 0) | 511 if (selectorList.length > 0) |
566 highlightElements(selectorList.join(",")); | 512 highlightElements(selectorList.join(",")); |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
686 case "clickhide-activate": | 632 case "clickhide-activate": |
687 clickHide_activate(); | 633 clickHide_activate(); |
688 break; | 634 break; |
689 case "clickhide-deactivate": | 635 case "clickhide-deactivate": |
690 clickHide_deactivate(); | 636 clickHide_deactivate(); |
691 break; | 637 break; |
692 case "clickhide-new-filter": | 638 case "clickhide-new-filter": |
693 if(lastRightClickEvent) | 639 if(lastRightClickEvent) |
694 { | 640 { |
695 clickHide_activated = true; | 641 clickHide_activated = true; |
696 currentElement = addElementOverlay(lastRightClickEvent.target); | 642 currentElement = lastRightClickEvent.target; |
697 clickHide_mouseClick(lastRightClickEvent); | 643 clickHide_mouseClick(lastRightClickEvent); |
698 } | 644 } |
699 break; | 645 break; |
700 case "clickhide-init": | 646 case "clickhide-init": |
701 if (clickHideFiltersDialog) | 647 if (clickHideFiltersDialog) |
702 { | 648 { |
703 sendResponse({filters: clickHide_filters}); | 649 sendResponse({filters: clickHide_filters}); |
704 | 650 |
705 clickHideFiltersDialog.style.width = msg.width + "px"; | 651 clickHideFiltersDialog.style.width = msg.width + "px"; |
706 clickHideFiltersDialog.style.height = msg.height + "px"; | 652 clickHideFiltersDialog.style.height = msg.height + "px"; |
(...skipping 19 matching lines...) Expand all Loading... | |
726 break; | 672 break; |
727 default: | 673 default: |
728 sendResponse({}); | 674 sendResponse({}); |
729 break; | 675 break; |
730 } | 676 } |
731 }); | 677 }); |
732 | 678 |
733 if (window == window.top) | 679 if (window == window.top) |
734 ext.backgroundPage.sendMessage({type: "report-html-page"}); | 680 ext.backgroundPage.sendMessage({type: "report-html-page"}); |
735 } | 681 } |
OLD | NEW |