Creating a Chrome extension

Creating a Chrome extension

Photo by Growtika on Unsplash

Today, I thought I would try out something a little bit different.

I didn't feel like learning more about Rust today so I thought I could try to learn something new, like making a chrome extension.

Although I am quite comfortable with web technologies (like HTML, CSS, javascript), I felt today I would just understand how to create a basic extension with minimal code. I feel consistency is much more important than quantity when learning stuff in order to keep motivation high.

Aim

I am going to make an extension that can convert any page into Dark mode. I am planning to achieve this by rendering a button that, when clicked, will update the background-color property of the currently rendered HTML to a darker color.

I know this is a very naive approach and will definitely fail for most websites since most components have a color defined for them, but it's okay for the time being since I just wanna understand the setup required for making an extension.

manifest.json

The most minimal chrome extension can be made by defining a single file, that is, the manifest.json.

This file will define the metadata of the extension (like name, version, description) as well as the entry point, pages, actions, etc.

For our extension, we only need the following:

  • Background script: This will save the color we need to the extension storage.

  • HTML: This should render the button.

  • CSS: To style the button using the stored color.

  • Javascript: This will handle the callback logic of the button. (change body.backgroundColor to the saved color)

We will also add a couple of stock icons to represent our extension.

Our manifest file will look like this:

{
    "name": "Dark mode",
    "description": "Build an Extension!",
    "version": "1.0",
    "manifest_version": 3,
    "background": {
        "service_worker": "background.js"
    },
    "permissions": ["storage", "activeTab", "scripting"],
    "action": {
        "default_popup": "popup.html",
        "default_icon": {
            "16": "/images/get_started16.png",
            "32": "/images/get_started32.png",
            "48": "/images/get_started48.png",
            "128": "/images/get_started128.png"
        }
    },
    "icons": {
        "16": "/images/get_started16.png",
        "32": "/images/get_started32.png",
        "48": "/images/get_started48.png",
        "128": "/images/get_started128.png"
    }
}

Let's try to understand these fields:

  • background: This will have our background script. It is called as a service worker.

  • permissions: Here we will define what permissions are required by our app. In our case, we need to access storage to save the color, the active tab to access the body tag, and scripting since we will be running a script to accomplish our task.

  • action: We will be using a popup to display our button which can be defined using this.

  • icons: This is used by extension management applications to display our icons. Don't worry about this, we will just download a bunch of stock images. Multiple images are needed because the app can be shown in different standard sizes.

That's it.

background.js

let color = '#121212';

chrome.runtime.onInstalled.addListener(() => {
    chrome.storage.sync.set({ color });
});

This is one of our simplest scripts, where we just store the color we need in a variable color.

Here, we access the chrome runtime object and add a callback method on the event onInstalled. This should get called when we install our extension.

Inside the callback, we will access the storage object and set the variable color, which is set to '#121212' (a dark grey).

popup.html

<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="button.css">
  </head>
  <body>
    <button id="changeColor"></button>
    <script src="popup.js"></script>
  </body>
</html>

This is the basic HTML that will be rendered in our popup.

This just contains a button and also links the CSS and a Javascript files.

We have added the script tag towards the end so that the javascript gets loaded after the HTML is rendered since we reference the button in the script.

button.css

button {
    height: 30px;
    width: 30px;
    outline: none;
    margin: 10px;
    border: none;
    border-radius: 2px;
}

button.current {
    box-shadow: 0 0 0 2px white,
            0 0 0 4px black;
}

This will style the button to look like a square.

popup.js

// Get a reference to the button.
let changeColor = document.getElementById("changeColor");

// Change the button background color to the stored color. 
chrome.storage.sync.get("color", ({ color }) => {
  changeColor.style.backgroundColor = color;
});

// When the button is clicked, inject setPageBackgroundColor into current page
changeColor.addEventListener("click", async () => {
    let [tab] = await chrome.tabs.query({ active: true, currentWindow: true });

    chrome.scripting.executeScript({
      target: { tabId: tab.id },
      function: setPageBackgroundColor,
    });
});

// Update the style of the current page's body element to the stored color.
function setPageBackgroundColor() {
    chrome.storage.sync.get("color", ({ color }) => {
        document.body.style.backgroundColor = color;
    });
}

I have added comments inline for your understanding.

Downloading images

You can create your own images if you want, otherwise, you can download them using this link: storage.googleapis.com/web-dev-uploads/file.. or even remove the images from manifest.json if you don't want them.

How to see it working

  1. Put all the files we created above into a folder.

  2. Go to chrome://extensions.

  3. Click on the load unpacked button and choose the folder you created in step 1.

  4. It should get loaded at this point. If you want, you can pin the extension to the task bar from the extensions menu on the top right corner of the browser.