概览
DevTools 扩展程序会向 Chrome DevTools 添加功能。它可以添加新的界面面板 与所检查的页面交互、获取有关网络请求的信息等。视图 精选开发者工具扩展程序。开发者工具扩展程序还可以访问另外一组 开发者工具专用扩展程序 API:
开发者工具扩展程序在结构上与任何其他扩展程序一样:可以有后台页面、内容 脚本和其他项。此外,每个开发者工具扩展程序都有一个开发者工具页面,该页面可以访问 向开发者工具 API 集成。
开发者工具页面
每次打开开发者工具窗口时,系统都会创建扩展程序的开发者工具页面实例。通过 开发者工具页面在开发者工具窗口的生命周期内会一直存在。通过“开发者工具”页面,您可以访问 开发者工具 API 和一组有限的扩展程序 API。具体来说,DevTools 页面可以:
- 使用
devtools.panels
API 创建面板并与之互动。 - 使用
devtools.inspectedWindow
API。 - 使用
devtools.network
API 获取有关网络请求的信息。
开发者工具页面无法直接使用大多数扩展程序 API。它有权访问
内容脚本有权访问的 extension
和 runtime
API 的两种版本。点赞内容
脚本中,开发者工具页面可以使用消息传递功能与后台页面进行通信。对于
示例,请参阅注入内容脚本。
创建开发者工具扩展程序
如需为您的扩展程序创建开发者工具页面,请在扩展程序中添加 devtools_page
字段
清单:
{
"name": ...
"version": "1.0",
"minimum_chrome_version": "10.0",
"devtools_page": "devtools.html",
...
}
对于每个 devtools_page
已打开开发者工具窗口。该页面可能会将其他扩展页面作为面板和边栏添加到
使用 devtools.panels
API 的开发者工具窗口。
chrome.devtools.*
API 模块仅适用于在开发者工具中加载的页面
窗口。内容脚本和其他扩展程序页面没有这些 API。因此,API
仅在开发者工具窗口的生命周期内可用。
此外,还有一些开发者工具 API 仍处于实验阶段。请参阅 chrome.experimental.* API,了解实验性 API 列表以及有关如何使用它们的指南。
开发者工具界面元素:面板和边栏窗格
除了常见的扩展程序界面元素(如浏览器操作、上下文菜单和弹出式窗口)外, DevTools 扩展程序可以将界面元素添加到开发者工具窗口:
- 面板是顶级标签页,例如“元素”面板、“来源”面板和“网络”面板。
- 边栏窗格提供与面板相关的补充界面。样式、计算样式和 “元素”面板上的“事件监听器”窗格就是边栏窗格的示例。(请注意, 边栏窗格的外观可能与图片不符,具体取决于您使用的 Chrome 版本 以及开发者工具窗口停靠的位置)。
每个面板都是其自己的 HTML 文件,其中可包含其他资源(JavaScript、CSS、图片等) on)。基本面板的创建过程如下所示:
chrome.devtools.panels.create("My Panel",
"MyPanelIcon.png",
"Panel.html",
function(panel) {
// code invoked on panel creation
}
);
在面板或边栏窗格中执行的 JavaScript 可以访问与开发者工具页面相同的 API。
为 Elements 面板创建基本的边栏窗格如下所示:
chrome.devtools.panels.elements.createSidebarPane("My Sidebar",
function(sidebar) {
// sidebar initialization code here
sidebar.setObject({ some_data: "Some data to show" });
});
您可以通过以下几种方式在边栏窗格中显示内容:
- HTML 内容。调用
setPage
可指定要在窗格中显示的 HTML 页面。 - JSON 数据。将 JSON 对象传递给
setObject
。 - JavaScript 表达式。将表达式传递给
setExpression
。开发者工具会评估 表达式,并显示返回值。
对于 setObject
和 setExpression
,窗格会显示其值,就像在
开发者工具控制台。不过,setExpression
可让您显示 DOM 元素和任意 JavaScript
对象,而 setObject
仅支持 JSON 对象。
在��展程序组件之间通信
以下部分介绍了在 Google Cloud 不同 的组件。
注入内容脚本
开发者工具页面无法直接调用 tabs.executeScript
。如需从 Cloud Storage 中注入内容脚本,
在开发者工具页面中,您必须使用
inspectedWindow.tabId
属性,并向后台页面发送消息。在
后台页面中,调用 tabs.executeScript
来注入脚本。
以下代码段展示了如何使用 executeScript
注入内容脚本。
// DevTools page -- devtools.js
// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
name: "devtools-page"
});
backgroundPageConnection.onMessage.addListener(function (message) {
// Handle responses from the background page, if any
});
// Relay the tab ID to the background page
chrome.runtime.sendMessage({
tabId: chrome.devtools.inspectedWindow.tabId,
scriptToInject: "content_script.js"
});
后台网页的代码:
// Background page -- background.js
chrome.runtime.onConnect.addListener(function(devToolsConnection) {
// assign the listener function to a variable so we can remove it later
var devToolsListener = function(message, sender, sendResponse) {
// Inject a content script into the identified tab
chrome.tabs.executeScript(message.tabId,
{ file: message.scriptToInject });
}
// add the listener
devToolsConnection.onMessage.addListener(devToolsListener);
devToolsConnection.onDisconnect.addListener(function() {
devToolsConnection.onMessage.removeListener(devToolsListener);
});
});
在检查的窗口中评估 JavaScript
您可以使用 inspectedWindow.eval
方法在
所检查的网页。您可以从开发者工具页面、面板或边栏窗格调用 eval
方法。
默认情况下,系统将在页面的主框架上下文中对表达式进行求值。现在,您可以
熟悉开发者工具 命令行 API 功能,例如元素检查
(inspect(elem)
)、破坏函数 (debug(fn)
)、复制到剪贴板 (copy()
) 等。
inspectedWindow.eval()
使用与在
开发者工具控制台,允许在评估期间访问这些 API。例如,SOAK 将其用于
用于检查元素:
chrome.devtools.inspectedWindow.eval(
"inspect($$('head script[data-soak=main]')[0])",
function(result, isException) { }
);
或者,对 inspectedWindow.eval()
使用 useContentScriptContext: true
选项
在与内容脚本相同的上下文中对表达式求值。正在拨打 eval
useContentScriptContext: true
不会创建内容脚本上下文,因此您必须加载
上下文脚本,然后再调用 eval
(通过调用 executeScript
或通过指定内容
脚本(位于 manifest.json
文件中)。
一旦存在上下文脚本上下文,您就可以使用此选项注入其他内容 脚本。
eval
方法在合适的上下文中使用时功能强大,但使用时危险
不当。如果您不需要访问 tabs.executeScript
方法,
所检查网页的 JavaScript 上下文。如需详细的注意事项和比较这两种方法,
请参阅 inspectedWindow
。
将所选元素传递给内容脚本
内容脚本无法直接访问当前所选的元素。然而,您创建的任何代码
使用 inspectedWindow.eval
执行时,有权访问开发者工具控制台和命令行 API。
例如,在经过评估的代码中,您可以使用 $0
访问选定的元素。
如需将所选元素传递给内容脚本,请执行以下操作:
- 在内容脚本中创建一个将所选元素作为参数的方法。
- 使用
inspectedWindow.eval
和useContentScriptContext: true
选项。
内容脚本中的代码可���如下所示:
function setSelectedElement(el) {
// do something with the selected element
}
从 DevTools 页面调用该方法,如下所示:
chrome.devtools.inspectedWindow.eval("setSelectedElement($0)",
{ useContentScriptContext: true });
useContentScriptContext: true
选项指定必须在
与内容脚本相同的上下文,以便它可以访问 setSelectedElement
方法。
获取参考面板的 window
如需从开发者工具面板执行 postMessage
,您需要引用其 window
对象。
从 panel.onShown
事件处理脚本中获取面板的 iframe 窗口:
onShown.addListener(function callback)
extensionPanel.onShown.addListener(function (extPanelWindow) {
extPanelWindow instanceof Window; // true
extPanelWindow.postMessage( // …
});
从内容脚本到开发者工具页面的消息传递
在开发者工具页面与内容脚本之间传递消息,消息通过后台页面间接进行。
向内容脚本发送消息时,后台网页可以使用
tabs.sendMessage
方法,用于将消息定向到特定标签页中的内容脚本。
如注入内容脚本中所示。
从内容脚本发送消息时,没有现成的方法可用于发送消息 与当前标签页关联的正确开发者工具页面实例。解决方法是 DevTools 页面会与后台页面建立长期连接,并且 后台网页保存标签页 ID 到连接的映射,以便将每一条消息路由到正确的 连接。
// background.js
var connections = {};
chrome.runtime.onConnect.addListener(function (port) {
var extensionListener = function (message, sender, sendResponse) {
// The original connection event doesn't include the tab ID of the
// DevTools page, so we need to send it explicitly.
if (message.name == "init") {
connections[message.tabId] = port;
return;
}
// other message handling
}
// Listen to messages sent from the DevTools page
port.onMessage.addListener(extensionListener);
port.onDisconnect.addListener(function(port) {
port.onMessage.removeListener(extensionListener);
var tabs = Object.keys(connections);
for (var i=0, len=tabs.length; i < len; i++) {
if (connections[tabs[i]] == port) {
delete connections[tabs[i]]
break;
}
}
});
});
// Receive message from content script and relay to the devTools page for the
// current tab
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
// Messages from content scripts should have sender.tab set
if (sender.tab) {
var tabId = sender.tab.id;
if (tabId in connections) {
connections[tabId].postMessage(request);
} else {
console.log("Tab not found in connection list.");
}
} else {
console.log("sender.tab not defined.");
}
return true;
});
DevTools 页面(或面板或边栏窗格)会建立如下连接:
// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
name: "panel"
});
backgroundPageConnection.postMessage({
name: 'init',
tabId: chrome.devtools.inspectedWindow.tabId
});
从注入的脚本向开发者工具页面发送消息
虽然上述解决方案适用于内容脚本,但代码会直接注入到网页中
(例如,通过附加 <script>
标记或通过 inspectedWindow.eval
)需要
不同的策略在这种情况下,runtime.sendMessage
不会将消息传递给
按预期运行后台脚本
一种权宜解决方法是,将注入的脚本与充当
中介。如需将消息传递给内容脚本,您可以使用 window.postMessage
API。下例假设为上一部分中的后台脚本:
// injected-script.js
window.postMessage({
greeting: 'hello there!',
source: 'my-devtools-extension'
}, '*');
// content-script.js
window.addEventListener('message', function(event) {
// Only accept messages from the same frame
if (event.source !== window) {
return;
}
var message = event.data;
// Only accept messages that we know are ours
if (typeof message !== 'object' || message === null ||
!message.source === 'my-devtools-extension') {
return;
}
chrome.runtime.sendMessage(message);
});
您的消息现在将从注入的脚本流向内容脚本,再流到后台 脚本,最后是“开发者工具”页面。
您还可以考虑在此处使用两种不同的消息传递技术。
检测开发者工具何时打开和关闭
如果您的扩展程序需要跟踪开发者工具窗口是否已打开,您可以添加 onConnect 监听器,并从开发者工具页面中调用 connect。由于每个标签页 自己的开发者工具窗口打开,您可能会收到多个连接事件。为了跟踪 DevTools 窗口已打开,您需要对连接和断开连接事件进行计数,如下所示:
// background.js
var openCount = 0;
chrome.runtime.onConnect.addListener(function (port) {
if (port.name == "devtools-page") {
if (openCount == 0) {
alert("DevTools window opening.");
}
openCount++;
port.onDisconnect.addListener(function(port) {
openCount--;
if (openCount == 0) {
alert("Last DevTools window closing.");
}
});
}
});
开发者工具页面会创建如下连接:
// devtools.js
// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
name: "devtools-page"
});
开发者工具扩展程序示例
浏览这些开发者工具扩展程序示例的源代码:
- Polymer Devtools 扩展程序 - 使用在主机页面中运行的许多帮助程序来查询 DOM/JS 将状态传回自定义面板。
- React DevTools 扩展程序 - 使用 Blink 的子模块来重复使用开发者工具界面组件。
- Ember Inspector - 具有适用于 Chrome 和 Firefox 的适配器的共享扩展程序核心。
- Coquette-inspect - 一个基于 React 的干净扩展程序,其中注入了调试代理 托管网页。
- DevTools 扩展程序库和扩展程序示例 安装、试用和学习。
更多信息
要了解扩展程序可以使用的标准 API,请参阅 chrome.*API 和网站 API。
向我们提供反馈!您的意见和建议有助于我们改进 API。
示例
您可以在示例中找到使用开发者工具 API 的示例。