Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: run webmessaging/broadcastchannel WPT #41962

Merged
merged 1 commit into from Feb 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
120 changes: 120 additions & 0 deletions test/fixtures/wpt/webmessaging/broadcastchannel/basics.any.js
@@ -0,0 +1,120 @@
async_test(t => {
let c1 = new BroadcastChannel('eventType');
let c2 = new BroadcastChannel('eventType');

c2.onmessage = t.step_func(e => {
assert_true(e instanceof MessageEvent);
assert_equals(e.target, c2);
assert_equals(e.type, 'message');
assert_equals(e.origin, location.origin, 'origin');
assert_equals(e.data, 'hello world');
assert_equals(e.source, null, 'source');
t.done();
});
c1.postMessage('hello world');
}, 'postMessage results in correct event');

async_test(t => {
let c1 = new BroadcastChannel('order');
let c2 = new BroadcastChannel('order');
let c3 = new BroadcastChannel('order');

let events = [];
let doneCount = 0;
let handler = t.step_func(e => {
events.push(e);
if (e.data == 'done') {
doneCount++;
if (doneCount == 2) {
assert_equals(events.length, 6);
assert_equals(events[0].target, c2, 'target for event 0');
assert_equals(events[0].data, 'from c1');
assert_equals(events[1].target, c3, 'target for event 1');
assert_equals(events[1].data, 'from c1');
assert_equals(events[2].target, c1, 'target for event 2');
assert_equals(events[2].data, 'from c3');
assert_equals(events[3].target, c2, 'target for event 3');
assert_equals(events[3].data, 'from c3');
assert_equals(events[4].target, c1, 'target for event 4');
assert_equals(events[4].data, 'done');
assert_equals(events[5].target, c3, 'target for event 5');
assert_equals(events[5].data, 'done');
t.done();
}
}
});
c1.onmessage = handler;
c2.onmessage = handler;
c3.onmessage = handler;

c1.postMessage('from c1');
c3.postMessage('from c3');
c2.postMessage('done');
}, 'messages are delivered in port creation order');

async_test(t => {
let c1 = new BroadcastChannel('closed');
let c2 = new BroadcastChannel('closed');
let c3 = new BroadcastChannel('closed');

c2.onmessage = t.unreached_func();
c2.close();
c3.onmessage = t.step_func(() => t.done());
c1.postMessage('test');
}, 'messages aren\'t delivered to a closed port');

async_test(t => {
let c1 = new BroadcastChannel('closed');
let c2 = new BroadcastChannel('closed');
let c3 = new BroadcastChannel('closed');

c2.onmessage = t.unreached_func();
c3.onmessage = t.step_func(() => t.done());
c1.postMessage('test');
c2.close();
}, 'messages aren\'t delivered to a port closed after calling postMessage.');

async_test(t => {
let c1 = new BroadcastChannel('create-in-onmessage');
let c2 = new BroadcastChannel('create-in-onmessage');

c2.onmessage = t.step_func(e => {
assert_equals(e.data, 'first');
c2.close();
let c3 = new BroadcastChannel('create-in-onmessage');
c3.onmessage = t.step_func(event => {
assert_equals(event.data, 'done');
t.done();
});
c1.postMessage('done');
});
c1.postMessage('first');
c2.postMessage('second');
}, 'closing and creating channels during message delivery works correctly');

async_test(t => {
let c1 = new BroadcastChannel('close-in-onmessage');
let c2 = new BroadcastChannel('close-in-onmessage');
let c3 = new BroadcastChannel('close-in-onmessage');
let events = [];
c1.onmessage = e => events.push('c1: ' + e.data);
c2.onmessage = e => events.push('c2: ' + e.data);
c3.onmessage = e => events.push('c3: ' + e.data);

// c2 closes itself when it receives the first message
c2.addEventListener('message', e => {
c2.close();
});

c3.addEventListener('message', t.step_func(e => {
if (e.data == 'done') {
assert_array_equals(events, [
'c2: first',
'c3: first',
'c3: done']);
t.done();
}
}));
c1.postMessage('first');
c1.postMessage('done');
}, 'Closing a channel in onmessage prevents already queued tasks from firing onmessage events');
83 changes: 83 additions & 0 deletions test/fixtures/wpt/webmessaging/broadcastchannel/blobs.html
@@ -0,0 +1,83 @@
<!DOCTYPE html>
<meta charset=utf-8>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
async_test(t => {
const c1 = new BroadcastChannel('blob');
const c2 = new BroadcastChannel('blob');
const c3 = new BroadcastChannel('blob');

let readCount = 0;
c2.onmessage = t.step_func(e => {
// check blob
assert_true('blob' in e.data);
assert_true(e.data.blob instanceof Blob);
assert_equals(e.data.blob.size, 6);
const reader = new FileReader();
reader.onerror = t.unreached_func();
reader.onload = t.step_func(() => {
assert_equals(reader.result, 'foobar');
if (++readCount == 2)
t.done();
});
reader.readAsText(e.data.blob);
});
c3.onmessage = c2.onmessage;
(() => {
c1.postMessage({blob: new Blob(['foo', 'bar'])});
})();
// TODO(https://github.com/web-platform-tests/wpt/issues/7899): Change to
// some sort of cross-browser GC trigger.
if (self.gc) self.gc();
}, 'Blobs work on BroadcastChannel');

