擴充開發人員工具

開發人員工具擴充功能透過新增至擴充功能的開發人員工具頁面存取 DevTools 專屬擴充功能 API,藉此為 Chrome 開發人員工具新增功能。

架構圖,顯示開發人員工具頁面與檢查過的視窗和服務工作站通訊。Service Worker 畫面能與內容指令碼進行通訊,以及存取擴充功能 API。開發人員工具頁面可以存取開發人員工具 API,例如建立面板。
開發人員工具擴充功能架構。

開發人員工具專屬的擴充功能 API 如下:

開發人員工具頁面

當「開發人員工具」視窗開啟時,開發人員工具視窗會在視窗開啟時,建立相應的開發人員工具頁面執行個體。這個頁面可以存取開發人員工具 API 和擴充功能 API,並可執行下列操作:

開發人員工具頁面可直接存取擴充功能 API。這包括可以使用訊息傳遞功能與 Service Worker 通訊。

建立開發人員工具擴充功能

如要為擴充功能建立開發人員工具頁面,請在擴充功能資訊清單中新增 devtools_page 欄位:

{
  "name": ...
  "version": "1.0",
  "devtools_page": "devtools.html",
  ...
}

devtools_page 欄位必須指向 HTML 網頁。由於開發人員工具頁面必須是擴充功能的本機版本,因此建議您使用相對網址指定。

只有在開發人員工具視窗開啟時載入的頁面,才能使用 chrome.devtools API 成員。內容指令碼和其他擴充功能頁面無法存取這些 API。

開發人員工具 UI 元素:面板和側欄窗格

除了一般擴充功能 UI 元素 (例如瀏覽器動作、內容選單和彈出式視窗),開發人員工具擴充功能還可以在開發人員工具視窗中加入 UI 元素:

  • 面板是頂層分頁,例如「元素」、「來源」和「網路」面板。
  • 側欄窗格會顯示與面板相關的補充 UI。「Elements」面板中的「Styles」、「Computed Styles」和「Event Listeners」窗格都是側欄窗格的範例。視您使用的 Chrome 版本和開發人員工具視窗插入位置而定,側欄窗格可能如下圖所示:
「DevTools」視窗,顯示「Elements」面板和「Styles」側欄窗格。
顯示「元素」面板和「樣式」側欄窗格的「開發人員工具」視窗。

每個面板都有專屬的 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() 時存取開發人員工具的 Console Utilities API 功能。例如,SOAK 會使用此值來檢查元素:

chrome.devtools.inspectedWindow.eval(
  "inspect($$('head script[data-soak=main]')[0])",
  function(result, isException) { }
);

此外,您也可以在呼叫 inspectedWindow.eval() 時將 useContentScriptContext 設為 true,以在與內容指令碼相同的結構定義中評估運算式。如要使用這個選項,請在呼叫 eval() 之前使用靜態內容指令碼宣告,方法是呼叫 executeScript() 或在 manifest.json 檔案中指定內容指令碼。結構定義指令碼結構定義載入後,您也可以使用這個選項插入其他內容指令碼。

將所選元素傳遞至內容指令碼

內容指令碼無法直接存取目前所選元素。不過,您透過 inspectedWindow.eval() 執行的任何程式碼都可以存取開發人員工具控制台和 Console Utilities API。舉例來說,在已評估的程式碼中,您可以使用 $0 存取所選元素。

如何將所選元素傳遞至內容指令碼:

  1. 在內容指令碼中建立方法,將所選元素做為引數。

    function setSelectedElement(el) {
        // do something with the selected element
    }
    
  2. 使用 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 事件監聽器新增至服務工作站,並從開發人員工具頁面呼叫 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 DevTools Extension - 使用轉譯器的子模組來重複使用開發人員工具 UI 元件。
  • Ember Inspector:共用 Chrome 和 Firefox 專用的擴充功能核心與轉接程式。
  • Coquette-Inspect - 以 React 為基礎的擴充功能,具有插入主機頁面中的偵錯代理程式。
  • 範例擴充功能具有更值得安裝、試用及學習的擴充功能。

更多資訊

如要瞭解擴充功能可使用的標準 API,請參閱 chrome.* API網路 API

請提供寶貴意見!您的意見和建議有助於我們改善 API。

示例

您可以在範例中找到使用開發人員工具 API 的範例。