Newer
Older
bugtrail / packages / extension / src / relay.ts
/**
 * Tiny relay content script present on every http(s) page. Its only job is to
 * let the BugTrail web panel talk to the extension through window messages —
 * the panel can't use runtime.sendMessage directly (it would need the
 * extension id in externally_connectable, which differs per installation).
 * The overlay is still injected on demand; this relay holds no UI.
 */
import browser from "webextension-polyfill";

const PANEL_SOURCE = "bugtrail-panel";
const EXT_SOURCE = "bugtrail-ext";

window.addEventListener("message", (event) => {
  // only accept messages from this same window (the page itself)
  if (event.source !== window) return;
  const data = event.data as { source?: string; type?: string; token?: string } | null;
  if (!data || data.source !== PANEL_SOURCE) return;

  if (data.type === "ping") {
    window.postMessage({ source: EXT_SOURCE, type: "pong", ok: true }, window.location.origin);
    return;
  }

  if (data.type === "replay_report" && typeof data.token === "string" && /^https?:$/.test(window.location.protocol)) {
    void browser.runtime
      .sendMessage({ type: "replay_report", token: data.token })
      .then((response) => {
        const r = response as { ok: boolean; data?: unknown; error?: string } | undefined;
        window.postMessage(
          { source: EXT_SOURCE, type: "replay_result", ok: r?.ok ?? false, data: r?.data ?? null, error: r?.error },
          window.location.origin
        );
      })
      .catch((error) => {
        // e.g. the extension context is gone after an update
        window.postMessage(
          { source: EXT_SOURCE, type: "replay_result", ok: false, data: null, error: String(error) },
          window.location.origin
        );
      });
  }
});