Skip to content

Commit

Permalink
Attach activate data to the portalactivate event.
Browse files Browse the repository at this point in the history
This allows authors to pass a serializable value along with the activation
event, so that the contexts can coordinate and transfer state across
the activation. Transfer is supported, so message ports and similar
objects can also be passed (subject to bug 940021).

The existing TransferableMessage mojo struct (used for postMessage elsewhere)
is reused, and is plumbed along the existing portal activation path.

Web platform test included.

Bug: 938549
Change-Id: Ib9a35a58c6317523b74fdd47cdd8e68c1d6ddfbd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1504046
Commit-Queue: Jeremy Roman <jbroman@chromium.org>
Reviewed-by: Nasko Oskov <nasko@chromium.org>
Reviewed-by: Kentaro Hara <haraken@chromium.org>
Reviewed-by: Lucas Gadani <lfg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#639981}
  • Loading branch information
jeremyroman authored and chromium-wpt-export-bot committed Mar 12, 2019
1 parent c706443 commit 652dc88
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
65 changes: 65 additions & 0 deletions portals/portal-activate-data.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<!DOCTYPE html>
<title>Tests passing of data along with portal activation</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
function nextMessage(target) {
return new Promise((resolve, reject) => {
target.addEventListener('message', e => resolve(e), {once: true});
});
}

async function openPortalAndActivate(logic, activateOptions) {
const bc = new BroadcastChannel('portal-activate-data');
const w = window.open();
try {
const portal = w.document.createElement('portal');
portal.src = new URL('resources/portal-activate-data-portal.html?logic=' + encodeURIComponent(logic), location.href);
w.document.body.appendChild(portal);
assert_equals((await nextMessage(bc)).data, 'ready');
await portal.activate(activateOptions);
return (await nextMessage(bc)).data;
} finally {
w.close();
bc.close();
}
}

promise_test(async () => {
const {echo} = await openPortalAndActivate(
'return {echo: event.data}',
{data: 'banana'});
assert_equals(echo, 'banana');
}, "A string can be passed through activate data.");

promise_test(async () => {
let {port1, port2} = new MessageChannel();
let replyViaPort = nextMessage(port1);
port1.start();
let ok = await openPortalAndActivate(
'let port2 = event.data; port2.postMessage(42); return true;',
{data: port2, transfer: [port2]});
assert_true(ok);
assert_equals((await replyViaPort).data, 42);
}, "A message port can be passed through activate data.");

if (window.SharedArrayBuffer) {
promise_test(async t => {
await promise_rejects(
t, 'DataCloneError',
openPortalAndActivate('', {data: new SharedArrayBuffer}));
}, "A SharedArrayBuffer cannot be passed through activate data.");
}

promise_test(async t => {
await promise_rejects(
t, new Error,
openPortalAndActivate('', {data: {get a() { throw new Error; }}}));
}, "Uncloneable data has its exception propagated.");

promise_test(async t => {
await promise_rejects(
t, new TypeError,
openPortalAndActivate('', {data: null, transfer: [null]}));
}, "Errors during transfer list processing are propagated.");
</script>
13 changes: 13 additions & 0 deletions portals/resources/portal-activate-data-portal.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<script>
const bc = new BroadcastChannel('portal-activate-data');
let logic = new Function('event', (new URL(location)).searchParams.get('logic'));
onload = () => bc.postMessage('ready');
onportalactivate = event => {
try {
bc.postMessage(logic(event));
} finally {
bc.close();
}
};
</script>

0 comments on commit 652dc88

Please sign in to comment.