Bug 1548687 - Add mochitest to exercise scrolling an oopif's ancestor. r=botond
☠☠ backed out by c05a24ea5373 ☠ ☠
authorKartikaya Gupta <kgupta@mozilla.com>
Wed, 19 Jun 2019 19:23:54 +0000
changeset 479244 a222c1b945407d9d9b816a8b1300dcb14a76b3d1
parent 479243 1ddcedc57f6ff5f8313cea655ea3f7425f8e7894
child 479245 b8f38148ccbc4bc094d685c296ad49f886a40689
push id36177
push userrmaries@mozilla.com
push dateThu, 20 Jun 2019 09:46:31 +0000
treeherdermozilla-central@a440f0629814 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond
bugs1548687
milestone69.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1548687 - Add mochitest to exercise scrolling an oopif's ancestor. r=botond This scrolls the document containing the OOPIF and ensures that hit-testing still works. Some of the fission hit-testing machinery is still WR-only, so we have to restrict the subtest to only run when WR is enabled. Differential Revision: https://phabricator.services.mozilla.com/D35204
gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
gfx/layers/apz/test/mochitest/browser_test_group_fission.js
gfx/layers/apz/test/mochitest/helper_fission_scroll_oopif.html
--- a/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
+++ b/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
@@ -394,16 +394,25 @@ function moveMouseAndScrollWheelOver(tar
     if (waitForScroll) {
       synthesizeNativeWheelAndWaitForScrollEvent(target, dx, dy, 0, -10, testDriver);
     } else {
       synthesizeNativeWheelAndWaitForWheelEvent(target, dx, dy, 0, -10, testDriver);
     }
   });
 }
 
+// Same as moveMouseAndScrollWheelOver, but returns a promise instead of taking
+// a callback function. Eventually we should convert all these callback-taking
+// functions into promise-producing functions but for now this is a stopgap.
+function promiseMoveMouseAndScrollWheelOver(target, dx, dy, waitForScroll = true) {
+  return new Promise(resolve => {
+    moveMouseAndScrollWheelOver(target, dx, dy, resolve, waitForScroll);
+  });
+}
+
 // Synthesizes events to drag |element|'s vertical scrollbar by the distance
 // specified, synthesizing a mousemove for each increment as specified.
 // Returns false if the element doesn't have a vertical scrollbar. Otherwise,
 // returns a generator that should be invoked after the mousemoves have been
 // processed by the widget code, to end the scrollbar drag. Mousemoves being
 // processed by the widget code can be detected by listening for the mousemove
 // events in the caller, or for some other event that is triggered by the
 // mousemove, such as the scroll event resulting from the scrollbar drag.
--- a/gfx/layers/apz/test/mochitest/browser_test_group_fission.js
+++ b/gfx/layers/apz/test/mochitest/browser_test_group_fission.js
@@ -11,16 +11,17 @@ add_task(async function test_main() {
   // is fission-enabled.
   var test_urls = [
     httpURL("helper_fission_basic.html"),
     // add additional tests here
   ];
   if (isWebRender) {
     test_urls = test_urls.concat([
       httpURL("helper_fission_transforms.html"),
+      httpURL("helper_fission_scroll_oopif.html"),
       // add additional WebRender-specific tests here
     ]);
   }
 
   let fissionWindow = await BrowserTestUtils.openNewBrowserWindow({fission: true});
 
   // We import the JSM here so that we can install functions on the class
   // below.
new file mode 100644
--- /dev/null
+++ b/gfx/layers/apz/test/mochitest/helper_fission_scroll_oopif.html
@@ -0,0 +1,91 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Test for async-scrolling an OOPIF and ensuring hit-testing still works</title>
+  <script src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script src="/tests/SimpleTest/paint_listener.js"></script>
+  <script src="helper_fission_utils.js"></script>
+  <script src="apz_test_utils.js"></script>
+  <script src="apz_test_native_event_utils.js"></script>
+  <script>
+
+fission_subtest_init();
+
+FissionTestHelper.startTestPromise
+  .then(waitUntilApzStable)
+  .then(loadOOPIFrame("testframe", "helper_fission_empty.html"))
+  .then(waitUntilApzStable)
+  .then(runAsyncContinuation(test))
+  .then(FissionTestHelper.subtestDone, FissionTestHelper.subtestDone);
+
+
+let code_for_oopif_to_run = function() {
+  document.addEventListener("click", function(e) {
+    dump(`OOPIF got click at ${e.clientX},${e.clientY}\n`);
+    let result = { x: e.clientX, y: e.clientY };
+    FissionTestHelper.fireEventInEmbedder("OOPIF:ClickData", result);
+  });
+  dump("OOPIF registered click listener\n");
+  return true;
+};
+
+async function clickOnIframe(x, y) {
+  let iframePromise = promiseOneEvent("OOPIF:ClickData", null);
+  synthesizeNativeClick(document.body, x, y, function() {
+    dump("Finished synthesizing click, waiting for OOPIF message...\n");
+  });
+  let iframeResponse = await iframePromise;
+  dump("OOPIF response: " + JSON.stringify(iframeResponse.data) + "\n");
+  return iframeResponse.data;
+}
+
+function failsafe() {
+  // Catch and fail faster on the case where the click ends up not going to
+  // the iframe like it should. Otherwise the test hangs until timeout which
+  // is more painful.
+  document.addEventListener("click", function(e) {
+    dump(`${location.href} got click at ${e.clientX},${e.clientY}\n`);
+    ok(false, "The OOPIF hosting page should not have gotten the click");
+    setTimeout(FissionTestHelper.subtestDone, 0);
+  }, {once: true});
+}
+
+// The actual test
+
+async function* test() {
+  ok(SpecialPowers.getBoolPref("apz.paint_skipping.enabled"),
+     "paint-skipping is expected to be enabled for this test to be meaningful");
+
+  let iframeElement = document.getElementById("testframe");
+
+  let iframeResponse = await FissionTestHelper.sendToOopif(iframeElement, code_for_oopif_to_run.toSource() + "()");
+  dump("OOPIF response: " + JSON.stringify(iframeResponse) + "\n");
+  ok(iframeResponse, "code_for_oopif_to_run successfully installed");
+
+  // hit-test into the iframe before scrolling
+  let oldClickPoint = await clickOnIframe(50, 250);
+
+  // do an APZ scroll and wait for the main-thread to get the repaint request,
+  // and queue up a paint-skip scroll notification back to APZ.
+  await promiseMoveMouseAndScrollWheelOver(document.body, 10, 10);
+  await promiseAllPaintsDone();
+
+  is(window.scrollY, 10, "window has scrolled by 10 pixels");
+
+  // hit-test into the iframe after scrolling. The coordinates here are the
+  // same relative to the body as before, but get computed to be different
+  // relative to the window/screen.
+  let newClickPoint = await clickOnIframe(50, 250);
+
+  is(newClickPoint.x, oldClickPoint.x, "x-coord of old and new match");
+  is(newClickPoint.y, oldClickPoint.y, "y-coord of old and new match");
+}
+
+  </script>
+</head>
+<body onload="failsafe()">
+<iframe style="margin-top: 200px" id="testframe"></iframe>
+<div style="height: 5000px">tall div to make the page scrollable</div>
+</body>
+</html>