Narzędzia dla programistów Extend

Rozszerzenia Narzędzi deweloperskich dodają funkcje do Narzędzi deweloperskich w Chrome, uzyskując dostęp do interfejsów API rozszerzeń specyficznych dla Narzędzi deweloperskich za pomocą strony Narzędzi deweloperskich dodanej do rozszerzenia.

Schemat architektury pokazujący stronę Narzędzi deweloperskich komunikującą się z oknem podlegającym inspekcji i z instancją skryptu service worker. Skrypt service worker jest przedstawiony jako komunikujący się ze skryptami treści i uzyskujący dostęp do interfejsów API rozszerzeń.
         Strona Narzędzi deweloperskich ma dostęp do interfejsów API Narzędzi deweloperskich, np. do tworzenia paneli.
Architektura rozszerzenia Narzędzi deweloperskich.

Interfejsy API rozszerzeń specyficzne dla Narzędzi deweloperskich obejmują te elementy:

Strona Narzędzi deweloperskich

Gdy otworzy się okno Narzędzi deweloperskich, rozszerzenie Narzędzi deweloperskich utworzy instancję swojej strony Narzędzi deweloperskich, która będzie istniała tak długo, jak długo okno będzie otwarte. Ta strona ma dostęp do interfejsów API Narzędzi deweloperskich i interfejsów API rozszerzeń oraz może wykonywać te czynności:

  • Tworzenie paneli i interakcja z nimi za pomocą interfejsów API devtools.panels, w tym dodawanie innych stron rozszerzeń jako paneli lub pasków bocznych do okna Narzędzi deweloperskich.
  • Uzyskiwanie informacji o sprawdzanym oknie i ocenianie kodu w sprawdzanym oknie za pomocą interfejsów API devtools.inspectedWindow.
  • Uzyskiwanie informacji o żądaniach sieciowych za pomocą interfejsów API devtools.network.
  • Rozszerzanie panelu Dyktafon za pomocą interfejsów API devtools.recorder.
  • Uzyskiwanie informacji o stanie nagrywania w panelu Wydajność za pomocą interfejsów API devtools.performance.

Strona Narzędzi deweloperskich może bezpośrednio uzyskiwać dostęp do interfejsów API rozszerzeń. Obejmuje to możliwość komunikowania się ze skryptem service worker za pomocą przekazywania wiadomości.

Tworzenie rozszerzenia Narzędzi deweloperskich

Aby utworzyć stronę Narzędzi deweloperskich dla rozszerzenia, dodaj pole devtools_page w manifeście rozszerzenia:

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

Pole devtools_page musi wskazywać stronę HTML. Ponieważ strona Narzędzi deweloperskich musi znajdować się lokalnie w rozszerzeniu, zalecamy określenie jej za pomocą względnego adresu URL.

Elementy interfejsu API chrome.devtools są dostępne tylko na stronach wczytywanych w oknie Narzędzi deweloperskich, gdy to okno jest otwarte. Skrypty zawartości i inne strony rozszerzeń nie mają dostępu do tych interfejsów API.

Przestrzeń nazw przeglądarki i rozszerzenia Narzędzi deweloperskich

W Chrome w wersji 152 i nowszej rozszerzenia ze stroną Narzędzi deweloperskich mogą używać przestrzeni nazw browser.

W Chrome w wersji starszej niż 152 przestrzeń nazw browser była wyłączona w przypadku rozszerzeń, które deklarują devtools_page. Rezygnacja dotyczyła całego rozszerzenia – nie tylko strony Narzędzi deweloperskich, ale też każdego kontekstu skryptu, w którym działają interfejsy API rozszerzeń.

Powodem była luka w zgodności z webextension-polyfill. Interfejsy API chrome.devtools.* przed Chrome 152 były dostępne tylko za pomocą wywołań zwrotnych – nie zwracały natywnie obietnic – dlatego rozszerzenia Narzędzi deweloperskich często korzystały z polyfill, aby je opakować. Polyfill pomija opakowywanie, gdy zdefiniowana jest przestrzeń nazw browser, zakładając, że host wykonał już tę pracę. Gdyby Chrome włączył przestrzeń nazw browser w przypadku tych rozszerzeń, polyfill nie działałby, a wywołania chrome.devtools.* przestałyby zwracać obietnice. Wyłączenie przestrzeni nazw browser spowodowało, że polyfill nadal opakowywał.

