Source code
Revision control
Copy as Markdown
Other Tools
<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>Ensure positioned content inside inactive scollframes but on top of OOPIFs hit-test properly</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>
    function getEventPromise(eventName) {
      let eventPromise = new Promise(resolve => {
        const listener = event => {
          if (event.data === eventName) {
            window.removeEventListener("message", listener);
            resolve();
          }
        }
        window.addEventListener("message", listener);
      });
      return eventPromise;
    }
    async function makeIframeScrollable(iframe) {
      let readyPromise = getEventPromise("scrollableReady");
      let ids = await SpecialPowers.spawn(iframe, [], async () => {
        // Ensure the oopif is scrollable, and wait for the paint so that the
        // compositor also knows it's scrollable.
        content.document.body.style.height = "200vh";
        await content.wrappedJSObject.promiseApzFlushedRepaints();
        content.window.parent.postMessage("scrollableReady", "*");
        let utils = SpecialPowers.getDOMWindowUtils(content.window);
        return [utils.getLayersId(), utils.getViewId(content.document.scrollingElement)];
      });
      await readyPromise;
      return ids;
    }
    async function test() {
      // Set up iframe
      let iframe = document.getElementById("testframe");
      await setupCrossOriginIFrame(iframe, "helper_fission_plain.html");
      const remoteType = await SpecialPowers.spawn(iframe, [], async () => {
        return await SpecialPowers.spawnChrome([], () => {
          return windowGlobalParent.domProcess.remoteType;
        });
      });
      if (remoteType === "web") {
        is(SpecialPowers.effectiveIsolationStrategy(), SpecialPowers.ISOLATION_STRATEGY.IsolateHighValue);
        ok(true, "Skipping this test since the document on example.com got loaded in the same content process");
        return;
      }
      let [layersId, viewId] = await makeIframeScrollable(iframe);
      let config = getHitTestConfig();
      let utils = config.utils;
      // The #scroller div is (a) inactive, and (b) under the OOPIF. However, it
      // also contains a positioned element with a high z-index (#abspos). #abspos
      // therefore sits on top of the OOPIF. Hit-testing on #abspos should hit
      // #scroller, but anywhere else within the OOPIF box should hit the OOPIF.
      checkHitResult(await hitTestOOPIF(centerOf("abspos"), iframe),
        APZHitResultFlags.VISIBLE |
        (config.activateAllScrollFrames ? 0 : APZHitResultFlags.INACTIVE_SCROLLFRAME),
        config.activateAllScrollFrames ?
          utils.getViewId(document.getElementById("scroller")) :
          utils.getViewId(document.scrollingElement),
        utils.getLayersId(),
        "abspos element on top of OOPIF should hit parent doc hosting the OOPIF");
      // If the fix for the bug this test is for is not active (as indicated by
      // config.activateAllScrollFrames) then we just accept the wrong answer. As
      // of writing this comment the fix will only be active if fission is pref'ed
      // on, not just enabled for this window, ie the test suite is run in fission
      // mode.
      checkHitResult(await hitTestOOPIF(centerOf("scroller"), iframe),
        APZHitResultFlags.VISIBLE |
        (config.activateAllScrollFrames ? 0 : APZHitResultFlags.INACTIVE_SCROLLFRAME),
        config.activateAllScrollFrames ?
          viewId :
          utils.getViewId(document.scrollingElement),
        config.activateAllScrollFrames ?
          layersId :
          utils.getLayersId(),
        "Part of OOPIF sitting on top of the inactive scrollframe should hit OOPIF");
      checkHitResult(await hitTestOOPIF({ x: 250, y: 100 }, iframe),
        APZHitResultFlags.VISIBLE,
        viewId,
        layersId,
        "part of OOPIF outside the inactive scfollframe rect should hit the OOPIF");
    }
    if (!SpecialPowers.Services.appinfo.fissionAutostart) {
      ok(true, "This test doesn't need to run with disabling Fission");
      subtestDone();
    } else {
      waitUntilApzStable()
        .then(test)
        .then(subtestDone, subtestFailed);
    }
  </script>
</head>
<body>
  <style>
    html,
    body {
      margin: 0;
    }
    body {
      /* Ensure root document is scrollable so that #scroller is inactive by
      default */
      height: 200vh;
    }
    iframe {
      position: absolute;
      width: 300px;
      height: 200px;
    }
    #scroller {
      position: absolute;
      top: 0;
      left: 0;
      width: 200px;
      height: 200px;
      background-color: transparent;
      overflow-y: scroll;
    }
  </style>
  <div id="scroller">
    <div style="height:500px">inside scroller</div>
    <div id="abspos"
      style="position: absolute; z-index: 5; left: 0; width: 80px; top: 20px; height: 80px; background-color: green">
      abspos inside scroller</div>
  </div>
  <iframe id="testframe"></iframe>
</body>
</html>