In this article we will create a simple custom chrome browser extension / plugin.
Chrome browser extension example
- Show clickable icon on browser bar.
- On click of icon show popup with checkbox to enable disable addition of header, a text area to provide all headers in JSON format & a save button.
- On click of save button, store value in browser local storage.
- After saving (if enable is checked), add/momdify the request headers from saved JSON in any website/url you visit.
Refer below sections for detailed explanation. To get source code directly go to GIT Repository
What chrome extension is made of
- Manifest file
- This is the first file that browser looks at to get information about extension.
- This is a JSON file.
- This file has information describing extension like name, version, java scripts to be used, permissions needed from browser etc.
- Background script
- This is a java script which executed on installation of extension, when chrome makes request & some other events. Rest of the time background script might stay dormant.
- As a best practice, background javascript adds listeners to certain events, so that even if background script is dormant, events will trigger listener code.
- User Interface
- User interface includes HTML, images, scripts etc. for extension
Manifest file
- Plugin info – Name, version & description provides information about the extension.
- permissions – Permissions informs browser about the intentions of access that this extension needs. Some of the permissions are shown to user before installation when its published. Permissions also limit damage by hackers in case compromised.
- storage – Requests access to save so that extension can save input header JSON.
- webRequest, webRequestBlocking – Request access to web request & blocking API which will provide call back before request is sent. This way we can set request headers before request is sent.
- <all_urls> – This is special keyword which request access to apply extension for all URLs. We can use url patterns in case we want to restrict use of extension for few URLs.
- background – This section registers background script.
- browser_action – This section registers user interface files.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ "name": "ChromeHeaderModifier", "version": "1.0", "description": "Modifies headers in chrome", "manifest_version": 2, "permissions":["storage","webRequest","webRequestBlocking","<all_urls>"], "background": { "scripts":["background.js"] }, "browser_action":{ "default_popup":"popup.html" } } |
Background script
This is the background script which will add listener for onBeforeSendHeaders event & then add or modify headers. Code comments provides documentation for logic.
- chrome.storage.sync – This API provides storage ability for extension so that user input data can be saved.
- chrome.webRequest.onBeforeSendHeaders – This is a event which is fired before request is sent & when request headers are available. We can add or modify request headers using this event.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
var customHeaders; var headerInjectionEnable; /* * Add listener for onBeforeSendHeaders events which provides access to headers. */ chrome.webRequest.onBeforeSendHeaders.addListener(function(info) { // Get already saved value of 'Enable' checkbox. chrome.storage.sync.get('headerInjectionEnable', function(items) { if (typeof items.headerInjectionEnable != "undefined") { headerInjectionEnable = items.headerInjectionEnable; } }); // If 'Enable' checkbox is checked, then only add header. if (headerInjectionEnable) { // Get already saved value of header JSON. chrome.storage.sync.get('headerJson', function(items) { if (typeof items.headerJson != "undefined") { customHeaders = JSON.parse(items.headerJson); } }); if (customHeaders) { // Iterate over headers from JSON. If its new, then add header. // If header is existing, then update value. for (var i = 0; i < customHeaders.length; i++) { var headerObj = customHeaders[i]; var existing = false; info.requestHeaders.forEach(function(header, i) { console.log("header - " + headerObj.name.toLowerCase()); if (header.name.toLowerCase() == headerObj.name.toLowerCase()) { header.value = headerObj.value; existing = true; } }); if (!existing) { info.requestHeaders.push({ name: headerObj.name, value: headerObj.value }); } } } } // Return updated header list. return { requestHeaders: info.requestHeaders }; }, // Do this for all URLs { urls: ["<all_urls>"] }, ["blocking", "requestHeaders"] ); |
Extension user interface (UI)
This is the HTML which will be shown in a popup when user clicks on extension icon in browser bar. This HTML has checkbox to enable/disable header addition/modification, text area to provide headers JSON & a save button.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<!DOCTYPE html> <html> <head> <title>Chrome Header Modifier</title> <script src="ui.js"></script> </head> <body> <div style="padding: 20px 20px 20px 20px;"> <h3>Chrome Header Modifier</h3> <!-- Enable checkbox. If this checkbox is checked, then only headers will be added/modified. --> <input type="checkbox" id="enable" name="enable" value="enable" checked>Enable<br> <!-- Input text area for JSON. --> <h4>Enter headers in JSON format</h4> <textarea id="header_input" rows="4" cols="50"> [{"name":"header-name-1","value":"header-value-1"},{"name":"header-name-2","value":"header-value-2"}] </textarea> <!-- Save button which will save value of enable checkbox & header JSON. --> <button id="save" type="button">Save</button> </div> </body> </html> |
ui.js which is included in popup.html. When popup HTML is loaded, this JS will get earlier saved values of enable checkbox & header JSON & set them in checkbox & text area respectively. Then this will add a click listener for save button which will store value of checkbox & header JSON in chrome.storage.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
// Add a callback when HTML is loaded. document.addEventListener('DOMContentLoaded', domLoadedCallback, false); // This is a callback method once HTML is loaded. function domLoadedCallback() { // Get already saved value of header JSON & set it in UI text area. chrome.storage.sync.get('headerJson', function(items) { if (typeof items.headerJson != "undefined") { document.getElementById("header_input").value = items.headerJson; } }); // Get already saved value of enable checkbox & check/uncheck UI checkbox with savd value. chrome.storage.sync.get('headerInjectionEnable', function(items) { if (typeof items.headerInjectionEnable != "undefined") { document.getElementById("enable").checked = items.headerInjectionEnable; } }); // Add a call back for save button document.getElementById('save').addEventListener('click', function() { buttonClickAction(); }); } /** * Action on save. Store value of enable checkbox & header JSON in chrome storage. */ function buttonClickAction() { chrome.storage.sync.set({ 'headerJson': document.getElementById('header_input').value }, function() {}); chrome.storage.sync.set({ 'headerInjectionEnable': document.getElementById("enable").checked }, function() {}); window.close(); } |
Now we will have these files in a directory as given below.
1 2 3 4 5 |
C:\<path>\ChromeHeaderModifier - background.js - manifest.json - popup.html - ui.js |
Installing extension in chrome browser
Refer to these slides with screenshots about how to install our extension in chrome browser.
Here is how our extension look
Complete source code available at GIT Repository