Google chrome 与后台页面通信的Chrome Devpanel扩展

Google chrome 与后台页面通信的Chrome Devpanel扩展,google-chrome,google-chrome-extension,google-chrome-devtools,Google Chrome,Google Chrome Extension,Google Chrome Devtools,我有一个ChromeDevTools面板的扩展。我可以使用chrome.devtools.inspectedWindow.eval向页面发送消息。。。但是我如何在dev面板中接收消息呢?具体地说,我需要我的devpanel连接页面上发生的事件。我无法让它在我的内容脚本或背景页面上收听事件 我在内容脚本中尝试了chrome.extension.sendMessage,在开发面板脚本中尝试了chrome.extension.onMessage.addListener。但是sendMessage抱怨端

我有一个ChromeDevTools面板的扩展。我可以使用chrome.devtools.inspectedWindow.eval向页面发送消息。。。但是我如何在dev面板中接收消息呢?具体地说,我需要我的devpanel连接页面上发生的事件。我无法让它在我的内容脚本或背景页面上收听事件

我在内容脚本中尝试了
chrome.extension.sendMessage
,在开发面板脚本中尝试了
chrome.extension.onMessage.addListener
。但是
sendMessage
抱怨
端口错误:无法建立连接。接收端不存在。

长寿命连接仍然存在此问题:

在内容脚本或背景页中:

var port = chrome.extension.connect({name: "test"});
port.postMessage({msg: "testing"});
在开发工具面板javascript中:

chrome.extension.onConnect.addListener(function(port) {
    port.onMessage.addListener(function(msg) {
         // never gets here
    });
 });

我如何监听在我的内容脚本中触发的事件——在我的开发工具面板中?Firefox的附加SDK中的类似图非常棒:

目标是创建一个用于通信的通道(“端口”)。只要正确维护连接,端口的创建方式无关紧要

devtools脚本必须启动端口,因为后台脚本不知道何时创建devtools面板

下面是一个基本示例,显示了一种双向通信方法:

devtools.js
chrome.devtools.panels.create('Test','/icon.png','/panel.html',函数(extensionPanel){
var _window;//将保留对panel.html的'window'的引用`
var数据=[];
var port=chrome.runtime.connect({name:'devtools'});
port.onMessage.addListener(函数(msg){
//将信息写入面板(如果存在)。
//如果我们还没有面板引用,请将数据排队。
如果(_窗口){
_窗口。做些什么(味精);
}否则{
数据推送(msg);
}
});
extensionPanel.onShown.addListener(函数tmp(panelWindow){
extensionPanel.onShown.removeListener(tmp);//只运行一次
_窗口=面板窗口;
//释放排队数据
var-msg;
while(msg=data.shift())
_窗口。做些什么(味精);
//只是为了表明,通过交谈可以很容易地回传信息:
_window.respond=函数(msg){
港口邮递信息(msg);
};
});
});
现在,面板能够通过端口发送/接收消息。面板的脚本(外部脚本文件,因为)可能如下所示:

panel.js
函数do\u something(msg){
document.body.textContent+='\n'+msg;//愚蠢的示例,PoC
}
document.documentElement.onclick=函数(){
//不需要检查“respond”是否存在,因为
//面板只有在可见时才能单击。。。
回应(“又一个愚蠢的例子!”);
};
现在,背景页的脚本:

background.js
var端口=[];
chrome.runtime.onConnect.addListener(函数(端口){
if(port.name!=“devtools”)返回;
端口。推送(端口);
//销毁时删除端口(例如当devtools实例关闭时)
port.onDisconnect.addListener(函数(){
var i=端口。indexOf(端口);
如果(i!=-1)端口拼接(i,1);
});
port.onMessage.addListener(函数(msg){
//收到来自devtools的消息。请执行以下操作:
log('从devtools页面收到消息',msg);
});
});
//函数向所有devtools.html视图发送消息:
函数notifyDevtools(msg){
forEach(函数(端口){
港口邮递信息(msg);
});
}
要进行测试,只需运行
notifyDevtools('Foo')(例如)。在本演示中,该消息将发送到所有devtools。收到消息后,devtools面板将包含收到的消息

使用以下方法将扩展组合在一起:

manifest.json
{
“名称”:“测试”,
“清单版本”:2,
“版本”:“1”,
“devtools_页面”:“devtools.html”,
“背景”:{“脚本”:[“background.js”]}
}
panel.html

devtools.html

另见
  • (“将不执行内联JavaScript(…)。此限制同时禁止内联
    块和内联事件处理程序。”)

本文档提供了后台脚本和devtools脚本之间通信的示例。看。(和)@RobW尽管在那个例子中后台脚本和devtools正在进行通信,但这种通信对我来说不起作用。在该示例中,devtools.js发送消息并获取回调。当事件发生时,我需要后台脚本向devtools页面发送消息,除非我连续轮询,否则回调方法无法工作——这是一种不好的方式。我想展示的概念是,连接是由devtools脚本初始化的,而不是由后台脚本初始化的。我现在已经在一个完整的答案中转换了这个概念,包括一个示例,该示例演示了如何在两个方向上传递消息,以及如何在消息之后修改面板的内容。出色的答案是,通过未断开连接的端口发送消息实现了这一点。我在使用内容脚本时也遇到了问题。我需要一个内容脚本,以便能够与devtools脚本对话。有这样一个例子吗?@RaymondCamden使用这个答案中的代码设置一个带有背景页面的频道(来自devtools)。包括选项卡的ID(从消息中派生)。在我的回答中,我通过一个任意选择的(未记录的)存储端口ID
.portId\uuuu
。您可以通过
tabId
来存储端口,并使用常规的消息传递方法在内容脚本和开发工具之间进行通信。感谢您提供的示例!我有一个后续问题:从文档中可以看出