tor-browser

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

element-request-fullscreen-cross-origin-multi-steps.sub.html (5771B)


      1 <!DOCTYPE html>
      2 <title>
      3  Element#requestFullscreen() works properly with a tree of cross-origin iframes, with multiple requests
      4 </title>
      5 <script src="/resources/testharness.js"></script>
      6 <script src="/resources/testharnessreport.js"></script>
      7 <script src="/resources/testdriver.js"></script>
      8 <script src="/resources/testdriver-vendor.js"></script>
      9 
     10 <body>
     11  <script>
     12    let childFrame = null;
     13    function waitFor(action, frameName) {
     14      return new Promise((resolve) => {
     15        window.addEventListener("message", function listener(e) {
     16          if (e.data.action === action && e.data.name === frameName) {
     17            window.removeEventListener("message", listener);
     18            resolve(event.data);
     19          }
     20        });
     21      });
     22    }
     23 
     24    function compare_report(report, frame, expectedIndex) {
     25      assert_array_equals(report.events, frame.expectedEvents[expectedIndex], `compare events for ${frame.name}`);
     26      assert_equals(report.fullscreenElementIsNull, frame.expectedNullFullscreenElement[expectedIndex], `frame ${frame.name} has expected fullscreen element`);
     27    }
     28 
     29    const iframes = [
     30      {
     31        name: "A",
     32        src: "http://{{hosts[][]}}:{{ports[http][0]}}/_mozilla/fullscreen/api/resources/recursive-iframe-fullscreen.html?a",
     33        allow_fullscreen: true,
     34        expectedEvents: [["fullscreenchange"], []],
     35        expectedNullFullscreenElement: [false, false]
     36      },
     37      { // first check should see its body go fs, 2nd should see it's <iframe> go fs
     38        name: "B",
     39        src: "http://{{hosts[alt][]}}:{{ports[http][1]}}/_mozilla/fullscreen/api/resources/recursive-iframe-fullscreen.html?b",
     40        allow_fullscreen: true,
     41        expectedEvents: [["fullscreenchange"], ["fullscreenchange"]],
     42        expectedNullFullscreenElement: [false, false]
     43      },
     44      {
     45        name: "C",
     46        src: "http://{{hosts[][www]}}:{{ports[http][0]}}/_mozilla/fullscreen/api/resources/recursive-iframe-fullscreen.html?c",
     47        allow_fullscreen: true,
     48        expectedEvents: [[], ["fullscreenchange"]],
     49        expectedNullFullscreenElement: [true, false]
     50      },
     51      {
     52        name: "D",
     53        src: "http://{{hosts[][]}}:{{ports[http][1]}}/_mozilla/fullscreen/api/resources/recursive-iframe-fullscreen.html?d",
     54        allow_fullscreen: true,
     55        expectedEvents: [[],["fullscreenchange"]],
     56        expectedNullFullscreenElement: [true, false]
     57      },
     58      {
     59        name: "E",
     60        src: "http://{{hosts[][]}}:{{ports[http][0]}}/_mozilla/fullscreen/api/resources/recursive-iframe-fullscreen.html?e",
     61        allow_fullscreen: true,
     62        expectedEvents: [[],[]],
     63        expectedNullFullscreenElement: [true, true]
     64      },
     65    ];
     66 
     67    promise_setup(async () => {
     68      // Add the first iframe.
     69      const iframeDetails = iframes[0];
     70      childFrame = document.createElement("iframe");
     71      childFrame.allow = iframeDetails.allow_fullscreen ? "fullscreen" : "";
     72      childFrame.name = iframeDetails.name;
     73      childFrame.style.width = "100%";
     74      childFrame.style.height = "100%";
     75      childFrame.src = iframeDetails.src;
     76      await new Promise((resolve) => {
     77        childFrame.onload = resolve;
     78        document.body.appendChild(childFrame);
     79      });
     80 
     81      // Create the nested iframes.
     82      for (let i = 1; i < iframes.length; i++) {
     83        const parentName = iframes[i - 1].name;
     84        const details = iframes[i];
     85        childFrame.contentWindow.postMessage(
     86          { action: "addIframe", iframe: details, name: parentName },
     87          "*"
     88        );
     89        await waitFor("load", details.name);
     90      }
     91    });
     92 
     93    promise_test(async (t) => {
     94      t.add_cleanup(async () => {
     95        if (document.fullscreenElement) {
     96          await new Promise((resolve) => {
     97             document.addEventListener("fullscreenchange", resolve, { once: true });
     98             document.exitFullscreen();
     99          });
    100        }
    101        if (childFrame) {
    102          childFrame.remove();
    103        }
    104      });
    105      document.onfullscreenerror = t.unreached_func(
    106        "fullscreenerror event fired"
    107      );
    108 
    109      const childFrame = document.querySelector("iframe[name=A]");
    110 
    111      // request fullscreen by trusted click in `name`
    112      // and wait until we've seen fullscreen events from
    113      // `expectedFrames`. This is to handle intermittent failures
    114      // where we check results before the request has completed entirely.
    115      const requestFullscreenIn = (name, expectedFrames) => {
    116        return new Promise((resolve) => {
    117          const pending = new Set(expectedFrames);
    118 
    119          function listener(e) {
    120            if (e.data.action === "fsEvent" && pending.has(e.data.name)) {
    121              pending.delete(e.data.name);
    122 
    123              if (pending.size === 0) {
    124                window.removeEventListener("message", listener);
    125                resolve();
    126              }
    127            }
    128          }
    129 
    130          window.addEventListener("message", listener);
    131          childFrame.contentWindow.postMessage(
    132            { action: "requestFullscreen", name },
    133            "*"
    134          );
    135        });
    136      };
    137 
    138      const verifyResult = async (expectedResultIndex) => {
    139        for (const frame of iframes) {
    140          const data = {
    141            action: "requestReport",
    142            name: frame.name,
    143          };
    144          childFrame.contentWindow.postMessage(data, "*");
    145          const { report } = await waitFor("report", frame.name);
    146          compare_report(report, frame, expectedResultIndex);
    147        }
    148      }
    149 
    150      await requestFullscreenIn("B", ["A", "B"]);
    151      await verifyResult(0);
    152 
    153      await requestFullscreenIn("D", ["B", "C", "D"]);
    154      await verifyResult(1);
    155    }, "Element#requestFullscreen() works properly with a tree of cross-origin iframes");
    156  </script>
    157 </body>