擴充開發人員工具

總覽

開發人員工具擴充功能可為 Chrome 開發人員工具新增功能。這項工具可新增新的 UI 面板和側邊面板、與檢查的網頁互動、取得網路要求相關資訊等等。查看精選的開發人員工具擴充功能。開發人員工具擴充功能可存取一組額外的開發人員工具專屬擴充功能 API:

DevTools 擴充功能的結構與其他擴充功能相同:可以包含背景頁面、內容指令碼和其他項目。此外,每個開發人員工具擴充功能都有一個開發人員工具頁面,可存取開發人員工具 API。

架構圖顯示開發人員工具頁面與檢查的視窗和背景頁面進行通訊。背景頁面會顯示與內容指令碼通訊並存取擴充功能 API 的畫面。開發人員工具頁面可以存取開發人員工具 API,例如建立面板。

開發人員工具頁面

每次開啟開發人員工具視窗時,系統都會建立擴充功能的「開發人員工具」頁面。 在「開發人員工具」視窗的生命週期內,都有「開發人員工具」頁面存在。開發人員工具頁面可存取開發人員工具 API 和一組有限的擴充功能 API。具體而言,開發人員工具頁面可執行下列操作:

開發人員工具頁面無法直接使用大部分的擴充功能 API。可存取內容指令碼可存取的 extensionruntime API 的相同子集。對內容表示喜歡 指令碼,開發人員工具頁面可以使用訊息傳遞功能與背景頁面通訊。對於 請參閱「插入內容指令碼」一文。

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

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

{
  "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 的使用指南。

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

除了一般擴充功能 UI 元素 (例如瀏覽器動作、內容相關選單和彈出式視窗) 之外,DevTools 擴充功能還可在 DevTools 視窗中新增 UI 元素:

  • 面板是頂層分頁,例如「元素」、「來源」和「網路」面板。
  • 側邊面板會顯示與面板相關的輔助 UI。元素面板中的「Styles」、「Computed Styles」和「Event Listener」窗格就是側欄窗格的範例。(請注意,側欄窗格的外觀可能與圖片不符,這取決於您使用的 Chrome 版本,以及 DevTools 視窗的停靠位置)。

開發人員工具視窗,顯示「元素」面板和「樣式」側邊面板。

每個面板都有專屬的 HTML 檔案,可包含其他資源 (JavaScript、CSS、圖片等) 開啟)。建立基本面板的畫面如下所示:

chrome.devtools.panels.create("My Panel",
    "MyPanelIcon.png",
    "Panel.html",
    function(panel) {
      // code invoked on panel creation
    }
);

在面板或側邊欄窗格中執行的 JavaScript 可存取與 DevTools 頁面相同的 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。開發人員工具會評估 運算式,並顯示傳回值。

如果是 setObjectsetExpression,窗格會顯示的值,與 開發人員工具控制台。不過,setExpression 可讓您顯示 DOM 元素和任意 JavaScript 物件,而 setObject 只支援 JSON 物件。

擴充功能元件之間的通訊

以下各節將說明在 DevTools 擴充功能的不同元件之間進行通訊的幾種常見情境。

插入內容指令碼

開發人員工具頁面無法直接呼叫 tabs.executeScript。如要從開發人員工具頁面插入內容指令碼,您必須使用 inspectedWindow.tabId 屬性擷取受檢視視窗分頁的 ID,並傳送訊息至背景頁面。在背景頁面中呼叫 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 選項,即可: 請在內容指令碼相同的情況下來評估運算式。使用 useContentScriptContext: true 呼叫 eval 不會建立內容指令碼結構定義,因此您必須先載入結構定義指令碼,再呼叫 eval,方法是呼叫 executeScript,或是在 manifest.json 檔案中指定內容指令碼。

一旦建立了內容指令碼,您就可以使用這個選項插入其他內容指令碼。

eval 方法在正確的情況下使用時非常強大,但如果使用不當,就可能造成危險。如果您不需要存取檢查網頁的 JavaScript 內容,請使用 tabs.executeScript 方法。如需詳細的注意事項和兩種方法的比較,請參閱 inspectedWindow

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

內容指令碼無法直接存取目前所選元素。但請注意, 使用 inspectedWindow.eval 執行時,可以使用開發人員工具控制台和指令列 API。 舉例來說,您可以在評估程式碼中使用 $0 存取所選元素。

如要將所選元素傳遞至內容指令碼,請按照下列步驟操作:

  • 在內容指令碼中建立方法,將所選元素做為引數。
  • 使用 inspectedWindow.eval 搭配 useContentScriptContext: true 選項,從開發人員工具頁面呼叫該方法。

內容指令碼中的程式碼可能如下所示:

function setSelectedElement(el) {
    // do something with the selected element
}

從開發人員工具頁面叫用方法,如下所示:

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 方法,將訊息導向特定分頁中的內容指令碼,如「插入內容指令碼」一節所述。

當您內容指令碼傳送訊息時,沒有現成的做法可將訊息傳送至與目前分頁相關聯的正確開發人員工具頁面執行個體。但請放心,在 開發人員工具頁面與背景頁面建立長期連線 背景頁面會將分頁 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;
});

開發人員工具頁面 (或面板或側邊欄窗格) 會建立以下連線:

// 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);
});

訊息現在會從插入的指令碼流向內容指令碼、背景指令碼,最後流向 DevTools 頁面。

您也可以考慮這裡的兩種其他訊息傳遞技巧

偵測開發人員工具的開啟和關閉時間

如果擴充功能需要追蹤開發人員工具視窗是否開啟,可以新增 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"
});

開發人員工具擴充功能範例

瀏覽以下開發人員工具擴充功能範例的來源:

更多資訊

如要進一步瞭解擴充功能可使用的標準 API,請前往 chrome*。*API網路 API

歡迎提供意見!您的意見和建議有助於我們改善 API。

範例

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