browser_canvasframe_helper_05.js (4380B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 // Test some edge cases of the CanvasFrameAnonymousContentHelper event handling 7 // mechanism. 8 9 const TEST_URL = 10 "data:text/html;charset=utf-8,CanvasFrameAnonymousContentHelper test"; 11 12 add_task(async function () { 13 const tab = await addTab(TEST_URL); 14 await SpecialPowers.spawn(tab.linkedBrowser, [], async function () { 15 const { require } = ChromeUtils.importESModule( 16 "resource://devtools/shared/loader/Loader.sys.mjs" 17 ); 18 const { 19 HighlighterEnvironment, 20 } = require("resource://devtools/server/actors/highlighters.js"); 21 const { 22 CanvasFrameAnonymousContentHelper, 23 } = require("resource://devtools/server/actors/highlighters/utils/markup.js"); 24 const doc = content.document; 25 26 const nodeBuilder = () => { 27 const root = doc.createElement("div"); 28 29 const parent = doc.createElement("div"); 30 parent.style = 31 "pointer-events:auto;width:300px;height:300px;background:yellow;"; 32 parent.id = "parent-element"; 33 root.appendChild(parent); 34 35 const child = doc.createElement("div"); 36 child.style = 37 "pointer-events:auto;width:200px;height:200px;background:red;"; 38 child.id = "child-element"; 39 parent.appendChild(child); 40 41 return root; 42 }; 43 44 info("Building the helper"); 45 const env = new HighlighterEnvironment(); 46 env.initFromWindow(doc.defaultView); 47 const helper = new CanvasFrameAnonymousContentHelper(env, nodeBuilder); 48 await helper.initialize(); 49 50 info("Getting the parent and child elements"); 51 const parentEl = helper.getElement("parent-element"); 52 const childEl = helper.getElement("child-element"); 53 54 info("Adding an event listener on both elements"); 55 let mouseDownHandled = []; 56 function onMouseDown(e, id) { 57 mouseDownHandled.push(id); 58 } 59 parentEl.addEventListener("mousedown", onMouseDown); 60 childEl.addEventListener("mousedown", onMouseDown); 61 62 function once(target, event) { 63 return new Promise(done => { 64 target.addEventListener(event, done, { once: true }); 65 }); 66 } 67 68 info("Synthesizing an event on the child element"); 69 let onDocMouseDown = once(doc, "mousedown"); 70 synthesizeMouseDown(100, 100, doc.defaultView); 71 await onDocMouseDown; 72 73 is(mouseDownHandled.length, 2, "The mousedown event was handled twice"); 74 is( 75 mouseDownHandled[0], 76 "child-element", 77 "The mousedown event was handled on the child element" 78 ); 79 is( 80 mouseDownHandled[1], 81 "parent-element", 82 "The mousedown event was handled on the parent element" 83 ); 84 85 info("Synthesizing an event on the parent, outside of the child element"); 86 mouseDownHandled = []; 87 onDocMouseDown = once(doc, "mousedown"); 88 synthesizeMouseDown(250, 250, doc.defaultView); 89 await onDocMouseDown; 90 91 is(mouseDownHandled.length, 1, "The mousedown event was handled only once"); 92 is( 93 mouseDownHandled[0], 94 "parent-element", 95 "The mousedown event was handled on the parent element" 96 ); 97 98 info("Removing the event listener"); 99 parentEl.removeEventListener("mousedown", onMouseDown); 100 childEl.removeEventListener("mousedown", onMouseDown); 101 102 info("Adding an event listener on the parent element only"); 103 mouseDownHandled = []; 104 parentEl.addEventListener("mousedown", onMouseDown); 105 106 info("Synthesizing an event on the child element"); 107 onDocMouseDown = once(doc, "mousedown"); 108 synthesizeMouseDown(100, 100, doc.defaultView); 109 await onDocMouseDown; 110 111 is(mouseDownHandled.length, 1, "The mousedown event was handled once"); 112 is( 113 mouseDownHandled[0], 114 "parent-element", 115 "The mousedown event did bubble to the parent element" 116 ); 117 118 info("Removing the parent listener"); 119 parentEl.removeEventListener("mousedown", onMouseDown); 120 121 env.destroy(); 122 helper.destroy(); 123 124 function synthesizeMouseDown(x, y, win) { 125 // We need to make sure the inserted anonymous content can be targeted by the 126 // event right after having been inserted, and so we need to force a sync 127 // reflow. 128 win.document.documentElement.offsetWidth; 129 EventUtils.synthesizeMouseAtPoint(x, y, { type: "mousedown" }, win); 130 } 131 }); 132 133 gBrowser.removeCurrentTab(); 134 });