FOR DEVELOPERS

How to Make a Chrome Extension

How to Make a Chrome Extension

A great approach to expand the functionality of Chromium-based browsers and improve the browsing experience is by creating a Chrome extension. These are small software applications that can be installed in a browser and used in conjunction with online pages. There are many things that one can do with chrome extensions. In this article, we will walk through the process of how to make a Chrome extension from scratch.

Creating a Chrome extension is not as difficult as it may seem. With just a basic understanding of HTML, CSS, and JavaScript, anyone can build a Chrome extension that enhances users’ browsing experience.

Steps to develop a Chrome extension

As we look at the steps to create a Chrome extension, we’ll also explore some of the components.

Folder structure

This section explains the structure of an extension, the function of each component, and how everything fits together.

Example of a Chrome extension file structure:

build a chrome extension.webp

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, such as:

  • 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 of 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.

It performs various tasks, such as heavy computing work that blocks the main thread, a network request, and listening for various kinds of events (executing some code on installation and uninstallation).

Example of 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');
})

Content script

Extensions use content scripts to inject code into host pages (websites with which a content script interacts). These scripts contain 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 of 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. Note: Make sure to provide activeTab permission on the manifest file.

Service worker and content script communication

When creating a Chrome extension, one of the key features we might want to include is the ability for the extension to communicate between the service worker and content script. Both of them run in different contexts and have different capabilities, such as the service worker's ability to access the browser storage and network, which can be useful for interacting with APIs or caching data.

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 developers want to show. Users can quickly locate it by selecting the Extension toolbar icon. It will shut down immediately when the user navigates away.

Additionally, extensions have an options page (options.html) which 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>

“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 off 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 () {
    chrome.runtime.sendMessage({ replace: true });
  });
});

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

//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');
  if (replacedText !== 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, we replace the original text node with a new one containing the replaced text.

Conclusion

As illustrated in this tutorial on how to make a Chrome extension, we can see that with basic knowledge of HTML, CSS and JavaScript, it’s easy to develop one. It’s a fun exercise too and can increase productivity by adding new functionality to a browser.

Author

  • How to Make a Chrome Extension

    Arjun Adhikari

    Arjun Adhikari, experienced in backend engineering since 2019. Skilled in building robust server-side systems, currently focused on web3 space, open to new opportunities

Frequently Asked Questions

"activeTab": Gives temporary access to the current active tab whenever the user invokes the extension.

"scripting": Gives access to inject JavaScript and CSS into websites.

“declarativeContent”: Depending on the URL of a webpage, it enables an extension's action without needing to add host permissions or inject a content script.

There are limitless things that we can do with extensions like text-to-speech, blocking ads and pop-ups, setting dark mode, enabling time tracker, etc. It’s a great approach to expand the functionality of Chromium-based browsers and improve the browsing experience for users.

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.

View more FAQs
Press

Press

What’s up with Turing? Get the latest news about us here.
Blog

Blog

Know more about remote work. Checkout our blog here.
Contact

Contact

Have any questions? We’d love to hear from you.

Hire remote developers

Tell us the skills you need and we'll find the best developer for you in days, not weeks.