| <!DOCTYPE html> |
| <title>Test postMessage on PortalHost</title> |
| <meta name="timeout" content="long"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <body> |
| <script> |
| function createPortal(portalSrc) { |
| var portal = document.createElement("portal"); |
| portal.src = portalSrc; |
| return new Promise((resolve, reject) => { |
| portal.onload = () => { |
| resolve(portal); |
| }; |
| document.body.appendChild(portal); |
| }); |
| } |
| |
| async function createPortalAndLoopMessage(portalSrc, params) { |
| assert_implements("HTMLPortalElement" in self); |
| var portal = await createPortal(portalSrc); |
| var waitForResponse = new Promise((resolve, reject) => { |
| portal.addEventListener("message", e => { resolve(e); }); |
| }); |
| portal.postMessage(params); |
| return waitForResponse; |
| } |
| |
| const sameOriginUrl = "resources/portal-host-post-message.html"; |
| const crossOriginUrl = "http://{{hosts[alt][www]}}:{{ports[http][0]}}/portals/resources/portal-host-post-message-x-origin.html"; |
| |
| promise_test(async () => { |
| var {data, origin} = await createPortalAndLoopMessage(sameOriginUrl, |
| ["test"]); |
| assert_equals(data, "test"); |
| assert_equals(origin, "http://{{host}}:{{ports[http][0]}}"); |
| }, "Message received after postMessage from portal host"); |
| |
| promise_test(async () => { |
| var message = { |
| prop1: "value1", |
| prop2: 2.5, |
| prop3: [1, 2, "3"], |
| prop4: { |
| prop4_1: "value4_1" |
| } |
| }; |
| var {data} = await createPortalAndLoopMessage(sameOriginUrl, |
| [message]); |
| assert_object_equals(data, message); |
| }, "postMessage with object message"); |
| |
| promise_test(async () => { |
| assert_implements("HTMLPortalElement" in self); |
| function checkPort(port) { |
| return new Promise((resolve, reject) => { |
| var channel = new MessageChannel(); |
| channel.port1.onmessage = resolve; |
| port.postMessage("sending port", {transfer: [channel.port2]}); |
| }); |
| } |
| |
| var {ports} = await createPortalAndLoopMessage(sameOriginUrl, { |
| type: "message-port" |
| }); |
| await checkPort(ports[0]); |
| }, "postMessage with message ports"); |
| |
| promise_test(async () => { |
| var {data} = await createPortalAndLoopMessage(sameOriginUrl, { |
| type: "array-buffer-without-transfer", |
| array: [0, 1, 2, 3, 4] |
| }); |
| assert_array_equals([0, 1, 2, 3, 4], new Int8Array(data.arrayBuffer)); |
| }, "postMessage with array buffer without transfer"); |
| |
| promise_test(async () => { |
| var {data} = await createPortalAndLoopMessage(sameOriginUrl, { |
| type: "array-buffer-with-transfer", |
| array: [0, 1, 2, 3, 4] |
| }); |
| assert_array_equals([0, 1, 2, 3, 4], new Int8Array(data.arrayBuffer)); |
| }, "postMessage with array buffer with transfer"); |
| |
| promise_test(async () => { |
| var {data} = await createPortalAndLoopMessage(sameOriginUrl, { |
| type: "invalid-message" |
| }); |
| assert_equals(data.errorType, "DataCloneError"); |
| }, "postMessage should throw error when serialization fails"); |
| |
| promise_test(async () => { |
| var {data} = await createPortalAndLoopMessage(sameOriginUrl,{ |
| type: "invalid-port" |
| }); |
| assert_equals(data.errorType, "TypeError"); |
| }, "postMessage with invalid transferable should throw error"); |
| |
| promise_test(async () => { |
| assert_implements("HTMLPortalElement" in self); |
| var receiveMessage = new Promise((resolve, reject) => { |
| var bc = new BroadcastChannel("portal-host-post-message-after-activate"); |
| bc.onmessage = e => { resolve(e); }; |
| }); |
| const portalUrl = encodeURIComponent( |
| "portal-host-post-message-after-activate.html"); |
| window.open(`resources/portal-embed-and-activate.html?url=${portalUrl}`); |
| var message = await receiveMessage; |
| assert_equals(message.data, "InvalidStateError"); |
| }, "Calling postMessage after receiving onactivate event should fail"); |
| |
| promise_test(() => { |
| assert_implements("HTMLPortalElement" in self); |
| var portal = document.createElement("portal"); |
| portal.src = "resources/portal-host-post-message-navigate-1.html"; |
| var count = 0; |
| var waitForMessages = new Promise((resolve, reject) => { |
| portal.addEventListener("message", e => { |
| count++; |
| if (count == 2) |
| resolve(); |
| }); |
| }); |
| document.body.appendChild(portal); |
| return waitForMessages; |
| }, "postMessage before and after portal navigation should work"); |
| |
| const TIMEOUT_DURATION_MS = 1000; |
| |
| promise_test(t => new Promise((resolve, reject) => { |
| const portal = document.createElement('portal'); |
| portal.src = crossOriginUrl; |
| portal.onmessage = () => reject('should not have received message'); |
| document.body.appendChild(portal); |
| t.step_timeout(resolve, TIMEOUT_DURATION_MS); |
| }), "postMessage from portal host in cross-origin-portal should be blocked"); |
| </script> |
| </body> |