tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

helper_long_tap.html (8857B)


      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 we get a touch-cancel after a contextmenu comes up</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 function addMouseEventListeners(aTarget) {
     13  aTarget.addEventListener("mousemove", recordEvent, true);
     14  aTarget.addEventListener("mouseover", recordEvent, true);
     15  aTarget.addEventListener("mouseenter", recordEvent, true);
     16  aTarget.addEventListener("mouseout", recordEvent, true);
     17  aTarget.addEventListener("mouseleave", recordEvent, true);
     18 }
     19 
     20 function removeMouseEventListeners(aTarget) {
     21  aTarget.removeEventListener("mousemove", recordEvent, true);
     22  aTarget.removeEventListener("mouseover", recordEvent, true);
     23  aTarget.removeEventListener("mouseenter", recordEvent, true);
     24  aTarget.removeEventListener("mouseout", recordEvent, true);
     25  aTarget.removeEventListener("mouseleave", recordEvent, true);
     26 }
     27 
     28 async function longPressLink() {
     29  let target = document.getElementById("b");
     30  addMouseEventListeners(target);
     31  await synthesizeNativeTouch(target, 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, function() {
     32    dump("Finished synthesizing touch-start, waiting for events...\n");
     33  });
     34 }
     35 
     36 var eventsFired = 0;
     37 function recordEvent(e) {
     38  let target = document.getElementById("b");
     39  const platform = getPlatform();
     40  if (platform == "windows") {
     41    // On Windows we get a mouselongtap event once the long-tap has been detected
     42    // by APZ, and that's what we use as the trigger to lift the finger. That then
     43    // triggers the contextmenu. This matches the platform convention.
     44    switch (eventsFired) {
     45      case 0: is(e.type, "touchstart", "Got a touchstart"); break;
     46      case 1:
     47        is(e.type, "mouselongtap", "Got a mouselongtap");
     48        setTimeout(async () => {
     49          await synthesizeNativeTouch(document.getElementById("b"), 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE);
     50        }, 0);
     51        break;
     52      case 2: is(e.type, "touchend", "Got a touchend"); break;
     53      case 3: is(e.type, "mouseover", "Got a mouseover"); break;
     54      case 4: is(e.type, "mouseenter", "Got a mouseenter"); break;
     55      case 5: is(e.type, "mousemove", "Got a mousemove"); break;
     56      case 6: is(e.type, "contextmenu", "Got a contextmenu"); e.preventDefault(); break;
     57      default: ok(false, "Got an unexpected event of type " + e.type); break;
     58    }
     59    eventsFired++;
     60 
     61    if (eventsFired == 7) {
     62      removeMouseEventListeners(target);
     63      dump("Finished waiting for events, doing an APZ flush to see if any more unexpected events come through...\n");
     64      promiseOnlyApzControllerFlushed().then(function() {
     65        dump("Done APZ flush, ending test...\n");
     66        subtestDone();
     67      });
     68    }
     69  } else if (platform != "android") {
     70    // On non-Windows desktop platforms we get a contextmenu event once the
     71    // long-tap has been detected. Since we prevent-default that, we don't get
     72    // a mouselongtap event at all, and instead get a touchcancel.
     73    switch (eventsFired) {
     74      case 0: is(e.type, "touchstart", "Got a touchstart"); break;
     75      case 1: is(e.type, "mouseover", "Got a mouseover"); break;
     76      case 2: is(e.type, "mouseenter", "Got a mouseenter"); break;
     77      case 3: is(e.type, "mousemove", "Got a mousemove"); break;
     78      case 4: is(e.type, "contextmenu", "Got a contextmenu");
     79        // Do preventDefault() in this content, thus we will not get any
     80        // touchcancel event.
     81        e.preventDefault();
     82        setTimeout(async () => {
     83          await synthesizeNativeTouch(target, 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, function() {
     84            dump("Finished synthesizing touch-end, waiting for a touchend event...\n");
     85          });
     86        }, 0);
     87        break;
     88      case 5: is(e.type, "touchend", "Got a touchend");
     89        // Send another long press.
     90        setTimeout(async () => {
     91          await synthesizeNativeTouch(target, 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, function() {
     92            dump("Finished synthesizing touch-start, waiting for events...\n");
     93          });
     94        }, 0);
     95        break;
     96      case 6: is(e.type, "touchstart", "Got another touchstart"); break;
     97      // NOTE: In this another event case, we don't get mouseover or mouseenter
     98      // event either since the target element hasn't been changed.
     99      case 7: is(e.type, "mousemove", "Got another mousemove"); break;
    100      case 8: is(e.type, "contextmenu", "Got another contextmenu");
    101        // DON'T DO preventDefault() this time, thus we should get a touchcancel
    102        // event.
    103        break;
    104      case 9: is(e.type, "mouselongtap", "Got a mouselongtap"); break;
    105      case 10: is(e.type, "touchcancel", "Got a touchcancel"); break;
    106      default: ok(false, "Got an unexpected event of type " + e.type); break;
    107    }
    108    eventsFired++;
    109 
    110    if (eventsFired == 11) {
    111      removeMouseEventListeners(target);
    112 
    113      setTimeout(async () => {
    114        // Ensure the context menu got closed, otherwise in the next test case
    115        // events will be consumed by the context menu unfortunately.
    116        await closeContextMenu();
    117 
    118        await synthesizeNativeTouch(target, 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, function() {
    119          dump("Finished synthesizing touch-end, doing an APZ flush to see if any more unexpected events come through...\n");
    120          promiseOnlyApzControllerFlushed().then(function() {
    121            dump("Done APZ flush, ending test...\n");
    122            subtestDone();
    123          });
    124        });
    125      }, 0);
    126    }
    127  } else {
    128    // On Android we get a contextmenu event once the long-tap has been
    129    // detected. If contextmenu opens we get a touchcancel event, and if
    130    // contextmenu didn't open because of preventDefault() in the content,
    131    // we will not get the touchcancel event.
    132    switch (eventsFired) {
    133      case 0: is(e.type, "touchstart", "Got a touchstart"); break;
    134      case 1: is(e.type, "mouseover", "Got a mouseover"); break;
    135      case 2: is(e.type, "mouseenter", "Got a mouseenter"); break;
    136      case 3: is(e.type, "mousemove", "Got a mousemove"); break;
    137      case 4: is(e.type, "contextmenu", "Got a contextmenu");
    138        // Do preventDefault() in this content, thus we will not get any
    139        // touchcancel event.
    140        e.preventDefault();
    141        setTimeout(async () => {
    142          await synthesizeNativeTouch(target, 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, function() {
    143            dump("Finished synthesizing touch-end, waiting for a touchend event...\n");
    144          });
    145        }, 0);
    146        break;
    147      case 5: is(e.type, "touchend", "Got a touchend");
    148        // Send another long press.
    149        setTimeout(async () => {
    150          await synthesizeNativeTouch(target, 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, function() {
    151            dump("Finished synthesizing touch-start, waiting for events...\n");
    152          });
    153        }, 0);
    154        break;
    155      case 6: is(e.type, "touchstart", "Got another touchstart"); break;
    156      // NOTE: In this another event case, we don't get mouseover or mouseenter
    157      // event either since the target element hasn't been changed.
    158      case 7: is(e.type, "mousemove", "Got another mousemove"); break;
    159      case 8: is(e.type, "contextmenu", "Got another contextmenu");
    160        // DON'T DO preventDefault() this time, thus we should get a touchcancel
    161        // event.
    162        break;
    163      case 9: is(e.type, "touchcancel", "Got a touchcancel"); break;
    164      default: ok(false, "Got an unexpected event of type " + e.type); break;
    165    }
    166    eventsFired++;
    167 
    168    if (eventsFired == 10) {
    169      removeMouseEventListeners(target);
    170      setTimeout(async () => {
    171        await synthesizeNativeTouch(target, 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, function() {
    172          dump("Finished synthesizing touch-end, doing an APZ flush to see if any more unexpected events come through...\n");
    173          promiseOnlyApzControllerFlushed().then(function() {
    174            dump("Done APZ flush, ending test...\n");
    175            subtestDone();
    176          });
    177        });
    178      }, 0);
    179    }
    180  }
    181 }
    182 
    183 window.addEventListener("touchstart", recordEvent, { passive: true, capture: true });
    184 window.addEventListener("touchend", recordEvent, { passive: true, capture: true });
    185 window.addEventListener("touchcancel", recordEvent, true);
    186 window.addEventListener("contextmenu", recordEvent, true);
    187 SpecialPowers.addChromeEventListener("mouselongtap", recordEvent, true);
    188 
    189 waitUntilApzStable()
    190 .then(longPressLink);
    191 
    192  </script>
    193 </head>
    194 <body>
    195 <a id="b" href="#">Link to nowhere</a>
    196 </body>
    197 </html>