Overzicht
Een DevTools-extensie voegt functionaliteit toe aan de Chrome DevTools. Hiermee kunnen nieuwe UI-panelen en zijbalken worden toegevoegd, interactie met de geïnspecteerde pagina mogelijk worden gemaakt, informatie over netwerkverzoeken worden verkregen en meer. Bekijk aanbevolen DevTools-extensies . DevTools-extensies hebben toegang tot een extra set DevTools-specifieke extensie-API's:
Een DevTools-extensie is op dezelfde manier opgebouwd als elke andere extensie: deze kan een achtergrondpagina, inhoudsscripts en andere elementen bevatten. Daarnaast heeft elke DevTools-extensie een DevTools-pagina, die toegang biedt tot de DevTools API's.

De DevTools-pagina
Er wordt een instantie van de DevTools-pagina van de extensie aangemaakt telkens wanneer een DevTools-venster wordt geopend. De DevTools-pagina blijft bestaan zolang het DevTools-venster open is. De DevTools-pagina heeft toegang tot de DevTools-API's en een beperkte set extensie-API's. Concreet kan de DevTools-pagina het volgende:
- Maak panelen aan en interacteer ermee met behulp van de
devtools.panelsAPI's. - Verkrijg informatie over het geïnspecteerde venster en evalueer code in het geïnspecteerde venster met behulp van de
devtools.inspectedWindowAPI's. - Verkrijg informatie over netwerkverzoeken met behulp van de
devtools.networkAPI's.
De DevTools-pagina kan de meeste API's van extensies niet rechtstreeks gebruiken. De pagina heeft toegang tot dezelfde subset van extension en runtime -API's als een contentscript. Net als een contentscript kan een DevTools-pagina met de achtergrondpagina communiceren via berichtoverdracht . Zie ' Een contentscript injecteren' voor een voorbeeld.
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",
"minimum_chrome_version": "10.0",
"devtools_page": "devtools.html",
...
}
Voor elk geopend DevTools-venster wordt een instantie van de devtools_page aangemaakt die is gespecificeerd in het manifest van uw extensie. Deze pagina kan andere extensiepagina's als panelen en zijbalken aan het DevTools-venster toevoegen met behulp van de devtools.panels API.
De API-modules chrome.devtools.* zijn alleen beschikbaar voor pagina's die in het DevTools-venster worden geladen. Inhoudsscripts en andere extensiepagina's beschikken niet over deze API's. De API's zijn dus alleen beschikbaar gedurende de levensduur van het DevTools-venster.
Er zijn ook enkele DevTools API's die nog experimenteel zijn. Raadpleeg chrome.experimental.* APIs voor een lijst met experimentele API's en richtlijnen voor het gebruik ervan.
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. (Houd er rekening mee dat het uiterlijk van zijpanelen mogelijk niet overeenkomt met de afbeelding, afhankelijk van de versie van Chrome die u gebruikt en waar het DevTools-venster is gedockt.)

