Обзор
Расширение DevTools добавляет функциональность Chrome DevTools. Он может добавлять новые панели пользовательского интерфейса и боковые панели, взаимодействовать с проверяемой страницей, получать информацию о сетевых запросах и многое другое. Просмотрите избранные расширения DevTools . Расширения DevTools имеют доступ к дополнительному набору API расширений, специфичных для DevTools:
Расширение DevTools структурировано так же, как и любое другое расширение: оно может иметь фоновую страницу, сценарии содержимого и другие элементы. Кроме того, каждое расширение DevTools имеет страницу DevTools, на которой есть доступ к API DevTools.

Страница инструментов разработчика
Экземпляр страницы DevTools расширения создается каждый раз, когда открывается окно DevTools. Страница DevTools существует в течение всего срока существования окна DevTools. Страница DevTools имеет доступ к API DevTools и ограниченному набору API расширений. В частности, страница DevTools может:
-  Создавайте панели и взаимодействуйте с ними с помощью API-интерфейсов devtools.panels.
-  Получите информацию о проверяемом окне и оцените код в проверяемом окне с помощью API-интерфейсов devtools.inspectedWindow.
-  Получите информацию о сетевых запросах с помощью API devtools.network.
 Страница DevTools не может напрямую использовать большинство API расширений. Он имеет доступ к тому же подмножеству API-интерфейсов extension и runtime , к которым имеет доступ сценарий содержимого. Как и сценарий содержимого, страница DevTools может взаимодействовать с фоновой страницей с помощью передачи сообщений . Пример см. в разделе «Внедрение сценария содержимого» .
Создание расширения DevTools
 Чтобы создать страницу DevTools для вашего расширения, добавьте поле devtools_page в манифест расширения:
{
  "name": ...
  "version": "1.0",
  "minimum_chrome_version": "10.0",
  "devtools_page": "devtools.html",
  ...
}
 Экземпляр devtools_page , указанный в манифесте вашего расширения, создается для каждого открытого окна DevTools. Страница может добавлять другие страницы расширения в виде панелей и боковых панелей в окно DevTools с помощью API devtools.panels .
 Модули API chrome.devtools.* доступны только для страниц, загруженных в окне DevTools. Сценарии контента и другие страницы расширений не имеют этих API. Таким образом, API доступны только на протяжении всего срока существования окна DevTools.
Есть также некоторые API-интерфейсы DevTools, которые все еще находятся на стадии эксперимента. Список экспериментальных API и рекомендации по их использованию см. в разделе chrome.experimental.* API.
Элементы пользовательского интерфейса DevTools: панели и боковые панели.
В дополнение к обычным элементам пользовательского интерфейса расширения, таким как действия браузера, контекстные меню и всплывающие окна, расширение DevTools может добавлять элементы пользовательского интерфейса в окно DevTools:
- Панель — это вкладка верхнего уровня, такая же, как панели «Элементы», «Источники» и «Сеть».
- На боковой панели представлен дополнительный пользовательский интерфейс, связанный с панелью. Панели «Стили», «Вычисляемые стили» и «Прослушиватели событий» на панели «Элементы» являются примерами боковых панелей. (Обратите внимание, что внешний вид боковых панелей может не совпадать с изображением в зависимости от используемой версии Chrome и места закрепления окна DevTools.)

Каждая панель представляет собой отдельный HTML-файл, который может включать в себя другие ресурсы (JavaScript, CSS, изображения и т. д.). Создание базовой панели выглядит следующим образом:
chrome.devtools.panels.create("My Panel",
    "MyPanelIcon.png",
    "Panel.html",
    function(panel) {
      // code invoked on panel creation
    }
);
JavaScript, выполняемый на панели или боковой панели, имеет доступ к тем же API, что и страница DevTools.
Создание базовой боковой панели для панели «Элементы» выглядит следующим образом:
chrome.devtools.panels.elements.createSidebarPane("My Sidebar",
    function(sidebar) {
        // sidebar initialization code here
        sidebar.setObject({ some_data: "Some data to show" });
});
Существует несколько способов отображения содержимого на боковой панели:
-  HTML-контент. Вызовите setPage, чтобы указать HTML-страницу, которая будет отображаться на панели.
-  Данные JSON. Передайте объект JSON в setObject.
-  Выражение JavaScript. Передайте выражение в setExpression. DevTools оценивает выражение в контексте проверяемой страницы и отображает возвращаемое значение.
 И для setObject , и setExpression на панели отображается значение так, как оно отображается в консоли DevTools. Однако setExpression позволяет отображать элементы DOM и произвольные объекты JavaScript, а setObject поддерживает только объекты JSON.
