Chrome 在 chrome 120 beta 中发布了用户脚本 API。 现在我们可以从扩展运行动态脚本,但定位特定选项卡的唯一方法似乎是与 url 匹配的 matches 属性。 我需要的是针对特定的 tabID 。
用例:内容脚本将消息发送到后台脚本,然后我们仅将动态脚本应用于该特定选项卡。 基于 URL 的定位是不够的,因为在某一时刻可能会使用相同的 URL 打开多个选项卡。
https://developer.chrome.com/docs/extensions/reference/userScripts
chrome.userScripts.register([{
id: 'test',
matches: ['*://*/*'],//not specific enough
tabId: 124473838,//not a part of api
js: [{code: 'alert("Hi!")'}]
}]);
userScripts API 目前没有这样的方法:https://github.com/w3c/webextensions/issues/477
低效的解决方法是在所有处于活动状态的 URL 上运行脚本,例如作为一个函数,然后在收到通过 chrome.tabs.sendMessage 从弹出窗口或后台脚本发送的消息时运行此函数:
chrome.userScripts.register([{
id: '1',
runAt: 'document_start',
matches: ['<all_urls>'],
js: [{
code: 'chrome.runtime.onMessage.addListener(fn);' +
function fn(msg, sender, sendResponse) {
console.log('onMessage', ...arguments);
sendResponse('foo');
},
}],
}]);
对于大型脚本,您可以通过在消息中传递的代码上使用
window.eval
对其进行稍微优化。这需要首先在后台/弹出脚本中允许 eval:
chrome.userScripts.configureWorld({
csp: "script-src 'self' 'unsafe-eval'"
});
这两种方法都会浪费地在所有页面中创建一个单独的 JS 世界,因此最有效的解决方法是使用 chrome.scripting.executeScript 创建 DOM 脚本元素,如 https://stackoverflow.com/a/70949953 ,但受页面CSP限制。