開發人員工具擴充功能會透過擴充功能新增的開發人員工具頁面,存取開發人員工具專用的擴充功能 API,藉此在 Chrome 開發人員工具中新增功能。
開發人員工具專用的擴充功能 API 包括:
開發人員工具頁面
開發人員工具視窗開啟時,開發人員工具擴充功能會建立開發人員工具頁面的執行個體,只要視窗開啟,該執行個體就會存在。這個頁面可存取開發人員工具 API 和擴充功能 API,並執行下列操作:
- 使用
devtools.panelsAPI 建立面板並與之互動,包括將其他擴充功能頁面新增為面板或側欄至開發人員工具視窗。 - 使用
devtools.inspectedWindowAPI 取得檢查視窗的相關資訊,並評估檢查視窗中的程式碼。 - 使用
devtools.networkAPI 取得網路要求相關資訊。 - 使用
devtools.recorderAPI 擴充錄音工具面板。 - 使用
devtools.performanceAPI 取得效能面板的記錄狀態相關資訊。
開發人員工具頁面可直接存取擴充功能 API。包括使用訊息傳遞與 Service Worker 通訊。
建立開發人員工具擴充功能
如要為擴充功能建立開發人員工具頁面,請在擴充功能資訊清單中新增 devtools_page 欄位:
{
"name": ...
"version": "1.0",
"devtools_page": "devtools.html",
...
}
devtools_page 欄位必須指向 HTML 網頁。由於開發人員工具頁面必須位於擴充功能本機,建議您使用相對網址指定該頁面。
chrome.devtools API 的成員僅適用於開發人員工具視窗開啟時,載入該視窗的網頁。內容指令碼和其他擴充功能頁面無法存取這些 API。
瀏覽器命名空間和開發人員工具擴充功能
Chrome 148 中導入的 browser 命名空間,會針對宣告 devtools_page 的擴充功能關閉。這項停用設定會套用至整個擴充功能,不只是開發人員工具頁面,而是擴充功能 API 執行的每個指令碼環境。在這些擴充功能中,請繼續使用 chrome.*。
這是因為與 webextension-polyfill 有相容性落差。chrome.devtools.* API 僅支援回呼,目前還不會原生傳回 promise,因此開發人員工具擴充功能通常會依賴 polyfill 包裝這些 API。只要定義 browser,這個 Polyfill 就會略過包裝作業,假設主機已完成這項工作。如果 Chrome 為這些擴充功能啟用 browser,polyfill 會無效,且 chrome.devtools.* 呼叫會停止傳回 Promise。如果關閉「browser」,polyfill 會繼續包裝。
如果選擇停用,這些擴充功能也會一併停用 Chrome 148 的其他訊息 API 變更,包括 runtime.onMessage 中的 Promise 回應。開發人員工具 API 原生支援 Promise 後,這項限制就會解除。
開發人員工具 UI 元素:面板和側邊窗格
除了瀏覽器動作、內容選單和彈出式視窗等常見的擴充功能 UI 元素,開發人員工具擴充功能還可以在開發人員工具視窗中新增 UI 元素:
- 「面板」是頂層分頁,例如「元素」、「來源」和「網路」面板。
- 側邊窗格會顯示與面板相關的補充 UI。「元素」面板上的「樣式」、「計算樣式」和「事件監聽器」窗格都是側欄窗格的例子。視您使用的 Chrome 版本和開發人員工具視窗的停駐位置而定,側邊欄窗格可能如下圖所示:
每個面板都是獨立的 HTML 檔案,可包含其他資源 (JavaScript、CSS、圖片等)。如要建立基本面板,請使用下列程式碼:
chrome.devtools.panels.create("My Panel",
"MyPanelIcon.png",
"Panel.html",
function(panel) {
// code invoked on panel creation
}
);
在面板或側欄窗格中執行的 JavaScript,可存取與開發人員工具頁面相同的 API。
如要建立基本側邊欄窗格,請使用下列程式碼:
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 物件。
在擴充功能元件之間通訊
以下各節說明幾種實用的方式,可讓開發人員工具擴充功能元件彼此通訊。
插入內容指令碼
如要插入內容指令碼,請使用 scripting.executeScript():
// DevTools page -- devtools.js
chrome.scripting.executeScript({
target: {
tabId: chrome.devtools.inspectedWindow.tabId
},
files: ["content_script.js"]
});
您可以使用 inspectedWindow.tabId 屬性,擷取檢查視窗的分頁 ID。
如果內容指令碼已注入,您可以使用訊息傳遞 API 與其通訊。
在檢查視窗中評估 JavaScript
您可以使用 inspectedWindow.eval() 方法,在檢查的網頁環境中執行 JavaScript 程式碼。您可以從開發人員工具頁面、面板或側邊面板叫用 eval() 方法。
根據預設,系統會在網頁的主要框架環境中評估運算式。
inspectedWindow.eval() 使用的指令碼執行環境和選項,與在開發人員工具控制台中輸入的程式碼相同,因此使用 eval() 時,可以存取開發人員工具控制台公用程式 API 功能。舉例來說,您可以使用這項功能檢查 HTML 文件 <head> 區段中的第一個指令碼元素:
chrome.devtools.inspectedWindow.eval(
"inspect($$('head script')[0])",
function(result, isException) { }
);
您也可以在呼叫 inspectedWindow.eval() 時將 useContentScriptContext 設為 true,在與內容指令碼相同的環境中評估運算式。如要使用這個選項,請在呼叫 eval() 前使用靜態內容指令碼宣告,方法是呼叫 executeScript(),或在 manifest.json 檔案中指定內容指令碼。載入內容指令碼環境後,您也可以使用這個選項插入其他內容指令碼。
將所選元素傳遞至內容指令碼
內容指令碼無法直接存取目前所選元素。不過,您使用 inspectedWindow.eval() 執行的任何程式碼,都能存取開發人員工具控制台和控制台公用程式 API。舉例來說,在評估的程式碼中,您可以使用 $0 存取所選元素。
如要將所選元素傳遞至內容指令碼,請按照下列步驟操作:
在內容指令碼中建立方法,將所選元素做為引數。
function setSelectedElement(el) { // do something with the selected element }使用
inspectedWindow.eval()和useContentScriptContext: true選項,從開發人員工具頁面呼叫方法。chrome.devtools.inspectedWindow.eval("setSelectedElement($0)", { useContentScriptContext: true });
useContentScriptContext: true 選項會指定運算式必須在與內容指令碼相同的環境中評估,因此可以存取 setSelectedElement 方法。
取得參照面板的 window
如要從開發人員工具面板呼叫 postMessage(),您需要參照其 window 物件。從 panel.onShown 事件處理常式取得面板的 iframe 視窗:
extensionPanel.onShown.addListener(function (extPanelWindow) {
extPanelWindow instanceof Window; // true
extPanelWindow.postMessage( // …
});
將訊息從插入的指令碼傳送至開發人員工具頁面
如果程式碼是直接插入網頁,且沒有內容指令碼 (包括附加 <script> 標記或呼叫 inspectedWindow.eval()),就無法使用 runtime.sendMessage() 將訊息傳送至開發人員工具頁面。建議您改為將注入的指令碼與可做為中介的內容指令碼合併,並使用 window.postMessage() 方法。下列範例使用前一節的背景指令碼:
// 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. Note that this is not foolproof
// and the page can easily spoof messages if it wants to.
if (typeof message !== 'object' || message === null ||
message.source !== 'my-devtools-extension') {
return;
}
chrome.runtime.sendMessage(message);
});
如要瞭解其他替代的訊息傳遞技術,請參閱 GitHub。
偵測開發人員工具的開啟和關閉時間
如要追蹤開發人員工具視窗是否開啟,請將 onConnect 監聽器新增至 Service Worker,並從開發人員工具頁面呼叫 connect()。因為每個分頁都可以開啟自己的開發人員工具視窗,您可能會收到多個連線事件。如要追蹤是否有任何開發人員工具視窗開啟,請計算連線和中斷連線事件,如下列範例所示:
// 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 service worker
const serviceWorkerConnection = chrome.runtime.connect({
name: "devtools-page"
});
// Send a periodic heartbeat to keep the port open.
setInterval(() => {
port.postMessage("heartbeat");
}, 15000);
開發人員工具擴充功能範例
本頁面的範例來自下列頁面:
- Polymer Devtools 擴充功能 - 使用主機網頁中執行的許多輔助程式,查詢 DOM/JS 狀態,然後傳送回自訂面板。
- React 開發人員工具擴充功能:使用轉譯器的子模組,重複使用開發人員工具 UI 元件。
- Ember Inspector - Shared extension core with adapters for both Chrome and Firefox.
- Coquette-inspect - 以 React 為基礎的乾淨擴充功能,可將偵錯代理程式注入主機頁面。
- 範例擴充功能提供更多值得安裝、試用及學習的擴充功能。
更多資訊
如要瞭解擴充功能可使用的標準 API,請參閱 chrome.* API 和 Web API。
請提供寶貴意見!您的意見和建議有助於我們改善 API。
範例
您可以在「範例」中找到使用開發人員工具 API 的範例。