async_test(t => {
const c1 = new BroadcastChannel('blobworker');
const c2 = new BroadcastChannel('blobworker');
const events = [];

const verifyEvents = function() {
assert_equals(events.length, 5);
assert_equals(events[0], 'from worker');
assert_equals(events[1], 'from worker');
assert_true(events[2].blob instanceof Blob);
assert_equals(events[2].blob.size, 11);
assert_true(events[3].blob instanceof Blob);
assert_equals(events[3].blob.size, 11);
assert_equals(events[4], 'done');
const reader = new FileReader();
reader.onerror = t.unreached_func();
reader.onload = t.step_func(() => {
assert_equals(reader.result, 'hello-world');
t.done();
});
reader.readAsText(events[3].blob);
};

let receivedDone = false;
let receivedWorkerDone = false;

c1.onmessage = e => events.push(e.data);
c2.onmessage = e => events.push(e.data);
c2.addEventListener('message', t.step_func(e => {
if (e.data.blob)
c1.postMessage('done');
if (e.data === 'done')
receivedDone = true;
if (receivedDone && receivedWorkerDone)
verifyEvents();
}));

const worker = new Worker('resources/worker.js');
worker.onmessage = t.step_func(e => {
receivedWorkerDone = true;
if (receivedDone && receivedWorkerDone)
verifyEvents();
});
worker.postMessage({channel: 'blobworker'});
worker.postMessage({blob: ['hello-world']});

}, 'Blobs work with workers on BroadcastChannel');

</script>
38 changes: 38 additions & 0 deletions test/fixtures/wpt/webmessaging/broadcastchannel/cross-origin.html
@@ -0,0 +1,38 @@
<!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 events = [];

function testCompletion(t) {
return new Promise((resolve) => {
window.addEventListener("message", t.step_func(e => {
if (e.data == 'done') {
assert_equals(events.length, 0);
resolve();
}
}));
});
}

promise_test(async t => {

const bc0 = new BroadcastChannel('no-cross-origin-messages');
bc0.onmessage = e => {window.events.push(e);};

const testResults = testCompletion(t);
const url = get_host_info().HTTPS_NOTSAMESITE_ORIGIN +
'/webmessaging/broadcastchannel/resources/cross-origin.html';
await with_iframe(url);

return testResults;
}, "Messages aren't delivered across origins");

</script>
</body>
@@ -0,0 +1,72 @@
<!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>
<script src="/common/utils.js"></script>
<script src="/common/dispatcher/dispatcher.js"></script>
<!-- Pull in executor_path needed by newPopup / newIframe -->
<script src="/html/cross-origin-embedder-policy/credentialless/resources/common.js"></script>
<!-- Pull in newPopup / newIframe -->
<script src="/html/cross-origin-embedder-policy/anonymous-iframe/resources/common.js"></script>
<body>
<script>

const emit_script = (channel_name, message, done_queue_name) => `
const bc = new BroadcastChannel("${channel_name}");
bc.postMessage("${message}");
send("${done_queue_name}", "done");
`;

promise_test(async t => {
const origin = get_host_info().HTTPS_ORIGIN;
const not_same_site_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
const response_queue_uuid = token();

const popup_init_script = `
const importScript = ${importScript};
await importScript("/html/cross-origin-embedder-policy/credentialless" +
"/resources/common.js");
await importScript("/html/cross-origin-embedder-policy/anonymous-iframe" +
"/resources/common.js");
await importScript("/common/utils.js");
send("${response_queue_uuid}", newIframe("${origin}"));
`;

// Create a same-origin iframe in a cross-site popup.
const not_same_site_popup_uuid = newPopup(t, not_same_site_origin);
send(not_same_site_popup_uuid, popup_init_script);
const iframe_1_uuid = await receive(response_queue_uuid);

// Create a same-origin iframe in a same-site popup.
const same_origin_popup_uuid = newPopup(t, origin);
send(same_origin_popup_uuid, popup_init_script);
const iframe_2_uuid = await receive(response_queue_uuid);

const channel_name = token();
const bc = new BroadcastChannel(channel_name);
bc.onmessage = t.step_func(e => {
assert_equals(e.data, "msg from iframe2");
t.done();
});

// Instruct the not-same-top-level-site iframe to send a message on the BC
// channel we are listening on. This message should not be received since
// the iframe should be in a different partition.
send(iframe_1_uuid,
emit_script(channel_name, "msg from iframe1", response_queue_uuid));
assert_equals(await receive(response_queue_uuid), "done");

// Now instruct the same-top-level-site iframe to send a BC message. By
// the time we send the script to execute, have it send the BC message,
// and then receive the BC message in our BC instance, it should be
// reasonable to assume that the message from the first iframe would have
// been delivered if it was going to be.
send(iframe_2_uuid,
emit_script(channel_name, "msg from iframe2", response_queue_uuid));
assert_equals(await receive(response_queue_uuid), "done");

}, "BroadcastChannel messages aren't received from a cross-partition iframe");

</script>
</body>