Create an extension that customizes the DevTools UI
This tutorial shows how to build your own DevTools extension from scratch. It's a good way to experience everything that's needed for typical development. At the end of the tutorial, you'll have a working extension that creates its own panel and interacts with the DevTools APIs.
First review the prerequisites. Then download and run the final extension from the Solution section to see what you'll be building in this tutorial. Otherwise, start at Step 1 - Create a Basic DevTools Extension to build the extension from scratch.
Prerequisites
- Microsoft Edge Browser to run the extension.
- A code editor such as Visual Studio Code to follow along with the tutorial.
Solution
In this section, you download and run the final state of the extension that the rest of this tutorial will teach you to build. Later, you'll start from scratch and learn to write the code to create your own extension.
Get the final extension code by downloading this zip file and extracting its content to a folder on your computer.
Open Microsoft Edge and go to
edge://extensions/
.Turn on the Developer mode toggle.
Click Load unpacked and navigate to the folder where you extracted the zip file. In this folder, select Demos-main > devtools-extension > sample 4, and then click Select Folder.
Your DevTools extension should now be loaded. Open a new tab in Microsoft Edge, and then open DevTools by pressing F12.
The extension creates a Sample Panel tab in the DevTools window:
Step 1 - Create a basic DevTools extension
A basic DevTools extension consists of two files, as shown in Step 1 code:
A manifest file.
{ "name": "DevTools Sample Extension", "description": "A Basic DevTools Extension", "manifest_version": 3, "version": "1.0", "devtools_page": "devtools.html" }
Property Description name The name of the extension that will appear under edge://extensions/
.description The description of the extension that will be displayed under the name of the extension. version The version of the extension that will appear next to the name of the extension. manifest_version Determines the set of features that the extension will be using, such as service workers or network request modification. The current version is version 3
. To learn more about this version and the differences with version2
, see Overview and timelines for migrating to Manifest V3.devtools_page The path to an HTML file that will be run every time the DevTools UI is opened. Though the page is not rendered in DevTools, it will be used to load the necessary JavaScript files for the extension. An html file to match the
devtools_page
field in the manifest file.<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> </head> <body> A Basic DevTools Extension. </body> </html>
To load and test your DevTools extension in Microsoft Edge, use the Developer mode:
In Microsoft Edge, go to
edge://extensions/
.Turn on the Developer mode toggle.
Click Load unpacked, navigate to the folder where you wrote the code for your extension, and click Select folder.
Your DevTools extension is now loaded. Open a new tab and then open DevTools (F12).
Your extension is loaded, but isn't displayed in DevTools yet, because you haven't created a panel for the extension.
Step 2 - Add a DevTools panel
In this step, you'll create a new panel in DevTools. You can find the code for this step in Step 2 code, or write it yourself by following the instructions below.
A panel is a tab in the main toolbar in DevTools, similar to the Elements, Console, and Sources tools shown below:
In this step, we will create a basic DevTools extension with a sample panel.
Create a
devtools.js
file with the following code:chrome.devtools.panels.create("Sample Panel", "icon.png", "panel.html", panel => { // code invoked on panel creation });
The
create
method requires four parameters:title
,iconpath
,pagePath
, and a callback function. Note that while the panel's icon is a required parameter, it does not get displayed in Microsoft Edge DevTools currently.To learn more about the
chrome.devtools.panels
extension API, see the chrome.devtools.panels API reference.Load the file from the HTML page specified in the
devtools_page
manifest field earlier (thedevtools.html
file), by adding ascript
element in the source code.<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> </head> <body> <script src="devtools.js"></script> </body> </html>
Create the
panel.html
file the you referenced in the previouschrome.devtools.panels.create
method call. This webpage will contain the user interface of the panel your extension is adding to DevTools.<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> </head> <body> <h1>A Basic DevTools Extension with Panel</h1> </body> </html>
To test your changes in Microsoft Edge, reload your extension from the edge://extensions/
page:
Navigate (or go back) to the
edge://extensions/
page.Find the unpacked extension entry you loaded in step 1.
Click Reload.
Your DevTools extension should now be reloaded. Open a new tab in Microsoft Edge and then open DevTools (F12). Your DevTools extension panel should be displayed in DevTools:
Step 3 - Call extension APIs from a DevTools extension
In this step, you will use extension APIs to display memory information in your DevTools panel. To do this, we will need to update the permissions
in the manifest file, the panel interface, and the devtools script. The source code for this step can be found in Step 3 code, or write it yourself by following the instructions below.
Use the
permissions
manifest member in yourmanifest.json
file. This member defines which permissions your extension requires from the user. Some permissions are needed to use certain extension APIs."permissions": [ "system.memory", ]
The
system-memory
permission is required to use extension APIs we will use later in this tutorial. To learn more about the available APIs and associated permissions, see the API reference.Add the following to the body in the
panel.html
file to display the data in the panel.<div> Available Memory Capacity: <span id="availableMemoryCapacity"></span> </div> <div> Total Memory Capacity: <span id="totalMemoryCapacity"></span> </div>
Update the
devtools.js
file with the following code.let availableMemoryCapacity; let totalMemoryCapacity; chrome.devtools.panels.create("Sample Panel", "icon.png", "panel.html", panel => { // code invoked on panel creation panel.onShown.addListener((extPanelWindow) => { availableMemoryCapacity = extPanelWindow.document.querySelector('#availableMemoryCapacity'); totalMemoryCapacity = extPanelWindow.document.querySelector('#totalMemoryCapacity'); }); }); setInterval(() => { chrome.system.memory.getInfo((data) => { if (availableMemoryCapacity) { availableMemoryCapacity.innerHTML = data.availableCapacity; } if (totalMemoryCapacity) { totalMemoryCapacity.innerHTML = data.capacity; } }); }, 1000);
The above code snippet does the following:
It creates a new panel
Sample Panel
in DevTools.When the panel is displayed (
panel.onShown
listener), theavailableMemoryCapacity
andtotalMemoryCapacity
elements are retrieved from the DOM.Next, a timer is set to run code every second after the panel is shown.
When the timer fires, the
chrome.system.memory.getInfo
method is used to retrieve the available and total memory capacity of the device and these values are displayed in the corresponding DOM elements.
To test your changes in Microsoft Edge, reload your extension from the edge://extensions/
page:
Navigate (or go back) to the
edge://extensions/
page.Find the unpacked extension entry you loaded in step 1.
Click Reload.
Your DevTools extension should now be reloaded. Open a new tab and then open DevTools (F12). Your DevTools extension panel should now show the available and total memory capacities.
More extension APIs can be found in the API Reference page.
Step 4 - Interact with the inspected webpage
In this step of the tutorial, you will add code that interacts with the inspected webpage. That code will:
- Listen to click events that happen on the webpage and log them into the DevTools Console tool.
- Show the mouse click position in the DevTools extension panel.
- Show a greeting alert in the inspected page when user clicks a button in the DevTools extension panel.
The source code for this step can be found in Step 4 code, or write it yourself by following the instructions below.
Unfortunately, the DevTools panel you just created does not have direct access to the inspected webpage and does not run until DevTools is opened. For this you will use a content script and a background service worker.
- A content script runs in the context of the inspected webpage and, in the same way other scripts are loaded by the page, they have access to the DOM and can change it.
- A background service worker is a script that the browser runs in a separate thread and has access to extension APIs.
The following diagram gives an overview of how the DevTools page, inspected page, content script, and background service worker fit together in an extension.
In this part of the tutorial, you will detect the user clicks on a webpage using a content script. The content script will relay this info to the devtools.js
file where the data will be displayed in both the console and the DevTools extension panel.
Append the following to the
manifest.json
file"content_scripts": [{ "matches": [ "http://*/*", "https://*/*" ], "run_at": "document_idle", "js": [ "content_script.js" ] }], "background": { "service_worker": "background.js" }
Property Value matches Specifies which pages this content script will be injected into. run_at Indicates when the browser injects the script onto the page. js The javascript files to be injected. Create the file
content_script.js
with the following content:document.addEventListener("click", (event) => { chrome.runtime.sendMessage({ click: true, xPosition: event.clientX + document.body.scrollLeft, yPosition: event.clientY + document.body.scrollTop }, response => { console.log("Received response", response); } ); });
The above code snippet prints a message to the console when the script is injected in the page. It also adds a click event listener to the page that will send a message with mouse click position in the inspected page by using the
chrome.runtime.sendMessage
API.In the
panel.html
file, add asayHello
button and ayouClickedOn
label . These two elements are used to demo the interaction between the inspected page, the DevTools panel, and the background service worker. When the user clicks thesayHello
button in the DevTools extension, it will display a greeting message in the inspected window. When the user clicks anywhere in the inspected page, it will display a message to show the mouse click position in the DevTools extension panel.<button id="sayHello">Say Hello to the inspected page!</button> <h2><span id="youClickedOn"></span></h2>
In the
devtools.js
file, use thechrome.runtime.connect
method to create a connection to the background service worker, and then send the inspected windowtabId
to the service worker by using thebackgroundPageConnection.postMessage
method. Finally, add event listeners to thesayHello
button andyouClickedOn
label that's defined in thepanel.html
file.let youClickedOn; chrome.devtools.panels.create("Sample Panel", "icon.png", "panel.html", panel => { // code invoked on panel creation panel.onShown.addListener( (extPanelWindow) => { let sayHello = extPanelWindow.document.querySelector('#sayHello'); youClickedOn = extPanelWindow.document.querySelector('#youClickedOn'); sayHello.addEventListener("click", () => { // show a greeting alert in the inspected page chrome.devtools.inspectedWindow.eval('alert("Hello from the DevTools extension");'); }); }); }); chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { // Messages from content scripts should have sender.tab set if (sender.tab && request.click == true) { console.log('I am here!'); if (youClickedOn) { youClickedOn.innerHTML = `You clicked on position (${request.xPosition}, ${request.yPosition}) in the inspected page.`; } sendResponse({ xPosition: request.xPosition, yPosition: request.yPosition }); } }); // Create a connection to the background service worker const backgroundPageConnection = chrome.runtime.connect({ name: "devtools-page" }); // Relay the tab ID to the background service worker backgroundPageConnection.postMessage({ name: 'init', tabId: chrome.devtools.inspectedWindow.tabId });
When the user clicks the
sayHello
button, the DevTools extension will run a code snippet ofalert("Hello from the DevTools Extension");
in the inspected window by invoking theeval()
method of the inspected windowchrome.devtools.inspectedWindow
.When the user clicks anywhere in the inspected window, the DevTools extension will receive a message, from the background service worker, with
request.click == true
and the mouse position information.Create the
background.js
file and add the following code to it:let id = null; const connections = {}; chrome.runtime.onConnect.addListener(devToolsConnection => { // Assign the listener function to a variable so we can remove it later let devToolsListener = (message, sender, sendResponse) => { if (message.name == "init") { id = message.tabId; connections[id] = devToolsConnection; // Send a message back to DevTools connections[id].postMessage("Connected!"); } }; // Listen to messages sent from the DevTools page devToolsConnection.onMessage.addListener(devToolsListener); devToolsConnection.onDisconnect.addListener(() => { devToolsConnection.onMessage.removeListener(devToolsListener); }); });
The above code snippet connects the background service worker with the DevTools page. It listens to when the DevTools page connects, saves the connection, and sends a response back to the DevTools page.
This is useful when your background service worker is collecting data or performing tasks in the background that you want to be available in your DevTools extension.
To test the new sayHello
button:
Go to
edge://extensions/
.Find the unpacked extension entry that you loaded in Step 1.
Click the Reload button.
Open a new browser tab, open DevTools (F12), and click the Sample Panel tab.
Click the
"Say Hello to The Inspected Page!"
button in your panel. You should see an alert in the inspected page, as shown below.
To learn more about content scripts, see the Content Scripts documentation.
To test the youClickedOn
label:
Click OK to close the alert window opened in the previous step.
Click anywhere in the inspected page. A You clicked on position (x,y) in the inspected page message should appear in the extension panel.
Open the Console tool. A message similar to the previous step should also appear in the Console tool.