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 |
(...skipping 22 matching lines...) Expand all Loading... |
33 | 33 |
34 // Highlighting state, used by the top frame during element picking and all | 34 // Highlighting state, used by the top frame during element picking and all |
35 // frames when the chosen element is highlighted red. | 35 // frames when the chosen element is highlighted red. |
36 let highlightedElementsSelector = null; | 36 let highlightedElementsSelector = null; |
37 let highlightedElementsInterval = null; | 37 let highlightedElementsInterval = null; |
38 | 38 |
39 // Last right click state stored for element blocking via the context menu. | 39 // Last right click state stored for element blocking via the context menu. |
40 let lastRightClickEvent = null; | 40 let lastRightClickEvent = null; |
41 let lastRightClickEventIsMostRecent = false; | 41 let lastRightClickEventIsMostRecent = false; |
42 | 42 |
| 43 let perFrameMessagingSupported = false; |
| 44 browser.runtime.sendMessage( |
| 45 {type: "app.get", what: "application"}, |
| 46 application => { perFrameMessagingSupported = application != "edge"; } |
| 47 ); |
43 | 48 |
44 /* Utilities */ | 49 /* Utilities */ |
45 | 50 |
46 function getFiltersForElement(element, callback) | 51 function getFiltersForElement(element, callback) |
47 { | 52 { |
48 let src = element.getAttribute("src"); | 53 let src = element.getAttribute("src"); |
49 browser.runtime.sendMessage({ | 54 browser.runtime.sendMessage({ |
50 type: "composer.getFilters", | 55 type: "composer.getFilters", |
51 tagName: element.localName, | 56 tagName: element.localName, |
52 id: element.id, | 57 id: element.id, |
53 src: src && src.length <= 1000 ? src : null, | 58 src: src && src.length <= 1000 ? src : null, |
54 style: element.getAttribute("style"), | 59 style: element.getAttribute("style"), |
55 classes: Array.prototype.slice.call(element.classList), | 60 classes: Array.prototype.slice.call(element.classList), |
56 urls: getURLsFromElement(element), | 61 urls: getURLsFromElement(element), |
57 mediatype: typeMap.get(element.localName), | 62 mediatype: typeMap.get(element.localName), |
58 baseURL: document.location.href | 63 baseURL: document.location.href |
59 }, | 64 }, |
60 response => | 65 response => |
61 { | 66 { |
62 callback(response.filters, response.selectors); | 67 callback(response.filters, response.selectors); |
63 }); | 68 }); |
64 } | 69 } |
65 | 70 |
66 function getBlockableElementOrAncestor(element, callback) | 71 function getBlockableElementOrAncestor(element, callback) |
67 { | 72 { |
| 73 // If we're offering to block the iframe element given by window.frameElement |
| 74 // we must use the context of the parent frame. |
| 75 let document = element.ownerDocument; |
| 76 let HTMLElement = document.defaultView.HTMLElement; |
| 77 |
68 // We assume that the user doesn't want to block the whole page. | 78 // We assume that the user doesn't want to block the whole page. |
69 // So we never consider the <html> or <body> element. | 79 // So we never consider the <html> or <body> element. |
70 while (element && element != document.documentElement && | 80 while (element && element != document.documentElement && |
71 element != document.body) | 81 element != document.body) |
72 { | 82 { |
73 // We can't handle non-HTML (like SVG) elements, as well as | 83 // We can't handle non-HTML (like SVG) elements, as well as |
74 // <area> elements (see below). So fall back to the parent element. | 84 // <area> elements (see below). So fall back to the parent element. |
75 if (!(element instanceof HTMLElement) || element.localName == "area") | 85 if (!(element instanceof HTMLElement) || element.localName == "area") |
76 element = element.parentElement; | 86 element = element.parentElement; |
77 | 87 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 // We reached the document root without finding a blockable element. | 126 // We reached the document root without finding a blockable element. |
117 callback(null); | 127 callback(null); |
118 } | 128 } |
119 | 129 |
120 | 130 |
121 /* Element highlighting */ | 131 /* Element highlighting */ |
122 | 132 |
123 // Adds an overlay to an element in order to highlight it. | 133 // Adds an overlay to an element in order to highlight it. |
124 function addElementOverlay(element) | 134 function addElementOverlay(element) |
125 { | 135 { |
| 136 let document = element.ownerDocument; |
| 137 |
126 let position = "absolute"; | 138 let position = "absolute"; |
127 let offsetX = window.scrollX; | 139 let offsetX = window.scrollX; |
128 let offsetY = window.scrollY; | 140 let offsetY = window.scrollY; |
129 | 141 |
130 for (let e = element; e; e = e.parentElement) | 142 for (let e = element; e; e = e.parentElement) |
131 { | 143 { |
132 let style = getComputedStyle(e); | 144 let style = getComputedStyle(e); |
133 | 145 |
134 // If the element isn't rendered (since its or one of its ancestor's | 146 // 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. | 147 // "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 }); | 427 }); |
416 } | 428 } |
417 }); | 429 }); |
418 | 430 |
419 if (selectors.length > 0) | 431 if (selectors.length > 0) |
420 highlightElements(selectors.join(",")); | 432 highlightElements(selectors.join(",")); |
421 | 433 |
422 highlightElement(currentElement, "#fd1708", "#f6a1b5"); | 434 highlightElement(currentElement, "#fd1708", "#f6a1b5"); |
423 }); | 435 }); |
424 | 436 |
425 event.preventDefault(); | 437 if (event) |
426 event.stopPropagation(); | 438 { |
| 439 event.preventDefault(); |
| 440 event.stopPropagation(); |
| 441 } |
427 } | 442 } |
428 | 443 |
429 function stopPickingElement() | 444 function stopPickingElement() |
430 { | 445 { |
431 currentlyPickingElement = false; | 446 currentlyPickingElement = false; |
432 | 447 |
433 document.removeEventListener("mousedown", stopEventPropagation, true); | 448 document.removeEventListener("mousedown", stopEventPropagation, true); |
434 document.removeEventListener("mouseup", stopEventPropagation, true); | 449 document.removeEventListener("mouseup", stopEventPropagation, true); |
435 document.removeEventListener("mouseenter", stopEventPropagation, true); | 450 document.removeEventListener("mouseenter", stopEventPropagation, true); |
436 document.removeEventListener("mouseleave", stopEventPropagation, true); | 451 document.removeEventListener("mouseleave", stopEventPropagation, true); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 active: currentlyPickingElement || blockelementPopupId != null | 532 active: currentlyPickingElement || blockelementPopupId != null |
518 }); | 533 }); |
519 } | 534 } |
520 break; | 535 break; |
521 case "composer.content.startPickingElement": | 536 case "composer.content.startPickingElement": |
522 if (window == window.top) | 537 if (window == window.top) |
523 startPickingElement(); | 538 startPickingElement(); |
524 break; | 539 break; |
525 case "composer.content.contextMenuClicked": | 540 case "composer.content.contextMenuClicked": |
526 let event = lastRightClickEvent; | 541 let event = lastRightClickEvent; |
| 542 let target = event && event.target; |
| 543 |
| 544 // When the user attempts to block an element inside an iframe for which |
| 545 // our right click event listener was trashed the best we can do is to |
| 546 // offer to block the entire iframe. This doesn't work for cross origin |
| 547 // frames, neither on Edge where per-frame messaging isn't supported |
| 548 // yet[1], but it's the best we can do. |
| 549 // [1] - https://developer.microsoft.com/en-us/microsoft-edge/platform/d
ocumentation/extensions/api-support/supported-apis/ |
| 550 if (!target && window.frameElement && perFrameMessagingSupported) |
| 551 target = addElementOverlay(window.frameElement); |
| 552 |
527 deactivateBlockElement(); | 553 deactivateBlockElement(); |
528 if (event) | 554 if (target) |
529 { | 555 { |
530 getBlockableElementOrAncestor(event.target, element => | 556 getBlockableElementOrAncestor(target, element => |
531 { | 557 { |
532 if (element) | 558 if (element) |
533 { | 559 { |
534 currentElement = element; | 560 currentElement = element; |
535 elementPicked(event); | 561 elementPicked(event); |
536 } | 562 } |
537 }); | 563 }); |
538 } | 564 } |
539 break; | 565 break; |
540 case "composer.content.finished": | 566 case "composer.content.finished": |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 if (document instanceof HTMLDocument) | 613 if (document instanceof HTMLDocument) |
588 { | 614 { |
589 // There's a bug in Firefox that causes document_end content scripts to run | 615 // 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 | 616 // before document_start content scripts on extension startup. In this case |
591 // the ext object is undefined, we fail to initialize, and initializeComposer | 617 // the ext object is undefined, we fail to initialize, and initializeComposer |
592 // returns false. As a workaround, try again after a timeout. | 618 // returns false. As a workaround, try again after a timeout. |
593 // https://bugzilla.mozilla.org/show_bug.cgi?id=1395287 | 619 // https://bugzilla.mozilla.org/show_bug.cgi?id=1395287 |
594 if (!initializeComposer()) | 620 if (!initializeComposer()) |
595 setTimeout(initializeComposer, 2000); | 621 setTimeout(initializeComposer, 2000); |
596 } | 622 } |
OLD | NEW |