概要
DevTools 拡張機能は、Chrome DevTools に機能を追加します。新しい UI パネルやサイドバーの追加、検査対象ページの操作、ネットワーク リクエストに関する情報の取得などを行うことができます。DevTools の注目の拡張機能を確認する。DevTools 拡張機能では、DevTools 固有の拡張機能 API のセットにアクセスできます。
DevTools 拡張機能は他の拡張機能と同様に構成されており、バックグラウンド ページ、コンテンツ スクリプト、その他のアイテムを含めることができます。また、各 DevTools 拡張機能には、DevTools API にアクセスできる DevTools ページがあります。
[DevTools] ページ
DevTools ウィンドウが開くたびに、拡張機能の DevTools ページのインスタンスが作成されます。[DevTools] ページは、[DevTools] ウィンドウの存続期間中は存在します。[DevTools] ページから、DevTools API と一部の拡張機能 API にアクセスできます。[DevTools] ページでは次のことができます。
devtools.panels
API を使用してパネルを作成し、操作します。devtools.inspectedWindow
API を使用して、検査対象ウィンドウに関する情報を取得し、検査対象ウィンドウでコードを評価します。devtools.network
API を使用して、ネットワーク リクエストに関する情報を取得します。
DevTools ページでは、ほとんどの拡張機能 API を直接使用することはできません。コンテンツ スクリプトがアクセスできる extension
API と runtime
API のサブセットにアクセスできます。コンテンツ スクリプトと同様に、DevTools ページはメッセージ パッシングを使用してバックグラウンド ページと通信できます。例については、Content Script の挿入をご覧ください。
DevTools 拡張機能の作成
拡張機能の DevTools ページを作成するには、拡張機能のマニフェストに devtools_page
フィールドを追加します。
{
"name": ...
"version": "1.0",
"minimum_chrome_version": "10.0",
"devtools_page": "devtools.html",
...
}
拡張機能のマニフェストで指定された devtools_page
のインスタンスが、DevTools ウィンドウが開かれるたびに作成されます。このページでは、devtools.panels
API を使用して、他の拡張機能ページをパネルやサイドバーとして [DevTools] ウィンドウに追加できます。
chrome.devtools.*
API モジュールは、[DevTools] ウィンドウ内で読み込まれたページでのみ使用できます。コンテンツ スクリプトなどの拡張機能のページには、これらの API がありません。そのため、API は DevTools ウィンドウの存続期間中のみ利用できます。
また、試験運用版の DevTools API もあります。参照: chrome.experimental.* API をご覧ください。
DevTools UI 要素: パネルとサイドバー ペイン
DevTools 拡張機能では、ブラウザのアクション、コンテキスト メニュー、ポップアップなどの通常の拡張機能 UI 要素に加えて、UI 要素を DevTools ウィンドウに追加できます。
- パネルは、[要素]、[ソース]、[ネットワーク] の各パネルと同様に最上位のタブです。
- サイドバー ペインは、パネルに関連する補足の UI を表示します。[要素] パネルの [スタイル]、[計算済みスタイル]、[イベント リスナー] ペインは、サイドバー ペインの例です。(使用している 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
に式を渡します。DevTools は検査対象のページのコンテキストで式を評価し、戻り値を表示します。
setObject
と setExpression
の両方で、DevTools コンソールに表示されるとおりに値がペインに表示されます。ただし、setExpression
では DOM 要素と任意の JavaScript オブジェクトを表示できますが、setObject
では JSON オブジェクトのみがサポートされます。
拡張機能コンポーネント間の通信
以降のセクションでは、DevTools 拡張機能のさまざまなコンポーネント間の通信の一般的なシナリオについて説明します。
コンテンツ スクリプトの挿入
DevTools ページから tabs.executeScript
を直接呼び出すことはできません。DevTools ページからコンテンツ スクリプトを挿入するには、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
メソッドを使用すると、検査対象のページ内で JavaScript コードを実行できます。eval
メソッドは、DevTools のページ、パネル、またはサイドバー ペインから呼び出すことができます。
デフォルトでは、式はページのメインフレームのコンテキストで評価されます。要素検査(inspect(elem)
)、関数での互換性の問題(debug(fn)
)、クリップボードへのコピー(copy()
)など、DevTools のコマンドライン API の機能にはすでに習熟しているはずです。inspectedWindow.eval()
は、DevTools コンソールで入力されたコードと同じスクリプト実行コンテキストとオプションを使用します。これにより、eval 内でこれらの API にアクセスできます。たとえば、SOAK ではこの要素を使用して要素の検査を行います。
chrome.devtools.inspectedWindow.eval(
"inspect($$('head script[data-soak=main]')[0])",
function(result, isException) { }
);
または、inspectedWindow.eval()
の useContentScriptContext: true
オプションを使用して、コンテンツ スクリプトと同じコンテキストで式を評価します。useContentScriptContext: true
を指定して eval
を呼び出しても、コンテンツ スクリプトのコンテキストは作成されないため、executeScript
を呼び出すか、manifest.json
ファイルでコンテンツ スクリプトを指定して、eval
を呼び出す前にコンテキスト スクリプトを読み込む必要があります。
コンテキスト スクリプトのコンテキストが存在する場合、このオプションを使用して追加のコンテンツ スクリプトを挿入できます。
eval
メソッドは、適切なコンテキストで使用すると強力になり、不適切に使用すると危険になります。検査対象ページの JavaScript コンテキストにアクセスする必要がない場合は、tabs.executeScript
メソッドを使用します。2 つの方法の詳細な注意事項と比較については、inspectedWindow
をご覧ください。
選択した要素をコンテンツ スクリプトに渡す
コンテンツ スクリプトには、現在選択されている要素に直接アクセスできません。ただし、inspectedWindow.eval
を使用して実行するコードはすべて、DevTools コンソールとコマンドライン API にアクセスできます。たとえば、評価済みコードでは、$0
を使用して選択された要素にアクセスできます。
選択した要素をコンテンツ スクリプトに渡すには:
- 選択した要素を引数として受け取るメソッドをコンテンツ スクリプト内に作成します。
- DevTools ページから、
useContentScriptContext: true
オプション付きでinspectedWindow.eval
を使用して、メソッドを呼び出します。
コンテンツ スクリプトのコードは次のようになります。
function setSelectedElement(el) {
// do something with the selected element
}
次のように、DevTools ページからメソッドを呼び出します。
chrome.devtools.inspectedWindow.eval("setSelectedElement($0)",
{ useContentScriptContext: true });
useContentScriptContext: true
オプションは、コンテンツ スクリプトと同じコンテキストで式を評価する必要があることを指定し、setSelectedElement
メソッドにアクセスできるようにします。
参照パネルの window
を取得する
DevTools パネルから postMessage
するには、その window
オブジェクトへの参照が必要です。パネルの iframe ウィンドウを panel.onShown
イベント ハンドラから取得します。
onShown.addListener(function callback)
extensionPanel.onShown.addListener(function (extPanelWindow) {
extPanelWindow instanceof Window; // true
extPanelWindow.postMessage( // …
});
コンテンツ スクリプトから DevTools ページへのメッセージング
DevTools ページとコンテンツ スクリプト間のメッセージは、バックグラウンド ページを経由して間接的です。
コンテンツ スクリプトにメッセージを送信する場合、バックグラウンド ページでは tabs.sendMessage
メソッドを使用して、メッセージを特定のタブのコンテンツ スクリプトに送信します。詳しくは、コンテンツ スクリプトの挿入をご覧ください。
コンテンツ スクリプトからメッセージを送信する場合、現在のタブに関連付けられている適切な DevTools ページ インスタンスにメッセージを配信する既製の方法はありません。回避策として、DevTools ページでバックグラウンド ページとの長期的な接続を確立し、バックグラウンド ページでタブ 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;
});
DevTools ページ(またはパネルやサイドバー ペイン)では、次のような接続を確立します。
// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
name: "panel"
});
backgroundPageConnection.postMessage({
name: 'init',
tabId: chrome.devtools.inspectedWindow.tabId
});
挿入されたスクリプトから DevTools ページへのメッセージ
上記の解決策はコンテンツ スクリプトには有効ですが、コードを直接ページに挿入する(<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 ページにメッセージが流れます。
また、メッセージ受け渡しの 2 つの代替手法についてもご検討ください。
DevTools の起動と終了の検出
[DevTools] ウィンドウが開いているかどうかを拡張機能でトラッキングする必要がある場合は、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 background page
var backgroundPageConnection = chrome.runtime.connect({
name: "devtools-page"
});
DevTools 拡張機能の例
以下に示す DevTools 拡張機能のソースを参照します。
- Polymer Devtools 拡張機能 - ホストページで実行されている多くのヘルパーを使用して、カスタムパネルに戻す DOM/JS の状態をクエリします。
- React DevTools 拡張機能 - Blink のサブモジュールを使用して DevTools UI コンポーネントを再利用します。
- Ember Inspector - Chrome と Firefox 用のアダプターを備えた共有拡張機能コアです。
- Coquette-inspect - ホストページにデバッグ エージェントが挿入された、クリーンな React ベースの拡張機能。
- DevTools 拡張機能ギャラリーとサンプル拡張機能には、インストール、試用、学習する価値のあるアプリが含まれています。
詳細
拡張機能が使用できる標準 API については、chrome.* をご覧ください。API とウェブ API をご覧ください。
フィードバックをお寄せくださいお寄せいただいたご意見やご提案は、API の改善に役立てさせていただきます。
例
DevTools API の使用例については、サンプルをご覧ください。