Przegląd
Rozszerzenie narzędzi deweloperskich dodaje funkcje do narzędzi deweloperskich w Chrome. Może dodawać nowe panele interfejsu i paski boczne, wchodzić w interakcje z badaną stroną, uzyskiwać informacje o żądaniach sieciowych i nie tylko. Wyświetl polecane rozszerzenia Narzędzi deweloperskich. Rozszerzenia Narzędzi deweloperskich mają dostęp do dodatkowego zestawu interfejsów API rozszerzeń przeznaczonych specjalnie dla Narzędzi deweloperskich:
Rozszerzenie Narzędzi deweloperskich ma taką samą strukturę jak każde inne rozszerzenie: może mieć stronę w tle, skrypty treści i inne elementy. Każde rozszerzenie Narzędzi deweloperskich ma też stronę Narzędzi deweloperskich, która ma dostęp do interfejsów API Narzędzi deweloperskich.

Strona Narzędzi deweloperskich
Za każdym razem, gdy otwierane jest okno narzędzi deweloperskich, tworzona jest instancja strony narzędzi deweloperskich rozszerzenia. Strona Narzędzia deweloperskie istnieje przez cały czas działania okna Narzędzi deweloperskich. Strona Narzędzi deweloperskich ma dostęp do interfejsów API Narzędzi deweloperskich i ograniczonego zestawu interfejsów API rozszerzeń. Strona Narzędzi deweloperskich może w szczególności:
- Twórz panele i korzystaj z nich za pomocą interfejsów API
devtools.panels. - Uzyskuj informacje o sprawdzanym oknie i oceniaj kod w tym oknie za pomocą interfejsów API
devtools.inspectedWindow. - Uzyskuj informacje o żądaniach sieciowych za pomocą interfejsów API
devtools.network.
Strona Narzędzi deweloperskich nie może bezpośrednio korzystać z większości interfejsów API rozszerzeń. Ma dostęp do tego samego podzbioru interfejsów API extension i runtime, do którego ma dostęp skrypt treści. Podobnie jak skrypt treści strona Narzędzi deweloperskich może komunikować się ze stroną w tle za pomocą przekazywania wiadomości. Przykład znajdziesz w sekcji Wstrzykiwanie skryptu treści.
Tworzenie rozszerzenia Narzędzi deweloperskich
Aby utworzyć stronę Narzędzi deweloperskich dla rozszerzenia, dodaj pole devtools_page w pliku manifestu rozszerzenia:
{
"name": ...
"version": "1.0",
"minimum_chrome_version": "10.0",
"devtools_page": "devtools.html",
...
}
Dla każdego otwartego okna Narzędzi deweloperskich tworzona jest instancja devtools_page określona w pliku manifestu rozszerzenia. Strona może dodawać inne strony rozszerzeń jako panele i paski boczne do okna Narzędzi deweloperskich za pomocą interfejsu devtools.panels API.
Moduły interfejsu API chrome.devtools.* są dostępne tylko na stronach wczytanych w oknie Narzędzi deweloperskich. Skrypty treści i inne strony rozszerzenia nie mają dostępu do tych interfejsów API. Dlatego interfejsy API są dostępne tylko przez cały okres istnienia okna Narzędzi deweloperskich.
Istnieją też interfejsy API Narzędzi deweloperskich, które są nadal w fazie eksperymentalnej. Zapoznaj się z chrome.experimental.* API, aby zapoznać się z listą eksperymentalnych interfejsów API i wskazówkami dotyczącymi ich używania.
Elementy interfejsu Narzędzi deweloperskich: panele i panele boczne
Oprócz zwykłych elementów interfejsu rozszerzenia, takich jak działania przeglądarki, menu kontekstowe i wyskakujące okienka, rozszerzenie Narzędzi deweloperskich może dodawać elementy interfejsu do okna Narzędzi deweloperskich:
- Panel to karta najwyższego poziomu, np. Elementy, Źródła czy Sieć.
- Panel paska bocznego zawiera dodatkowy interfejs powiązany z panelem. Panele Style, Style wynikowe i Detektory zdarzeń na panelu Elementy to przykłady paneli bocznych. (Wygląd paneli bocznych może się różnić od tego na ilustracji w zależności od używanej wersji Chrome i miejsca zadokowania okna Narzędzi deweloperskich).