Ta sama rezygnacja wyłączyła też inne zmiany w interfejsie API przesyłania wiadomości w Chrome 148 w przypadku tych rozszerzeń, w tym odpowiedzi obietnic w runtime.onMessage. Ograniczenie zostało zniesione, gdy interfejsy API Narzędzi deweloperskich zaczęły natywnie obsługiwać obietnice.

Elementy interfejsu Narzędzi deweloperskich: panele i paski 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, taka jak panele Elementy, Źródła i Sieć.
  • Pasek boczny zawiera dodatkowy interfejs związany z panelem. Przykładami pasków bocznych są paski Style, Style wynikowe i Słuchacze zdarzeń w panelu Elementy. W zależności od używanej wersji Chrome i miejsca zadokowania okna Narzędzi deweloperskich paski boczne mogą wyglądać jak na tym przykładowym obrazie:
Okno narzędzi dla deweloperów z panelem Elementy i paskiem bocznym Style.
Okno Narzędzi deweloperskich z panelem Elementy i paskiem bocznym Style.

Każdy panel to osobny plik HTML, który może zawierać inne zasoby (JavaScript, CSS, obrazy itp.). Aby utworzyć podstawowy panel, użyj tego kodu:

chrome.devtools.panels.create("My Panel",
    "MyPanelIcon.png",
    "Panel.html",
    function(panel) {
      // code invoked on panel creation
    }
);

JavaScript wykonywany w panelu lub pasku bocznym ma dostęp do tych samych interfejsów API co strona Narzędzi deweloperskich.

Aby utworzyć podstawowy pasek boczny, użyj tego kodu:

chrome.devtools.panels.elements.createSidebarPane("My Sidebar",
    function(sidebar) {
        // sidebar initialization code here
        sidebar.setObject({ some_data: "Some data to show" });
});

Istnieje kilka sposobów wyświetlania treści na pasku bocznym:

  • Treść HTML: wywołaj setPage(), aby określić stronę HTML, która ma być wyświetlana w panelu.
  • Dane JSON: przekaż obiekt JSON do setObject().
  • Wyrażenie JavaScript: przekaż wyrażenie do setExpression(). Narzędzia deweloperskie oceniają wyrażenie w kontekście sprawdzanej strony, a następnie wyświetlają wartość zwracaną.

W przypadku setObject() i setExpression() panel wyświetla wartość tak, jak pojawiłaby się w konsoli Narzędzi deweloperskich. 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 kolejnych sekcjach opisujemy przydatne sposoby umożliwiające komunikację między komponentami rozszerzenia Narzędzi deweloperskich.

Wstrzykiwanie skryptu zawartości

Aby wstrzyknąć skrypt zawartości, użyj scripting.executeScript():

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

Identyfikator karty sprawdzanego okna możesz pobrać za pomocą właściwości inspectedWindow.tabId.

Jeśli skrypt zawartości został już wstrzyknięty, możesz się z nim komunikować za pomocą interfejsów API przesyłania wiadomości.

Ocenianie JavaScriptu w sprawdzanym oknie

Za pomocą metody inspectedWindow.eval() możesz wykonywać kod JavaScript w kontekście sprawdzanej strony. Metodę eval() możesz wywołać ze strony Narzędzi deweloperskich, panelu lub paska bocznego.

Domyślnie wyrażenie jest oceniane w kontekście głównej ramki strony. inspectedWindow.eval() używa tego samego kontekstu wykonywania skryptu i tych samych opcji co kod wprowadzony w konsoli Narzędzi deweloperskich, co umożliwia dostęp do funkcji interfejsu API narzędzi konsoli Narzędzi deweloperskich podczas korzystania z eval(). Możesz na przykład użyć go do sprawdzenia pierwszego elementu skryptu w sekcji <head> dokumentu HTML:

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

