11cb0ef41Sopenharmony_ci<!DOCTYPE html>
21cb0ef41Sopenharmony_ci<meta charset=utf-8>
31cb0ef41Sopenharmony_ci<script src="/resources/testharness.js"></script>
41cb0ef41Sopenharmony_ci<script src="/resources/testharnessreport.js"></script>
51cb0ef41Sopenharmony_ci<script src="/common/get-host-info.sub.js"></script>
61cb0ef41Sopenharmony_ci<!-- Pull in the with_iframe helper function from the service worker tests -->
71cb0ef41Sopenharmony_ci<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
81cb0ef41Sopenharmony_ci<body>
91cb0ef41Sopenharmony_ci<script>
101cb0ef41Sopenharmony_ciconst TEST_IFRAME_CLASS_NAME = 'test-iframe';
111cb0ef41Sopenharmony_ciconst events = [];
121cb0ef41Sopenharmony_civar bc1;
131cb0ef41Sopenharmony_ciconst DONE_MSG = 'done';
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_cifunction DetachedIframeTestCheckForOneMessage(t) {
161cb0ef41Sopenharmony_ci  return new Promise((resolve) => {
171cb0ef41Sopenharmony_ci    bc1.onmessage = t.step_func(e => {
181cb0ef41Sopenharmony_ci      events.push(e);
191cb0ef41Sopenharmony_ci      if (e.data == DONE_MSG) {
201cb0ef41Sopenharmony_ci        assert_equals(events.length, 1);
211cb0ef41Sopenharmony_ci        resolve();
221cb0ef41Sopenharmony_ci      }
231cb0ef41Sopenharmony_ci    });
241cb0ef41Sopenharmony_ci  });
251cb0ef41Sopenharmony_ci}
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ciconst IframeAction = {
281cb0ef41Sopenharmony_ci  REMOVE_BEFORE_CREATION: 'remove-before-creation',
291cb0ef41Sopenharmony_ci  REMOVE_AFTER_CREATION: 'remove-after-creation',
301cb0ef41Sopenharmony_ci};
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ciasync function doMessageSentTest(t, channelName, action) {
331cb0ef41Sopenharmony_ci  await with_iframe('about:blank');
341cb0ef41Sopenharmony_ci  const iframe = document.getElementsByClassName(TEST_IFRAME_CLASS_NAME)[0];
351cb0ef41Sopenharmony_ci  const iframe_BroadcastChannel = iframe.contentWindow.BroadcastChannel;
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci  if (action === IframeAction.REMOVE_BEFORE_CREATION) {
381cb0ef41Sopenharmony_ci    iframe.remove();
391cb0ef41Sopenharmony_ci  }
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci  events.length = 0;
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci  bc1 = new BroadcastChannel(channelName);
441cb0ef41Sopenharmony_ci  const bc2 = new BroadcastChannel(channelName);
451cb0ef41Sopenharmony_ci  const iframe_bc = new iframe_BroadcastChannel(channelName);
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci  if (action === IframeAction.REMOVE_AFTER_CREATION) {
481cb0ef41Sopenharmony_ci    iframe.remove();
491cb0ef41Sopenharmony_ci  }
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci  const testResultsPromise = DetachedIframeTestCheckForOneMessage(t);
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  iframe_bc.postMessage('test');
541cb0ef41Sopenharmony_ci  bc2.postMessage(DONE_MSG);
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci  bc2.close();
571cb0ef41Sopenharmony_ci  iframe_bc.close();
581cb0ef41Sopenharmony_ci  t.add_cleanup(() => bc1.close());
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  return testResultsPromise;
611cb0ef41Sopenharmony_ci}
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_cipromise_test(async t => {
641cb0ef41Sopenharmony_ci  return doMessageSentTest(
651cb0ef41Sopenharmony_ci      t, 'postMessage-from-detached-iframe-pre',
661cb0ef41Sopenharmony_ci      IframeAction.REMOVE_AFTER_CREATION);
671cb0ef41Sopenharmony_ci}, 'BroadcastChannel messages from detached iframe to parent should be ignored (BC created before detaching)');
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_cipromise_test(async t => {
701cb0ef41Sopenharmony_ci  return doMessageSentTest(
711cb0ef41Sopenharmony_ci      t, 'postMessage-from-detached-iframe-post',
721cb0ef41Sopenharmony_ci      IframeAction.REMOVE_BEFORE_CREATION);
731cb0ef41Sopenharmony_ci}, 'BroadcastChannel messages from detached iframe to parent should be ignored (BC created after detaching)');
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ciasync function doMessageReceivedTest(t, channelName, action) {
771cb0ef41Sopenharmony_ci  await with_iframe('about:blank');
781cb0ef41Sopenharmony_ci  const iframe = document.getElementsByClassName(TEST_IFRAME_CLASS_NAME)[0];
791cb0ef41Sopenharmony_ci  const iframe_BroadcastChannel = iframe.contentWindow.BroadcastChannel;
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  if (action === IframeAction.REMOVE_BEFORE_CREATION) {
821cb0ef41Sopenharmony_ci    iframe.remove();
831cb0ef41Sopenharmony_ci  }
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci  events.length = 0;
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  // `iframe_bc` must be created first so that it receives messages before
881cb0ef41Sopenharmony_ci  // `bc1`. That way we can tell whether `iframe_bc` received a message by
891cb0ef41Sopenharmony_ci  // inspecting `events` in the `bc1` message handler.
901cb0ef41Sopenharmony_ci  const iframe_bc = new iframe_BroadcastChannel(channelName);
911cb0ef41Sopenharmony_ci  iframe_bc.onmessage = e => {
921cb0ef41Sopenharmony_ci    events.push(e)
931cb0ef41Sopenharmony_ci  };
941cb0ef41Sopenharmony_ci  bc1 = new BroadcastChannel(channelName);
951cb0ef41Sopenharmony_ci  const bc2 = new BroadcastChannel(channelName);
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci  if (action === IframeAction.REMOVE_AFTER_CREATION) {
981cb0ef41Sopenharmony_ci    iframe.remove();
991cb0ef41Sopenharmony_ci  }
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  const testResultsPromise = DetachedIframeTestCheckForOneMessage(t);
1021cb0ef41Sopenharmony_ci  bc2.postMessage(DONE_MSG);
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci  bc2.close();
1051cb0ef41Sopenharmony_ci  iframe_bc.close();
1061cb0ef41Sopenharmony_ci  t.add_cleanup(() => bc1.close());
1071cb0ef41Sopenharmony_ci}
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_cipromise_test(async t => {
1101cb0ef41Sopenharmony_ci  return doMessageReceivedTest(
1111cb0ef41Sopenharmony_ci      t, 'postMessage-to-detached-iframe-pre',
1121cb0ef41Sopenharmony_ci      IframeAction.REMOVE_AFTER_CREATION);
1131cb0ef41Sopenharmony_ci}, 'BroadcastChannel messages from parent to detached iframe should be ignored (BC created before detaching)');
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_cipromise_test(async t => {
1161cb0ef41Sopenharmony_ci  return doMessageReceivedTest(
1171cb0ef41Sopenharmony_ci      t, 'postMessage-to-detached-iframe-post',
1181cb0ef41Sopenharmony_ci      IframeAction.REMOVE_BEFORE_CREATION);
1191cb0ef41Sopenharmony_ci}, 'BroadcastChannel messages from parent to detached iframe should be ignored (BC created after detaching)');
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ciasync function doMessageSendReceiveTest(t, channelName, action) {
1231cb0ef41Sopenharmony_ci  await with_iframe('about:blank');
1241cb0ef41Sopenharmony_ci  const iframe = document.getElementsByClassName(TEST_IFRAME_CLASS_NAME)[0];
1251cb0ef41Sopenharmony_ci  const iframe_BroadcastChannel = iframe.contentWindow.BroadcastChannel;
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  if (action === IframeAction.REMOVE_BEFORE_CREATION) {
1281cb0ef41Sopenharmony_ci    iframe.remove();
1291cb0ef41Sopenharmony_ci  }
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  const iframe_bc1 = new iframe_BroadcastChannel(channelName);
1321cb0ef41Sopenharmony_ci  const iframe_bc2 = new iframe_BroadcastChannel(channelName);
1331cb0ef41Sopenharmony_ci  iframe_bc1.onmessage = t.unreached_func(
1341cb0ef41Sopenharmony_ci      'Detached iframe BroadcastChannel instance received message unexpectedly');
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci  if (action === IframeAction.REMOVE_AFTER_CREATION) {
1371cb0ef41Sopenharmony_ci    iframe.remove();
1381cb0ef41Sopenharmony_ci  }
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci  iframe_bc2.postMessage(DONE_MSG);
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci  iframe_bc2.close();
1431cb0ef41Sopenharmony_ci  t.add_cleanup(() => iframe_bc1.close());
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci  // To avoid calling t.step_timeout here, instead just create two new
1461cb0ef41Sopenharmony_ci  // BroadcastChannel instances and complete the test when a message is passed
1471cb0ef41Sopenharmony_ci  // between them.  Per the spec, all "BroadcastChannel objects whose relevant
1481cb0ef41Sopenharmony_ci  // agents are the same" must have messages delivered to them in creation
1491cb0ef41Sopenharmony_ci  // order, so if we get this message then it's safe to assume the earlier
1501cb0ef41Sopenharmony_ci  // message would have been delivered if it was going to be.
1511cb0ef41Sopenharmony_ci  const bc1 = new BroadcastChannel(channelName);
1521cb0ef41Sopenharmony_ci  const bc2 = new BroadcastChannel(channelName);
1531cb0ef41Sopenharmony_ci  return new Promise((resolve) => {
1541cb0ef41Sopenharmony_ci    bc1.onmessage = t.step_func(e => {
1551cb0ef41Sopenharmony_ci      resolve();
1561cb0ef41Sopenharmony_ci    });
1571cb0ef41Sopenharmony_ci    bc2.postMessage(DONE_MSG);
1581cb0ef41Sopenharmony_ci  });
1591cb0ef41Sopenharmony_ci}
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_cipromise_test(async t => {
1621cb0ef41Sopenharmony_ci  return doMessageSendReceiveTest(
1631cb0ef41Sopenharmony_ci      t, 'postMessage-within-detached-iframe-pre',
1641cb0ef41Sopenharmony_ci      IframeAction.REMOVE_AFTER_CREATION);
1651cb0ef41Sopenharmony_ci}, 'BroadcastChannel messages within detached iframe should be ignored (BCs created before detaching)');
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_cipromise_test(async t => {
1681cb0ef41Sopenharmony_ci  return doMessageSendReceiveTest(
1691cb0ef41Sopenharmony_ci      t, 'postMessage-within-detached-iframe-post',
1701cb0ef41Sopenharmony_ci      IframeAction.REMOVE_BEFORE_CREATION);
1711cb0ef41Sopenharmony_ci}, 'BroadcastChannel messages within detached iframe should be ignored (BCs created after detaching)');
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_ci</script>
1741cb0ef41Sopenharmony_ci</body>
175