Elk paneel is een eigen HTML-bestand, dat andere elementen kan bevatten (JavaScript, CSS, afbeeldingen, enzovoort). Het maken van een basispaneel ziet er als volgt uit:
chrome.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.
Het maken van een eenvoudig zijpaneel voor het Elementen-paneel ziet er als volgt uit:
chrome.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
setPageaan 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 de retourwaarde weer.
Bij zowel setObject als setExpression wordt de waarde in het venster weergegeven zoals deze in de DevTools-console zou verschijnen. setExpression maakt het echter mogelijk om DOM-elementen en willekeurige JavaScript-objecten weer te geven, terwijl setObject alleen JSON-objecten ondersteunt.
Communicatie tussen uitbreidingscomponenten
In de volgende paragrafen worden enkele typische scenario's beschreven voor de communicatie tussen de verschillende componenten van een DevTools-extensie.
Een inhoudsscript injecteren
De pagina DevTools kan tabs.executeScript niet rechtstreeks aanroepen. Om een script met inhoud vanuit de pagina DevTools te injecteren, moet u de ID van het tabblad van het geïnspecteerde venster ophalen met behulp van de eigenschap inspectedWindow.tabId en een bericht naar de achtergrondpagina sturen. Roep vanuit de achtergrondpagina tabs.executeScript aan om het script te injecteren.
De volgende codefragmenten laten zien hoe je een contentscript kunt injecteren met 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"
});
Code voor de achtergrondpagina:
// 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);
});
});
JavaScript evalueren in het geïnspecteerde venster
Je kunt de inspectedWindow.eval -methode 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.
Standaard wordt de expressie geëvalueerd in de context van het hoofdframe van de pagina. U bent wellicht bekend met de API-functies van de DevTools-opdrachtregel , zoals elementinspectie ( inspect(elem) ), het onderbreken van de uitvoering bij functies ( debug(fn) ), kopiëren naar het klembord ( copy() ) en meer. inspectedWindow.eval() gebruikt dezelfde scriptuitvoeringscontext en opties als de code die in de DevTools-console wordt getypt, waardoor toegang tot deze API's binnen de eval mogelijk is. SOAK gebruikt het bijvoorbeeld om een element te inspecteren:
chrome.devtools.inspectedWindow.eval(
"inspect($$('head script[data-soak=main]')[0])",
function(result, isException) { }
);
Als alternatief kunt u de optie useContentScriptContext: true gebruiken voor inspectedWindow.eval() om de expressie in dezelfde context als de content scripts te evalueren. Het aanroepen van eval met useContentScriptContext: true creëert geen content script context, dus u moet een context script laden voordat u eval aanroept, hetzij door executeScript aan te roepen, hetzij door een content script op te geven in het manifest.json bestand.
Zodra de contextscriptcontext bestaat, kunt u deze optie gebruiken om extra inhoudsscripts te injecteren.
De eval methode is krachtig wanneer deze in de juiste context wordt gebruikt, maar gevaarlijk wanneer deze onjuist wordt toegepast. Gebruik de tabs.executeScript -methode als u geen toegang nodig hebt tot de JavaScript-context van de geïnspecteerde pagina. Zie inspectedWindow voor gedetailleerde waarschuwingen en een vergelijking van de twee methoden.
Het geselecteerde element doorgeven aan een inhoudsscript
Het script dat de inhoud genereert, 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 API's voor de opdrachtregel. 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:
- Maak in het contentscript een methode aan die het geselecteerde element als argument accepteert.
- Roep de methode aan vanuit de DevTools-pagina met behulp van
inspectedWindow.evalen de optieuseContentScriptContext: true.
De code in je contentscript zou er ongeveer zo uit kunnen zien:
function setSelectedElement(el) {
// do something with the selected element
}
Roep de methode aan vanuit de DevTools-pagina op deze manier:
chrome.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 verkrijgen
Om postMessage vanuit een ontwikkelaarstools-paneel, hebt u een verwijzing naar het window nodig. U kunt het iframe-venster van een paneel verkrijgen via de eventhandler panel.onShown :
onShown.addListener(function callback)
extensionPanel.onShown.addListener(function (extPanelWindow) {
extPanelWindow instanceof Window; // true
extPanelWindow.postMessage( // …
});
Berichten van contentscripts naar de DevTools-pagina
De communicatie tussen de DevTools-pagina en de contentscripts verloopt indirect, via de achtergrondpagina.
Bij het verzenden van een bericht naar een contentscript kan de achtergrondpagina de methode tabs.sendMessage gebruiken, waarmee een bericht naar de contentscripts in een specifiek tabblad wordt gestuurd, zoals weergegeven in 'Een contentscript injecteren' .
Bij het verzenden van een bericht vanuit een contentscript is er geen kant-en-klare methode om een bericht af te leveren bij de juiste DevTools-pagina-instantie die is gekoppeld aan het huidige tabblad. Als alternatief kunt u de DevTools-pagina een langdurige verbinding laten leggen met de achtergrondpagina, en de achtergrondpagina een overzicht laten bijhouden van tabblad-ID's en bijbehorende verbindingen, zodat elk bericht naar de juiste verbinding kan worden doorgestuurd.
// 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;
});
De DevTools-pagina (of het paneel of de zijbalk) legt de verbinding als volgt tot stand:
// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
name: "panel"
});
backgroundPageConnection.postMessage({
name: 'init',
tabId: chrome.devtools.inspectedWindow.tabId
});
Berichten van geïnjecteerde scripts naar de DevTools-pagina
Hoewel de bovenstaande oplossing werkt voor scripts die rechtstreeks in de pagina worden geïnjecteerd (bijvoorbeeld door een <script> -tag toe te voegen of via inspectedWindow.eval ), vereist dit een andere strategie. In deze context zal runtime.sendMessage de berichten niet zoals verwacht doorgeven aan het achtergrondscript.
Als tijdelijke oplossing kunt u uw geïnjecteerde script combineren met een contentscript dat als tussenpersoon fungeert. Om berichten naar het contentscript door te geven, kunt u de window.postMessage API gebruiken. Hier is een voorbeeld, uitgaande van het achtergrondscript uit de vorige sectie:
// 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);
});
Je bericht zal nu via het geïnjecteerde script naar het contentscript, vervolgens naar het achtergrondscript en uiteindelijk naar de DevTools-pagina stromen.
Je kunt hier ook twee alternatieve berichtoverdrachtstechnieken overwegen.
Detecteren wanneer DevTools wordt geopend en gesloten
Als uw extensie moet bijhouden of het DevTools-venster geopend is, kunt u een onConnect- listener toevoegen aan de achtergrondpagina en de connect-methode vanuit de DevTools-pagina aanroepen. Omdat elk tabblad een eigen DevTools-venster kan hebben geopend, kunt u meerdere connect-gebeurtenissen ontvangen. Om bij te houden of een DevTools-venster geopend is, moet u de connect- en disconnect-gebeurtenissen tellen zoals hieronder weergegeven:
// 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.");
}
});
}
});
De DevTools-pagina maakt een verbinding zoals deze:
// devtools.js
// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
name: "devtools-page"
});
Voorbeelden van DevTools-extensies
Bekijk de broncode van deze DevTools-extensievoorbeelden:
- 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 - Maakt gebruik van een submodule van Blink om de UI-componenten van DevTools 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.
- Onze DevTools Extension Gallery en Sample Extensions bevatten nog meer nuttige apps die je kunt installeren, uitproberen en waarvan je kunt leren.
Meer informatie
Voor informatie over de standaard-API's die extensies kunnen gebruiken, zie chrome.* 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 .