Podczas wywoływania inspectedWindow.eval() możesz też ustawić wartość useContentScriptContext na true, aby ocenić wyrażenie w tym samym kontekście co skrypty zawartości. Aby użyć tej opcji, przed wywołaniem eval() użyj statycznej deklaracji skryptu zawartości, wywołując executeScript() lub określając skrypt zawartości w pliku manifest.json. Po wczytaniu kontekstu skryptu zawartości możesz też użyć tej opcji do wstrzyknięcia dodatkowych skryptów zawartości.

Przekazywanie wybranego elementu do skryptu zawartości

Skrypt zawartości nie ma bezpośredniego dostępu do aktualnie 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 narzędzi konsoli. Na przykład w ocenianym kodzie możesz użyć $0, aby uzyskać dostęp do wybranego elementu.

Aby przekazać wybrany element do skryptu zawartości:

  1. Utwórz w skrypcie zawartości metodę, która przyjmuje wybrany element jako argument.

    function setSelectedElement(el) {
        // do something with the selected element
    }
    
  2. Wywołaj metodę ze strony Narzędzi deweloperskich za pomocą inspectedWindow.eval() z opcją useContentScriptContext: true.

    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 zawartości, dzięki czemu może uzyskać dostęp do metody setSelectedElement.

Pobieranie window panelu odniesień

Aby wywołać postMessage() z panelu Narzędzi deweloperskich, musisz mieć odniesienie do jego obiektu window. Pobierz okno iframe panelu z modułu obsługi zdarzeń panel.onShown:

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

Wysyłanie wiadomości ze wstrzykniętych skryptów na stronę Narzędzi deweloperskich

Kod wstrzyknięty bezpośrednio do strony bez skryptu zawartości, w tym przez dołączenie <script> tagu lub wywołanie inspectedWindow.eval(), nie może wysyłać wiadomości na stronę Narzędzi deweloperskich za pomocą runtime.sendMessage(). Zamiast tego zalecamy połączenie wstrzykniętego skryptu ze skryptem zawartości, który może działać jako pośrednik, i użycie metody window.postMessage(). W tym przykładzie używamy skryptu działającego w tle 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. 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);
});

Inne alternatywne metody przesyłania wiadomości znajdziesz na GitHubie.

Wykrywanie otwierania i zamykania Narzędzi deweloperskich

Aby śledzić, czy okno Narzędzi deweloperskich jest otwarte, dodaj moduł obsługi onConnect listener do skryptu service worker i wywołaj connect() ze strony Narzędzi deweloperskich. Ponieważ każda karta może mieć otwarte własne okno Narzędzi deweloperskich, możesz otrzymać wiele zdarzeń connect. Aby śledzić, czy jakiekolwiek okno Narzędzi deweloperskich jest otwarte, zliczaj zdarzenia connect i disconnect, jak pokazano w tym przykładzie:

// 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 service worker
const serviceWorkerConnection = chrome.runtime.connect({
    name: "devtools-page"
});

// Send a periodic heartbeat to keep the port open.
setInterval(() => {
  port.postMessage("heartbeat");
}, 15000);

Przykłady rozszerzeń Narzędzi deweloperskich

Przykłady na tej stronie pochodzą z tych stron:

  • Rozszerzenie Polymer Devtools – używa wielu pomocników działających na stronie hosta do wysyłania zapytań o stan DOM/JS do panelu niestandardowego.
  • Rozszerzenie React DevTools – używa podmodułu renderera do ponownego wykorzystania komponentów interfejsu Narzędzi deweloperskich.
  • Ember Inspector – wspólny rdzeń rozszerzenia z adapterami dla Chrome i Firefoxa.
  • Coquette-inspect – czyste rozszerzenie oparte na React z agentem debugowania wstrzykniętym na stronę hosta.
  • Przykładowe rozszerzenia zawierają więcej przydatnych rozszerzeń, które można zainstalować, wypróbować i z których można się uczyć.

Więcej informacji

Informacje o standardowych interfejsach API, z których mogą korzystać rozszerzenia, znajdziesz w sekcji chrome.* Interfejsy API i interfejsy API sieci.

Prześlij opinię! Twoje komentarze i sugestie pomagają nam ulepszać interfejsy API.

Przykłady

Przykłady użycia interfejsów API Narzędzi deweloperskich znajdziesz w sekcji Przykłady.