DevTools の拡張

DevTools 拡張機能は、拡張機能に追加された DevTools ページから DevTools 固有の拡張機能 API にアクセスすることで、Chrome DevTools に機能を追加します。

検査対象のウィンドウおよび Service Worker と通信する DevTools ページを示すアーキテクチャ図。Service Worker がコンテンツ スクリプトと通信し、拡張機能 API にアクセスする様子が示されています。[DevTools] ページでは、パネルの作成など、DevTools API にアクセスできます。
DevTools 拡張機能のアーキテクチャ。

DevTools 固有の拡張機能 API は次のとおりです。

[DevTools] ページ

[DevTools] ウィンドウが開くと、DevTools 拡張機能によって DevTools ページのインスタンスが作成されます。このインスタンスはウィンドウが開いている間存在します。このページから DevTools API と拡張機能 API にアクセスし、次の操作を行うことができます。

  • devtools.panels API を使用してパネルを作成し、操作します(他の拡張機能ページをパネルまたはサイドバーとして DevTools ウィンドウに追加するなど)。
  • devtools.inspectedWindow API を使用して、検査対象ウィンドウに関する情報を取得し、検査対象ウィンドウでコードを評価します。
  • devtools.network API を使用して、ネットワーク リクエストに関する情報を取得します。
  • devtools.recorder API を使用して、[レコーダー] パネルを拡張します。

DevTools ページから拡張機能 API に直接アクセスできます。これには、メッセージの受け渡しを使用して Service Worker と通信できることが含まれます。

DevTools 拡張機能を作成する

拡張機能の DevTools ページを作成するには、拡張機能のマニフェストに devtools_page フィールドを追加します。

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

devtools_page フィールドは HTML ページを指している必要があります。DevTools ページは拡張機能のローカルページである必要があるため、相対 URL を使用して指定することをおすすめします。

chrome.devtools API のメンバーは、DevTools ウィンドウが開いている間、そのウィンドウ内で読み込まれたページでのみ使用できます。コンテンツ スクリプトなどの拡張機能のページからは、これらの API にアクセスできません。

DevTools UI 要素: パネルとサイドバー ペイン

DevTools 拡張機能では、ブラウザのアクション、コンテキスト メニュー、ポップアップなどの通常の拡張機能 UI 要素に加えて、UI 要素を DevTools ウィンドウに追加できます。

  • パネルは、[要素]、[ソース]、[ネットワーク] などの最上位のタブです。
  • サイドバー ペインには、パネルに関連する補足 UI が表示されます。[要素] パネルの [スタイル]、[計算済みスタイル]、[イベント リスナー] ペインは、サイドバー ペインの例です。使用している Chrome のバージョンと、DevTools ウィンドウがドッキングされている場所に応じて、サイドバー ペインは次の例のようになります。
[要素] パネルと [スタイル] サイドバー ペインが表示されている DevTools ウィンドウ。
[要素] パネルと [スタイル] サイドバー ペインが表示されている 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() に式を渡します。DevTools は、検査対象のページのコンテキストで式を評価し、戻り値を表示します。

setObject()setExpression() の両方で、DevTools コンソールに表示される値がペインに表示されます。ただし、setExpression() では DOM 要素と任意の JavaScript オブジェクトを表示できますが、setObject() では JSON オブジェクトのみがサポートされます。

拡張機能コンポーネント間の通信

以降のセクションでは、DevTools 拡張機能コンポーネントが相互に通信できるようにする便利な方法について説明します。

コンテンツ スクリプトを挿入する

コンテンツ スクリプトを挿入するには、scripting.executeScript() を使用します。

// DevTools page -- devtools.js
chrome.scripting.executeScript({
  target: {
    tabId: chrome.devtools.inspectedWindow.tabId
  },
  files: ["content_script.js"]
});

検査対象のウィンドウのタブ ID は、inspectedWindow.tabId プロパティを使用して取得できます。

コンテンツ スクリプトがすでに挿入されている場合は、メッセージング API を使用して通信できます。

検査対象のウィンドウで JavaScript を評価する

inspectedWindow.eval() メソッドを使用すると、検査対象のページで JavaScript コードを実行できます。eval() メソッドは、DevTools のページ、パネル、サイドバーペインから呼び出すことができます。

