Breid DevTools uit

DevTools-extensies voegen functionaliteit toe aan Chrome DevTools door toegang te krijgen tot DevTools-specifieke extensie-API's via een DevTools-pagina die aan de extensie is toegevoegd.

Architectuurdiagram dat laat zien hoe de DevTools-pagina communiceert met het geïnspecteerde venster en de service worker. De service worker communiceert met de content scripts en heeft toegang tot de extensie-API's.  De DevTools-pagina heeft toegang tot de DevTools-API's, bijvoorbeeld voor het maken van panelen.
Architectuur van de DevTools-extensie.

De DevTools-specifieke extensie-API's omvatten de volgende:

De DevTools-pagina

Wanneer een DevTools-venster wordt geopend, maakt een DevTools-extensie een instantie van de bijbehorende DevTools-pagina aan. Deze instantie blijft bestaan ​​zolang het venster open is. De pagina heeft toegang tot de DevTools-API's en extensie-API's en kan het volgende doen:

Via de DevTools-pagina heb je direct toegang tot de API's van extensies. Dit houdt onder andere in dat je via berichtoverdracht met de service worker kunt communiceren.

Een DevTools-extensie maken

Om een ​​DevTools-pagina voor uw extensie te maken, voegt u het veld devtools_page toe aan het extensiemanifest:

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

Het veld devtools_page moet verwijzen naar een HTML-pagina. Omdat de DevTools-pagina lokaal moet zijn voor uw extensie, raden we aan een relatieve URL te gebruiken.

De leden van de browser.devtools API zijn alleen beschikbaar voor de pagina's die geladen zijn binnen het DevTools-venster zolang dat venster geopend is. Inhoudsscripts en andere extensiepagina's hebben geen toegang tot deze API's.

De browsernaamruimte en DevTools-extensies

In Chrome-versies 152 en later kunnen extensies met een DevTools-pagina de browser gebruiken.

In Chrome-versies ouder dan 152 werd de browser uitgeschakeld voor extensies die devtools_page declareren. Deze uitschakeling gold voor de gehele extensie, niet alleen voor de DevTools-pagina, maar voor elke scriptcontext waarin extensie-API's worden uitgevoerd.

The reason was a compatibility gap with webextension-polyfill . The browser.devtools.* APIs prior to Chrome 152 were callback-only—they didn't return Promises natively—so DevTools extensions commonly relied on the polyfill to wrap them. The polyfill skips wrapping whenever browser is defined, assuming the host has already done the work. If Chrome had enabled browser for these extensions, the polyfill would no-op and browser.devtools.* calls would have stopped returning Promises. Keeping browser off kept the polyfill keep wrapping.

Dezelfde opt-out schakelde ook de andere wijzigingen in de Chrome 148 messaging API voor deze extensies uit, waaronder Promise-reacties in runtime.onMessage . De beperking werd opgeheven zodra de DevTools API's Promises native ondersteunden.

UI-elementen van DevTools: panelen en zijbalken

Naast de gebruikelijke UI-elementen van extensies, zoals browseracties, contextmenu's en pop-ups, kan een DevTools-extensie ook UI-elementen aan het DevTools-venster toevoegen:

  • Een paneel is een tabblad op het hoogste niveau, zoals de panelen Elementen, Bronnen en Netwerk.
  • Een zijpaneel toont aanvullende gebruikersinterface-elementen die bij een paneel horen. De panelen Stijlen, Berekende stijlen en Gebeurtenislisteners in het paneel Elementen zijn voorbeelden van zijpanelen. Afhankelijk van de versie van Chrome die u gebruikt en waar het DevTools-venster is gedockt, kunnen uw zijpanelen eruitzien zoals in de volgende voorbeeldafbeelding:
Het DevTools-venster toont het Elementen-paneel en het Stijlen-zijpaneel.
Het DevTools-venster toont het Elementen-paneel en het Stijlen-zijpaneel.

Elk paneel is een eigen HTML-bestand, dat andere elementen kan bevatten (JavaScript, CSS, afbeeldingen, enzovoort). Gebruik de volgende code om een ​​basispaneel te maken:

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

JavaScript dat wordt uitgevoerd in een paneel of zijbalk heeft toegang tot dezelfde API's als de DevTools-pagina.

Om een ​​eenvoudig zijpaneel te maken, gebruikt u de volgende code:

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

Er zijn verschillende manieren om inhoud in een zijbalk weer te geven:

  • HTML-inhoud: Roep setPage() aan om een ​​HTML-pagina op te geven die in het paneel moet worden weergegeven.
  • JSON-gegevens: Geef een JSON-object door aan setObject() .
  • JavaScript-expressie: Geef een expressie door aan setExpression() . DevTools evalueert de expressie in de context van de geïnspecteerde pagina en geeft vervolgens de retourwaarde weer.

Bij zowel setObject() als setExpression() wordt de waarde in het venster weergegeven zoals deze in de DevTools-console zou verschijnen. Met setExpression() kunt u echter DOM-elementen en willekeurige JavaScript-objecten weergeven, terwijl setObject() alleen JSON-objecten ondersteunt.

