# How to Make a Chrome Extension

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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674574104431/e214108d-e146-42d7-991f-a97df2774a62.jpeg align="center")

### 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*
    
    ```typescript
    {
      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

```typescript
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 `activeTab`permission on manifest file

### *Example service worker*

```typescript
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.

```xml
<!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

```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

```xml
<!DOCTYPE html>
<html>
<head>
    <title>Love Replacer Extension</title>
</head>
<body>
    <button id="replace-button">Replace</button>
    <script src="popup.js"></script>
</body>
</html>
```

```javascript
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

```javascript
//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
    
    ```javascript
    // 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
    
    ```javascript
    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
    

```javascript
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`.
