Last active
May 17, 2024 01:29
-
-
Save TaijaQ/5aff8ade70b386ba8527f6328914879f to your computer and use it in GitHub Desktop.
Guide to Extending DevTools
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
A DevTools extension adds functionality to the Chrome DevTools. It can add new UI panels and sidebars, interact with the inspected page, get information about network requests, and more. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
chrome.devtools.panels.create("My Panel", | |
"MyPanelIcon.png", | |
"Panel.html", | |
function(panel) { | |
// code invoked on panel creation | |
} | |
); | |
chrome.devtools.panels.elements.createSidebarPane("My Sidebar", | |
function(sidebar) { | |
// sidebar initialization code here | |
sidebar.setObject({ some_data: "Some data to show" }); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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.js | |
// Create a connection to the background page | |
var backgroundPageConnection = chrome.runtime.connect({ | |
name: "devtools-page" | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Use the inspectedWindow.eval method to execute JavaScript in the context of the inspected page, | |
allowing features like element inspection (inspect(elem)), breaking on functions (debug(fn)) | |
and copying to clipboard (copy()). */ | |
chrome.devtools.inspectedWindow.eval( | |
"inspect($$('head script[data-soak=main]')[0])", | |
function(result, isException) { } | |
); | |
function setSelectedElement(el) { | |
// do something with the selected element | |
} | |
// Invoke the method from the DevTools page like this: | |
chrome.devtools.inspectedWindow.eval("setSelectedElement($0)", | |
{ useContentScriptContext: true }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///////////////////////////////// | |
// devtools.js - DevTools page // | |
///////////////////////////////// | |
// 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.js - Background page // | |
///////////////////////////////////// | |
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); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": ... | |
"version": "1.0", | |
"minimum_chrome_version": "10.0", | |
"devtools_page": "devtools.html", | |
... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Messaging between the DevTools page and content scripts is indirect, by way of the background page. | |
// Getting a reference panel's window | |
//onShown.addListener(function callback); | |
extensionPanel.onShown.addListener(function (extPanelWindow) { | |
extPanelWindow instanceof Window; // true | |
extPanelWindow.postMessage(); // … | |
}); | |
//////////////////////////////////////////////// | |
// Messaging from content scripts to 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; | |
}); | |
//////////////////////////////////////////////// | |
// Create a connection to the background page // | |
//////////////////////////////////////////////// | |
var backgroundPageConnection = chrome.runtime.connect({ | |
name: "panel" | |
}); | |
backgroundPageConnection.postMessage({ | |
name: 'init', | |
tabId: chrome.devtools.inspectedWindow.tabId | |
}); | |
///////////////////////////////////////////////// | |
// Messaging from injected scripts to DevTools // | |
///////////////////////////////////////////////// | |
// 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); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
awesome, thanks for sharing