1
0
silverbullet/plugbox/environment/iframe_sandbox.ts

55 lines
1.5 KiB
TypeScript
Raw Normal View History

2022-03-23 14:41:12 +00:00
import { safeRun } from "../util";
// @ts-ignore
import sandboxHtml from "bundle-text:./iframe_sandbox.html";
2022-03-23 14:41:12 +00:00
import { Sandbox } from "../sandbox";
import { System } from "../system";
import { WorkerLike } from "./worker";
class IFrameWrapper implements WorkerLike {
private iframe: HTMLIFrameElement;
onMessage?: (message: any) => Promise<void>;
2022-03-21 14:21:34 +00:00
ready: Promise<void>;
2022-03-24 09:48:56 +00:00
private messageListener: (evt: any) => void;
constructor() {
const iframe = document.createElement("iframe", {});
this.iframe = iframe;
iframe.style.display = "none";
// Let's lock this down significantly
iframe.setAttribute("sandbox", "allow-scripts");
iframe.srcdoc = sandboxHtml;
2022-03-24 09:48:56 +00:00
this.messageListener = (evt: any) => {
if (evt.source !== iframe.contentWindow) {
return;
}
let data = evt.data;
if (!data) return;
safeRun(async () => {
await this.onMessage!(data);
});
2022-03-24 09:48:56 +00:00
};
window.addEventListener("message", this.messageListener);
document.body.appendChild(iframe);
2022-03-21 14:21:34 +00:00
this.ready = new Promise((resolve) => {
iframe.onload = () => {
resolve();
iframe.onload = null;
};
});
}
postMessage(message: any): void {
this.iframe.contentWindow!.postMessage(message, "*");
}
terminate() {
2022-03-24 09:48:56 +00:00
window.removeEventListener("message", this.messageListener);
return this.iframe.remove();
}
}
export function createSandbox(system: System<any>) {
return new Sandbox(system, new IFrameWrapper());
}