1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 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>
|