JSFiddle - React, Tailwind, and code Playground
HTML
<iframe id=iframe src='data:text/html,<!DOCTYPE html><script type=module>
async function initComm(allowedOrigins = []) {
const unsafe = new MessageChannel();
parent.postMessage("negotiation", {
targetOrigin: "*",
transfer: [unsafe.port1]
});
const timeout = AbortSignal.timeout(100);
const targetOrigin = await Promise.race([
new Promise((res, rej) => timeout.onabort = (evt) => {
unsafe.port2.close();
rej(timeout.reason);
}),
new Promise((res) => unsafe.port2.onmessage = ({data}) => res(data))
]);
unsafe.port2.close();
if (!allowedOrigins.includes(targetOrigin)) {
throw new Error("Unknown origin: " + targetOrigin);
}
const safe = new MessageChannel();
parent.postMessage("begin", {
targetOrigin,
transfer: [safe.port1]
});
return safe.port2;
}
const safePort = await initComm(["https://embedder-1.com", "https://another-origin.com", "https://fiddle.jshell.net"]);
safePort.postMessage("Here is a secret");
</script>'>
</iframe>
JavaScript
const YOUR_ORIGIN = "null"; // we're in a data: URL...
onmessage = ({origin, data, ports}) => {
if (origin === YOUR_ORIGIN) {
switch(data) {
case "negotiation":
ports[0].postMessage(window.origin);
break;
case "begin":
beginComm(ports[0]);
break;
}
}
}
function beginComm(safePort) {
safePort.onmessage = ({data}) => {
console.log("Safely received a new message:", data);
};
}