Extender Herramientas para desarrolladores

Las extensiones de Herramientas para desarrolladores agregan funciones a las Herramientas para desarrolladores de Chrome accediendo a las APIs de extensión específicas de Herramientas para desarrolladores a través de una página de Herramientas para desarrolladores agregada a la extensión.

Diagrama de arquitectura en el que se muestra la página de Herramientas para desarrolladores que se comunica con la ventana inspeccionada y el service worker. Se muestra que el service worker se comunica con las secuencias de comandos del contenido y accede a las APIs de extensiones.
         La página de Herramientas para desarrolladores tiene acceso a las APIs de Herramientas para desarrolladores; por ejemplo, creando paneles.
Arquitectura de extensión de Herramientas de desarrollo.

Las APIs de extensión específicas de Herramientas para desarrolladores incluyen las siguientes:

Página de Herramientas para desarrolladores

Cuando se abre una ventana de Herramientas para desarrolladores, una extensión crea una instancia de su página de Herramientas para desarrolladores que existe mientras la ventana esté abierta. Esta página tiene acceso a las APIs de Herramientas para desarrolladores y a las APIs de la extensión, y permite hacer lo siguiente:

  • Crea paneles e interactúa con ellos usando las APIs de devtools.panels, lo que incluye agregar otras páginas de extensiones como paneles o barras laterales a la ventana de Herramientas para desarrolladores.
  • Obtén información sobre la ventana inspeccionada y evalúa el código en ella con las APIs de devtools.inspectedWindow.
  • Obtén información sobre las solicitudes de red con las APIs de devtools.network.
  • Extiende el panel de Grabadora con las APIs de devtools.recorder.

La página de Herramientas para desarrolladores puede acceder directamente a las APIs de extensiones. Esto incluye poder comunicarte con el service worker mediante la transmisión de mensajes.

Crea una extensión de Herramientas para desarrolladores

A fin de crear una página de Herramientas para desarrolladores para tu extensión, agrega el campo devtools_page en el manifiesto de la extensión:

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

El campo devtools_page debe dirigir a una página HTML. Debido a que la página de Herramientas para desarrolladores debe ser local para tu extensión, te recomendamos que la especifiques mediante una URL relativa.

Los miembros de la API de chrome.devtools solo están disponibles para las páginas cargadas dentro de la ventana de Herramientas para desarrolladores mientras esa ventana está abierta. Las secuencias de comandos de contenido y otras páginas de extensiones no tienen acceso a estas APIs.

Elementos de la IU de Herramientas para desarrolladores: paneles y paneles de la barra lateral

Además de los elementos habituales de la IU de la extensión, como las acciones del navegador, los menús contextuales y las ventanas emergentes, una extensión de Herramientas para desarrolladores puede agregar elementos de la IU a la ventana de Herramientas para desarrolladores:

  • Un panel es una pestaña de nivel superior, como los paneles Elements, Sources y Network.
  • Un panel de la barra lateral presenta una IU complementaria relacionada con un panel. Los paneles Estilos, Estilos calculados y Objetos de escucha de eventos del panel Elementos son ejemplos de paneles de la barra lateral. Según la versión de Chrome que uses y el lugar donde esté anclada la ventana de Herramientas para desarrolladores, los paneles de la barra lateral podrían parecerse a la siguiente imagen de ejemplo:
Ventana de Herramientas para desarrolladores que muestra el panel de elementos y el panel de la barra lateral Estilos.
La ventana de Herramientas para desarrolladores muestra el panel de elementos y el panel de la barra lateral Estilos.

Cada panel tiene su propio archivo HTML, que puede incluir otros recursos (JavaScript, CSS, imágenes, etc.). Para crear un panel básico, usa el siguiente código:

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

El código JavaScript que se ejecuta en un panel o en la barra lateral tiene acceso a las mismas APIs que la página de Herramientas para desarrolladores.

Para crear un panel básico de la barra lateral, usa el siguiente código:

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

Existen varias formas de mostrar contenido en un panel de la barra lateral:

  • Contenido HTML: Llama a setPage() para especificar una página HTML que se mostrará en el panel.
  • Datos JSON: Pasa un objeto JSON a setObject().
  • Expresión de JavaScript: Pasa una expresión a setExpression(). Herramientas para desarrolladores evalúa la expresión en el contexto de la página inspeccionada y, luego, muestra el valor que se muestra.

Tanto para setObject() como para setExpression(), el panel muestra el valor como lo haría en la consola de Herramientas para desarrolladores. Sin embargo, setExpression() te permite mostrar elementos DOM y objetos arbitrarios de JavaScript, mientras que setObject() solo admite objetos JSON.

Cómo comunicarse entre los componentes de la extensión

En las siguientes secciones, se describen algunas formas útiles de permitir que los componentes de extensión de Herramientas para desarrolladores se comuniquen entre sí.

Cómo insertar una secuencia de comandos de contenido

Para insertar una secuencia de comandos de contenido, usa scripting.executeScript():

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

Puedes recuperar el ID de pestaña de la ventana inspeccionada con la propiedad inspectedWindow.tabId.

