Create a Real Browser Extension (Chrome, Firefox, Chromium based)
Tags: javascript, beginners, tutorial, extension
Published: 2019-08-01 23:35:13


In this post we will create a real browser extension. By "real" i mean this is not just a demo, if you work a little bit more on it you can publish this as your first extension :)


## Goal

We will create a browser extension to help people with visual impairments or other conditions to browse the web easier

This extension will have tools which will give the ability to the users to change font size, colours etc

## Requirements / Tools

* basic knowledge of js, html
* a code editor (tip: if you are student you can have all jetbrains software for free)

**My setup:**
* **OS:** Fedora Linux
* **Browser:** Firefox
* **IDE:** WebStorm

I'm also using [web-ext](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Getting_started_with_web-ext), it's a cli tool to help you in the development of your extension

**example:** `web-ext run` will launch a new firefox window with a new temporary profile so you can test the extension
and if you make any changes in the source it will automatically reload the extension for you

for now web-ext supports only firefox but it will make your life so much easier


## How Extensions Work

There 3 + 1 "places" in the browser where an extension exists

* background: as its name says this part run in the background, there is no UI, from here you can do some cool things like modify http requests

* content: this is how you can inject your js, css etc in the websites you visit

* popup: this put an icon on the right of the address bar and when you click it it can show a popup

* options: this is a html page where the user can change the settings of the extension


## File structure

This is example of my personal preference, the extension will have similar file structure
![file structure](https://thepracticaldev.s3.amazonaws.com/i/dqzzu7rtwlmnit6b4qvx.png)

## Manifest file


All extensions need to have the `manifest.json`, this is the file with all the information about the extension

You must add the basic information of the extension like name, version etc
```json
{
  "name": "Accessibility Helper",
  "version": "1.0.0",
  "description": "Accessibility Helper",
  "homepage_url": "https://github.com/chr314/accessibility-extension",
  "author": "Aslanov Christoforos",
  "manifest_version": 2,
  "icons": {
    "16": "assets/icon.16.jpg",
    "48": "assets/icon.48.jpg",
    "128": "assets/icon.128.jpg"
  },
```
Here we need to add the permissions we will use

`<all_urls>` means that the extension have access to all web pages, you can add custom like `https://*.example.com/*`

Also we will use the `tabs` permission to access the current tab

Be careful to not add permissions you don't need
```json
  "permissions": [
    "<all_urls>",
    "tabs"
  ],
```
`browser_action` manages what will open when you click on the extension icon right to the address bar
```json
  "browser_action": {
    "default_title": "Accessibility Helper",
    "default_popup": "src/popup/popup.html",
    "default_icon": {
      "16": "assets/icon.16.jpg",
      "48": "assets/icon.48.jpg",
      "128": "assets/icon.128.jpg"
    }
  },
```
In `content_scripts` you can set what will be injected in the web pages

you can also inject `css` the same way as `js`
```json
  "content_scripts": [
    {
      "matches": [
        "<all_urls>"
      ],
      "js": [
        "src/content/script.js"
      ]
    }
  ]
}
```

## The fun part (Coding)

As we saw in the `manifest.json` the popup is a simple html page

The logic in our case is very simple

The popup is the control panel, when you click a action button, a message is sent to the content of the current tab to alter the page

`chrome.tabs.query()` is used to get the current tab and the `chrome.tabs.sendMessage()` is to send the message

don't worry the `chrome` namespace is supported in firefox too, for Firefox and Edge you can also use the `browser` namespace with some advantages like promises

**example**: if you click the font increase button, the object `{action: 'font-size-increase'}` is sent as message to the current tab and then the content script will receive the message and do the appropriate action

{% jsfiddle https://jsfiddle.net/chr314/eowcfbk1/4/ %}

In the content script using `chrome.runtime.onMessage.addListener()` we can listen for the messages

Here we see how our message to increase the font size is handled

```js
chrome.runtime.onMessage.addListener(msg => {
    if (msg.action === "font-size-decrease") {
        changeFontSize(-1);
    }
    if (msg.action === "font-size-increase") {
        changeFontSize(1);
    }
});

function changeFontSize(change) {
    let elements = document.querySelectorAll("*");
    let newFontSizes = [];
    for (let x = 0; x < elements.length; x++) {
        newFontSizes.push((parseFloat(window.getComputedStyle(elements[x]).getPropertyValue('font-size')) + change) + 'px');
    }
    for (let x = 0; x < elements.length; x++) {
        elements[x].style.fontSize = newFontSizes[x];
    }
}
```


# Result

![gif](https://media.giphy.com/media/QYRo03OSTuHbbrUPKu/giphy.gif)

# Source Code

For now this extension have 3 tools font size, grayscale, invert colours

You can contribute and add more tools :)

{% github chr314/accessibility-extension %}