<!DOCTYPE html>
<meta charset="utf-8">
<title></title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<script src="/tests/SimpleTest/paint_listener.js"></script>
<script src="/tests/gfx/layers/apz/test/mochitest/apz_test_utils.js"></script>
<script src="/tests/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js"></script>
<iframe width=100 height=200 scrolling="no"></iframe>
<script>
let state = "start";

const scale = window.devicePixelRatio;

function getScreenPosition(aElement, aOffsetX, aOffsetY) {
  const rect = aElement.getBoundingClientRect();
  const x = aOffsetX + window.mozInnerScreenX + rect.left;
  const y = aOffsetY + window.mozInnerScreenY + rect.top;
  return [Math.round(x * scale), Math.round(y * scale)];
}

add_task(async () => {
  await SimpleTest.promiseFocus();

  const loadsPromise = new Promise((resolve, reject) => {
    let readyMiddle = false;
    let readyInner = false;
    window.addEventListener("message", function listener(event) {
      info(`receive ${event.data}`);
      if (event.data == "middleready") {
        readyMiddle = true;
      } else if (event.data == "innerready") {
        readyInner = true;
      } else {
        reject("Unexpected message when waiting for ready " + event.data);
      }
      if (readyInner && readyMiddle) {
        state = "ready";
        window.removeEventListener("message", listener);
        resolve();
      }
    });
  });

  const iframe = document.querySelectorAll("iframe")[0];
  iframe.src = "https://example.com/tests/dom/events/test/file_focus_blur_on_click_in_deep_cross_origin_iframe_middle.html";

  await loadsPromise;

  // Wait for APZ state stable so that mouse event handling APZ works properly
  // in out-of-process iframes.
  await waitUntilApzStable();

  // NOTE: synthesizeMouseAtCenter doesn't work for OOP iframes (bug 1528935),
  // so we use promiseNativeMouseEventWithAPZ instead.
  const [expectedScreenX, expectedScreenY] =
    getScreenPosition(iframe, 10, 10);

  const firstClickPromise = new Promise((resolve, reject) => {
    window.addEventListener("message", function listener(event) {
      info(`receive ${event.data}`);
      if (state == "ready") {
        if (event.data == "innerfocus") {
          state = "innerfocusbeforeclick";
        } else if (event.data == "innerclick") {
          ok(false, "Focusing failed to complete before mouseup");
          state = "innerclickbeforefocus";
        } else if (event.data == "middlefocus") {
          is(false, "Should not get an extra middlefocus.");
        } else {
          is(event.data, "neverthisevent", "Unexpected event (first click)");
        }
      } else if (state == "innerfocusbeforeclick") {
        is(event.data, "innerclick", "The second event should be 'innerclick'");
        state = "firstclick";
        window.removeEventListener("message", listener);
        resolve();
      } else if (state == "innerclickbeforefocus") {
        is(event.data, "innerfocus", "The second event should be 'innerfocus'");
        state = "firstclick";
        window.removeEventListener("message", listener);
        resolve();
     } else {
        reject("Unexpected message in firstClickPromise " + event.data);
      }
    });
  });

  await promiseNativeMouseEventWithAPZ({
    type: "click",
    target: iframe,
    screenX: expectedScreenX,
    screenY: expectedScreenY + Math.round(110 * scale),
  });

  await firstClickPromise;

  SimpleTest.requestFlakyTimeout("Waiting for unwanted events that don't exist on success.");

  const secondClickPromise = new Promise((resolve, reject) => {
    window.addEventListener("message", function listener(event) {
      info(`receive ${event.data}`);
      if (state == "firstclick") {
        is(event.data, "middlefocus", "The third event should be 'middlefocus'.");
        state = "middlefocusbeforeclick";
      } else if (state == "middlefocusbeforeclick") {
        // The order of blur and click is non-deterministic even in the non-Fission case.
        if (event.data == "middleclick") {
          state = "waitingforinnerblurafterclick";
        } else if (event.data == "innerblur") {
          state = "innerblurbeforeclick";
        } else {
          is(event.data, "neverthisevent", "Unexpected event (first click)");
        }
      } else if (state == "waitingforinnerblurafterclick") {
        is(event.data, "innerblur", "The fifth event should be 'innerblur'.");
        state = "secondclick";
        setTimeout(function() {
          // Wait for potential other unwanted events
          window.removeEventListener("message", listener);
          resolve()
        }, 200);
      } else if (state == "innerblurbeforeclick") {
        is(event.data, "middleclick", "The fifth event should be 'middleclick'.");
        state = "secondclick";
        setTimeout(function() {
          // Wait for potential other unwanted events
          window.removeEventListener("message", listener);
          resolve()
        }, 200);
      } else {
        reject("Unexpected message in secondClickPromise " + event.data);
      }
    });
  });

  await promiseNativeMouseEventWithAPZ({
    type: "click",
    target: iframe,
    screenX: expectedScreenX,
    screenY: expectedScreenY,
  });

  await secondClickPromise;
});
</script>