Każdy panel to osobny plik HTML, który może zawierać inne zasoby (JavaScript, CSS, obrazy itp.). Tworzenie podstawowego panelu wygląda tak:
chrome.devtools.panels.create("My Panel",
"MyPanelIcon.png",
"Panel.html",
function(panel) {
// code invoked on panel creation
}
);
Kod JavaScript wykonywany w panelu lub w okienku paska bocznego ma dostęp do tych samych interfejsów API co strona Narzędzi deweloperskich.
Tworzenie podstawowego panelu bocznego w panelu Elementy wygląda tak:
chrome.devtools.panels.elements.createSidebarPane("My Sidebar",
function(sidebar) {
// sidebar initialization code here
sidebar.setObject({ some_data: "Some data to show" });
});
Treści w panelu bocznym można wyświetlać na kilka sposobów:
- Treść HTML. Wywołaj funkcję
setPage, aby określić stronę HTML, która ma być wyświetlana w panelu. - dane JSON, Przekaż obiekt JSON do funkcji
setObject. - Wyrażenie JavaScript. Przekazywanie wyrażenia do funkcji
setExpression. Narzędzia deweloperskie obliczają wartość wyrażenia w kontekście sprawdzanej strony i wyświetlają wartość zwracaną.
W przypadku obu typów setObject i setExpression w panelu wyświetlana jest wartość, która pojawiłaby się w konsoli Narzędzi deweloperskich. setExpression umożliwia jednak wyświetlanie elementów DOM i dowolnych obiektów JavaScript, a setObject obsługuje tylko obiekty JSON.
Komunikacja między komponentami rozszerzenia
W sekcjach poniżej opisujemy typowe scenariusze komunikacji między różnymi komponentami rozszerzenia Narzędzi deweloperskich.
Wstrzykiwanie skryptu treści
Strona Narzędzi deweloperskich nie może bezpośrednio wywołać tabs.executeScript. Aby wstrzyknąć skrypt treści ze strony Narzędzi deweloperskich, musisz pobrać identyfikator karty sprawdzanego okna za pomocą właściwości inspectedWindow.tabId i wysłać wiadomość do strony w tle. Na stronie w tle wywołaj tabs.executeScript, aby wstrzyknąć skrypt.
Poniższe fragmenty kodu pokazują, jak wstrzyknąć skrypt treści za pomocą 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"
});
Kod strony w tle:
// 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);
});
});
Ocena JavaScriptu w sprawdzanym oknie
Możesz użyć metody inspectedWindow.eval, aby wykonać kod JavaScript w kontekście sprawdzanej strony. Metodę eval możesz wywołać ze strony, panelu lub panelu bocznego Narzędzi deweloperskich.
Domyślnie wyrażenie jest oceniane w kontekście ramki głównej strony. Być może znasz już funkcje interfejsu API wiersza poleceń Narzędzi deweloperskich, takie jak sprawdzanie elementów (inspect(elem)), zatrzymywanie wykonywania kodu w funkcjach (debug(fn)), kopiowanie do schowka (copy()) i inne.
inspectedWindow.eval() używa tego samego kontekstu i opcji wykonywania skryptu co kod wpisany w konsoli Narzędzi deweloperskich, co umożliwia dostęp do tych interfejsów API w funkcji eval. Na przykład SOAK używa go do sprawdzania elementu:
chrome.devtools.inspectedWindow.eval(
"inspect($$('head script[data-soak=main]')[0])",
function(result, isException) { }
);
Możesz też użyć opcji useContentScriptContext: true dla inspectedWindow.eval(), aby ocenić wyrażenie w tym samym kontekście co skrypty treści. Wywołanie funkcji eval za pomocą useContentScriptContext: true nie tworzy kontekstu skryptu treści, więc przed wywołaniem funkcji eval musisz wczytać skrypt kontekstu, wywołując funkcję executeScript lub określając skrypt treści w pliku manifest.json.
Gdy skrypt kontekstu istnieje, możesz użyć tej opcji, aby wstrzyknąć dodatkowe skrypty treści.
Metoda eval jest skuteczna, gdy jest używana we właściwym kontekście, a niebezpieczna, gdy jest używana nieprawidłowo. Użyj metody tabs.executeScript, jeśli nie potrzebujesz dostępu do kontekstu JavaScriptu sprawdzanej strony. Szczegółowe ostrzeżenia i porównanie tych 2 metod znajdziesz w artykule inspectedWindow.
Przekazywanie wybranego elementu do skryptu treści
Skrypt treści nie ma bezpośredniego dostępu do obecnie wybranego elementu. Jednak każdy kod, który wykonujesz za pomocą inspectedWindow.eval, ma dostęp do konsoli Narzędzi deweloperskich i interfejsów API wiersza poleceń.
Na przykład w ocenianym kodzie możesz użyć $0, aby uzyskać dostęp do wybranego elementu.
Aby przekazać wybrany element do skryptu treści:
- Utwórz w skrypcie treści metodę, która przyjmuje wybrany element jako argument.
- Wywołaj metodę ze strony Narzędzi deweloperskich za pomocą
inspectedWindow.evalz opcjąuseContentScriptContext: true.
Kod w skrypcie treści może wyglądać tak:
function setSelectedElement(el) {
// do something with the selected element
}
Wywołaj metodę ze strony Narzędzi deweloperskich w ten sposób:
chrome.devtools.inspectedWindow.eval("setSelectedElement($0)",
{ useContentScriptContext: true });
Opcja useContentScriptContext: true oznacza, że wyrażenie musi być oceniane w tym samym kontekście co skrypty treści, dzięki czemu może uzyskać dostęp do metody setSelectedElement.
Uzyskiwanie window z panelu odniesień
Aby postMessage z panelu narzędzi deweloperskich, musisz mieć odniesienie do jego obiektu window.
Pobierz okno elementu iframe panelu z modułu obsługi zdarzeń panel.onShown:
onShown.addListener(function callback)
extensionPanel.onShown.addListener(function (extPanelWindow) {
extPanelWindow instanceof Window; // true
extPanelWindow.postMessage( // …
});
Wysyłanie wiadomości ze skryptów treści na stronę Narzędzi deweloperskich
Komunikacja między stroną Narzędzi deweloperskich a skryptami treści jest pośrednia i odbywa się za pomocą strony w tle.
Podczas wysyłania wiadomości do skryptu treści strona w tle może używać metody tabs.sendMessage, która kieruje wiadomość do skryptów treści na określonej karcie, jak pokazano w sekcji Wstrzykiwanie skryptu treści.
Podczas wysyłania wiadomości ze skryptu treści nie ma gotowej metody dostarczania wiadomości do prawidłowej instancji strony Narzędzi deweloperskich powiązanej z bieżącą kartą. Możesz jednak sprawić, że strona Narzędzi deweloperskich nawiąże długotrwałe połączenie ze stroną w tle, a strona w tle będzie przechowywać mapę identyfikatorów kart i połączeń, aby móc kierować każdą wiadomość do odpowiedniego połączenia.
// 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;
});
Strona Narzędzi deweloperskich (lub panel albo panel boczny) nawiązuje połączenie w ten sposób:
// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
name: "panel"
});
backgroundPageConnection.postMessage({
name: 'init',
tabId: chrome.devtools.inspectedWindow.tabId
});
Wysyłanie wiadomości ze skryptów wstrzykiwanych na stronę Narzędzi deweloperskich
Powyższe rozwiązanie działa w przypadku skryptów treści, ale kod wstrzykiwany bezpośrednio na stronę (np. przez dodanie tagu <script> lub za pomocą inspectedWindow.eval) wymaga innej strategii. W tym przypadku funkcja runtime.sendMessage nie będzie przekazywać wiadomości do skryptu działającego w tle zgodnie z oczekiwaniami.
Możesz połączyć wstrzyknięty skrypt ze skryptem treści, który będzie działać jako pośrednik. Aby przekazywać wiadomości do skryptu treści, możesz użyć interfejsu window.postMessage. Oto przykład przy założeniu, że skrypt działający w tle pochodzi z poprzedniej sekcji:
// 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);
});
Wiadomość będzie teraz przepływać ze wstrzykniętego skryptu do skryptu treści, a następnie do skryptu działającego w tle i wreszcie do strony Narzędzi deweloperskich.
Możesz też rozważyć 2 alternatywne techniki przekazywania wiadomości.
Wykrywanie otwierania i zamykania Narzędzi deweloperskich
Jeśli rozszerzenie musi śledzić, czy okno Narzędzi deweloperskich jest otwarte, możesz dodać do strony w tle odbiornik onConnect i wywołać connect ze strony Narzędzi deweloperskich. Każda karta może mieć otwarte własne okno Narzędzi deweloperskich, więc możesz otrzymać wiele zdarzeń połączenia. Aby śledzić, czy jest otwarte jakiekolwiek okno Narzędzi deweloperskich, musisz zliczać zdarzenia połączenia i rozłączenia, jak pokazano poniżej:
// 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.");
}
});
}
});
Strona Narzędzi deweloperskich tworzy połączenie w ten sposób:
// devtools.js
// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
name: "devtools-page"
});
Przykłady rozszerzeń Narzędzi deweloperskich
Przejrzyj źródło tych przykładów rozszerzeń Narzędzi deweloperskich:
- Rozszerzenie Polymer Devtools – korzysta z wielu pomocników działających na stronie hosta, aby wysyłać zapytania do stanu DOM/JS i przesyłać je z powrotem do panelu niestandardowego.
- Rozszerzenie React DevTools – używa podmodułu Blink do ponownego wykorzystywania komponentów interfejsu Narzędzi deweloperskich.
- Ember Inspector – wspólny rdzeń rozszerzenia z adapterami dla Chrome i Firefox.
- Coquette-inspect – przejrzyste rozszerzenie oparte na React z agentem debugowania wstrzykiwanym na stronę hosta.
- W naszej galerii rozszerzeń Narzędzi deweloperskich i w przykładowych rozszerzeniach znajdziesz więcej przydatnych aplikacji, które możesz zainstalować, wypróbować i z których możesz się czegoś nauczyć.
Więcej informacji
Informacje o standardowych interfejsach API, z których mogą korzystać rozszerzenia, znajdziesz w artykule chrome.* interfejsy API i interfejsy API.
Prześlij nam opinię Twoje komentarze i sugestie pomogą nam ulepszyć interfejsy API.
Przykłady
Przykłady korzystania z interfejsów API Narzędzi deweloperskich znajdziesz w sekcji Przykłady.