summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/webmessaging/broadcastchannel/detached-iframe.html
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--testing/web-platform/tests/webmessaging/broadcastchannel/detached-iframe.html174
1 files changed, 174 insertions, 0 deletions
diff --git a/testing/web-platform/tests/webmessaging/broadcastchannel/detached-iframe.html b/testing/web-platform/tests/webmessaging/broadcastchannel/detached-iframe.html
new file mode 100644
index 0000000000..b9b06c3a46
--- /dev/null
+++ b/testing/web-platform/tests/webmessaging/broadcastchannel/detached-iframe.html
@@ -0,0 +1,174 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<!-- Pull in the with_iframe helper function from the service worker tests -->
+<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
+<body>
+<script>
+const TEST_IFRAME_CLASS_NAME = 'test-iframe';
+const events = [];
+var bc1;
+const DONE_MSG = 'done';
+
+function DetachedIframeTestCheckForOneMessage(t) {
+ return new Promise((resolve) => {
+ bc1.onmessage = t.step_func(e => {
+ events.push(e);
+ if (e.data == DONE_MSG) {
+ assert_equals(events.length, 1);
+ resolve();
+ }
+ });
+ });
+}
+
+const IframeAction = {
+ REMOVE_BEFORE_CREATION: 'remove-before-creation',
+ REMOVE_AFTER_CREATION: 'remove-after-creation',
+};
+
+async function doMessageSentTest(t, channelName, action) {
+ await with_iframe('about:blank');
+ const iframe = document.getElementsByClassName(TEST_IFRAME_CLASS_NAME)[0];
+ const iframe_BroadcastChannel = iframe.contentWindow.BroadcastChannel;
+
+ if (action === IframeAction.REMOVE_BEFORE_CREATION) {
+ iframe.remove();
+ }
+
+ events.length = 0;
+
+ bc1 = new BroadcastChannel(channelName);
+ const bc2 = new BroadcastChannel(channelName);
+ const iframe_bc = new iframe_BroadcastChannel(channelName);
+
+ if (action === IframeAction.REMOVE_AFTER_CREATION) {
+ iframe.remove();
+ }
+
+ const testResultsPromise = DetachedIframeTestCheckForOneMessage(t);
+
+ iframe_bc.postMessage('test');
+ bc2.postMessage(DONE_MSG);
+
+ bc2.close();
+ iframe_bc.close();
+ t.add_cleanup(() => bc1.close());
+
+ return testResultsPromise;
+}
+
+promise_test(async t => {
+ return doMessageSentTest(
+ t, 'postMessage-from-detached-iframe-pre',
+ IframeAction.REMOVE_AFTER_CREATION);
+}, 'BroadcastChannel messages from detached iframe to parent should be ignored (BC created before detaching)');
+
+promise_test(async t => {
+ return doMessageSentTest(
+ t, 'postMessage-from-detached-iframe-post',
+ IframeAction.REMOVE_BEFORE_CREATION);
+}, 'BroadcastChannel messages from detached iframe to parent should be ignored (BC created after detaching)');
+
+
+async function doMessageReceivedTest(t, channelName, action) {
+ await with_iframe('about:blank');
+ const iframe = document.getElementsByClassName(TEST_IFRAME_CLASS_NAME)[0];
+ const iframe_BroadcastChannel = iframe.contentWindow.BroadcastChannel;
+
+ if (action === IframeAction.REMOVE_BEFORE_CREATION) {
+ iframe.remove();
+ }
+
+ events.length = 0;
+
+ // `iframe_bc` must be created first so that it receives messages before
+ // `bc1`. That way we can tell whether `iframe_bc` received a message by
+ // inspecting `events` in the `bc1` message handler.
+ const iframe_bc = new iframe_BroadcastChannel(channelName);
+ iframe_bc.onmessage = e => {
+ events.push(e)
+ };
+ bc1 = new BroadcastChannel(channelName);
+ const bc2 = new BroadcastChannel(channelName);
+
+ if (action === IframeAction.REMOVE_AFTER_CREATION) {
+ iframe.remove();
+ }
+
+ const testResultsPromise = DetachedIframeTestCheckForOneMessage(t);
+ bc2.postMessage(DONE_MSG);
+
+ bc2.close();
+ iframe_bc.close();
+ t.add_cleanup(() => bc1.close());
+}
+
+promise_test(async t => {
+ return doMessageReceivedTest(
+ t, 'postMessage-to-detached-iframe-pre',
+ IframeAction.REMOVE_AFTER_CREATION);
+}, 'BroadcastChannel messages from parent to detached iframe should be ignored (BC created before detaching)');
+
+promise_test(async t => {
+ return doMessageReceivedTest(
+ t, 'postMessage-to-detached-iframe-post',
+ IframeAction.REMOVE_BEFORE_CREATION);
+}, 'BroadcastChannel messages from parent to detached iframe should be ignored (BC created after detaching)');
+
+
+async function doMessageSendReceiveTest(t, channelName, action) {
+ await with_iframe('about:blank');
+ const iframe = document.getElementsByClassName(TEST_IFRAME_CLASS_NAME)[0];
+ const iframe_BroadcastChannel = iframe.contentWindow.BroadcastChannel;
+
+ if (action === IframeAction.REMOVE_BEFORE_CREATION) {
+ iframe.remove();
+ }
+
+ const iframe_bc1 = new iframe_BroadcastChannel(channelName);
+ const iframe_bc2 = new iframe_BroadcastChannel(channelName);
+ iframe_bc1.onmessage = t.unreached_func(
+ 'Detached iframe BroadcastChannel instance received message unexpectedly');
+
+ if (action === IframeAction.REMOVE_AFTER_CREATION) {
+ iframe.remove();
+ }
+
+ iframe_bc2.postMessage(DONE_MSG);
+
+ iframe_bc2.close();
+ t.add_cleanup(() => iframe_bc1.close());
+
+ // To avoid calling t.step_timeout here, instead just create two new
+ // BroadcastChannel instances and complete the test when a message is passed
+ // between them. Per the spec, all "BroadcastChannel objects whose relevant
+ // agents are the same" must have messages delivered to them in creation
+ // order, so if we get this message then it's safe to assume the earlier
+ // message would have been delivered if it was going to be.
+ const bc1 = new BroadcastChannel(channelName);
+ const bc2 = new BroadcastChannel(channelName);
+ return new Promise((resolve) => {
+ bc1.onmessage = t.step_func(e => {
+ resolve();
+ });
+ bc2.postMessage(DONE_MSG);
+ });
+}
+
+promise_test(async t => {
+ return doMessageSendReceiveTest(
+ t, 'postMessage-within-detached-iframe-pre',
+ IframeAction.REMOVE_AFTER_CREATION);
+}, 'BroadcastChannel messages within detached iframe should be ignored (BCs created before detaching)');
+
+promise_test(async t => {
+ return doMessageSendReceiveTest(
+ t, 'postMessage-within-detached-iframe-post',
+ IframeAction.REMOVE_BEFORE_CREATION);
+}, 'BroadcastChannel messages within detached iframe should be ignored (BCs created after detaching)');
+
+</script>
+</body>