diff options
Diffstat (limited to 'testing/web-platform/tests/portals/portals-post-message.sub.html')
-rw-r--r-- | testing/web-platform/tests/portals/portals-post-message.sub.html | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/testing/web-platform/tests/portals/portals-post-message.sub.html b/testing/web-platform/tests/portals/portals-post-message.sub.html new file mode 100644 index 0000000000..d556dd43d8 --- /dev/null +++ b/testing/web-platform/tests/portals/portals-post-message.sub.html @@ -0,0 +1,189 @@ +<!DOCTYPE html> +<title>Test postMessage on HTMLPortalElement</title> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="resources/stash-utils.sub.js"></script> +<script src="/common/utils.js"></script> +<body> + <input id="input"/> + <script> + const sameOriginUrl = "resources/portal-post-message-portal.html" + const crossOriginUrl = "http://{{hosts[alt][www]}}:{{ports[http][0]}}/portals/resources/portal-post-message-x-origin-portal.html" + + async function createAndInsertPortal(portalSrc) { + assert_implements("HTMLPortalElement" in self); + var portal = document.createElement("portal"); + portal.src = portalSrc; + document.body.append(portal); + + var loadPromise = new Promise((resolve, reject) => { + portal.onload = resolve; + }); + await loadPromise; + return portal; + } + + function postMessage(portal, ...postMessageArgs) { + return new Promise((resolve, reject) => { + portal.postMessage(...postMessageArgs); + portal.onmessage = e => { resolve(e.data); }; + }); + } + + function postMessageWithMessagePorts(portal, message) { + return new Promise((resolve, reject) => { + var channel = new MessageChannel(); + channel.port1.onmessage = e => { + channel.port1.close(); + resolve(e.data); + }; + portal.postMessage(message, {transfer: [channel.port2]}); + }); + } + + promise_test(async () => { + var portal = await createAndInsertPortal(sameOriginUrl); + var message = "test message"; + var {origin, data, sourceIsPortalHost} = await postMessage(portal, message); + assert_equals(data, message); + assert_equals(origin, window.location.origin); + assert_true(sourceIsPortalHost); + }, "postMessage message received by portalHost"); + + promise_test(async () => { + var portal = await createAndInsertPortal(sameOriginUrl); + var message = { + prop1: "value1", + prop2: 2.5, + prop3: [1, 2, "3"], + prop4: { + prop4_1: "value4_1" + } + } + var {data} = await postMessage(portal, message); + assert_object_equals(data, message); + }, "postMessage with message object"); + + promise_test(async () => { + var portal = await createAndInsertPortal(sameOriginUrl); + var message = "test message"; + var {data} = await postMessageWithMessagePorts(portal, message); + assert_equals(data, message); + }, "postMessage with message ports and same-origin portal"); + + promise_test(async () => { + var portal = await createAndInsertPortal(sameOriginUrl); + var arrayBuffer = new ArrayBuffer(5); + var int8View = new Int8Array(arrayBuffer); + for (var i = 0; i < int8View.length; i++) + int8View[i] = i; + var message = { + arrayBuffer: arrayBuffer + }; + var {data} = await postMessage(portal, message); + assert_array_equals([0, 1, 2, 3, 4], int8View); + assert_array_equals([0, 1, 2, 3, 4], data.array); + }, "postMessage with array buffer without transfer"); + + promise_test(async () => { + var portal = await createAndInsertPortal(sameOriginUrl); + var arrayBuffer = new ArrayBuffer(5); + var int8View = new Int8Array(arrayBuffer); + for (var i = 0; i < int8View.length; i++) + int8View[i] = i; + var message = { + arrayBuffer: arrayBuffer + }; + var {data} = await postMessage(portal, message, {transfer: [arrayBuffer]}); + assert_equals(int8View.length, 0); + assert_array_equals(data.array, [0, 1, 2, 3, 4]); + }, "postMessage with transferred array buffer"); + + promise_test(async t => { + var portal = await createAndInsertPortal(sameOriginUrl); + + var {gotUserActivation} = await postMessage(portal, "test"); + assert_false(gotUserActivation); + + var {gotUserActivation, userActivation} = await postMessage(portal, "test", {includeUserActivation: true}); + assert_true(gotUserActivation); + assert_false(userActivation.isActive); + assert_false(userActivation.hasBeenActive); + + await test_driver.click(document.getElementById("input")); + assert_true(navigator.userActivation.isActive); + assert_true(navigator.userActivation.hasBeenActive); + + var {userActivation} = await postMessage(portal, "test", {includeUserActivation: true}); + assert_true(userActivation.isActive, "should have sent gesture"); + assert_true(userActivation.hasBeenActive); + }, "postMessage with includeUserActivation"); + + promise_test(async t => { + var portal = document.createElement("portal"); + return promise_rejects_dom(t, "InvalidStateError", + postMessage(portal, "test message")); + }, "cannot call postMessage on portal without portal browsing context"); + + promise_test(async t => { + var portal = await createAndInsertPortal(sameOriginUrl); + return promise_rejects_dom(t, "DataCloneError", + postMessage(portal, document.body)); + }, "postMessage should fail if message serialization fails"); + + promise_test(async t => { + var portal = await createAndInsertPortal(sameOriginUrl); + return promise_rejects_js(t, TypeError, + postMessage(portal, "test", {transfer: [null]})); + }, "postMessage should fail with invalid ports"); + + async function waitForMessage(channelName) { + var bc = new BroadcastChannel(channelName); + return new Promise((resolve, reject) => { + bc.onmessage = e => { + bc.close(); + resolve(e.data); + } + }); + } + + promise_test(async t => { + assert_implements("HTMLPortalElement" in self); + window.open("resources/portal-post-message-before-activate-window.html"); + let {postMessageTS, activateTS} = await waitForMessage( + "portals-post-message-before-activate"); + assert_less_than_equal(postMessageTS, activateTS); + }, "postMessage before activate should work and preserve order"); + + promise_test(async t => { + assert_implements("HTMLPortalElement" in self); + window.open("resources/portal-post-message-during-activate-window.html"); + let error = await waitForMessage("portals-post-message-during-activate"); + assert_equals(error, "InvalidStateError"); + }, "postMessage during activate throws error"); + + promise_test(async t => { + assert_implements("HTMLPortalElement" in self); + window.open("resources/portal-post-message-after-activate-window.html"); + let error = await waitForMessage("portals-post-message-after-activate"); + assert_equals(error, "InvalidStateError"); + }, "postMessage after activate throws error"); + + const TIMEOUT_DURATION_MS = 1000; + + promise_test(async t => { + const key = token(); + const portal = await createAndInsertPortal(`${crossOriginUrl}?key=${key}`); + portal.postMessage('test message'); + t.step_timeout(() => { + StashUtils.putValue(key, 'passed'); + }, TIMEOUT_DURATION_MS); + const result = await StashUtils.takeValue(key); + assert_equals(result, 'passed'); + }, 'postMessage should be blocked for cross-origin portals'); + + </script> +</body> |