Chrome 扩展消息传递不起作用(background.js 到 content.js)
Chrome extension message passing not working (background.js to content.js)
我无计可施,想弄清楚为什么我无法让消息传递在我的 Chrome 扩展中工作。
请记住,上个月我对 javascript 绝对是全新的,我一直在用在线视频自学(我的编码背景完全是 java)。
我想要的只是让我的后台脚本能够通知我的内容脚本正在发生的事情,然后在内容脚本中执行一些代码。正如您在下面看到的,I have set up my code identically to the documentation,但它不起作用!
这是我在加载扩展程序时遇到的错误:
Errors
manifest.json
{
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
],
"background": {
"scripts": ["background.js"],
"persistent": true
},
"permissions": [
"activeTab",
"tabs",
"storage"
],
"manifest_version": 2,
"name": "eSports YT Viewer",
"version": "1.0.0",
"description": "An eSports viewer for youtube"
}
background.js
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
console.log(response.farewell);
});
});
content.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.greeting == "hello") {
sendResponse({farewell: "goodbye"});
}
});
非常感谢任何帮助!谢谢。
根据我在您的 post 中看到的情况,一切看起来都井井有条,所以我只是抛出一些想法:
我认为这里错误的线索是第一个错误,而不是第二个——看起来脚本之间的通信没有established correctly。
可能尝试将后台脚本的 persistent
设置更改为 false:
"background": {
"scripts": ["background.js"],
"persistent": false
},
From the docs,仅当您使用 chrome.webRequest
API 修改网络请求时才需要,并且可能会导致此处设置出现一些奇怪的问题。
但正如我所说,只是初步猜测。
祝你好运!
您当前的后台脚本是错误的,或者说什么都没做meaningful/useful。后台脚本 运行s 在单独的隐藏后台页面中(或 ManifestV3 中的服务工作者)。另见 Accessing console and devtools of extension's background.js.
当 a) 浏览器配置文件启动,b) 扩展名 re-enabled/re-loaded 或 c) installed/updated 时,后台脚本 运行s。因此,您的代码会立即查询选项卡并将消息发送到任何处于活动状态的选项卡,因此不能保证它甚至包含一个网页:可能什么都没有(一个空的新选项卡)或者它可以是一个内部 chrome :// 浏览器设置页面或选项卡可能仍在等待内容脚本执行(请参阅此答案末尾的注释)。
ManifestV2 扩展注意事项:将后台脚本切换为 "persistent": false
也无济于事。它只会使脚本在 API 事件或弹出窗口打开时唤醒,但您没有注册任何 API 事件,也没有声明弹出窗口。无论如何,您应该切换到 "persistent": false
,但对于 different reason:只有在需要时才 运行ning。
解决方案
后台脚本的通常目的是为chrome
API事件注册处理程序,例如chrome.tabs.onUpdated或chrome.webNavigation.onHistoryStateUpdated等,否则很可能你根本不需要后台脚本。在事件处理程序中,您可以使用带有此选项卡 ID 的 chrome.tabs.sendMessage 或 chrome.tabs.connect 向选项卡发送消息。很多人错误地将它发送到活动选项卡,但通常它没有意义,因为事件可能发生在 inactive/backgrounded 选项卡中。通常你应该将它发送到生成事件的选项卡,在传递给处理程序的参数中寻找 tab
或 tabId
,参考那些事件上的 documentation。
另请注意,内容脚本 运行 默认情况下在 DOMContentLoaded 之后,因此如果您在页面仍在加载时发送消息,它将失败。在这种情况下,您可以 运行 他们 document_start 或使用不同的方法,例如不要声明内容脚本,而是以编程方式注入它。没有通用的答案,这取决于用例。
如果您确实需要向扩展 startup/restart 上的内容脚本发送消息,那么您必须先通过 chrome.tabs.reload 重新加载所有匹配的选项卡(因此内容脚本将 运行 自动) 或 reinject the scripts explicitly.
我无计可施,想弄清楚为什么我无法让消息传递在我的 Chrome 扩展中工作。
请记住,上个月我对 javascript 绝对是全新的,我一直在用在线视频自学(我的编码背景完全是 java)。
我想要的只是让我的后台脚本能够通知我的内容脚本正在发生的事情,然后在内容脚本中执行一些代码。正如您在下面看到的,I have set up my code identically to the documentation,但它不起作用!
这是我在加载扩展程序时遇到的错误:
Errors
manifest.json
{
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
],
"background": {
"scripts": ["background.js"],
"persistent": true
},
"permissions": [
"activeTab",
"tabs",
"storage"
],
"manifest_version": 2,
"name": "eSports YT Viewer",
"version": "1.0.0",
"description": "An eSports viewer for youtube"
}
background.js
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
console.log(response.farewell);
});
});
content.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.greeting == "hello") {
sendResponse({farewell: "goodbye"});
}
});
非常感谢任何帮助!谢谢。
根据我在您的 post 中看到的情况,一切看起来都井井有条,所以我只是抛出一些想法:
我认为这里错误的线索是第一个错误,而不是第二个——看起来脚本之间的通信没有established correctly。
可能尝试将后台脚本的 persistent
设置更改为 false:
"background": {
"scripts": ["background.js"],
"persistent": false
},
From the docs,仅当您使用 chrome.webRequest
API 修改网络请求时才需要,并且可能会导致此处设置出现一些奇怪的问题。
但正如我所说,只是初步猜测。
祝你好运!
您当前的后台脚本是错误的,或者说什么都没做meaningful/useful。后台脚本 运行s 在单独的隐藏后台页面中(或 ManifestV3 中的服务工作者)。另见 Accessing console and devtools of extension's background.js.
当 a) 浏览器配置文件启动,b) 扩展名 re-enabled/re-loaded 或 c) installed/updated 时,后台脚本 运行s。因此,您的代码会立即查询选项卡并将消息发送到任何处于活动状态的选项卡,因此不能保证它甚至包含一个网页:可能什么都没有(一个空的新选项卡)或者它可以是一个内部 chrome :// 浏览器设置页面或选项卡可能仍在等待内容脚本执行(请参阅此答案末尾的注释)。
ManifestV2 扩展注意事项:将后台脚本切换为 "persistent": false
也无济于事。它只会使脚本在 API 事件或弹出窗口打开时唤醒,但您没有注册任何 API 事件,也没有声明弹出窗口。无论如何,您应该切换到 "persistent": false
,但对于 different reason:只有在需要时才 运行ning。
解决方案
后台脚本的通常目的是为chrome
API事件注册处理程序,例如chrome.tabs.onUpdated或chrome.webNavigation.onHistoryStateUpdated等,否则很可能你根本不需要后台脚本。在事件处理程序中,您可以使用带有此选项卡 ID 的 chrome.tabs.sendMessage 或 chrome.tabs.connect 向选项卡发送消息。很多人错误地将它发送到活动选项卡,但通常它没有意义,因为事件可能发生在 inactive/backgrounded 选项卡中。通常你应该将它发送到生成事件的选项卡,在传递给处理程序的参数中寻找 tab
或 tabId
,参考那些事件上的 documentation。
另请注意,内容脚本 运行 默认情况下在 DOMContentLoaded 之后,因此如果您在页面仍在加载时发送消息,它将失败。在这种情况下,您可以 运行 他们 document_start 或使用不同的方法,例如不要声明内容脚本,而是以编程方式注入它。没有通用的答案,这取决于用例。
如果您确实需要向扩展 startup/restart 上的内容脚本发送消息,那么您必须先通过 chrome.tabs.reload 重新加载所有匹配的选项卡(因此内容脚本将 运行 自动) 或 reinject the scripts explicitly.