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 procesem 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ń przeznaczone dla Narzędzi deweloperskich obejmują:

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:

Strona Narzędzi deweloperskich ma bezpośredni 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 pliku manifestu rozszerzenia:

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

Pole devtools_page musi wskazywać stronę HTML. Strona Narzędzi deweloperskich musi być lokalna dla rozszerzenia, dlatego zalecamy określanie jej za pomocą względnego adresu URL.

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

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

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

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

Przyczyną była niezgodność z biblioteką webextension-polyfill. Interfejsy API browser.devtools.* w wersjach Chrome starszych niż 152 obsługiwały tylko wywołania zwrotne – nie zwracały natywnie obiektów Promise – dlatego rozszerzenia Narzędzi deweloperskich często korzystały z polyfillu, aby je opakować. Polyfill pomija opakowywanie, gdy zdefiniowana jest wartość browser, zakładając, że host już wykonał to zadanie. Jeśli Chrome włączył browser w przypadku tych rozszerzeń, polyfill nie będzie działać, a wywołania browser.devtools.* przestaną zwracać obietnice. Wyłączenie browser powodowało, że polyfill nadal zawijał tekst.

Ta sama rezygnacja wyłączała w tych rozszerzeniach inne zmiany w interfejsie API do obsługi wiadomości w Chrome 148, w tym odpowiedzi Promise 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 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 boczny zawiera dodatkowy interfejs związany z panelem. Przykładami paneli bocznych są panele Style, Style wynikowe i Detektory zdarzeń na panelu Elementy. W zależności od wersji Chrome, której używasz, i miejsca, w którym zadokowane jest okno Narzędzi deweloperskich, panele boczne mogą wyglądać jak na tym przykładzie:
Okno Narzędzi deweloperskich z panelem Elementy i panelem bocznym Style.
Okno Narzędzi deweloperskich z panelem Elementy i panelem 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:

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

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

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

browser.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: przekaż wyrażenie do funkcji setExpression(). Narzędzia deweloperskie oceniają wyrażenie w kontekście sprawdzanej strony, a następnie wyświetlają wartość zwracaną.

W przypadku obu tych elementów setObject()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 znajdziesz opis przydatnych sposobów umożliwiających komponentom rozszerzenia Narzędzi deweloperskich komunikację ze sobą.

Wstrzykiwanie skryptu dotyczącego zawartości

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

// DevTools page -- devtools.js
browser.scripting.executeScript({
  target: {
    tabId: browser.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 treści został już wstrzyknięty, możesz użyć interfejsów API do przesyłania wiadomości, aby się z nim komunikować.

Sprawdzanie kodu JavaScript 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 okienka bocznego Narzędzi deweloperskich.

Domyślnie wyrażenie jest oceniane w kontekście głównej ramki strony. 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 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:

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

Możesz też ustawić wartość useContentScriptContext na true podczas wywoływania inspectedWindow.eval(), aby ocenić wyrażenie w tym samym kontekście co skrypty treści. Aby użyć tej opcji, przed wywołaniem funkcji eval() użyj deklaracji skryptu treści statycznych, wywołując funkcję executeScript() lub określając skrypt treści w pliku manifest.json. Po wczytaniu kontekstu skryptu treści możesz też użyć tej opcji, aby wstrzyknąć dodatkowe skrypty treści.

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 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 treści:

  1. Utwórz w skrypcie treś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.

    browser.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 referencyjnego

Aby wywołać funkcję postMessage() z panelu narzędzi deweloperskich, musisz mieć odniesienie do jej obiektu window. Pobierz okno elementu 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 skryptów wstrzykiwanych na stronę Narzędzi deweloperskich

Kod wstrzyknięty bezpośrednio na stronę bez skryptu treści, w tym przez dołączenie tagu <script> lub wywołanie funkcji inspectedWindow.eval(), nie może wysyłać wiadomości na stronę Narzędzi deweloperskich za pomocą funkcji runtime.sendMessage(). Zamiast tego zalecamy połączenie wstrzykniętego skryptu ze skryptem treści, który może pełnić rolę pośrednika, 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;
  }

  browser.runtime.sendMessage(message);
});

Inne alternatywne techniki przekazywania wiadomości znajdziesz na GitHubie.

Wykrywanie otwierania i zamykania Narzędzi deweloperskich

Aby śledzić, czy okno Narzędzi deweloperskich jest otwarte, dodaj do skryptu service worker odbiornik onConnect i wywołaj 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, zliczaj zdarzenia połączenia i rozłączenia, jak pokazano w tym przykładzie:

// background.js
var openCount = 0;
browser.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 = browser.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 – korzysta z wielu pomocników działających na stronie hosta, aby wysyłać zapytania do stanu DOM/JS i zwracać je 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 do Chrome i Firefoxa.
  • Coquette-inspect – czyste rozszerzenie oparte na React z wstrzykniętym agentem debugowania na stronie hosta.
  • Przykładowe rozszerzenia zawierają więcej przydatnych rozszerzeń, 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 browser.* interfejsy APIinterfejsy 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.