tor-browser

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

detached-iframe.html (5756B)


      1 <!DOCTYPE html>
      2 <meta charset=utf-8>
      3 <script src="/resources/testharness.js"></script>
      4 <script src="/resources/testharnessreport.js"></script>
      5 <script src="/common/get-host-info.sub.js"></script>
      6 <!-- Pull in the with_iframe helper function from the service worker tests -->
      7 <script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
      8 <body>
      9 <script>
     10 const TEST_IFRAME_CLASS_NAME = 'test-iframe';
     11 const events = [];
     12 var bc1;
     13 const DONE_MSG = 'done';
     14 
     15 function DetachedIframeTestCheckForOneMessage(t) {
     16  return new Promise((resolve) => {
     17    bc1.onmessage = t.step_func(e => {
     18      events.push(e);
     19      if (e.data == DONE_MSG) {
     20        assert_equals(events.length, 1);
     21        resolve();
     22      }
     23    });
     24  });
     25 }
     26 
     27 const IframeAction = {
     28  REMOVE_BEFORE_CREATION: 'remove-before-creation',
     29  REMOVE_AFTER_CREATION: 'remove-after-creation',
     30 };
     31 
     32 async function doMessageSentTest(t, channelName, action) {
     33  await with_iframe('about:blank');
     34  const iframe = document.getElementsByClassName(TEST_IFRAME_CLASS_NAME)[0];
     35  const iframe_BroadcastChannel = iframe.contentWindow.BroadcastChannel;
     36 
     37  if (action === IframeAction.REMOVE_BEFORE_CREATION) {
     38    iframe.remove();
     39  }
     40 
     41  events.length = 0;
     42 
     43  bc1 = new BroadcastChannel(channelName);
     44  const bc2 = new BroadcastChannel(channelName);
     45  const iframe_bc = new iframe_BroadcastChannel(channelName);
     46 
     47  if (action === IframeAction.REMOVE_AFTER_CREATION) {
     48    iframe.remove();
     49  }
     50 
     51  const testResultsPromise = DetachedIframeTestCheckForOneMessage(t);
     52 
     53  iframe_bc.postMessage('test');
     54  bc2.postMessage(DONE_MSG);
     55 
     56  bc2.close();
     57  iframe_bc.close();
     58  t.add_cleanup(() => bc1.close());
     59 
     60  return testResultsPromise;
     61 }
     62 
     63 promise_test(async t => {
     64  return doMessageSentTest(
     65      t, 'postMessage-from-detached-iframe-pre',
     66      IframeAction.REMOVE_AFTER_CREATION);
     67 }, 'BroadcastChannel messages from detached iframe to parent should be ignored (BC created before detaching)');
     68 
     69 promise_test(async t => {
     70  return doMessageSentTest(
     71      t, 'postMessage-from-detached-iframe-post',
     72      IframeAction.REMOVE_BEFORE_CREATION);
     73 }, 'BroadcastChannel messages from detached iframe to parent should be ignored (BC created after detaching)');
     74 
     75 
     76 async function doMessageReceivedTest(t, channelName, action) {
     77  await with_iframe('about:blank');
     78  const iframe = document.getElementsByClassName(TEST_IFRAME_CLASS_NAME)[0];
     79  const iframe_BroadcastChannel = iframe.contentWindow.BroadcastChannel;
     80 
     81  if (action === IframeAction.REMOVE_BEFORE_CREATION) {
     82    iframe.remove();
     83  }
     84 
     85  events.length = 0;
     86 
     87  // `iframe_bc` must be created first so that it receives messages before
     88  // `bc1`. That way we can tell whether `iframe_bc` received a message by
     89  // inspecting `events` in the `bc1` message handler.
     90  const iframe_bc = new iframe_BroadcastChannel(channelName);
     91  iframe_bc.onmessage = e => {
     92    events.push(e)
     93  };
     94  bc1 = new BroadcastChannel(channelName);
     95  const bc2 = new BroadcastChannel(channelName);
     96 
     97  if (action === IframeAction.REMOVE_AFTER_CREATION) {
     98    iframe.remove();
     99  }
    100 
    101  const testResultsPromise = DetachedIframeTestCheckForOneMessage(t);
    102  bc2.postMessage(DONE_MSG);
    103 
    104  bc2.close();
    105  iframe_bc.close();
    106  t.add_cleanup(() => bc1.close());
    107 }
    108 
    109 promise_test(async t => {
    110  return doMessageReceivedTest(
    111      t, 'postMessage-to-detached-iframe-pre',
    112      IframeAction.REMOVE_AFTER_CREATION);
    113 }, 'BroadcastChannel messages from parent to detached iframe should be ignored (BC created before detaching)');
    114 
    115 promise_test(async t => {
    116  return doMessageReceivedTest(
    117      t, 'postMessage-to-detached-iframe-post',
    118      IframeAction.REMOVE_BEFORE_CREATION);
    119 }, 'BroadcastChannel messages from parent to detached iframe should be ignored (BC created after detaching)');
    120 
    121 
    122 async function doMessageSendReceiveTest(t, channelName, action) {
    123  await with_iframe('about:blank');
    124  const iframe = document.getElementsByClassName(TEST_IFRAME_CLASS_NAME)[0];
    125  const iframe_BroadcastChannel = iframe.contentWindow.BroadcastChannel;
    126 
    127  if (action === IframeAction.REMOVE_BEFORE_CREATION) {
    128    iframe.remove();
    129  }
    130 
    131  const iframe_bc1 = new iframe_BroadcastChannel(channelName);
    132  const iframe_bc2 = new iframe_BroadcastChannel(channelName);
    133  iframe_bc1.onmessage = t.unreached_func(
    134      'Detached iframe BroadcastChannel instance received message unexpectedly');
    135 
    136  if (action === IframeAction.REMOVE_AFTER_CREATION) {
    137    iframe.remove();
    138  }
    139 
    140  iframe_bc2.postMessage(DONE_MSG);
    141 
    142  iframe_bc2.close();
    143  t.add_cleanup(() => iframe_bc1.close());
    144 
    145  // To avoid calling t.step_timeout here, instead just create two new
    146  // BroadcastChannel instances and complete the test when a message is passed
    147  // between them.  Per the spec, all "BroadcastChannel objects whose relevant
    148  // agents are the same" must have messages delivered to them in creation
    149  // order, so if we get this message then it's safe to assume the earlier
    150  // message would have been delivered if it was going to be.
    151  const bc1 = new BroadcastChannel(channelName);
    152  const bc2 = new BroadcastChannel(channelName);
    153  return new Promise((resolve) => {
    154    bc1.onmessage = t.step_func(e => {
    155      resolve();
    156    });
    157    bc2.postMessage(DONE_MSG);
    158  });
    159 }
    160 
    161 promise_test(async t => {
    162  return doMessageSendReceiveTest(
    163      t, 'postMessage-within-detached-iframe-pre',
    164      IframeAction.REMOVE_AFTER_CREATION);
    165 }, 'BroadcastChannel messages within detached iframe should be ignored (BCs created before detaching)');
    166 
    167 promise_test(async t => {
    168  return doMessageSendReceiveTest(
    169      t, 'postMessage-within-detached-iframe-post',
    170      IframeAction.REMOVE_BEFORE_CREATION);
    171 }, 'BroadcastChannel messages within detached iframe should be ignored (BCs created after detaching)');
    172 
    173 </script>
    174 </body>