Подтвердить что ты не робот

Расширение Chrome Devpanel, связанное с справочной страницей

У меня есть расширение для панели chrome devtools. Я могу отправлять сообщения на страницу с помощью chrome.devtools.inspectedWindow.eval... но как я могу получать сообщения в панели dev? В частности, мне нужно, чтобы мой devpanel подключался к событиям, которые происходят на странице. Я не могу заставить его слушать события на моем контенте script, а не на фоновом изображении.

Я пробовал chrome.extension.sendMessage в контенте script вместе с chrome.extension.onMessage.addListener в панели dev script. Но sendMessage жалуется на Port error: Could not establish connection. Receiving end does not exist.

Проблема сохраняется с долговременными подключениями:

В содержании script или в фоновой странице:

var port = chrome.extension.connect({name: "test"});
port.postMessage({msg: "testing"});

В панели инструментов dev javascript:

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

Как я могу прослушивать события, которые были запущены в моем контенте script - на панели инструментов Dev? Диаграмма, подобная этому из Firefox Add-On SDK, будет отличной: https://addons.mozilla.org/en-US/developers/docs/sdk/latest/static-files/media/content-scripting-overview.png

4b9b3361

Ответ 1

Целью является создание канала ( "порт" ) для связи. Неважно, как создается порт, если соединение правильно поддерживается.

devtools script должен инициировать порт, потому что фон script не знает, когда создается панель devtools.

Вот базовый пример, который показывает метод двунаправленной связи:

devtools.js

chrome.devtools.panels.create('Test', '/icon.png', '/panel.html', function(extensionPanel) {
    var _window; // Going to hold the reference to panel.html `window`

    var data = [];
    var port = chrome.runtime.connect({name: 'devtools'});
    port.onMessage.addListener(function(msg) {
        // Write information to the panel, if exists.
        // If we don't have a panel reference (yet), queue the data.
        if (_window) {
            _window.do_something(msg);
        } else {
            data.push(msg);
        }
    });

    extensionPanel.onShown.addListener(function tmp(panelWindow) {
        extensionPanel.onShown.removeListener(tmp); // Run once only
        _window = panelWindow;

        // Release queued data
        var msg;
        while (msg = data.shift()) 
            _window.do_something(msg);
        // Just to show that it easy to talk to pass a message back:
        _window.respond = function(msg) {
            port.postMessage(msg);
        };
    });
});

Теперь панель может отправлять/получать сообщения через порт. Панель script (внешний script файл, из-за CSP) может выглядеть так:

panel.js

function do_something(msg) {
    document.body.textContent += '\n' + msg; // Stupid example, PoC
}
document.documentElement.onclick = function() {
    // No need to check for the existence of `respond`, because
    // the panel can only be clicked when it visible...
    respond('Another stupid example!');
};

Теперь, справочная страница script:

background.js

var ports = [];
chrome.runtime.onConnect.addListener(function(port) {
    if (port.name !== "devtools") return;
    ports.push(port);
    // Remove port when destroyed (eg when devtools instance is closed)
    port.onDisconnect.addListener(function() {
        var i = ports.indexOf(port);
        if (i !== -1) ports.splice(i, 1);
    });
    port.onMessage.addListener(function(msg) {
        // Received message from devtools. Do something:
        console.log('Received message from devtools page', msg);
    });
});
// Function to send a message to all devtools.html views:
function notifyDevtools(msg) {
    ports.forEach(function(port) {
        port.postMessage(msg);
    });
}

Чтобы протестировать, просто запустите notifyDevtools('Foo'); на исходной странице (например, через консоль). В этой демонстрации сообщение будет отправлено всем devtools. После получения панель devtools будет содержать принятое сообщение.

Поместите расширение вместе, используя:

manifest.json

{ "name": "Test",
  "manifest_version": 2,
  "version": "1",
  "devtools_page": "devtools.html",
  "background":{"scripts":["background.js"]}
}

panel.html

<script src="panel.js"></script> <!-- Doctype etc not added for conciseness-->

devtools.html

<script src="devtools.js"></script>

См. также