// service worker
openSandbox().then(sbPort => {
sbPort.onmessage = console.log;
sbPort.postMessage('foo');
});
async function openSandbox(url = 'sandbox.html') {
try {
await chrome.offscreen.createDocument({
url: 'offscreen.html',
justification: 'foo',
reasons: ['BLOBS'],
});
} catch(e) {
if (!e.message.includes('single offscreen document')) throw e;
}
const mc = new MessageChannel();
const doc = (await clients.matchAll({includeUncontrolled: true}))
.find(c => c.url.endsWith('/offscreen.html'));
doc.postMessage({cmd: 'sb', url}, [mc.port1]);
return mc.port2;
}
// offscreen.js
navigator.serviceWorker.onmessage = evsw => {
if (evsw.data.cmd === 'sbPort') {
const sb = window.open(evsw.data.url);
addEventListener('message', function fn(evsb) {
if (evsb.data === 'sb' && evsb.source === sb) {
removeEventListener('message', fn);
sb.postMessage('swPort', '*', evsw.ports);
window.close();
}
});
}
}
// sandbox.js
let /** @type {MessagePort} */ swPort;
opener.postMessage('sb', '*');
window.onmessage = e => {
if (e.data === 'swPort') {
swPort = e.ports[0];
swPort.postMessage('hello');
swPort.onmessage = console.log;
}
};