tor-browser

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

closes-on-navigation-or-destroy.https.html (5571B)


      1 <!DOCTYPE html>
      2 <title>Test that a document picture-in-picture window closes when itself or the opener is navigated / destroyed</title>
      3 <script src="/resources/testharness.js"></script>
      4 <script src="/resources/testharnessreport.js"></script>
      5 <script src="/resources/testdriver.js"></script>
      6 <script src="/resources/testdriver-vendor.js"></script>
      7 <link rel="help" href="https://wicg.github.io/document-picture-in-picture/#close-on-destroy"/>
      8 <link rel="help" href="https://wicg.github.io/document-picture-in-picture/#close-on-navigate"/>
      9 <body>
     10 <script>
     11 function waitForEvent(target, event) {
     12  return new Promise(resolve => target.addEventListener(event, resolve, {once: true}))
     13 }
     14 
     15 async function waitForMessage(target, type) {
     16  const { data } = await waitForEvent(target, 'message');
     17  assert_equals(data.type, type, "Got the expected message");
     18  return data;
     19 }
     20 
     21 window.addEventListener('message', ({data}) => {
     22  if (data.type == 'error') {
     23    throw data;
     24  }
     25 });
     26 
     27 let last_id = 0;
     28 async function new_opener_with_pip_window(t) {
     29  // We cannot navigate this window, so do the tests in a popup.
     30  const channelName = `pip channel ${++last_id}`;
     31 
     32  const opener = window.open(`support/popup-opens-pip.html`);
     33  await waitForEvent(opener, "load");
     34  assert_true(true, "Popup loaded");
     35 
     36  const pipChannel = new BroadcastChannel(channelName);
     37  pipChannel.addEventListener('message', ({data}) => {
     38    if (data.type == 'error') {
     39      throw new Error(`${data.name}: ${data.message}`);
     40    }
     41  });
     42 
     43  await test_driver.bless('activate popup window', null, opener);
     44  opener.postMessage({ type: 'request-pip', channelName });
     45  await waitForMessage(pipChannel, 'pip-ready');
     46 
     47  t.add_cleanup(function() {
     48    pipChannel.close();
     49    opener.close();
     50  });
     51 
     52  return { opener, pipChannel };
     53 }
     54 
     55 function evalInPIP(pipChannel, code, args = []) {
     56  pipChannel.postMessage({ type: "exec", code: code.toString(), args });
     57  return waitForMessage(pipChannel, "exec-result");
     58 }
     59 
     60 promise_test(async (t) => {
     61  // Trivial test case, mostly a sanity-check for this test infrastructure
     62  const { opener, pipChannel } = await new_opener_with_pip_window(t);
     63  assert_true(true, 'Succeded in getting an opener with pip window');
     64 
     65  opener.postMessage({ type: 'close-pip' });
     66  // This also tests that a PIP window gets a pagehide
     67  await waitForMessage(pipChannel, 'pip-pagehide');
     68 
     69  opener.postMessage({ type: 'get-pip-status' });
     70  const statusMsg = await waitForMessage(window, 'pip-status');
     71  assert_true(statusMsg.closed, 'Succeeded in closing the pip window');
     72 }, 'PIP window can be closed');
     73 
     74 promise_test(async (t) => {
     75  const { opener, pipChannel } = await new_opener_with_pip_window(t);
     76 
     77  opener.close();
     78  await waitForMessage(pipChannel, 'pip-pagehide');
     79 }, 'PIP window closes when opener closes');
     80 
     81 function waitTillPiPClosed(t, opener) {
     82  let closed = false;
     83  let shouldPing = true;
     84 
     85  const listener = ({ data }) => {
     86    if (data.type == "pip-status") {
     87      closed = data.closed;
     88      shouldPing = true;
     89    }
     90  }
     91  window.addEventListener("message", listener);
     92 
     93  const condition = () => {
     94    if (shouldPing && !closed) {
     95      opener.postMessage({ type: 'get-pip-status' });
     96      shouldPing = false;
     97    }
     98    return closed;
     99  }
    100  return t.step_wait(condition, "PiP window .closed becomes true")
    101    .finally(() => {
    102      window.removeEventListener("message", listener)
    103    })
    104 }
    105 
    106 promise_test(async (t) => {
    107  const { opener, pipChannel } = await new_opener_with_pip_window(t);
    108 
    109  // Per spec, #close-a-top-level-traversable doesn't set #is-closing and thus
    110  // window.closed only becomes true when the traversable is destroyed. This happens
    111  // via `afterAllUnloads` after pagehide. This is different for window.close().
    112  // https://github.com/whatwg/html/issues/11853
    113  opener.postMessage({ type: 'navigate-pip', href: "/common/blank.html" });
    114  const statusMsg = await waitForMessage(pipChannel, 'pip-pagehide');
    115  assert_false(statusMsg.closed, "window.closed is false during pagehide");
    116  await waitTillPiPClosed(t, opener);
    117 }, "window.closed becomes true after pagehide if not window.close() initiated");
    118 
    119 promise_test(async (t) => {
    120  const { opener, pipChannel } = await new_opener_with_pip_window(t);
    121 
    122  opener.postMessage({ type: 'navigate-pip', href: "about:blank#0" });
    123 
    124  opener.postMessage({ type: 'get-pip-status' });
    125  const statusMsg = await waitForMessage(window, 'pip-status');
    126  assert_false(statusMsg.closed, 'Same-page navigation did not close PIP');
    127 
    128  opener.postMessage({ type: 'navigate-pip', href: "/common/blank.html" });
    129  await waitForMessage(pipChannel, 'pip-pagehide');
    130  await waitTillPiPClosed(t, opener);
    131 }, 'PIP window closes when navigated');
    132 
    133 promise_test(async (t) => {
    134  const { opener, pipChannel } = await new_opener_with_pip_window(t);
    135 
    136  await evalInPIP(pipChannel, () => window.name = "pipwindow" )
    137 
    138  const w = window.open("/common/blank.html", "pipwindow");
    139  await waitForMessage(pipChannel, "pip-pagehide");
    140  await waitTillPiPClosed(t, opener);
    141 }, 'PIP window closes when navigated by name');
    142 
    143 promise_test(async (t) => {
    144  const { opener, pipChannel } = await new_opener_with_pip_window(t);
    145 
    146  opener.location = opener.location.href + "#0";
    147 
    148  opener.postMessage({ type: 'get-pip-status' });
    149  const statusMsg = await waitForMessage(window, 'pip-status');
    150  assert_false(statusMsg.closed, 'Same-page navigation of opener did not close PIP');
    151 
    152  opener.location = "/common/blank.html";
    153  await waitForMessage(pipChannel, 'pip-pagehide');
    154 }, 'PIP window closes when opener navigates');
    155 </script>
    156 </body>