デフォルトでは、式はページのメインフレームのコンテキストで評価されます。inspectedWindow.eval() は、DevTools コンソールで入力されたコードと同じスクリプト実行コンテキストとオプションを使用します。これにより、eval() の使用時に DevTools Console Utilities API 機能にアクセスできます。たとえば、SOAK ではこの変数を使用して要素の検査を行います。

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

また、inspectedWindow.eval() を呼び出すときに useContentScriptContexttrue に設定して、コンテンツ スクリプトと同じコンテキストで式を評価することもできます。このオプションを使用するには、eval() を呼び出す前に静的コンテンツ スクリプトの宣言を使用します。そのためには、executeScript() を呼び出すか、manifest.json ファイルでコンテンツ スクリプトを指定します。コンテキスト スクリプトのコンテキストが読み込まれた後、このオプションを使用して追加のコンテンツ スクリプトを挿入することもできます。

選択した要素をコンテンツ スクリプトに渡す

コンテンツ スクリプトには、現在選択されている要素に直接アクセスする権限がありません。ただし、inspectedWindow.eval() を使用して実行するコードは、DevTools コンソールと Console Utilities API にアクセスできます。たとえば、評価されたコードでは、$0 を使用して選択した要素にアクセスできます。

選択した要素をコンテンツ スクリプトに渡すには:

  1. 選択した要素を引数として受け取るメソッドをコンテンツ スクリプト内に作成します。

    function setSelectedElement(el) {
        // do something with the selected element
    }
    
  2. useContentScriptContext: true オプション付きで inspectedWindow.eval() を使用して、DevTools ページからメソッドを呼び出します。

    chrome.devtools.inspectedWindow.eval("setSelectedElement($0)",
        { useContentScriptContext: true });
    

useContentScriptContext: true オプションは、コンテンツ スクリプトと同じコンテキストで式を評価する必要があることを指定します。これにより、setSelectedElement メソッドにアクセスできます。

参照パネルの window を取得する

DevTools パネルから postMessage() を呼び出すには、その window オブジェクトへの参照が必要です。パネルの iframe ウィンドウを panel.onShown イベント ハンドラから取得します。

extensionPanel.onShown.addListener(function (extPanelWindow) {
    extPanelWindow instanceof Window; // true
    extPanelWindow.postMessage( // …
});

挿入されたスクリプトから DevTools ページにメッセージを送信する

<script> タグの追加や inspectedWindow.eval() の呼び出しなどによってコンテンツ スクリプトなしでページに直接挿入されたコードは、runtime.sendMessage() を使用して DevTools ページにメッセージを送信できません。代わりに、挿入したスクリプトを、中継点として機能するコンテンツ スクリプトと組み合わせて、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 をご覧ください。

DevTools の開始と終了を検出する

[DevTools] ウィンドウが開いているかどうかを追跡するには、Service Worker に onConnect リスナーを追加し、DevTools ページから connect() を呼び出します。各タブで独自の DevTools ウィンドウを開くことができるため、複数の接続イベントを受け取ることがあります。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 ページでは、次のような接続が作成されます。

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

DevTools 拡張機能の例

このページの例は、次のページのものです。

  • Polymer Devtools 拡張機能 - ホストページで実行されている多くのヘルパーを使用して、カスタムパネルに戻す DOM/JS の状態をクエリします。
  • React DevTools 拡張機能 - レンダラのサブモジュールを使用して、DevTools UI コンポーネントを再利用します。
  • Ember Inspector - Chrome と Firefox 用のアダプタを備えた共有拡張機能コア。
  • Coquette-inspect - ホストページに挿入されたデバッグ エージェントを使用したクリーンな React ベースの拡張機能。
  • 拡張機能のサンプルには、インストールして試し、学習するのに役立つ、より価値のある拡張機能が掲載されています。

詳細

拡張機能で使用できる標準 API については、chrome.* をご覧ください。APIウェブ API

フィードバックをお寄せくださいお寄せいただいたご意見やご提案は、API の改善に活用させていただきます。

DevTools API の使用例については、サンプルをご覧ください。