自定义DevTools Elements侧边栏窗格如何与面板通信?

est*_*why 7 google-chrome-extension google-chrome-devtools

我正在创建我的自定义元素侧边栏窗格,如下所示:

chrome.devtools.panels.elements.createSidebarPane(
    "MyPane",
    function (sidebar) {
        sidebar.setPage('my-pane.html');
    }
);
Run Code Online (Sandbox Code Playgroud)

我-pane.html:

<html>
    <head>
    <script src="my-pane.js"></script>
    </head>
    <body>
    <!-- custom UI -->
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

在my-pane.js里面我正在观看当前选中的元素:

chrome.devtools.panels.elements.onSelectionChanged.addListener(function() {
    chrome.devtools.inspectedWindow.eval("$0", function (res) {
       <!-- process res and want to push detailed results into custom panel -->
    });
});
// expecting request from panel here
chrome.extension.onMessage.addListener(function (msg, _, sendResponse) {
    console.log(msg, _, sendResponse);
});
Run Code Online (Sandbox Code Playgroud)

到目前为止,一切都运行得很好:我可以选择并在窗格中围绕它构建自定义HTML UI.更进一步,我想在另一个Panel中显示一些更详细的UI.这就是我正在尝试(创建窗格后立即):

chrome.devtools.panels.create(
    'My details',
    'icon.png',
    'my-panel.html',
    function (panel) {
        panel.onShown.addListener(function (window) {
            chrome.extension.sendMessage({}, function (response) {
                console.log(response);
            });
        });
    }
);
Run Code Online (Sandbox Code Playgroud)

这些线路以(in)着名的方式失败:

端口错误:无法建立连接.接收端不存在.

sendMessage/onMessage模式是否在窗格和面板之间进行通信的正确方式,两者都表示为.html页面?

编辑

试图完全避免DevTools物流并通过DOM访问页面(my-pane.htmlmy-panel.html似乎都在<iframe/>单个父页面中):

..
panel.onShown.addListener(function (window) {
    console.log(["PANEL",
       window
           .top
           .frames[0] // Assume this is my-pane.html
           .document
           .getElementsByTagName('ol')
    ]);
});
..
Run Code Online (Sandbox Code Playgroud)

这不起作用:

不安全的JavaScript尝试使用URL chrome-extension:// <..> /devtools.html从具有URL chrome-extension:// <..> /devtools.html的框架访问框架.域,协议和端口必须匹配.

编辑2

傻我!当然,上述关于第一个<iframe/>是正确的假设是完全错误的.以下产生更有意义的结果:

panel.onShown.addListener(function (window) {
    for (var i = 0; i < window.top.frames.length; i++) {
        try {
            console.log(["PANEL",
                window.top.frames[i].document.getElementsByTagName('ol')
            ]);
            break;
        } catch (e) {
            console.log('BAD!', e);
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

编辑3(解决方案,但不是答案)

chrome.devtools.panels.create(
    'My Panel',
    'icon.png',
    'my-panel.html', // Must define function callbackInMyPanelPage(doc) { .. }
    function (panel) {
        panel.onShown.addListener(function (window) {
            for (var i = 0; i < window.top.frames.length; i++) {
                try {
                    // Use any unique marker to identify our pane document,
                    // at worst case a security exception will be thrown..
                    var $el = window.top.frames[i].document.getElementById('myPane');

                    if ($el) {
                        try {
                            // pass pane's document to panel page
                            window.callbackInMyPanelPage(window.top.frames[i].document);
                        } catch(ex) {} // Don't interfere with a handler below 
                        break;
                    }
                } catch (e) {
                    console.warn('Cannot access <iframe/>', e);
                }
            }
        });
     }
 );
Run Code Online (Sandbox Code Playgroud)

奖励:我试图实现什么样的沟通(绿色箭头)的可视化

kbt*_*tzr 0

根据您最后的评论

到目前为止,将onMessage 事件处理程序放入background.js 后就可以工作了。但这正是我想避免的。相反,我更喜欢 my-pane.html 和 my-panel.html 直接相互对话。当不使用 HTML 页面作为窗格和面板内容时,这当然是可能的。

我知道发生了什么事...

您的面板/窗格不是扩展进程,它被视为内容脚本。因此,您需要使用chrome.tabs.sendMessage而不是chrome.extension.sendMessage