Связь между компонентами расширения
В следующих разделах описаны некоторые типичные сценарии взаимодействия между различными компонентами расширения DevTools.
Внедрение скрипта контента
 Страница DevTools не может напрямую вызывать tabs.executeScript . Чтобы внедрить сценарий содержимого со страницы DevTools, вы должны получить идентификатор вкладки проверяемого окна с помощью свойства inspectedWindow.tabId и отправить сообщение на фоновую страницу. На фоновой странице вызовите tabs.executeScript , чтобы внедрить скрипт.
 Следующие фрагменты кода показывают, как внедрить скрипт содержимого с помощью 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"
});
Код для фоновой страницы:
// 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 в проверяемом окне
 Вы можете использовать метод inspectedWindow.eval для выполнения кода JavaScript в контексте проверяемой страницы. Вы можете вызвать метод eval со страницы DevTools, панели или боковой панели.
 По умолчанию выражение оценивается в контексте основного фрейма страницы. Теперь вы, возможно, знакомы с функциями API командной строки DevTools, такими как проверка элементов ( inspect(elem) ), прерывание функций ( debug(fn) ), копирование в буфер обмена ( copy() ) и многое другое. inspectedWindow.eval() использует тот же контекст и параметры выполнения скрипта, что и код, введенный в консоли DevTools, что позволяет получить доступ к этим API в рамках eval. Например, SOAK использует его для проверки элемента:
chrome.devtools.inspectedWindow.eval(
  "inspect($$('head script[data-soak=main]')[0])",
  function(result, isException) { }
);
 В качестве альтернативы используйте опцию useContentScriptContext: true для inspectedWindow.eval() чтобы оценить выражение в том же контексте, что и сценарии содержимого. Вызов eval с помощью useContentScriptContext: true не создает контекст сценария содержимого, поэтому перед вызовом eval необходимо загрузить сценарий контекста либо путем вызова executeScript , либо путем указания сценария содержимого в файле manifest.json .
Как только контекст контекстного сценария существует, вы можете использовать эту опцию для добавления дополнительных сценариев содержимого.
 Метод eval эффективен при использовании в правильном контексте и опасен при неправильном использовании. Используйте метод tabs.executeScript если вам не нужен доступ к контексту JavaScript проверяемой страницы. Подробные предупреждения и сравнение двух методов см. в inspectedWindow .
Передача выбранного элемента в скрипт содержимого
 Сценарий содержимого не имеет прямого доступа к текущему выбранному элементу. Однако любой код, который вы выполняете с помощью inspectedWindow.eval имеет доступ к консоли DevTools и API командной строки. Например, в оцененном коде вы можете использовать $0 для доступа к выбранному элементу.
Чтобы передать выбранный элемент в скрипт содержимого:
- Создайте в сценарии содержимого метод, который принимает выбранный элемент в качестве аргумента.
-  Вызовите метод со страницы DevTools, используя inspectedWindow.evalс опциейuseContentScriptContext: true.
Код в вашем сценарии контента может выглядеть примерно так:
function setSelectedElement(el) {
    // do something with the selected element
}
Вызовите метод со страницы DevTools следующим образом:
chrome.devtools.inspectedWindow.eval("setSelectedElement($0)",
    { useContentScriptContext: true });
 Параметр useContentScriptContext: true указывает, что выражение должно оцениваться в том же контексте, что и сценарии содержимого, чтобы оно могло получить доступ к методу setSelectedElement .
 Получение window справочной панели
 Чтобы postMessage из панели инструментов разработчика, вам понадобится ссылка на его объект window . Получите окно iframe панели из обработчика событий panel.onShown :
