Omówienie
Rozszerzenie DevTools dodaje funkcje do narzędzi deweloperskich w Chrome. Może dodawać nowe panele i paski boczne interfejsu użytkownika, wchodzić w interakcje ze sprawdzaną stroną, uzyskiwać informacje o żądaniach sieci i wykonywać inne czynności. wyświetlać polecane rozszerzenia Narzędzi deweloperskich. Rozszerzenia DevTools mają dostęp do dodatkowego zestawu interfejsów API rozszerzeń DevTools:
Rozszerzenie DevTools jest skonstruowane tak samo jak inne rozszerzenia: może zawierać stronę tła, 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ędzia deweloperskie
Za każdym razem, gdy otwiera się okno Narzędzi deweloperskich, tworzona jest instancja strony rozszerzenia w Narzędziach deweloperskich. Strona DevTools istnieje przez cały czas trwania okna narzędzi dla deweloperów. Strona DevTools ma dostęp do interfejsów API DevTools oraz ograniczonego zestawu interfejsów API rozszerzeń. Na stronie Narzędzi deweloperskich możesz:
- Tworzenie paneli i interakcje z nimi przy użyciu interfejsów API
devtools.panels
. - Pobieraj informacje o oknie inspekcji i sprawdzaj kod w tym oknie za pomocą interfejsów
devtools.inspectedWindow
API. - Pobieraj informacje o żądaniach sieci za pomocą interfejsów API
devtools.network
.
Na stronie Narzędzia deweloperskie nie można 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órych ma dostęp skrypt treści. Podobnie jak skrypt treści, strona DevTools może komunikować się ze stroną w tle za pomocą przesyłania wiadomości. Przykład znajdziesz w sekcji Wstrzykiwanie skryptu treści.
Tworzenie rozszerzenia do Narzędzi deweloperskich
Aby utworzyć stronę rozszerzenia w narzędziach dla programistów, dodaj w pliku manifestu rozszerzenia pole devtools_page
:
{
"name": ...
"version": "1.0",
"minimum_chrome_version": "10.0",
"devtools_page": "devtools.html",
...
}
Dla każdego otwartego okna DevTools tworzona jest instancja devtools_page
określonego w pliku manifestu rozszerzenia. Strona może dodawać inne strony rozszerzenia jako panele i paski boczne do okna DevTools za pomocą interfejsu API devtools.panels
.
Moduły interfejsu API chrome.devtools.*
są dostępne tylko dla stron wczytanych w oknie DevTools. Skrypty treści i inne strony rozszerzeń nie mają tych interfejsów API. W związku z tym interfejsy API są dostępne tylko przez czas trwania okna Narzędzi deweloperskich.
Niektóre interfejsy DevTools są nadal w fazie eksperymentalnej. Zapoznaj się z chrome.experimental.* interfejsów API, aby poznać listę interfejsów API w wersji eksperymentalnej i wskazówki dotyczące ich używania;
Elementy interfejsu DevTools: panele i panele boczne
Oprócz typowych elementów interfejsu rozszerzenia, takich jak działania przeglądarki, menu kontekstowe i wyskakujące okienka, rozszerzenie DevTools może dodawać elementy interfejsu do okna DevTools:
- Panel to karta najwyższego poziomu, np. Elementy, Źródła i Sieć.
- Panel boczny zawiera dodatkowe elementy interfejsu związane z danym panelem. Paski boczne Style, Style wynikowe i Wydarzenia są widoczne w panelu Elementy. (Uwaga: wygląd paneli na pasku bocznym może się różnić od tego na obrazku, w zależności od wersji Chrome, której używasz, oraz od tego, gdzie jest dokowane okno 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 panelu bocznym ma dostęp do tych samych interfejsów API co strona DevTools.
Tworzenie podstawowego panelu bocznego dla 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 można wyświetlać na pasku bocznym na kilka sposobów:
- Treść HTML. Aby określić stronę HTML, która ma być wyświetlana w panelu, wywołaj funkcję
setPage
. - Dane w formacie JSON. Przekaż obiekt JSON do
setObject
. - wyrażenie JavaScript; Przekaż wyrażenie do funkcji
setExpression
. Narzędzie DevTools ocenia wyrażenie w kontekście skanowanej strony i wyświetla zwróconą wartość.
W przypadku wartości setObject
i setExpression
w panelu wyświetlana jest wartość, która pojawi się w konsoli DevTools. Jednak setExpression
umożliwia wyświetlanie elementów DOM i dowolnych obiektów JavaScript, a setObject
obsługuje tylko obiekty JSON.
Komunikacja między komponentami rozszerzenia
W następnych sekcjach opisujemy typowe scenariusze komunikacji między różnymi komponentami rozszerzenia DevTools.
Wstrzykiwanie skryptu treści
Strona Narzędzi deweloperskich nie może bezpośrednio wywołać funkcji tabs.executeScript
. Aby wstrzyknąć skrypt treści na stronie Narzędzia programistyczne, musisz pobrać identyfikator karty przeglądanego okna za pomocą właściwości inspectedWindow.tabId
i wysłać wiadomość do strony w tle. Na stronie w tle wywołaj funkcję 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 z tłem:
// 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);
});
});
Ocenianie kodu JavaScript w oknie inspekcji
Aby wykonać kod JavaScript w kontekście skanowanej strony, możesz użyć metody inspectedWindow.eval
. Metodę eval
możesz wywołać na stronie Narzędzi deweloperskich, w panelu lub w panelu bocznym.
Domyślnie wyrażenie jest oceniane w kontekście głównej ramki strony. Być może znasz już funkcje interfejsu wiersza poleceń API w Narzędziach deweloperskich, takie jak inspekcja elementu (inspect(elem)
), przerywanie funkcji (debug(fn)
), kopiowanie do schowka (copy()
) i inne.
inspectedWindow.eval()
używa tego samego kontekstu wykonywania skryptu i tych samych opcji co kod wpisany w konsoli Narzędzia deweloperskie, co umożliwia dostęp do tych interfejsów API w ramach 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ą funkcji useContentScriptContext: true
nie create 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 kontekstowy już istnieje, możesz użyć tej opcji, aby wstrzyknąć dodatkowe skrypty treści.
Metoda eval
jest skuteczna, gdy jest używana w odpowiednim kontekście, ale niebezpieczna, gdy jest używana nieodpowiednio. Użyj metody tabs.executeScript
, jeśli nie potrzebujesz dostępu do kontekstu JavaScriptu na stronie, którą sprawdzasz. Szczegółowe ostrzeżenia i porównanie tych 2 sposobów znajdziesz w artykule inspectedWindow
.
Przekazywanie wybranego elementu do skryptu treści
Skrypt treści nie ma bezpośredniego dostępu do aktualnie wybranego elementu. Jednak każdy kod, który wykonasz za pomocą inspectedWindow.eval
, ma dostęp do konsoli DevTools i interfejsów API wiersza poleceń.
Na przykład w skontrolowanym kodzie możesz użyć elementu $0
, aby uzyskać dostęp do wybranego elementu.
Aby przekazać wybrany element do skryptu treści:
- W skrypcie treści utwórz metodę, która przyjmuje jako argument wybrany element.
- Wywołaj metodę na stronie Narzędzia deweloperskie za pomocą
inspectedWindow.eval
z 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ę na stronie Narzędzi deweloperskich w ten sposób:
chrome.devtools.inspectedWindow.eval("setSelectedElement($0)",
{ useContentScriptContext: true });
Opcja useContentScriptContext: true
określa, że wyrażenie musi być oceniane w tym samym kontekście co skrypty treści, aby móc uzyskać dostęp do metody setSelectedElement
.
Pobieranie window
panelu odniesienia
Aby postMessage
z panelu DevTools, musisz mieć odwołanie do obiektu window
.
Pobierz okno iframe panelu z modułu obsługi zdarzenia panel.onShown
:
onShown.addListener(function callback)
extensionPanel.onShown.addListener(function (extPanelWindow) {
extPanelWindow instanceof Window; // true
extPanelWindow.postMessage( // …
});
Przesyłanie wiadomości ze skryptów treści do strony Narzędzia deweloperskie
Komunikacja między stroną Narzędzia deweloperskie a skryptami treści odbywa się pośrednio, za pomocą strony w tle.
Podczas wysyłania wiadomości do skryptu treści strona w tle może użyć metody tabs.sendMessage
, która kieruje wiadomość do skryptów treści na określonej karcie, jak pokazano w sekcji Wstawianie skryptu treści.
Podczas wysyłania wiadomości z skryptu treści nie ma gotowej metody przesyłania wiadomości do odpowiedniej instancji strony Narzędzi deweloperskich powiązanej z bieżącą kartą. Aby obejść ten problem, możesz ustawić, aby strona Narzędzia programistyczne nawiązała długotrwałe połączenie ze stroną w tle i aby strona w tle przechowywała mapę identyfikatorów kart do połączeń, aby mogła 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 lub 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
});
Przesyłanie wiadomości z wstrzykniętych skryptów do strony Narzędzia deweloperskie
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 zastosowania innej strategii. W tym kontekście runtime.sendMessage
nie przekaże wiadomości do skryptu w tle zgodnie z oczekiwaniami.
Aby obejść ten problem, możesz połączyć wstrzyknięty skrypt z 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 API window.postMessage
. Oto przykład, w którym wykorzystano skrypt tła 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);
});
Teraz wiadomość przejdzie z wstrzykniętego skryptu do skryptu treści, a potem do skryptu tła i wreszcie do strony DevTools.
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 listenera onConnect i wywoływać metodę connect na stronie Narzędzi deweloperskich. Każda karta może mieć własne okno Narzędzi deweloperskich, więc możesz otrzymywać wiele zdarzeń połączenia. Aby śledzić, czy jakiekolwiek okno DevTools jest otwarte, musisz policzyć 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.");
}
});
}
});
Na stronie Narzędzia deweloperskie tworzy się takie połączenie:
// devtools.js
// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
name: "devtools-page"
});
Przykłady rozszerzeń DevTools
Przejrzyj kod źródłowy tych przykładów rozszerzeń DevTools:
- Rozszerzenie Polymer Devtools – korzysta z wielu pomocników działających na stronie hosta, aby zapytać o stan DOM/JS i przesłać go do panelu niestandardowego.
- Rozszerzenie Narzędzia deweloperskie React – korzysta z podmodułu Blink do ponownego używania komponentów interfejsu Narzędzi deweloperskich.
- Ember Inspector – wspólny rdzeń rozszerzenia z adapterami do Chrome i Firefoxa.
- Coquette-inspect – czyste rozszerzenie oparte na React z dodatkiem agenta debugowania wstrzykniętego na stronie hosta.
- W galerii rozszerzeń DevTools i przykładowych rozszerzeniach znajdziesz więcej przydatnych aplikacji do zainstalowania, wypróbowania i nauki.
Więcej informacji
Informacje o standardowych interfejsach API, których mogą używać rozszerzenia, znajdziesz w artykule chrome.* interfejsy API i interfejsy API.
Prześlij nam opinię Twoje komentarze i sugestie pomagają nam ulepszać interfejsy API.
Przykłady
Przykłady kodu korzystającego z interfejsów API Narzędzi deweloperskich znajdziesz w sekcji Przykłady.