helper_tap_default_passive.html (3508B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=device-width; initial-scale=1.0"> 6 <title>Ensure APZ doesn't wait for passive listeners</title> 7 <script type="application/javascript" src="apz_test_native_event_utils.js"></script> 8 <script type="application/javascript" src="apz_test_utils.js"></script> 9 <script src="/tests/SimpleTest/paint_listener.js"></script> 10 <script type="application/javascript"> 11 12 var touchdownTime; 13 14 async function longPressLink() { 15 await synthesizeNativeTouch(document.getElementById("b"), 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, function() { 16 dump("Finished synthesizing touch-start, waiting for events...\n"); 17 }); 18 } 19 20 var touchstartReceived = false; 21 function recordEvent(e) { 22 if (!touchstartReceived) { 23 touchstartReceived = true; 24 is(e.type, "touchstart", "Got a touchstart"); 25 e.preventDefault(); // should be a no-op because it's a passive listener 26 return; 27 } 28 29 // If APZ decides to wait for the content response on a particular input block, 30 // it needs to wait until both the touchstart and touchmove event are handled 31 // by the main thread. In this case there is no touchmove at all, so APZ would 32 // end up waiting indefinitely and time out the test. The fact that we get this 33 // contextmenu event (mouselongtap on Windows) at all means that APZ decided 34 // not to wait for the content response, which is the desired behaviour, since 35 // the touchstart listener was registered as a passive listener. 36 if (getPlatform() == "windows") { 37 is(e.type, "mouselongtap", "Got a mouselongtap"); 38 } else { 39 is(e.type, "contextmenu", "Got a contextmenu"); 40 } 41 e.preventDefault(); 42 43 setTimeout(async () => { 44 // On Windows below TOUCH_REMOVE event triggers opening a context menu, we 45 // need to prevent it. 46 const contextmenuPromise = promiseOneEvent(window, "contextmenu", event => { 47 event.preventDefault(); 48 return true; 49 }); 50 const touchendPromise = promiseOneEvent(window, "touchend", () => { 51 return true; 52 }); 53 54 await synthesizeNativeTouch(document.getElementById("b"), 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, function() { 55 dump("Finished synthesizing touch-end to clear state; finishing test...\n"); 56 }); 57 58 await touchendPromise; 59 if (getPlatform() == "windows") { 60 await contextmenuPromise; 61 } 62 subtestDone(); 63 }, 0); 64 } 65 66 function preventDefaultListener(e) { 67 e.preventDefault(); 68 } 69 70 // Note, not passing 'passive'. 71 window.addEventListener("touchstart", recordEvent, { capture: true }); 72 window.ontouchstart = preventDefaultListener; 73 if (getPlatform() == "windows") { 74 SpecialPowers.addChromeEventListener("mouselongtap", recordEvent, true); 75 } else { 76 window.addEventListener("contextmenu", recordEvent, true); 77 } 78 79 waitUntilApzStable() 80 .then(longPressLink); 81 82 </script> 83 </head> 84 <body> 85 <a id="b" href="#">Link to nowhere</a> 86 <script> 87 document.addEventListener("touchstart", preventDefaultListener, { capture: true }); 88 document.ontouchstart = preventDefaultListener; 89 document.documentElement.addEventListener("touchstart", preventDefaultListener, { capture: true }); 90 document.documentElement.ontouchstart = preventDefaultListener; 91 document.body.addEventListener("touchstart", preventDefaultListener, { capture: true }); 92 document.body.ontouchstart = preventDefaultListener; 93 document.body.setAttribute("ontouchstart", "event.preventDefault()"); 94 </script> 95 </body> 96 </html>