helper_hittest_overscroll_contextmenu.html (4598B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <title>Test APZ hit-testing while overscrolled</title> 5 <script type="application/javascript" src="apz_test_utils.js"></script> 6 <script type="application/javascript" src="apz_test_native_event_utils.js"></script> 7 <script src="/tests/SimpleTest/paint_listener.js"></script> 8 <meta name="viewport" content="width=device-width"/> 9 <style> 10 html, body { 11 margin: 0; 12 padding: 0; 13 } 14 .spacer { 15 height: 5000px; 16 } 17 #target { 18 margin-left: 100px; 19 margin-top: 2px; 20 height: 4px; 21 width: 4px; 22 background: red; 23 } 24 </style> 25 </head> 26 <body> 27 <div id="target"></div> 28 <div class="spacer"></div> 29 </body> 30 <script type="application/javascript"> 31 32 // Some helper functions for listening for contextmenu events in the browser chrome. 33 34 // A handle used to interact with the chrome script used to implement 35 // [start|stop]ListeningForContextmenuEventsInChrome(). 36 let chromeScriptHandle = null; 37 38 function startListeningForContextmenuEventsInChrome() { 39 function chromeScript() { 40 /* eslint-env mozilla/chrome-script */ 41 let topWin = Services.wm.getMostRecentWindow("navigator:browser"); 42 if (!topWin) { 43 topWin = Services.wm.getMostRecentWindow("navigator:geckoview"); 44 } 45 let chromeReceivedContextmenu = false; 46 function chromeListener() { 47 chromeReceivedContextmenu = true; 48 } 49 topWin.addEventListener("contextmenu", chromeListener); 50 function queryContextmenu() { 51 sendAsyncMessage("query-contextmenu-response", { chromeReceivedContextmenu }); 52 } 53 function cleanup() { 54 topWin.removeEventListener("contextmenu", chromeListener); 55 removeMessageListener("query-contextmenu", queryContextmenu); 56 removeMessageListener("cleanup", cleanup); 57 } 58 addMessageListener("query-contextmenu", queryContextmenu); 59 addMessageListener("cleanup", cleanup); 60 } 61 chromeScriptHandle = SpecialPowers.loadChromeScript(chromeScript); 62 } 63 64 async function didChromeReceiveContextmenu() { 65 chromeScriptHandle.sendAsyncMessage("query-contextmenu", null); 66 let response = await chromeScriptHandle.promiseOneMessage("query-contextmenu-response"); 67 ok(response && ("chromeReceivedContextmenu" in response), 68 "Received a well-formed response from chrome script"); 69 return response.chromeReceivedContextmenu; 70 } 71 72 function stopListeningForContextmenuEventsInChrome() { 73 chromeScriptHandle.sendAsyncMessage("cleanup", null); 74 chromeScriptHandle.destroy(); 75 } 76 77 async function test() { 78 var config = getHitTestConfig(); 79 var utils = config.utils; 80 81 // Overscroll the root scroll frame at the top, creating a gutter. 82 // Note that the size of the gutter will only be 8px, because 83 // setAsyncScrollOffset() applies the overscroll as a single delta, 84 // and current APZ logic that transforms a delta into an overscroll 85 // amount limits each delta to at most 8px. 86 utils.setAsyncScrollOffset(document.documentElement, 0, -200); 87 88 // Now, perform a right-click in the gutter and check that APZ prevents 89 // the contextevent from reaching Gecko. 90 // To be sure that no event was dispatched to Gecko, install listeners 91 // on both the browser chrome window and the content window. 92 // This makes sure we catch the case where the overscroll transform causes 93 // the event to incorrectly target the browser chrome. 94 let deviceScale = window.devicePixelRatio; 95 let midGutter = 4 / deviceScale; // gutter is 8 *screen* pixels 96 startListeningForContextmenuEventsInChrome(); 97 let contentReceivedContextmenu = false; 98 let contentListener = function() { 99 contentReceivedContextmenu = true; 100 }; 101 document.addEventListener("contextmenu", contentListener); 102 await synthesizeNativeMouseEventWithAPZ({ 103 type: "click", 104 button: 2, // eSecondary (= "right mouse button") 105 target: window, 106 offsetX: 100, 107 offsetY: midGutter 108 }); 109 // Wait 10 frames for the event to maybe arrive, and if it 110 // hasn't, assume it won't. 111 for (let i = 0; i < 10; i++) { 112 await promiseFrame(); 113 } 114 info("Finished waiting around for contextmenu event"); 115 let chromeReceivedContextmenu = await didChromeReceiveContextmenu(); 116 ok(!chromeReceivedContextmenu, 117 "Gecko received contextmenu event in browser chrome when it shouldn't have"); 118 ok(!contentReceivedContextmenu, 119 "Gecko received contextmenu event targeting web content when it shouldn't have"); 120 stopListeningForContextmenuEventsInChrome(); 121 document.removeEventListener("contextmenu", contentListener); 122 } 123 124 waitUntilApzStable() 125 .then(test) 126 .then(subtestDone, subtestFailed); 127 128 </script> 129 </html>