我们可以使用devtools_page 本身作为连接中继,而不是后台脚本。当打开当前选项卡的 devtools 时,此隐藏页面会在 devtools 内部运行,并且它可以完全访问与后台脚本相同的所有 chrome API。
manifest.json:
"devtools_page": "devtools.html",
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["content.js"],
"run_at": "document_start"
}]
devtools.html:
<script src="devtools.js"></script>
devtools.js:
let portDev, portTab;
const tabId = chrome.devtools.inspectedWindow.tabId;
const onDevMessage = msg => portTab.postMessage(msg);
const onTabMessage = msg => portDev.postMessage(msg);
chrome.runtime.onConnect.addListener(port => {
if (+port.name !== tabId) return;
portDev = port;
portDev.onMessage.addListener(onDevMessage);
portTab = chrome.tabs.connect(tabId, {name: 'dev'});
portTab.onMessage.addListener(onTabMessage);
});
// chrome.devtools.panels.create...
panel.js:
const port = chrome.runtime.connect({
name: `${chrome.devtools.inspectedWindow.tabId}`,
});
port.onMessage.addListener(msg => {
// This prints in devtools-on-devtools: https://stackoverflow.com/q/12291138
// To print in tab's console see `chrome.devtools.inspectedWindow.eval`
console.log(msg);
});
self.onclick = () => port.postMessage('foo');
content.js:
let portDev;
const onMessage = msg => {
console.log(msg);
portDev.postMessage('bar');
};
const onDisconnect = () => {
portDev = null;
};
chrome.runtime.onConnect.addListener(port => {
if (port.name !== 'dev') return;
portDev = port;
portDev.onMessage.addListener(onMessage);
portDev.onDisconnect.addListener(onDisconnect);
});
附:关于the 5-minute timer reset trick,在这种情况下它是相当可靠的,因为在此选项卡的开发工具打开时,该选项卡保证是打开的。