OLD | NEW |
1 /* | 1 /* |
2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
3 * Copyright (C) 2006-present eyeo GmbH | 3 * Copyright (C) 2006-present 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 |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 * GNU General Public License for more details. | 12 * GNU General Public License for more details. |
13 * | 13 * |
14 * You should have received a copy of the GNU General Public License | 14 * You should have received a copy of the GNU General Public License |
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
16 */ | 16 */ |
17 | 17 |
18 "use strict"; | 18 "use strict"; |
19 | 19 |
20 const {checkCollapse, elemhide, | 20 const {checkCollapse, elemhide, |
21 getURLsFromElement, typeMap} = require("./include.preload"); | 21 getURLsFromElement, typeMap} = require("./include.preload"); |
| 22 const info = require("info"); |
22 | 23 |
23 // The page ID for the popup filter selection dialog (top frame only). | 24 // The page ID for the popup filter selection dialog (top frame only). |
24 let blockelementPopupId = null; | 25 let blockelementPopupId = null; |
25 | 26 |
26 // Element picking state (top frame only). | 27 // Element picking state (top frame only). |
27 let currentlyPickingElement = false; | 28 let currentlyPickingElement = false; |
28 let lastMouseOverEvent = null; | 29 let lastMouseOverEvent = null; |
29 | 30 |
30 // During element picking this is the currently highlighted element. When | 31 // During element picking this is the currently highlighted element. When |
31 // element has been picked this is the element that is due to be blocked. | 32 // element has been picked this is the element that is due to be blocked. |
(...skipping 26 matching lines...) Expand all Loading... |
58 baseURL: document.location.href | 59 baseURL: document.location.href |
59 }, | 60 }, |
60 response => | 61 response => |
61 { | 62 { |
62 callback(response.filters, response.selectors); | 63 callback(response.filters, response.selectors); |
63 }); | 64 }); |
64 } | 65 } |
65 | 66 |
66 function getBlockableElementOrAncestor(element, callback) | 67 function getBlockableElementOrAncestor(element, callback) |
67 { | 68 { |
| 69 // If we're offering to block the iframe element given by window.frameElement |
| 70 // we must use the context of the parent frame. |
| 71 let document = element.ownerDocument; |
| 72 let HTMLElement = document.defaultView.HTMLElement; |
| 73 |
68 // We assume that the user doesn't want to block the whole page. | 74 // We assume that the user doesn't want to block the whole page. |
69 // So we never consider the <html> or <body> element. | 75 // So we never consider the <html> or <body> element. |
70 while (element && element != document.documentElement && | 76 while (element && element != document.documentElement && |
71 element != document.body) | 77 element != document.body) |
72 { | 78 { |
73 // We can't handle non-HTML (like SVG) elements, as well as | 79 // We can't handle non-HTML (like SVG) elements, as well as |
74 // <area> elements (see below). So fall back to the parent element. | 80 // <area> elements (see below). So fall back to the parent element. |
75 if (!(element instanceof HTMLElement) || element.localName == "area") | 81 if (!(element instanceof HTMLElement) || element.localName == "area") |
76 element = element.parentElement; | 82 element = element.parentElement; |
77 | 83 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 // We reached the document root without finding a blockable element. | 122 // We reached the document root without finding a blockable element. |
117 callback(null); | 123 callback(null); |
118 } | 124 } |
119 | 125 |
120 | 126 |
121 /* Element highlighting */ | 127 /* Element highlighting */ |
122 | 128 |
123 // Adds an overlay to an element in order to highlight it. | 129 // Adds an overlay to an element in order to highlight it. |
124 function addElementOverlay(element) | 130 function addElementOverlay(element) |
125 { | 131 { |
| 132 let document = element.ownerDocument; |
| 133 |
126 let position = "absolute"; | 134 let position = "absolute"; |
127 let offsetX = window.scrollX; | 135 let offsetX = window.scrollX; |
128 let offsetY = window.scrollY; | 136 let offsetY = window.scrollY; |
129 | 137 |
130 for (let e = element; e; e = e.parentElement) | 138 for (let e = element; e; e = e.parentElement) |
131 { | 139 { |
132 let style = getComputedStyle(e); | 140 let style = getComputedStyle(e); |
133 | 141 |
134 // If the element isn't rendered (since its or one of its ancestor's | 142 // If the element isn't rendered (since its or one of its ancestor's |
135 // "display" property is "none"), the overlay wouldn't match the element. | 143 // "display" property is "none"), the overlay wouldn't match the element. |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 }); | 423 }); |
416 } | 424 } |
417 }); | 425 }); |
418 | 426 |
419 if (selectors.length > 0) | 427 if (selectors.length > 0) |
420 highlightElements(selectors.join(",")); | 428 highlightElements(selectors.join(",")); |
421 | 429 |
422 highlightElement(currentElement, "#fd1708", "#f6a1b5"); | 430 highlightElement(currentElement, "#fd1708", "#f6a1b5"); |
423 }); | 431 }); |
424 | 432 |
425 event.preventDefault(); | 433 if (event) |
426 event.stopPropagation(); | 434 { |
| 435 event.preventDefault(); |
| 436 event.stopPropagation(); |
| 437 } |
427 } | 438 } |
428 | 439 |
429 function stopPickingElement() | 440 function stopPickingElement() |
430 { | 441 { |
431 currentlyPickingElement = false; | 442 currentlyPickingElement = false; |
432 | 443 |
433 document.removeEventListener("mousedown", stopEventPropagation, true); | 444 document.removeEventListener("mousedown", stopEventPropagation, true); |
434 document.removeEventListener("mouseup", stopEventPropagation, true); | 445 document.removeEventListener("mouseup", stopEventPropagation, true); |
435 document.removeEventListener("mouseenter", stopEventPropagation, true); | 446 document.removeEventListener("mouseenter", stopEventPropagation, true); |
436 document.removeEventListener("mouseleave", stopEventPropagation, true); | 447 document.removeEventListener("mouseleave", stopEventPropagation, true); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 active: currentlyPickingElement || blockelementPopupId != null | 528 active: currentlyPickingElement || blockelementPopupId != null |
518 }); | 529 }); |
519 } | 530 } |
520 break; | 531 break; |
521 case "composer.content.startPickingElement": | 532 case "composer.content.startPickingElement": |
522 if (window == window.top) | 533 if (window == window.top) |
523 startPickingElement(); | 534 startPickingElement(); |
524 break; | 535 break; |
525 case "composer.content.contextMenuClicked": | 536 case "composer.content.contextMenuClicked": |
526 let event = lastRightClickEvent; | 537 let event = lastRightClickEvent; |
| 538 let target = event && event.target; |
| 539 |
| 540 // When the user attempts to block an element inside an iframe for which |
| 541 // our right click event listener was trashed the best we can do is to |
| 542 // offer to block the entire iframe. This doesn't work for cross origin |
| 543 // frames, neither on Edge where per-frame messaging isn't supported |
| 544 // yet[1], but it's the best we can do. |
| 545 // [1] - https://developer.microsoft.com/en-us/microsoft-edge/platform/d
ocumentation/extensions/api-support/supported-apis/ |
| 546 if (!target && window.frameElement && info.application != "edge") |
| 547 target = addElementOverlay(window.frameElement); |
| 548 |
527 deactivateBlockElement(); | 549 deactivateBlockElement(); |
528 if (event) | 550 if (target) |
529 { | 551 { |
530 getBlockableElementOrAncestor(event.target, element => | 552 getBlockableElementOrAncestor(target, element => |
531 { | 553 { |
532 if (element) | 554 if (element) |
533 { | 555 { |
534 currentElement = element; | 556 currentElement = element; |
535 elementPicked(event); | 557 elementPicked(event); |
536 } | 558 } |
537 }); | 559 }); |
538 } | 560 } |
539 break; | 561 break; |
540 case "composer.content.finished": | 562 case "composer.content.finished": |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 if (document instanceof HTMLDocument) | 609 if (document instanceof HTMLDocument) |
588 { | 610 { |
589 // There's a bug in Firefox that causes document_end content scripts to run | 611 // There's a bug in Firefox that causes document_end content scripts to run |
590 // before document_start content scripts on extension startup. In this case | 612 // before document_start content scripts on extension startup. In this case |
591 // the ext object is undefined, we fail to initialize, and initializeComposer | 613 // the ext object is undefined, we fail to initialize, and initializeComposer |
592 // returns false. As a workaround, try again after a timeout. | 614 // returns false. As a workaround, try again after a timeout. |
593 // https://bugzilla.mozilla.org/show_bug.cgi?id=1395287 | 615 // https://bugzilla.mozilla.org/show_bug.cgi?id=1395287 |
594 if (!initializeComposer()) | 616 if (!initializeComposer()) |
595 setTimeout(initializeComposer, 2000); | 617 setTimeout(initializeComposer, 2000); |
596 } | 618 } |
OLD | NEW |