🦊 启用 Firefox MV3 构建并完善 sandbox/offscreen 通信#1561
Conversation
…target audiences
诊断 Firefox MV3 offscreen<->SW 握手问题时临时加入,问题已定位并修复,探针不再需要。
|
b6329d4 修正了 定时脚本 没有自动执行的问题
在 Chrome 中,这一机制可以正常工作,因为 offscreen document 运行在独立进程中。 但在 Firefox 中, 因此,当 service worker 侧调用:
消息无法到达 offscreen 侧队列的监听器,因为两个队列都位于同一个发送者 Frame 中。 cron 调度机制本身没有问题。使用 两种执行方式的差异如下: 手动运行通过 自动调度依赖
该消息需要触发
但在 Firefox 中,这条广播无法到达,因此 实际问题不是“任务执行一次后停止”,而是任务从一开始就没有完成调度。 同一问题还会导致以下消息无法同步到 Firefox 的 sandbox:
这些失败不会产生明显错误,因此容易被忽略。 修复方案为 这样不会影响 Chrome 的
共享同一个 新增测试覆盖以下场景:
|
因此 Firefox MV3版 用了 WebRequest blocking 来避免 Event Page 被 kill 掉 (定时脚本需要这个设计) mozilla 不接受再处理吧 |
|
更新:已修正 harness 的等待与结果卡解析,并补做无 CSP 页面上的完整 Firefox Nightly headed 验证。下面是当前最终证据口径。 环境
原目标页上的确定问题同步 Example 的 window.foo = "bar";原 无 CSP 隔离验证为了只隔离目标页面因素,本轮采用 match-only variant,不是 exact-example:
结果:
两份结果均满足:
因此可以确认:原同步版 Example 本身的页面耦合另用无 CSP 的 document.querySelector(".container").insertBefore(
script,
document.querySelector(".masthead"),
);原因是 建议更新 Example 时:
对上一版评论的纠错说明上一版指出 harness 曾在约 2~3 秒后早退、不能据此判断 XHR 或 notification 产品行为,这个纠错仍然成立。现在的新 harness 已使用持续轮询等待完整结果卡,并实际运行到 29/29,因此本次无 CSP 隔离运行补齐了此前缺失的完整验证证据。 |
pnpm run check:i18n 此前因缺失 ko-KR/pt-BR 的 enable_background.enable_success/disable_success 及 keep_scripts_alive.* 而失败;architecture-build.md 仍描述 PACK_FIREFOX 默认关闭、 Firefox manifest 会删除 sandbox 等已被本 PR 改写的旧行为。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Reviewed docs and translation completeness against
|
|
@CodFrm 现在这个 PR 还有什么是卡住的吗?? |
This comment was marked as low quality.
This comment was marked as low quality.
之前的CSP问题,popup菜单点击更多的UI/UX问题 其它的我还没手动测试,明天着重来处理这个 我将截图、视频放上面了: https://my.feishu.cn/docx/VqgYdrfNaoaHnsx6nGkcjJskn8e |
This comment was marked as low quality.
This comment was marked as low quality.
|
“所以不应修改 ScriptCat 产品逻辑来绕过宿主页面的 CSP。” 在chrome下是可以的,要改产品逻辑呀 |
我觉得这个浏览器 spec 差异的问题不是一时三刻能解决。 Chrome 在 content 里可跳过CSP执行脚本 说不定还要去 Bugzilla 那边回报问题 |
| "sandbox allow-downloads allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-scripts allow-storage-access-by-user-activation allow-top-navigation allow-top-navigation-by-user-activation allow-top-navigation-to-custom-protocols; script-src 'unsafe-inline' 'unsafe-eval' https: http: data: blob: 'self';"; | ||
|
|
||
| /** | ||
| * Firefox MV3 的 sandbox manifest 支持要求显式声明 CSP;Chrome 继续使用原有 manifest。 |
There was a problem hiding this comment.
这会造成两种 sandbox. 影响代码维护。建议统一成 firefox 那个。日后再调整
目标是尽量减少分支代码。降低维护负担
There was a problem hiding this comment.
补充: 可以调整这些 sandbox feature. 如果你有自动化测试,应该可以找出最少 sandbox feature
There was a problem hiding this comment.
这会影响chrome商店审核,所以删掉,mv2的时候打包就会特意删掉
Firefox MV3
|
目前我在推测 ScriptCat 在 Chrome 的 inline script execution 是由于 Chrome 本身的CSP模型有漏洞 |
不清楚,暂时没发现其它问题了,csp这个问题后续再处理吧 明天再手动看一下 就合并发布 应该本来就是feature,这个csp受扩展csp/chrome.user.configureWorld控制的,反而是ff的bug |
This comment was marked as low quality.
This comment was marked as low quality.
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1875475#c1 看来是 FF 未做好 userScripts API 的问题 用 https://github.com/cyfung1031/mv3-userscript-world-csp-unsafe-inline 重现了问题 |
Firefox Nightly E2E 最终补充:PR HEAD 定向复跑 + #1629 高价值合同更新此前结论:原评论中的 background/crontab 两项 基线与总结果
1.
|
| 场景 | Run 1 | Run 2 |
|---|---|---|
| normal page ↔ crontab sharing | PASS | PASS |
| background reader observation | PASS | PASS |
取得的直接证据包括:
- crontab 注册、启用并实际进入调度;每轮两次 instrumented 写入间隔均为
5001ms,距真实 5 秒边界约4–5ms; GM_setValue前后 marker 完整,底层value:example真实变化;- normal、background、crontab 均解析到相同 storage identity
example; - background sandbox 启动、listener 注册,normal/background 两端均观察到
remote:true; - 换回仓库 byte-exact 原始脚本后,background reader 仍收到两次更新;
- 两轮 fresh profile 结果一致,PR HEAD 和 tracked tree 前后不变。
所以旧的“9 PASS / 0 FAIL / 2 INCONCLUSIVE”应更新为:normal-page 主链路,以及 normal/background/crontab 共享组合,均已在 #1561 HEAD 真 Firefox 上验证通过。此前 INCONCLUSIVE 是 harness 缺少分层证据,不是产品失败。
2. 参考 #1629 的高价值 Firefox 合同覆盖
本轮把 #1629 的行为断言作为契约,适配到能真实加载 WebExtension 的 Firefox/Selenium harness;没有把 Chromium Playwright 结果冒充 Firefox 结果。
已通过:
- 相同
@storageName的 sync/async 跨 UUID 读写及双向 remote listener;不同 storageName 隔离; - owner 进入回收站、purge/restore、最后 owner purge 清除旧共享值;
- install.html v1 安装/执行 → 同源 v2 更新 → 新页面仅执行 v2;
- 真实备份回环:导出有效 ZIP → 删除原脚本和值 → 实际导入 → 脚本执行且 GM value 恢复;
- 订阅生命周期 A/B → A/B/C → A/C → 删除后不再注入;
- 本地
script-src 'none'CSP 下 page/content@early-start均为14/14,另有 probe 证明普通 inline script 确实被 CSP 阻止; - 本地 GM XHR:允许的
@connect请求为 200、自定义 header 到达服务端、内部 DNR marker 未泄漏、非@connect请求在到达服务端前被拒绝; - 🦊 启用 Firefox MV3 构建并完善 sandbox/offscreen 通信 #1561 event-page/sandbox/background/crontab 启动、跨上下文通信及真实 Firefox 进程重启恢复;
- keep-alive optional permission 与配置开关的可观察状态;
- Firefox 重启后的 options/install/import/confirm 页面稳定状态和已安装脚本恢复。
最强的 #1561 生命周期证据:真实关闭 Firefox 并用同一 fresh profile 启动新进程后,background start 从 1 增至 2,cron tick 从 2 增至 3 且时间戳继续推进,normal/background/crontab 三类脚本仍在。
3. 唯一 SKIP:GM_addElement inline script 与 Firefox CSP
可移植 GM 断言全部通过:sync 28/28、async 29/29。
剩余一项是在 script-src 'none' 页面通过 GM_addElement 插入 inline <script>,并期待 unsafeWindow.foo === "bar"。Firefox 按页面 CSP 阻止其执行,实际为 undefined;两个 focused fresh profile 稳定复现。
该项分类为 Firefox 平台语义 + #1629/示例的跨浏览器可移植性边界,不是 #1561 产品回归,也不建议通过绕过页面 CSP 让断言变绿。
4. gm_xhr_test.js redirect 的原调查结论仍成立
仓库原始 example/tests/gm_xhr_test.js 两轮均为 138 total / 134 PASS / 4 FAIL / 0 pending;四个显示红项实际是 [xhr] / [fetch] 标签下重复的两类 redirect 预期:
redirect:"error":Firefox native Fetch reject,onloadstart → onerror → onloadend,status 为 0,而非示例预期的合成 408;redirect:"manual":Firefox 返回opaqueredirect,response headers 按平台语义不可见。
这仍更支持 Example 的跨浏览器预期与第三方 fixture 问题,不建议为了变绿伪造 status 或 opaque response headers。若项目要把 Chromium/Tampermonkey 风格的合成值定义为跨浏览器产品契约,应先补 Firefox failing regression,再单独决定兼容策略。
5. 未扩大宣称的非阻塞边界
- keep-alive 的 packaged optional permission、权限和配置切换已验证;浏览器授权弹窗 UX 与 invalid-domain keep-alive 实际网络效果缺少稳定自动化成功信号,不包含在 PASS 内;
- manifest 的
incognito:"spanning"与提交测试已检查,但这 15 项合同没有单独执行真实 Firefox 私密窗口@run-in;若它是合并门禁,应增加专门场景; - ✅ 补全并重构高价值 E2E 覆盖 #1629 的 WindowMessage/sandbox 示例没有原样运行,其公网依赖和不同语义由 🦊 启用 Firefox MV3 构建并完善 sandbox/offscreen 通信 #1561 集成 background/page remote、scheduled sandbox 和真实重启恢复覆盖替代。
结论
基于 #1561 HEAD 的真实 Firefox Nightly 证据:
- 此前 background/crontab
@storageName的两项 INCONCLUSIVE 已更新为 PASS; - 本轮 15 项高价值合同为 14 PASS / 1 SKIP / 0 FAIL / 0 INCONCLUSIVE;
- 没有新增已确认的 Firefox 产品问题,也没有观察到 Firefox MV3 合并阻塞。
所有 broad 非通过项都在至少两个额外完成的 fresh profile 中复跑;最终做了 51 项一致性审计,全部通过,HEAD 精确且 tracked tree 干净。
|
看起来没什么严重的问题了合并了 我直接发 Firefox beta |

Checklist / 检查清单
Description / 描述
本 PR 启用 ScriptCat 的 Firefox MV3 构建,并修复 Firefox 下 sandbox、event page 与 Service Worker 之间的启动时序和跨上下文通信问题。
主要改动
启用 Firefox MV3 打包
sandbox配置,并补充 sandbox CSP。154.0a1,以匹配 manifest sandbox 支持。重构 sandbox/offscreen 就绪流程
preparationSandbox,不再由父层猜测、轮询或伪造就绪状态。getExtensionEnv请求执行非阻塞通道自检,并将检测结果上报到父层日志。修复 Firefox 下的消息通道问题
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。补充测试与文档
兼容性说明
154.0a1或更高版本。验证
tsc --noEmiteslintprettier --checkScreenshots / 截图
不适用:本 PR 仅涉及构建配置、启动协议和内部消息通信。