擴充套件開發者工具

注意:本頁面介紹了 Firefox 55 中的 devtools API。雖然這些 API 基於 Chrome devtools APIs,但 Firefox 並不實現所有這些功能;因此,並非所有功能都在此處記錄。要檢視哪些功能缺失,請參閱 devtools APIs 的侷限性

您可以使用 WebExtensions APIs 來擴充套件瀏覽器內建的開發者工具。要建立 devtools 擴充套件,請在您的 manifest.json 檔案中包含 "devtools_page" 鍵。

json
"devtools_page": "devtools/devtools-page.html"

此鍵的值是指向隨您的擴充套件一起打包的 HTML 檔案的 URL,這是一個特殊的擴充套件頁面,稱為 devtools 頁面。URL 必須相對於 manifest.json 檔案。

此 manifest 鍵會隱式設定 "devtools" 許可權,這會觸發 安裝時有關 devtools 的許可權警告。為避免此警告,請透過在 optional_permissions manifest 鍵中列出 "devtools" 許可權,將該功能標記為可選。設定可選許可權在更新中引入 devtools 功能時可能特別有用,因為它可防止擴充套件被停用(在 Chrome 中)或阻止更新(在 Firefox 中)。

Devtools 頁面

Devtools 頁面在瀏覽器開發者工具開啟時載入,在關閉時解除安裝。請注意,由於 devtools 視窗與單個標籤頁相關聯,因此很可能同時存在多個 devtools 視窗(因此也就有多個 devtools 頁面)。

Devtools 頁面沒有可見的 DOM,但可以使用 <script> 標籤包含 JavaScript 原始檔。原始檔必須隨擴充套件本身一起打包。這些原始檔可以訪問:

請注意,devtools 頁面無法訪問任何其他 WebExtension API,background 頁面也無法訪問 devtools API。相反,devtools 頁面和 background 頁面必須使用 runtime 訊息 API 進行通訊。這是一個示例:

html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <title>DevTools Extension</title>
  </head>
  <body>
    <script src="devtools.js"></script>
  </body>
</html>

devtools.js 檔案將包含建立您的 dev tools 擴充套件的實際程式碼。

建立面板

Devtools 視窗託管了許多單獨的工具——JavaScript 偵錯程式、網路監視器等。頂部的標籤行允許使用者在不同工具之間切換。託管每個工具使用者介面的視窗稱為“面板”。

使用 devtools.panels.create() API,您可以在 devtools 視窗中建立自己的面板。

js
browser.devtools.panels
  .create(
    "My Panel", // title
    "/icons/star.png", // icon
    "/devtools/panel/panel.html", // content
  )
  .then((newPanel) => {
    newPanel.onShown.addListener(initializePanel);
    newPanel.onHidden.addListener(unInitializePanel);
  });

這需要三個必需引數:面板的標題、圖示和內容。它返回一個 Promise,該 Promise 解析為代表新面板的 devtools.panels.ExtensionPanel 物件。

與目標視窗互動

開發者工具始終附加到特定的瀏覽器標籤頁。這被稱為開發者工具的“目標”或“檢查的視窗”。您可以使用 devtools.inspectedWindow API 與被檢查的視窗進行互動。

在目標視窗中執行程式碼

devtools.inspectedWindow.eval() 提供了一種在被檢查視窗中執行程式碼的方式。

這在某種程度上類似於使用 tabs.executeScript() 來注入內容指令碼,但有一個重要的區別:

  • 與內容指令碼不同,使用 devtools.inspectedWindow.eval() 載入的指令碼不會獲得 “乾淨的 DOM 檢視”:也就是說,它們可以看到頁面指令碼對頁面的更改。

注意:乾淨的 DOM 檢視是一項安全功能,旨在幫助防止惡意頁面透過重新定義原生 DOM 函式的行為來欺騙擴充套件。這意味著您在使用 eval() 時需要非常小心,如果可以的話,應該使用普通的內容指令碼。

使用 devtools.inspectedWindow.eval() 載入的指令碼也看不到內容指令碼定義的任何 JavaScript 變數。

使用內容指令碼

devtools 文件不能直接訪問 tabs.executeScript(),因此如果您需要注入內容指令碼,devtools 文件必須向 background 指令碼傳送一條訊息,要求它注入指令碼。devtools.inspectedWindow.tabId 提供了目標標籤頁的 ID:devtools 文件可以將此 ID 傳遞給 background 指令碼,然後 background 指令碼可以將其傳遞給 tabs.executeScript()

js
// devtools-panel.js

const scriptToAttach = "document.body.innerHTML = 'Hi from the devtools';";

window.addEventListener("click", () => {
  browser.runtime.sendMessage({
    tabId: browser.devtools.inspectedWindow.tabId,
    script: scriptToAttach,
  });
});
js
// background.js

function handleMessage(request, sender, sendResponse) {
  browser.tabs.executeScript(request.tabId, {
    code: request.script,
  });
}

browser.runtime.onMessage.addListener(handleMessage);

如果您需要在目標視窗中執行的內容指令碼與 devtools 文件之間交換訊息,建議使用 runtime.connect()runtime.onConnect 來建立 background 頁面和 devtools 文件之間的連線。然後,background 頁面可以維護標籤 ID 與 runtime.Port 物件之間的對映,並使用此對映來路由這兩個作用域之間的訊息。

The background page tab ID is connected to the content script on the content page by a runtime.sendMessage() object. The Port of the background page is connected to the port of the DevTools document by a port.postMessage() object.

Devtools APIs 的侷限性

這些 API 基於 Chrome devtools API,但與 Chrome 相比,仍有許多功能缺失。本節列出了截至 Firefox 54 仍未實現的有功能。請注意,devtools API 正在積極開發中,我們預計將在未來的版本中新增對其中大部分功能的支援。

devtools.inspectedWindow

以下功能不受支援:

  • inspectedWindow.getResources()
  • inspectedWindow.onResourceAdded
  • inspectedWindow.onResourceContentCommitted

inspectedWindow.eval() 的所有選項均不受支援。

使用 inspectedWindow.eval() 注入的指令碼不能使用所有 Console 的命令列輔助函式,但 $0inspect() 都受支援(從 Firefox 55 開始)。

devtools.panels

以下功能不受支援:

  • panels.elements
  • panels.sources
  • panels.setOpenResourceHandler()
  • panels.openResource()
  • panels.ExtensionPanel.createStatusBarButton()
  • panels.Button
  • panels.ElementsPanel
  • panels.SourcesPanel

示例

GitHub 上的 webextensions-examples 儲存庫包含幾個使用 devtools 面板的擴充套件示例。