blob: d589235ec3bf9befbe8e41dd98d98134fea887a8 [file] [log] [blame]
<!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>