Si ya se insertó una secuencia de comandos de contenido, puedes usar las APIs de mensajería para comunicarte con ella.

Evalúa JavaScript en la ventana inspeccionada

Puedes usar el método inspectedWindow.eval() para ejecutar el código JavaScript en el contexto de la página inspeccionada. Puedes invocar el método eval() desde una página, un panel o un panel de la barra lateral de Herramientas para desarrolladores.

De forma predeterminada, la expresión se evalúa en el contexto del marco principal de la página. inspectedWindow.eval() usa el mismo contexto de ejecución de secuencia de comandos y las mismas opciones que el código ingresado en la consola de Herramientas para desarrolladores, lo que permite acceder a las funciones de la API de utilidades de la consola de Herramientas para desarrolladores cuando se usa eval(). Por ejemplo, SOAK lo usa para inspeccionar un elemento:

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

También puedes configurar useContentScriptContext como true cuando llames a inspectedWindow.eval() para evaluar la expresión en el mismo contexto que las secuencias de comandos de contenido. Para usar esta opción, usa una declaración de secuencia de comandos de contenido estática antes de llamar a eval(). Para ello, llama a executeScript() o especifica una secuencia de comandos de contenido en el archivo manifest.json. Después de que se cargue el contexto de la secuencia de comandos contextual, también puedes usar esta opción para insertar secuencias de comandos de contenido adicionales.

Pasa el elemento seleccionado a una secuencia de comandos del contenido

La secuencia de comandos del contenido no tiene acceso directo al elemento seleccionado actualmente. Sin embargo, cualquier código que ejecutes con inspectedWindow.eval() tiene acceso a la consola de Herramientas para desarrolladores y a las APIs de utilidades de la consola. Por ejemplo, en el código evaluado, puedes usar $0 para acceder al elemento seleccionado.

Para pasar el elemento seleccionado a una secuencia de comandos de contenido, haz lo siguiente:

  1. Crea un método en la secuencia de comandos de contenido que tome el elemento seleccionado como argumento.

    function setSelectedElement(el) {
        // do something with the selected element
    }
    
  2. Llama al método desde la página de Herramientas para desarrolladores usando inspectedWindow.eval() con la opción useContentScriptContext: true.

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

La opción useContentScriptContext: true especifica que la expresión debe evaluarse en el mismo contexto que las secuencias de comandos de contenido para que pueda acceder al método setSelectedElement.

Obtén el window de un panel de referencia

Para llamar a postMessage() desde un panel de Herramientas para desarrolladores, necesitarás una referencia a su objeto window. Obtén la ventana de iframe de un panel desde el controlador de eventos panel.onShown:

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

Enviar mensajes de secuencias de comandos insertadas a la página de Herramientas para desarrolladores

El código insertado directamente en la página sin una secuencia de comandos de contenido, lo que incluye agregar una etiqueta <script> o llamar a inspectedWindow.eval(), no puede enviar mensajes a la página de Herramientas para desarrolladores mediante runtime.sendMessage(). En su lugar, te recomendamos que combines la secuencia de comandos insertada con una de contenido que puede actuar como intermediario y que uses el método window.postMessage(). En el siguiente ejemplo, se usa la secuencia de comandos en segundo plano de la sección 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. 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);
});

Puedes encontrar otras técnicas alternativas para pasar mensajes en GitHub.

Detecta cuándo se abre y se cierra Herramientas para desarrolladores

Para saber si la ventana de Herramientas para desarrolladores está abierta, agrega un objeto de escucha onConnect al service worker y llama a connect() desde la página de Herramientas para desarrolladores. Debido a que cada pestaña puede tener su propia ventana de Herramientas para desarrolladores abierta, es posible que recibas varios eventos de conexión. Para saber si una ventana de Herramientas para desarrolladores está abierta, cuenta los eventos de conexión y desconexión como se muestra en el siguiente ejemplo:

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

La página de Herramientas para desarrolladores crea una conexión como la siguiente:

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

Ejemplos de extensión de Herramientas para desarrolladores

Los ejemplos que se incluyen en esta página provienen de las siguientes páginas:

  • Extensión de Polymer Devtools: Usa muchos asistentes que se ejecutan en la página de host para consultar el estado del DOM/JS y enviarlo de vuelta al panel personalizado.
  • React Herramientas para desarrolladores: Usa un submódulo del procesador para reutilizar los componentes de la IU de Herramientas para desarrolladores.
  • Ember Inspector: Núcleo de extensión compartido con adaptadores para Chrome y Firefox
  • Coquette-inspect: Es una extensión limpia basada en React con un agente de depuración insertado en la página host.
  • Las extensiones de ejemplo tienen más extensiones que valen la pena instalar, probar y de usar.

Más información

Para obtener información sobre las APIs estándar que pueden usar las extensiones, consulta chrome.* APIs y web.

Envíanos tus comentarios. Tus comentarios y sugerencias nos ayudan a mejorar las APIs.

Ejemplos

Puedes encontrar ejemplos en los que se usan las APIs de Herramientas para desarrolladores en Muestras.