How to Make a Chrome Extension

Arjun AdhikariArjun Adhikari
6 min read

A great approach to expand the functionality of Chromium-based browsers and improve the browsing experience for users is by creating a Chrome extension.

Small software applications known as extensions can be installed in a browser and used in conjunction with online pages.

There are limitless things that you can do with extensions. In this article, we will walk through the process of creating a simple Chrome extension from scratch, covering the basics of extension

Creating a Chrome extension is not as difficult as it may seem, and with just a basic understanding of HTML, CSS, and JavaScript, anyone can create an extension that enhances the browsing experience for users.

Folder Structure

A Chrome extension is made up of various components. This section explains the structure of an extension, the function of each component, and how everything fits together.

Here's an example of a Chrome Extension file structure

The manifest

Manifest (manifest.json) is the configuration file of a Chrome extension. It is an important file to look after as it provides the browser with a blueprint of the extension and other important information like:

  • name, description, current version, and icons for extensions

  • the Chrome API keys, and permissions that the extension needs.

  • the scripts used in the content, the HTML file used in the pop-up window, the extension service worker files, etc.

    Example Manifest File

      {
        manifest_version: 3,
        name: "Name of extension ",
        description: "a detailed description",
        version: "1.0",
        icons: { 
          16: "images/icon-16.png",
          32: "images/icon-32.png",
          48: "images/icon-48.png",
          128: "images/icon-128.png",
        },
        background: {
          service_worker: "service-worker.js",
        },
        permissions: ["scripting", "activeTab"],
      }
    

Service Worker

A service worker (previously called a background script) is an event-based script that runs separately from a web page in the background. An extension's service worker is loaded when it is necessary and released when it is no longer required. A heavy computing task that blocks the main thread, a network request, and listening for various kinds of events (executing some code on installation and uninstallation) is performed by the service worker.

Content Script

Extensions use content scripts to inject code into host pages (websites with which a content script interacts). This script contains all the logic that is needed to manipulate the dom like injecting the node, deleting a node, editing the dom, changing the style of an element, etc

Node is the basic building block of a dom the whole document. Each element, text and attributes everything is a node

Example content script

document.addEventListener("click", function(event) {
  if (event.target.tagName === "") {
    chrome.runtime.sendMessage({url: event.target.href});
  }
});

This code listens for clicks on the page and checks if the target of the click is an anchor tag. If it is, it sends a message to the service worker with the URL of the link that was clicked. make sure to provide activeTabpermission on manifest file

Example service worker

console.log("Hi from background script file")
chrome.runtime.onMessage.addListener( function (request, sender, sendResponse) {
    console.log("Got your message from content.js : ", request);
    sendResponse('Got it');
})

Communication between Service worker and content script

Chrome exposes chrome.runtime.sendMessage()api to the content script and chrome.runtime.onMessage.addListener() api to the background service worker for these scripts to communicate with each other.

The Popup

Many extensions make use of a popup (popup.html) to provide functionality, such as showing more details about the active tab, or any content the developers want to show. By selecting the extension toolbar icon, users may quickly locate it. It will shut down immediately when the user navigates away.

Additionally, the extensions also have an options page (options.html). It allows users to have the option of personalizing an extension by selecting which websites will function.

<!DOCTYPE html>
<html>
<head>
    <title>Extension Name</title>
</head>
<body>
    <button>Click me</button>
    <script src="popup/popup.js"></script>
</body>
</html>

Only Love Extension

We will be creating a Chrome extension that replaces all instances of the word "hate" with "love" on a webpage when the extension icon is clicked,

Starting with manifest.json

{
  "manifest_version": 3,
  "name": "Only Love Extension",
  "description": "Replaces all instances of the word 'hate' with 'love' ",
  "version": "1.0",
  "action": {
    "default_popup": "popup/popup.html"
  },
  "permissions": ["activeTab", "declarativeContent", "scripting"],
  "background": {
    "service_worker": "service-worker.js"
  }
}

Create a new file called "popup.html" and "popup.js" in the extension directory and add the following code

<!DOCTYPE html>
<html>
<head>
    <title>Love Replacer Extension</title>
</head>
<body>
    <button id="replace-button">Replace</button>
    <script src="popup.js"></script>
</body>
</html>
document.addEventListener('DOMContentLoaded', function () {
  var replaceButton = document.getElementById('replace-button');
  replaceButton.addEventListener('click', function () {
    //send message to service-worker.js
    chrome.runtime.sendMessage({ replace: true });
  });
});

create a new file called service-worker.js and add the following code

//service-worker.js
//listens for the event and fires a event to execute content.js
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
  if (request.replace) {
    chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
      chrome.scripting
        .executeScript({
          target: { tabId: tabs[0].id },
          files: ['scripts/content.js'],
        })
        .then(() => {
          console.log('Executed script');
        });
    });
  }
});
  • now create a new file named content.js and add the following code

      // content.js
      const elements = document.querySelectorAll('*');
      elements.forEach((element) => {
        element.childNodes.forEach((node) => {
          if (node.nodeType === Node.TEXT_NODE) {
            const text = node.textContent;
            const replacedText = text.replace(/hate/gi, 'love');
            // Check if the text was changed
            if (replacedText !== text) {
              // Replace the original text node with a new one containing the replaced text
              node.textContent = replacedText;
            }
          }
        });
      });
    

    Walk through the code

  • create a popup.html with a script(popup.js) and button which onClick sends the message to service-worker.js. The message is an object with a replace property { replace: true }

  • The service worker listens for the event in the current tab as mentioned in

      chrome.tabs.query({ active: true, currentWindow: true })
    

    and fires a new event to execute content.js using chrome.scripting API.

  • chrome.scripting API is used to inject JavaScript and CSS into websites so that extensions can make decisions at runtime. make sure to have scripting permission enabled in the manifest.

  • Here the decision is executing the content.js

chrome.scripting
    .executeScript({
      target: { tabId: tabs[0].id },
      files: ['scripts/content.js'],
    })
    .then(() => {
      console.log('Executed script');
    });
  • In content.js, we get all elements on the page and iterate through all elements. again we iterate through all child nodes of the current element

  • inside each child node, we make sure that the current node is a text node

  • if it is a text node we get the text of the node and replace 'hate' with 'love' text.replace(/hate/gi, 'love')

  • now we check if the text was changed or not. if changed then we replace the original text node with a new one containing the replaced text

Conclusion

so we can see that with basic knowledge of HTML, CSS and Javascript we can easily make a Chrome extension. creating a Chrome extension is fun and can increase your productivity by adding new functionality to your browser.

If you've developed your extension, please share your insights and experiences and let me know if you have any questions or need any additional help at arjunadhikari0509@gmail.com.

1
Subscribe to my newsletter

Read articles from Arjun Adhikari directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Arjun Adhikari
Arjun Adhikari