Web扩展-chrome.runtime.sendMessage在匿名选项卡中不起作用



我正在开发一个具有自定义devtools面板的web扩展,该面板通过脚本API注入内容脚本。然后,内容脚本通过chrome.runtime.sendMessage发送一条消息,devtools面板正在侦听该消息。以下是该流程的最小样本(在面板中):

function onMessageFromContentScript(message) {
// React to message
}
async function injectContentScript() {
chrome.runtime.onMessage.addListener(onMessageFromContentScript);
const tabId = chrome.devtools.inspectedWindow.tabId;
await chrome.scripting.executeScript({
func: () => {
chrome.runtime.sendMessage({
id: "injected"
});
},
target: {
tabId,
}
});
}

这在常规选项卡中运行良好,但在隐姓埋名模式下,会引发错误,而不是

Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist.

根据MV3文档,默认spanning模式下的扩展存在一些限制,特别是:

默认模式为";"跨度";,这意味着扩展将在单个共享进程中运行。来自隐姓埋名选项卡的任何事件或消息都将发送到共享进程,并带有一个指示其来源的隐名标志。由于隐姓埋名标签无法使用此共享进程;跨度";隐身模式将无法将页面从其扩展包加载到隐身选项卡的主框架中。

(来源:https://developer.chrome.com/docs/extensions/mv3/manifest/incognito/#spanning)

虽然将隐姓埋名模式切换到split似乎可以解决问题,但我不理解文档中提到的确切限制。我确认内容脚本仍然被注入,只是消息通道似乎被破坏了。如果注入是从弹出窗口而不是devtools页面触发的,那么在spanning模式下似乎也能正常工作。

我的问题是:

  1. Chrome文档中的部分到底是什么意思,有什么限制,哪些API不起作用?

  2. 除了切换隐姓埋名模式之外,还有其他方法可以解决这个问题吗?split模式可能会对其他功能产生一些不必要的副作用。此外,根据https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/incognito

我向https://github.com/StefanBlamberg/chrome-ext-spanning-issue其可以加载在Chrome中以便再现该问题。

看起来Chrome中有一个错误:incognito devtools内部的Chrome扩展://页面实际上是在split模式下运行的(这是incognite窗口的另一个进程),这与默认spanning模式对单个扩展进程的期望相矛盾。

解决方法是使用chrome.devtools.inspectedWindow.eval而不是executeScript,并指定useContentScriptContext来模仿executeScript的默认行为。

function injectContentScript() {
chrome.devtools.inspectedWindow.eval(`(${() => {
return {id: "injected"};
}})()`, {useContentScriptContext: true}, (res, err) => {
document.body.append(document.createElement('br'), JSON.stringify({res, err}));
});
}

最新更新