wxt-dev / wxt

⚡ Next-gen Web Extension Framework
https://wxt.dev
MIT License
4.7k stars 204 forks source link

Cannot load iframed sandbox #1111

Closed avi12 closed 1 month ago

avi12 commented 1 month ago

Describe the bug

I keep getting this error when I try to load the sandbox with an iframe

Uncaught Error: This script should only be loaded in a browser extension.

Reproduction

<!-- google-maps-search-box.sandbox/index.html -->
<!doctype html>
<html lang="en">
  <head>
    <title>Google Maps Search Box</title>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="manifest.exclude" content="['firefox']" />
  </head>
  <body>
    <div id="app"></div>
    <script src="./main.ts" type="module"></script>
  </body>
</html>
// google-maps-search-box.sandbox/main.ts
import { mount } from "svelte"; // svelte@5
import GoogleMapsSearch from "@/entrypoints/google-maps-search-box.sandbox/GoogleMapsSearch.svelte";

mount(GoogleMapsSearch, {
  target: document.getElementById("app")!
});
// wxt.config.ts

export default defineConfig({
  manifest({ mode }) {
    // ...
    const devSandbox = "http://localhost:3000";
    manifest = {
      ...manifest,
      content_security_policy: {
        sandbox: "sandbox allow-scripts; script-src-elem 'self' https://maps.googleapis.com " + (mode === "dev" ? devSandbox : "")
      },
      web_accessible_resources: [
        {
          resources: ["google-maps-search-box.html"],
          matches: ["https://www.youtube.com/*"]
        }
      ]
    };
    // ...
    return manifest;
  }
});

FYI, I didn't run into this issue in Plasmo

Steps to reproduce

No response

System Info

System:
    OS: Windows 10 10.0.19045
    CPU: (20) x64 Intel(R) Core(TM) i7-6950X CPU @ 3.00GHz
    Memory: 31.99 GB / 63.91 GB
  Binaries:
    Node: 20.14.0 - C:\Program Files\nodejs\node.EXE
    npm: 10.7.0 - C:\Program Files\nodejs\npm.CMD
    pnpm: 9.12.2 - C:\Program Files\nodejs\pnpm.CMD
  Browsers:
    Edge: Chromium (127.0.2651.74)
    Internet Explorer: 11.0.19041.4355

Used Package Manager

pnpm

Validations

avi12 commented 1 month ago

I looked into google-maps-search-box.html's output and found something interesting

<!DOCTYPE html>
<html lang="en">
  <head>
    <script type="module" src="http://localhost:3000/@vite/client"></script>
<script src="http://localhost:3000/@id/virtual:wxt-html-plugins" type="module"></script>
    <title>Google Maps Search Box</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="manifest.exclude" content="['firefox']">
  <script type="module" crossorigin="" src="/chunks/google-maps-search-box-BxzUToPe.js"></script>
</head>
  <body>
    <div id="app"></div>
    <script src="http://localhost:3000/src/entrypoints/google-maps-search-box.sandbox/main.ts" type="module"></script>
  </body>
</html>

By commenting out the import of main.ts, the error goes away (although the Google Maps search box won't load)

avi12 commented 1 month ago

When I built a version for production, this is what I got:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Google Maps Search Box</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="manifest.exclude" content="['firefox']">
    <script type="module" crossorigin src="/chunks/google-maps-search-box-5_0kcOXx.js"></script>
    <link rel="stylesheet" crossorigin href="/assets/google-maps-search-box-CsnkNW2S.css">
  </head>
  <body>
    <div id="app"></div>

  </body>
</html>

Considering the <meta name="manifest.exclude" content="['firefox']">, it seems like the framework does not properly process the sandbox

aklinker1 commented 1 month ago

Sandbox is a MV3 only feature. Are you targeting MV3 for Firefox?

avi12 commented 1 month ago

For Firefox MV3 I'm not using a sandbox But after some debugging, I discovered that the Svelte component I used for the sandbox imported a function that used browser.i18n.getUILanguage(), which caused the error in the first post to throw What I changed:

export async someFunc({ language }: { language: string }) {
  return ...
}

in the sandbox:

import { someFunc } from "@/lib/some-util";

const searchParams = new URLSearchParams(location.search);
const languageUi = $state(searchParams.get("langaugeUi") || "en-US");

async function processInputAddress() {
  const result = await someFunc({ language: languageUi });
}

embedding

{#if import.meta.env.BROWSER !== "firefox"}
  {@const params = new URLSearchParams({
    langaugeUi: chrome.i18n.getLanguageUI()
  })}
  <iframe src="{browser.runtime.getURL(`/google-maps-search-box.html`)}?{params}"></iframe>
{/if}

that resolved it