onShown.addListener(function callback)
extensionPanel.onShown.addListener(function (extPanelWindow) {
    extPanelWindow instanceof Window; // true
    extPanelWindow.postMessage( // …
});
Передача сообщений из сценариев контента на страницу DevTools
Обмен сообщениями между страницей DevTools и сценариями контента осуществляется косвенно, через фоновую страницу.
 При отправке сообщения в сценарий содержимого фоновая страница может использовать метод tabs.sendMessage , который направляет сообщение в сценарии содержимого на определенной вкладке, как показано в разделе «Внедрение сценария содержимого» .
При отправке сообщения из сценария контента не существует готового метода доставки сообщения в правильный экземпляр страницы DevTools, связанный с текущей вкладкой. В качестве обходного пути вы можете настроить страницу DevTools на долговременное соединение с фоновой страницей, а на фоновой странице сохранить карту идентификаторов вкладок с соединениями, чтобы она могла направлять каждое сообщение к правильному соединению.
// 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;
});
Страница DevTools (или панель, или боковая панель) устанавливает соединение следующим образом:
// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
    name: "panel"
});
backgroundPageConnection.postMessage({
    name: 'init',
    tabId: chrome.devtools.inspectedWindow.tabId
});
Передача сообщений из внедренных скриптов на страницу DevTools.
 Хотя приведенное выше решение работает для сценариев контента, код, который вводится непосредственно на страницу (например, путем добавления тега <script> или с помощью inspectedWindow.eval ), требует другой стратегии. В этом контексте runtime.sendMessage не будет передавать сообщения в фоновый скрипт, как ожидалось.
 В качестве обходного пути вы можете объединить внедренный сценарий со сценарием содержимого, который действует как посредник. Чтобы передавать сообщения в скрипт содержимого, вы можете использовать API window.postMessage . Вот пример, предполагающий фоновый сценарий из предыдущего раздела: 
// 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);
});
Теперь ваше сообщение будет передаваться из внедренного сценария в сценарий содержимого, в фоновый сценарий и, наконец, на страницу DevTools.
Здесь вы также можете рассмотреть два альтернативных метода передачи сообщений .
Обнаружение того, когда DevTools открывается и закрывается
Если вашему расширению необходимо отслеживать, открыто ли окно DevTools, вы можете добавить прослушиватель onConnect на фоновую страницу и вызывать соединение со страницы DevTools. Поскольку на каждой вкладке может быть открыто собственное окно DevTools, вы можете получать несколько событий подключения. Чтобы отслеживать, открыто ли какое-либо окно DevTools, вам необходимо подсчитать события подключения и отключения, как показано ниже:
// 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.");
          }
      });
    }
});
Страница DevTools создает такое соединение:
// devtools.js
// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
    name: "devtools-page"
});
Примеры расширений DevTools
Просмотрите исходный код этих примеров расширений DevTools:
- Расширение Polymer Devtools — использует множество помощников, работающих на главной странице, для запроса состояния DOM/JS для отправки обратно на пользовательскую панель.
- Расширение React DevTools — использует подмодуль Blink для повторного использования компонентов пользовательского интерфейса DevTools.
- Ember Inspector — общее ядро расширения с адаптерами для Chrome и Firefox.
- Coquette-inspect — чистое расширение на основе React с агентом отладки, внедренным в хост-страницу.
- В нашей галерее расширений DevTools и примерах расширений есть еще много полезных приложений, которые можно установить, опробовать и изучить.
Дополнительная информация
Информацию о стандартных API, которые могут использовать расширения, см. в разделе API chrome.* и веб-API .
Дайте нам обратную связь! Ваши комментарии и предложения помогают нам улучшить API.
Примеры
Вы можете найти примеры, использующие API DevTools, в разделе Samples .