<!DOCTYPE html>
<title>
  Element#requestFullscreen() works properly with a tree of cross-origin iframes
</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>

<body>
  <script>
    function waitFor(action, frameName) {
      return new Promise((resolve) => {
        window.addEventListener("message", function listener(e) {
          if (e.data.action === action && e.data.name === frameName) {
            window.removeEventListener("message", listener);
            resolve(event.data);
          }
        });
      });
    }

    function compare_report(report, expectedEvents) {
      assert_equals(
        report.events.length,
        expectedEvents.length,
        `Expected report for iframe "${report.frame}" to have ${expectedEvents.length} events: [${expectedEvents}]`
      );
      report.events.forEach((value, i) => {
        assert_equals(
          value,
          expectedEvents[i],
          "Event type matches in order expected"
        );
      });

      report.events.length
        ? assert_false(
            report.fullscreenElementIsNull,
            "Event fired, fullscreenElement is set"
          )
        : assert_true(
            report.fullscreenElementIsNull,
            "No event fired, fullscreenElement is null"
          );
    }

    const iframes = [
      {
        name: "A",
        src: "http://{{hosts[][]}}:{{ports[http][0]}}/fullscreen/api/resources/recursive-iframe-fullscreen.html?a",
        allow_fullscreen: true,
        expectedEvents: ["fullscreenchange"],
      },
      {
        name: "B",
        src: "http://{{hosts[][]}}:{{ports[http][1]}}/fullscreen/api/resources/recursive-iframe-fullscreen.html?b",
        allow_fullscreen: true,
        expectedEvents: ["fullscreenchange"],
      },
      {
        name: "C",
        src: "http://{{hosts[alt][]}}:{{ports[http][0]}}/fullscreen/api/resources/recursive-iframe-fullscreen.html?c",
        allow_fullscreen: true,
        expectedEvents: ["fullscreenchange"],
      },
      {
        name: "D",
        src: "http://{{hosts[alt][]}}:{{ports[http][1]}}/fullscreen/api/resources/recursive-iframe-fullscreen.html?d",
        allow_fullscreen: true,
        expectedEvents: ["fullscreenchange"],
      },
      {
        name: "E",
        src: "http://{{hosts[][]}}:{{ports[http][0]}}/fullscreen/api/resources/recursive-iframe-fullscreen.html?e",
        allow_fullscreen: true,
        expectedEvents: [],
      },
    ];

    promise_setup(async () => {
      // Add the first iframe.
      const iframeDetails = iframes[0];
      const child_frame = document.createElement("iframe");
      child_frame.allow = iframeDetails.allow_fullscreen ? "fullscreen" : "";
      child_frame.name = iframeDetails.name;
      child_frame.style.width = "100%";
      child_frame.style.height = "100%";
      child_frame.src = iframeDetails.src;
      await new Promise((resolve) => {
        child_frame.onload = resolve;
        document.body.appendChild(child_frame);
      });

      // Create the nested iframes.
      for (let i = 1; i < iframes.length; i++) {
        const parentName = iframes[i - 1].name;
        const details = iframes[i];
        child_frame.contentWindow.postMessage(
          { action: "addIframe", iframe: details, name: parentName },
          "*"
        );
        await waitFor("load", details.name);
      }
    });

    promise_test(async (t) => {
      t.add_cleanup(() => {
        if (document.fullscreenElement) {
          return document.exitFullscreen();
        }
      });
      document.onfullscreenerror = t.unreached_func(
        "fullscreenerror event fired"
      );
      const fsChangeFiredPromise = new Promise((resolve) => {
        document.onfullscreenchange = resolve;
      });

      const child_frame = document.querySelector("iframe[name=A]");
      child_frame.contentWindow.postMessage(
        {
          action: "requestFullscreen",
          name: "D",
        },
        "*"
      );

      await waitFor("requestFullscreen", "D");

      for (const frame of iframes.slice(1)) {
        const data = {
          action: "requestReport",
          name: frame.name,
        };
        child_frame.contentWindow.postMessage(data, "*");
        const { report } = await waitFor("report", frame.name);
        compare_report(report, frame.expectedEvents);
      }
      await fsChangeFiredPromise;
    }, "Element#requestFullscreen() works properly with a tree of cross-origin iframes");
  </script>
</body>
