├── README.md ├── background.js ├── devtools.html ├── devtools.js ├── inserted-script.js ├── manifest.json ├── messageback-script.js ├── messaging.js ├── panel.html ├── panel.js └── toast.png /README.md: -------------------------------------------------------------------------------- 1 | DevTools Extension Example 2 | === 3 | 4 | This is a small boilerplate project to be used as a starting point for developing a Chrome DevTools Extension. 5 | 6 | Installation 7 | === 8 | 9 | * Open [chrome://extensions](chrome://extensions) 10 | * Enable 'Developer Mode' checkbox 11 | * Click 'Load unpacked extensions...' 12 | * Select the `devtools-extension` folder 13 | 14 | Usage 15 | === 16 | 17 | While on any page, launch the devtools, you should see a new tab called 'DemoPanel' which contains 3 buttons. 18 | 19 | `Execute script in inspected page` 20 | --- 21 | 22 | Uses `chrome.tabs.executeScript` to execute an inline script in the context of the page you're inspecting (via `background.html`). 23 | 24 | `Insert script into inspected page` 25 | --- 26 | 27 | Uses `chrome.tabs.executeScript` to append an external file (included in the extension folder) to the inspected page (via `background.html`). 28 | 29 | `Insert button to send a message` 30 | --- 31 | 32 | With the grace of a gorilla, replaces the entire DOM of the inspected page with a button which has an `onclick` attached. Clicking the button will send a message from the inspected page to the background.html. It is then relayed back to the DemoPanel where it changes the text on the button. 33 | 34 | Background 35 | === 36 | 37 | While working on a feature for [GhostStory](https://github.com/thingsinjars/GhostStory), I found myself trying to figure out how Chrome DevTools Extensions worked. Seeing as it took the best part of a day to actually get the basics in place (even using the [docs](http://developer.chrome.com/extensions/devtools.html) and [samples](http://developer.chrome.com/extensions/samples.html)), I figure it might help to have a working example. 38 | -------------------------------------------------------------------------------- /background.js: -------------------------------------------------------------------------------- 1 | // Chrome automatically creates a background.html page for this to execute. 2 | // This can access the inspected page via executeScript 3 | // 4 | // Can use: 5 | // chrome.tabs.* 6 | // chrome.extension.* 7 | 8 | chrome.extension.onConnect.addListener(function (port) { 9 | 10 | var extensionListener = function (message, sender, sendResponse) { 11 | 12 | if(message.tabId && message.content) { 13 | 14 | //Evaluate script in inspectedPage 15 | if(message.action === 'code') { 16 | chrome.tabs.executeScript(message.tabId, {code: message.content}); 17 | 18 | //Attach script to inspectedPage 19 | } else if(message.action === 'script') { 20 | chrome.tabs.executeScript(message.tabId, {file: message.content}); 21 | 22 | //Pass message to inspectedPage 23 | } else { 24 | chrome.tabs.sendMessage(message.tabId, message, sendResponse); 25 | } 26 | 27 | // This accepts messages from the inspectedPage and 28 | // sends them to the panel 29 | } else { 30 | port.postMessage(message); 31 | } 32 | sendResponse(message); 33 | } 34 | 35 | // Listens to messages sent from the panel 36 | chrome.extension.onMessage.addListener(extensionListener); 37 | 38 | port.onDisconnect.addListener(function(port) { 39 | chrome.extension.onMessage.removeListener(extensionListener); 40 | }); 41 | 42 | // port.onMessage.addListener(function (message) { 43 | // port.postMessage(message); 44 | // }); 45 | 46 | }); 47 | chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { 48 | return true; 49 | }); -------------------------------------------------------------------------------- /devtools.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /devtools.js: -------------------------------------------------------------------------------- 1 | // Can use 2 | // chrome.devtools.* 3 | // chrome.extension.* 4 | 5 | // Create a tab in the devtools area 6 | chrome.devtools.panels.create("DemoPanel", "toast.png", "panel.html", function(panel) {}); -------------------------------------------------------------------------------- /inserted-script.js: -------------------------------------------------------------------------------- 1 | // This is included and executed in the inspected page 2 | function inserted() { 3 | console.log('External script attached'); 4 | } 5 | inserted(); -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DevToolsPanel", 3 | "version": "0.1", 4 | "description": "A bare-bones example of communication between devtools and an inspected page", 5 | "devtools_page": "devtools.html", 6 | "background": { 7 | "scripts": [ 8 | "background.js" 9 | ] 10 | }, 11 | "permissions": [ 12 | "tabs", 13 | "http://*/*", 14 | "https://*/*" 15 | ], 16 | "manifest_version": 2 17 | } -------------------------------------------------------------------------------- /messageback-script.js: -------------------------------------------------------------------------------- 1 | // document.querySelector('button').addEventListener('click', function() { 2 | // chrome.extension.sendMessage({action: 'message', content:"Changed by page"}, function(message){}); 3 | // }); 4 | document.querySelector('button').addEventListener('click', function() { 5 | sendObjectToDevTools({content: "Changed by page"}); 6 | }); 7 | function sendObjectToDevTools(message) { 8 | // The callback here can be used to execute something on receipt 9 | chrome.extension.sendMessage(message, function(message){}); 10 | } -------------------------------------------------------------------------------- /messaging.js: -------------------------------------------------------------------------------- 1 | // This creates and maintains the communication channel between 2 | // the inspectedPage and the dev tools panel. 3 | // 4 | // In this example, messages are JSON objects 5 | // { 6 | // action: ['code'|'script'|'message'], // What action to perform on the inspected page 7 | // content: [String|Path to script|Object], // data to be passed through 8 | // tabId: [Automatically added] 9 | // } 10 | 11 | (function createChannel() { 12 | //Create a port with background page for continous message communication 13 | var port = chrome.extension.connect({ 14 | name: "Sample Communication" //Given a Name 15 | }); 16 | 17 | // Listen to messages from the background page 18 | port.onMessage.addListener(function (message) { 19 | document.querySelector('#insertmessagebutton').innerHTML = message.content; 20 | // port.postMessage(message); 21 | }); 22 | 23 | }()); 24 | 25 | // This sends an object to the background page 26 | // where it can be relayed to the inspected page 27 | function sendObjectToInspectedPage(message) { 28 | message.tabId = chrome.devtools.inspectedWindow.tabId; 29 | chrome.extension.sendMessage(message); 30 | } -------------------------------------------------------------------------------- /panel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /panel.js: -------------------------------------------------------------------------------- 1 | // This one acts in the context of the panel in the Dev Tools 2 | // 3 | // Can use 4 | // chrome.devtools.* 5 | // chrome.extension.* 6 | 7 | document.querySelector('#executescript').addEventListener('click', function() { 8 | sendObjectToInspectedPage({action: "code", content: "console.log('Inline script executed')"}); 9 | }, false); 10 | 11 | document.querySelector('#insertscript').addEventListener('click', function() { 12 | sendObjectToInspectedPage({action: "script", content: "inserted-script.js"}); 13 | }, false); 14 | 15 | document.querySelector('#insertmessagebutton').addEventListener('click', function() { 16 | sendObjectToInspectedPage({action: "code", content: "document.body.innerHTML=''"}); 17 | sendObjectToInspectedPage({action: "script", content: "messageback-script.js"}); 18 | }, false); -------------------------------------------------------------------------------- /toast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsinjars/devtools-extension/0f6e0928d4d2e777d5633c2f7bc226468e8e8faa/toast.png --------------------------------------------------------------------------------