Skip to content

🦊 启用 Firefox MV3 构建并完善 sandbox/offscreen 通信#1561

Open
cyfung1031 wants to merge 19 commits into
scriptscat:mainfrom
cyfung1031:pr/ff3-mv3-002
Open

🦊 启用 Firefox MV3 构建并完善 sandbox/offscreen 通信#1561
cyfung1031 wants to merge 19 commits into
scriptscat:mainfrom
cyfung1031:pr/ff3-mv3-002

Conversation

@cyfung1031

@cyfung1031 cyfung1031 commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

Checklist / 检查清单

  • Fixes mentioned issues / 修复已提及的问题(无关联 Issue)
  • Code reviewed by human / 代码通过人工检查
  • Changes tested / 已完成测试

Description / 描述

本 PR 启用 ScriptCat 的 Firefox MV3 构建,并修复 Firefox 下 sandbox、event page 与 Service Worker 之间的启动时序和跨上下文通信问题。

主要改动

  • 启用 Firefox MV3 打包

    • 开启 Firefox 构建产物生成。
    • 保留 Firefox manifest 中的 sandbox 配置,并补充 sandbox CSP。
    • 将 Firefox 最低版本设为 154.0a1,以匹配 manifest sandbox 支持。
    • Chrome 构建继续移除 Firefox 专用的 sandbox CSP,避免影响现有 Chromium 路径。
  • 重构 sandbox/offscreen 就绪流程

    • 由 sandbox 在自身初始化完成后主动发送 preparationSandbox,不再由父层猜测、轮询或伪造就绪状态。
    • offscreen/event page 收到信号后再通知 Service Worker 环境已就绪。
    • 增加 15 秒兜底超时,sandbox 未能上报时仍可继续启动,并输出明确日志,避免永久阻塞。
    • 复用已有的 getExtensionEnv 请求执行非阻塞通道自检,并将检测结果上报到父层日志。
  • 修复 Firefox 下的消息通道问题

    • Firefox MV3 中 event page 与 Service Worker 运行在同一脚本/进程内,新增 InProcessMessage 处理 offscreen → Service Worker 通信,避免 chrome.runtime.sendMessage 向自身发送时出现 Receiving end does not exist
    • WindowMessage 支持惰性解析目标窗口,避免 iframe 尚处于 about:blank 时过早缓存 contentWindow,导致导航到跨源 sandbox 页面后消息来源匹配失败。
    • MessageQueue.publish() 主动捕获无接收方时 Firefox 返回的 rejected Promise,避免产生未处理的 Promise rejection。
  • 补充测试与文档

    • 新增或更新 sandbox 就绪、进程内消息桥接、惰性窗口目标及无接收方广播等单元测试。
    • 更新架构文档,说明 Firefox MV3 下 sandbox/offscreen 的初始化和通信机制。

兼容性说明

  • Firefox 构建要求 154.0a1 或更高版本。
  • Chromium 继续使用真实 offscreen document,现有通信路径保持不变。
  • 本 PR 不包含界面改动。

验证

  • tsc --noEmit
  • eslint
  • prettier --check
  • 完整测试套件通过:292 个测试文件、3099 个测试用例

Screenshots / 截图

不适用:本 PR 仅涉及构建配置、启动协议和内部消息通信。

@cyfung1031 cyfung1031 changed the title ♻️ 修复 Firefox MV3 sandbox 就绪握手与 offscreen↔SW 通信问题 ♻️ ScriptCat MV3 正式支持 Firefox - 修复 Firefox MV3 sandbox 就绪握手与 offscreen↔SW 通信问题 Jul 11, 2026
@cyfung1031 cyfung1031 changed the title ♻️ ScriptCat MV3 正式支持 Firefox - 修复 Firefox MV3 sandbox 就绪握手与 offscreen↔SW 通信问题 🦊 启用 Firefox MV3 构建并完善 sandbox/offscreen 通信 Jul 11, 2026
@cyfung1031

cyfung1031 commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

b6329d4 修正了 定时脚本 没有自动执行的问题


RuntimeService(service worker 侧)和 ScriptService(offscreen 侧)各自持有一个独立的 MessageQueue 实例。两者之间的跨上下文消息传递,完全依赖 MessageQueue.publish() 通过 chrome.runtime.sendMessage() 广播。

在 Chrome 中,这一机制可以正常工作,因为 offscreen document 运行在独立进程中。

但在 Firefox 中,EventPageOffscreenManager 与 service worker 代码运行在同一个脚本和 Frame 内。根据 WebExtensions 的 runtime.onMessage 规则,广播会发送到扩展中的其他 Frame,但不会触发发送者所在 Frame 的监听器。

因此,当 service worker 侧调用:

publish("enableScripts", ...)

消息无法到达 offscreen 侧队列的监听器,因为两个队列都位于同一个发送者 Frame 中。

cron 调度机制本身没有问题。使用 createCronJob* * * * * * 进行独立测试时,3.5 秒内按计划触发了 3 次,说明问题不在 cron 包的集成。

两种执行方式的差异如下:

手动运行通过 runScript() 执行,使用 this.msgSender 进行点对点 RPC,也就是 IOffscreenSend / InProcessMessage 桥接。这条路径可以正常工作。

自动调度依赖 RuntimeServicepreparationOffscreen 订阅者发布:

this.mq.publish("enableScripts", res)

该消息需要触发 ScriptService"enableScripts" 的订阅,然后才能在 sandbox 中执行:

enableScript()crontabScript()

但在 Firefox 中,这条广播无法到达,因此 crontabScript() 根本不会被调用。

实际问题不是“任务执行一次后停止”,而是任务从一开始就没有完成调度。

同一问题还会导致以下消息无法同步到 Firefox 的 sandbox:

  • deleteScripts
  • installScript
  • setSandboxLanguage

这些失败不会产生明显错误,因此容易被忽略。

修复方案

BackgroundEnvManagerBase 增加可注入的 messageQueue 构造参数,默认值仍为 new MessageQueue()

这样不会影响 Chrome 的 OffscreenManager。在 Chrome 中,offscreen 和 service worker 本来就运行在不同进程中,因此仍然需要各自独立的队列。

EventPageOffscreenManager 现在要求通过第二个构造参数传入队列。service_worker.ts 会将现有的 messageQueue 实例传给它,避免基类再创建一个互不连通的新实例。

共享同一个 MessageQueue 实例后,publish() 内部的本地 this.EE.emit() 就可以直接完成两侧通信,无需再通过 chrome.runtime.sendMessage() 中转。

新增测试覆盖以下场景:

  • 注入的 MessageQueue 实例会被正确保留,不会被新的实例覆盖。
  • 在共享队列上调用 publish() 后,offscreen 侧订阅能够正常收到消息。

@cyfung1031 cyfung1031 added P0 🚑 需要紧急处理的内容 Pre-FF-MV3 labels Jul 11, 2026
@cyfung1031

cyfung1031 commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

Firefox retains WebRequest blocking in MV3

https://blog.mozilla.org/addons/2022/10/31/begin-your-mv3-migration-by-implementing-new-features-today/

因此 Firefox MV3版 用了 WebRequest blocking 来避免 Event Page 被 kill 掉 (定时脚本需要这个设计)

mozilla 不接受再处理吧
例如先关掉这功能,之后再换成 Alarms

@cyfung1031 cyfung1031 requested a review from CodFrm July 11, 2026 04:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P0 🚑 需要紧急处理的内容 Pre-FF-MV3

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant