Visão geral
Uma extensão das DevTools adiciona funcionalidades às DevTools do Chrome. Ele pode adicionar novos painéis de interface e barras laterais, interagir com a página inspecionada, receber informações sobre solicitações de rede e muito mais. Confira as extensões de destaque do DevTools. As extensões do DevTools têm acesso a um conjunto adicional de APIs de extensão específicas do DevTools:
Uma extensão do DevTools é estruturada como qualquer outra extensão: ela pode ter uma página de plano de fundo, scripts de conteúdo e outros itens. Além disso, cada extensão do DevTools tem uma página do DevTools, que tem acesso às APIs do DevTools.
Página do DevTools
Uma instância da página do DevTools da extensão é criada sempre que uma janela do DevTools é aberta. A página do DevTools existe durante todo o ciclo de vida da janela. A página das Ferramentas do desenvolvedor tem acesso às APIs das Ferramentas do desenvolvedor e a um conjunto limitado de APIs de extensão. Especificamente, a página do DevTools pode:
- Crie e interaja com painéis usando as APIs
devtools.panels
. - Receba informações sobre a janela inspecionada e avalie o código nela usando as
APIs
devtools.inspectedWindow
. - Receba informações sobre solicitações de rede usando as APIs
devtools.network
.
A página do DevTools não pode usar a maioria das APIs de extensões diretamente. Ele tem acesso ao mesmo subconjunto
das APIs extension
e runtime
que um script de conteúdo tem. Assim como um script de conteúdo, uma página do DevTools pode se comunicar com a página em segundo plano usando a Transmissão de mensagens. Para conferir um
exemplo, consulte Como injetar um script de conteúdo.
Como criar uma extensão das DevTools
Para criar uma página do DevTools para sua extensão, adicione o campo devtools_page
no manifesto
da extensão:
{
"name": ...
"version": "1.0",
"minimum_chrome_version": "10.0",
"devtools_page": "devtools.html",
...
}
Uma instância do devtools_page
especificado no manifesto da extensão é criada para cada
janela do DevTools aberta. A página pode adicionar outras páginas de extensão como painéis e barras laterais à
janela do DevTools usando a API devtools.panels
.
Os módulos da API chrome.devtools.*
estão disponíveis apenas para as páginas carregadas na janela do
DevTools. Os scripts de conteúdo e outras páginas de extensão não têm essas APIs. Portanto, as APIs estão
disponíveis apenas durante a vida útil da janela do DevTools.
Algumas APIs do DevTools ainda são experimentais. Consulte chrome.experimental.* APIs para conferir a lista de APIs experimentais e as diretrizes de uso.
Elementos da interface do DevTools: painéis e painéis da barra lateral
Além dos elementos de interface da extensão habituais, como ações do navegador, menus de contexto e pop-ups, uma extensão das ferramentas do desenvolvedor pode adicionar elementos de interface à janela das ferramentas do desenvolvedor:
- Um painel é uma guia de nível superior, como os painéis "Elementos", "Origens" e "Rede".
- Um painel da barra lateral apresenta uma IU complementar relacionada a um painel. Os painéis "Styles", "Computed Styles" e "Event Listeners" no painel "Elements" são exemplos de painéis da barra lateral. A aparência dos painéis da barra lateral pode não corresponder à imagem, dependendo da versão do Chrome que você está usando e de onde a janela do DevTools está fixada.
Cada painel é um arquivo HTML, que pode incluir outros recursos (JavaScript, CSS, imagens etc.). A criação de um painel básico é assim:
chrome.devtools.panels.create("My Panel",
"MyPanelIcon.png",
"Panel.html",
function(panel) {
// code invoked on panel creation
}
);
O JavaScript executado em um painel ou painel da barra lateral tem acesso às mesmas APIs da página do DevTools.
A criação de um painel de barra lateral básico para o painel "Elements" é assim:
chrome.devtools.panels.elements.createSidebarPane("My Sidebar",
function(sidebar) {
// sidebar initialization code here
sidebar.setObject({ some_data: "Some data to show" });
});
Há várias maneiras de mostrar conteúdo em um painel da barra lateral:
- Conteúdo HTML. Chame
setPage
para especificar uma página HTML a ser exibida no painel. - Dados JSON. Transmita um objeto JSON para
setObject
. - Expressão JavaScript. Transmita uma expressão para
setExpression
. As ferramentas do desenvolvedor avaliam a expressão no contexto da página inspecionada e exibem o valor de retorno.
Para setObject
e setExpression
, o painel mostra o valor como ele apareceria no
console do DevTools. No entanto, setExpression
permite mostrar elementos DOM e objetos JavaScript
arbitrários, enquanto setObject
oferece suporte apenas a objetos JSON.
Como se comunicar entre componentes da extensão
As seções a seguir descrevem alguns cenários típicos de comunicação entre os diferentes componentes de uma extensão das DevTools.
Como injetar um script de conteúdo
A página do DevTools não pode chamar tabs.executeScript
diretamente. Para injetar um script de conteúdo da
página do DevTools, é necessário recuperar o ID da guia da janela inspecionada usando a
propriedade inspectedWindow.tabId
e enviar uma mensagem para a página em segundo plano. Na
página em segundo plano, chame tabs.executeScript
para injetar o script.
Os snippets de código abaixo mostram como injetar um script de conteúdo usando 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"
});
Código da página de plano de fundo:
// 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);
});
});
Como avaliar o JavaScript na janela inspecionada
É possível usar o método inspectedWindow.eval
para executar o código JavaScript no contexto da
página inspecionada. É possível invocar o método eval
em uma página, painel ou painel lateral do DevTools.
Por padrão, a expressão é avaliada no contexto do frame principal da página. Talvez você
conheça os recursos da API de linha de comando do DevTools, como a inspeção de elementos
(inspect(elem)
), a interrupção de funções (debug(fn)
), a cópia para a área de transferência (copy()
) e muito mais.
inspectedWindow.eval()
usa o mesmo contexto de execução do script e as mesmas opções que o código digitado no
console do DevTools, o que permite o acesso a essas APIs na avaliação. Por exemplo, o SOAK o usa
para inspecionar um elemento:
chrome.devtools.inspectedWindow.eval(
"inspect($$('head script[data-soak=main]')[0])",
function(result, isException) { }
);
Como alternativa, use a opção useContentScriptContext: true
para inspectedWindow.eval()
para
avaliar a expressão no mesmo contexto dos scripts de conteúdo. Chamar eval
com
useContentScriptContext: true
não create um contexto de script de conteúdo. Portanto, é necessário carregar um
script de contexto antes de chamar eval
, chamando executeScript
ou especificando um script
de conteúdo no arquivo manifest.json
.
Quando o script de contexto existir, você poderá usar essa opção para injetar outros scripts de conteúdo.
O método eval
é poderoso quando usado no contexto certo e perigoso quando usado
inadequadamente. Use o método tabs.executeScript
se não precisar de acesso ao
contexto JavaScript da página inspecionada. Para ver avisos detalhados e uma comparação dos dois métodos,
consulte inspectedWindow
.
Transmitir o elemento selecionado para um script de conteúdo
O script de conteúdo não tem acesso direto ao elemento selecionado. No entanto, qualquer código executado
usando inspectedWindow.eval
tem acesso ao console do DevTools e às APIs de linha de comando.
Por exemplo, no código avaliado, é possível usar $0
para acessar o elemento selecionado.
Para transmitir o elemento selecionado a um script de conteúdo:
- Crie um método no script de conteúdo que use o elemento selecionado como argumento.
- Chame o método na página do DevTools usando
inspectedWindow.eval
com a opçãouseContentScriptContext: true
.
O código no script de conteúdo pode ficar assim:
function setSelectedElement(el) {
// do something with the selected element
}
Invoque o método na página do DevTools desta forma:
chrome.devtools.inspectedWindow.eval("setSelectedElement($0)",
{ useContentScriptContext: true });
A opção useContentScriptContext: true
especifica que a expressão precisa ser avaliada no
mesmo contexto que os scripts de conteúdo para acessar o método setSelectedElement
.
Como receber o window
de um painel de referência
Para postMessage
em um painel do DevTools, você precisa de uma referência ao objeto window
dele.
Receba a janela de iframe de um painel do manipulador de eventos panel.onShown
:
onShown.addListener(function callback)
extensionPanel.onShown.addListener(function (extPanelWindow) {
extPanelWindow instanceof Window; // true
extPanelWindow.postMessage( // …
});
Mensagens de scripts de conteúdo para a página do DevTools
A mensagem entre a página do DevTools e os scripts de conteúdo é indireta, por meio da página em segundo plano.
Ao enviar uma mensagem para um script de conteúdo, a página em segundo plano pode usar o método
tabs.sendMessage
, que direciona uma mensagem aos scripts de conteúdo em uma guia específica,
conforme mostrado em Como injetar um script de conteúdo.
Ao enviar uma mensagem de um script de conteúdo, não há um método pronto para enviar uma mensagem à instância correta da página do DevTools associada à guia atual. Como solução alternativa, é possível fazer com que a página do DevTools estabeleça uma conexão de longa duração com a página em segundo plano e que a página em segundo plano mantenha um mapa de IDs de guias para conexões, para que ela possa encaminhar cada mensagem para a conexão correta.
// 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;
});
A página do DevTools (ou painel ou painel da barra lateral) estabelece a conexão da seguinte maneira:
// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
name: "panel"
});
backgroundPageConnection.postMessage({
name: 'init',
tabId: chrome.devtools.inspectedWindow.tabId
});
Mensagens de scripts injetados para a página do DevTools
Embora a solução acima funcione para scripts de conteúdo, o código injetado diretamente na página
(por exemplo, ao anexar uma tag <script>
ou inspectedWindow.eval
) exige uma
estratégia diferente. Nesse contexto, runtime.sendMessage
não vai transmitir mensagens para o
script em segundo plano como esperado.
Como solução alternativa, é possível combinar o script injetado com um script de conteúdo que atua como um
intermediário. Para transmitir mensagens ao script de conteúdo, use a API
window.postMessage
. Confira um exemplo, considerando o script em segundo plano da seção anterior:
// 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);
});
Agora, a mensagem vai fluir do script injetado para o script de conteúdo, para o script em segundo plano e, finalmente, para a página do DevTools.
Confira também duas técnicas alternativas de transmissão de mensagens.
Como detectar quando o DevTools é aberto e fechado
Se a extensão precisar rastrear se a janela do DevTools está aberta, adicione um listener onConnect à página em segundo plano e chame connect na página do DevTools. Como cada guia pode ter a própria janela do DevTools aberta, você pode receber vários eventos de conexão. Para acompanhar se alguma janela do DevTools está aberta, é necessário contar os eventos de conexão e desconexão, conforme mostrado abaixo:
// 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.");
}
});
}
});
A página do DevTools cria uma conexão assim:
// devtools.js
// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
name: "devtools-page"
});
Exemplos de extensões do DevTools
Confira a origem destes exemplos de extensão do DevTools:
- Extensão Polymer Devtools: usa muitos helpers em execução na página host para consultar o estado do DOM/JS e enviar de volta ao painel personalizado.
- Extensão do React DevTools: usa um submódulo do Blink para reutilizar componentes da interface do DevTools.
- Ember Inspector: núcleo de extensão compartilhada com adaptadores para Chrome e Firefox.
- Coquette-inspect: uma extensão limpa baseada em React com um agente de depuração injetado na página de destino.
- Nossa Galeria de extensões do DevTools e as Extensões de amostra têm mais apps interessantes para instalar, testar e aprender.
Mais informações
Para informações sobre as APIs padrão que as extensões podem usar, consulte chrome.* APIs e APIs da Web.
Envie seu feedback. Seus comentários e sugestões nos ajudam a melhorar as APIs.
Exemplos
Confira exemplos que usam as APIs do DevTools em Exemplos.