Files
sproutclaw/packages/browser-extension/src/components/SandboxIframe.ts
2025-10-02 02:15:33 +02:00

71 lines
1.7 KiB
TypeScript

import { LitElement } from "lit";
import { customElement, property } from "lit/decorators.js";
// @ts-ignore - browser global exists in Firefox
declare const browser: any;
@customElement("sandbox-iframe")
export class SandboxIframe extends LitElement {
@property() content = "";
private iframe?: HTMLIFrameElement;
createRenderRoot() {
return this;
}
override connectedCallback() {
super.connectedCallback();
window.addEventListener("message", this.handleMessage);
this.createIframe();
}
override disconnectedCallback() {
super.disconnectedCallback();
window.removeEventListener("message", this.handleMessage);
this.iframe?.remove();
}
private handleMessage = (e: MessageEvent) => {
if (e.data.type === "sandbox-ready" && e.source === this.iframe?.contentWindow) {
// Sandbox is ready, send content
this.iframe?.contentWindow?.postMessage(
{
type: "loadContent",
content: this.content,
artifactId: "test",
attachments: [],
},
"*",
);
}
};
private createIframe() {
this.iframe = document.createElement("iframe");
this.iframe.sandbox.add("allow-scripts");
this.iframe.sandbox.add("allow-modals");
this.iframe.style.width = "100%";
this.iframe.style.height = "100%";
this.iframe.style.border = "none";
const isFirefox = typeof browser !== "undefined" && browser.runtime !== undefined;
if (isFirefox) {
this.iframe.src = browser.runtime.getURL("sandbox.html");
} else {
this.iframe.src = chrome.runtime.getURL("sandbox.html");
}
this.appendChild(this.iframe);
}
public updateContent(newContent: string) {
this.content = newContent;
// Recreate iframe for clean state
if (this.iframe) {
this.iframe.remove();
this.iframe = undefined;
}
this.createIframe();
}
}