Communicatie tussen uitbreidingscomponenten

In de volgende paragrafen worden enkele handige manieren beschreven om DevTools-extensiecomponenten met elkaar te laten communiceren.

Een inhoudsscript invoegen

Om een ​​script met inhoud te injecteren, gebruikt u scripting.executeScript() :

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

Je kunt de tab-ID van het geïnspecteerde venster ophalen met behulp van de eigenschap inspectedWindow.tabId .

Als er al een contentscript is geïnjecteerd, kunt u berichten-API's gebruiken om ermee te communiceren.

Evalueer JavaScript in het geïnspecteerde venster.

Je kunt de methode inspectedWindow.eval() gebruiken om JavaScript-code uit te voeren in de context van de geïnspecteerde pagina. Je kunt de eval() -methode aanroepen vanuit een pagina, paneel of zijbalk van de ontwikkelaarstools.

By default, the expression is evaluated in the context of the main frame of the page. inspectedWindow.eval() uses the same script execution context and options as code entered in the DevTools console, which allows access to DevTools Console Utilities API features when using eval() . For example, use it to inspect the first script element within the <head> section of the HTML document:

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

You can also set the useContentScriptContext to true when calling inspectedWindow.eval() to evaluate the expression in the same context as the content scripts. To use this option, use a static content script declaration before calling eval() , either by calling executeScript() or by specifying a content script in the manifest.json file. After the content script context loads, you can also use this option to inject additional content scripts.

Geef het geselecteerde element door aan een inhoudsscript.

Het script dat de inhoud weergeeft, heeft geen directe toegang tot het momenteel geselecteerde element. Code die je uitvoert met inspectedWindow.eval() heeft echter wel toegang tot de DevTools-console en de Console Utilities API's. In geëvalueerde code kun je bijvoorbeeld $0 gebruiken om toegang te krijgen tot het geselecteerde element.

Om het geselecteerde element door te geven aan een contentscript:

  1. Maak in het contentscript een methode aan die het geselecteerde element als argument accepteert.

    function setSelectedElement(el) {
        // do something with the selected element
    }
    
  2. Roep de methode aan vanuit de DevTools-pagina met behulp van inspectedWindow.eval() met de optie useContentScriptContext: true .

    browser.devtools.inspectedWindow.eval("setSelectedElement($0)",
        { useContentScriptContext: true });
    

De optie useContentScriptContext: true geeft aan dat de expressie in dezelfde context als de content scripts moet worden geëvalueerd, zodat de setSelectedElement -methode kan worden aangeroepen.

window van een referentiepaneel openen

Om postMessage() vanuit een ontwikkelaarstools-paneel aan te roepen, hebt u een verwijzing naar het window nodig. U kunt het iframe-venster van een paneel verkrijgen via de eventhandler panel.onShown :

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

Verzend berichten vanuit geïnjecteerde scripts naar de DevTools-pagina.

Code injected directly into the page without a content script, including by appending a <script> tag or calling inspectedWindow.eval() , can't send messages to the DevTools page using runtime.sendMessage() . Instead, we recommend combining your injected script with a content script that can act as an intermediary, and using the window.postMessage() method. The following example uses the background script from the previous section:

// 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);
});

Andere alternatieve berichtuitwisselingstechnieken zijn te vinden op GitHub .

Detecteer wanneer DevTools wordt geopend en gesloten.

Om bij te houden of het DevTools-venster geopend is, voegt u een onConnect- listener toe aan de service worker en roept u de methode connect() aan vanuit de DevTools-pagina. Omdat elk tabblad een eigen DevTools-venster kan hebben geopend, kunt u meerdere verbindingsgebeurtenissen ontvangen. Om bij te houden of er een DevTools-venster geopend is, telt u de verbindings- en ontkoppelingsgebeurtenissen zoals in het volgende voorbeeld:

// 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.");
          }
      });
    }
});

De DevTools-pagina maakt een verbinding zoals deze:

// 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);

Voorbeelden van DevTools-extensies

De voorbeelden op deze pagina zijn afkomstig van de volgende pagina's:

  • Polymer Devtools-extensie - Maakt gebruik van diverse hulpprogramma's die op de hostpagina draaien om de DOM/JS-status op te vragen en terug te sturen naar het aangepaste paneel.
  • React DevTools-extensie - Gebruikt een submodule van de renderer om DevTools UI-componenten te hergebruiken.
  • Ember Inspector - Gedeelde extensiekern met adapters voor zowel Chrome als Firefox.
  • Coquette-inspect - Een strakke, op React gebaseerde extensie met een debug-agent die in de hostpagina is geïnjecteerd.
  • Sample Extensions bevat meer nuttige extensies om te installeren, uit te proberen en van te leren.

Meer informatie

Voor informatie over de standaard-API's die extensies kunnen gebruiken, zie browser.* API's en web-API's .

Geef ons feedback! Uw opmerkingen en suggesties helpen ons de API's te verbeteren.

Voorbeelden

Voorbeelden van het gebruik van DevTools API's vindt u in de sectie Voorbeelden .