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

Side by Side Diff: composer.postload.js

Issue 29370947: Issue 3138 - Improve how context menu "block element" handles iframes (Closed)
Patch Set: Use messaging instead of requiring the info module Created Oct. 19, 2017, 10:52 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | ext/background.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | ext/background.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld