Ответ 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>
См. также
- Как изменить содержимое панели devtools в расширении Chrome?
-
chrome.devtools
API - Передача сообщений: Долгосрочные подключения
- Политика безопасности контента в расширениях Chrome ( "Встроенный JavaScript (...) не будет выполнен. Это ограничение запрещает как встроенные
<script>
блоки и встроенные обработчики событий." )