Firefox MV3 #1330
Replies: 5 comments 8 replies
-
|
@CodFrm |
Beta Was this translation helpful? Give feedback.
-
|
@CodFrm https://bugzilla.mozilla.org/show_bug.cgi?id=1685123 原因是,Firefox团队最初让 eval 在MV3完全禁止让扩充变得安全的想法,被 executeScript 这个API打破了缺口,因此Firefox整个团队的想法是舍弃 executeScript, 而倒过来为了扩充能使用 自定义代码, 会重新在MV3实现 sandbox 现在最新版是 151.0a1 (2026-04-06) 应该今年内就会补回 sandbox, 然后 Firefox那边也可以踏入 MV3 时代了 |
Beta Was this translation helpful? Give feedback.
-
|
https://blog.mozilla.org/addons/2026/04/23/webextensions-api-changes-firefox-149-152/ 未提及 Firefox MV3 sandbox 支持的时间表 |
Beta Was this translation helpful? Give feedback.
-
Firefox MV3 待處理1 - WindowMessage// ==UserScript==
// @name WindowMessage Transport Test
// @namespace https://docs.scriptcat.org/
// @version 0.1.0
// @description Verifies the WindowMessage paths used by ScriptCat sandbox and offscreen pages.
// @author ScriptCat
// @match *://*/*?WINDOW_MESSAGE_TEST_SC
// @grant GM.xmlHttpRequest
// @grant GM_xmlhttpRequest
// @grant GM.setClipboard
// @grant unsafeWindow
// @connect httpbun.com
// @run-at document-end
// @noframes
// ==/UserScript==
(async function () {
"use strict";
const results = {
passed: 0,
failed: 0,
total: 0,
};
console.log(
"%c=== WindowMessage transport test start ===",
"color: blue; font-size: 16px; font-weight: bold;",
);
console.log(
"This userscript exercises the production WindowMessage route used by the sandbox/offscreen document. Run it on a URL ending with ?WINDOW_MESSAGE_TEST_SC.",
);
function section(name) {
console.log(`\n%c--- ${name} ---`, "color: orange; font-weight: bold;");
}
function assertSame(expected, actual, message) {
if (!Object.is(expected, actual)) {
throw new Error(
`${message} - expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`,
);
}
}
function assertTrue(condition, message) {
if (!condition) {
throw new Error(message || "Assertion failed");
}
}
function withTimeout(promise, label, ms = 10000) {
let timer = null;
const timeout = new Promise((_, reject) => {
timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
});
return Promise.race([promise, timeout]).finally(() => clearTimeout(timer));
}
async function test(name, fn) {
results.total++;
try {
await fn();
results.passed++;
console.log(`%cPASS ${name}`, "color: green;");
return true;
} catch (error) {
results.failed++;
console.error(`%cFAIL ${name}`, "color: red;", error);
return false;
}
}
section("Sandbox endpoint");
await test("default userscript runs in the sandbox window", () => {
assertSame("object", typeof unsafeWindow, "unsafeWindow should be available");
assertTrue(window !== unsafeWindow, "window should be the sandbox window, not the page window");
assertSame(window, self, "self should point at the sandbox window");
assertSame(window, globalThis, "globalThis should point at the sandbox window");
});
section("One-shot sendMessage path");
await test("GM.setClipboard resolves through the offscreen sendMessage bridge", async () => {
const text = `ScriptCat WindowMessage ${Date.now()} ${Math.random().toString(36).slice(2)}`;
await withTimeout(GM.setClipboard(text, { type: "text", mimetype: "text/plain" }), "GM.setClipboard");
});
section("Long-lived connect path");
await test("GM.xmlHttpRequest receives offscreen response data over a connect channel", async () => {
const marker = `window-message-${Date.now()}-${Math.random().toString(36).slice(2)}`;
const response = await withTimeout(
GM.xmlHttpRequest({
method: "GET",
url: `https://httpbun.com/get?marker=${encodeURIComponent(marker)}`,
responseType: "json",
}),
"GM.xmlHttpRequest",
);
assertSame(200, response.status, "status should be 200");
assertTrue(response.finalUrl.includes("httpbun.com/get"), "finalUrl should be populated");
assertTrue(typeof response.responseHeaders === "string", "responseHeaders should be a string");
assertTrue(response.response && typeof response.response === "object", "JSON response should be parsed");
const args =
response.response.args ||
response.response.query ||
response.response.params ||
{};
assertSame(marker, args.marker, "query marker should round-trip through the response");
});
await test("GM_xmlhttpRequest forwards readyState events over the connect channel", async () => {
const states = [];
const response = await withTimeout(
new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: "https://httpbun.com/bytes/64",
onreadystatechange: (res) => {
states.push(res.readyState);
},
onload: resolve,
onerror: reject,
ontimeout: reject,
timeout: 10000,
});
}),
"GM_xmlhttpRequest readyState",
);
assertSame(200, response.status, "status should be 200");
assertTrue(states.includes(4), "readyState DONE should be observed");
assertTrue(response.responseText.length > 0, "responseText should contain the payload");
});
await test("GM_xmlhttpRequest abort disconnects a pending connect channel", async () => {
await withTimeout(
new Promise((resolve, reject) => {
const request = GM_xmlhttpRequest({
method: "GET",
url: "https://httpbun.com/delay/5",
onload: () => reject(new Error("request loaded before abort")),
onerror: reject,
ontimeout: reject,
onabort: (res) => {
try {
assertSame(0, res.readyState, "aborted readyState should be UNSENT");
assertSame(0, res.status, "aborted status should be 0");
resolve();
} catch (error) {
reject(error);
}
},
timeout: 10000,
});
setTimeout(() => request.abort(), 100);
}),
"GM_xmlhttpRequest abort",
);
});
console.log(
"\n%c=== WindowMessage transport test complete ===",
"color: blue; font-size: 16px; font-weight: bold;",
);
console.log(
`%cTotal: ${results.total} | Passed: ${results.passed} | Failed: ${results.failed}`,
results.failed === 0
? "color: green; font-weight: bold;"
: "color: red; font-weight: bold;",
);
})();
DNR modifyHeaders -> onBeforeRedirect |
Beta Was this translation helpful? Give feedback.
-
Issue - No sandbox support -> Cannot do background scripthttps://bugzilla.mozilla.org/show_bug.cgi?id=1685123 Sandbox issue (might also need #1347 ) Issue - xhr request id -> need to do back the original proposed wayhttps://bugzilla.mozilla.org/show_bug.cgi?id=2040251 Inconsistent MV3 behavior - DNR modifyHeaders with Inconsistency: Execution order for DNR modifyHeaders and Issue - Failed in "WindowMessage Transport Test" |
Beta Was this translation helpful? Give feedback.

Uh oh!
There was an error while loading. Please reload this page.
-
Firefox MV3 不支持在 扩充页面进行
eval/new Function查过很多资料和方法。没有任何可行的做法
除非打开一个网络的沙盒页
当作一般页面的脚本注入,在里面跑代码
Beta Was this translation helpful? Give feedback.
All reactions