summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/portals/portals-post-message.sub.html
diff options
context:
space:
mode:
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.html189
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>