DevTools の拡張

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

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

DevTools 固有の拡張機能 API には次のようなものがあります。

DevTools ページ

DevTools ウィンドウが開くと、DevTools 拡張機能によって DevTools ページのインスタンスが作成され、ウィンドウが開いている限り存在します。このページは、DevTools API と拡張機能 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 要素に加えて、DevTools ウィンドウに UI 要素を追加できます。

  • パネルは、[要素]、[ソース]、[ネットワーク] パネルなどの最上位タブです。
  • サイドバー ペインには、パネルに関連する補足 UI が表示されます。要素パネルの [スタイル]、[計算済みスタイル]、[イベント リスナー] ペインは、サイドバー ペインの例です。使用している Chrome のバージョンと、DevTools ウィンドウのドッキング場所に応じて、サイドバー ペインは次のサンプル画像のようになります。
[要素] パネルと [スタイル] サイドバー ペインが表示されている DevTools ウィンドウ。
[Elements] パネルと [Styles] サイドバー ペインが表示された 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 に設定して、コンテンツ スクリプトと同じコンテキストで式を評価することもできます。このオプションを使用するには、executeScript() を呼び出すか、manifest.json ファイルでコンテンツ スクリプトを指定して、eval() を呼び出す前に静的コンテンツ スクリプト宣言を使用します。コンテキスト スクリプトのコンテキストが読み込まれた後、このオプションを使用して追加のコンテンツ スクリプトを挿入することもできます。

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

コンテンツ スクリプトは、現在選択されている要素に直接アクセスできません。ただし、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 を取得する

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

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 を使用する例については、サンプルをご覧ください。