// writing.browser

All You Need to Know to Get Started with Chrome Extensions

If you perform repetitive tasks on the browser, you may need to build a browser extension. An extension can add features, enhance the functionality of a website, and even remove unwanted elements. For this article, I will delve into the basics of Chrome Extensions by going over the manifest file, content scripts, background scripts, the popup, working with browser storage, and detecting browser events.

Manifest File

Manifest.json is a JSON file that is the backbone of a Chrome extension. The manifest.json specifies all the important information that pertains to the extension. For a Chrome extension, you must specify the manifest version, your extension’s name, and the extension version:

{ 
    "manifest_version": 3,
    // manifest v2 is deprecated
    "name": "My Extension",
    "version": "1.0.1"
}

Optionally, you may specify attributes such as author, description, permissions, and content_scripts.

Content Scripts

Content scripts manipulate the DOM and can be used to modify a webpage, click on buttons, insert new content, or remove content (such as ads). Content scripts can be loaded into a webpage either through the manifest.json file or through the service worker. Manifest.json:

“content_scripts”: [{
    "matches": ["https://somewebsite.com/*"],
    "js": ["content.js"]<
}],

or background.js

chrome.action.onClicked.addListener((tab) => {
    chrome.scripting.executeScript({ target: { tabId: tab.id }, files: ['content-script.js'] });
});

Check out the differences between the two options here.

Background Scripts

The background script is the extension’s service worker and therefore does not have access to the DOM. The background script has storage permissions by default and can execute a variety of commands including navigating to a new page, closing a tab, and it has access to the tab information too. The background script is specified in the manifest.json file:

"background": { "service_worker": "background.js" }

The background script communicates with other scripts through messages. For example:

chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
    if (changeInfo.status === "complete") {
        if (tab.url && tab.includes(“somewebsite.com”)) {
            chrome.tabs.sendMessage(tabId, { type: “doSomething", });
        }
    }
});
The Popup

The popup is the visible content when the user clicks on the extension in the toolbar. The popup may be used to provide information on the extension and allow customization. The popup’s markup language is HTML, it can be styled using CSS, and you can include JavaScript as well. To specify the popup file in the manifest.json:

"action": { "default_popup": "popup/popup.html" }
Working with Browser Storage

You may need to store, retrieve, and track changes to user data. To accomplish this, you can use Chrome’s storage API. Chrome can store the user data in either the session storage or the local storage. You can choose between the two depending on your requirements. Here are some important considerations when making your choice.

Session Storage Local Storage
Limit The storage limit is set to a max of 10 MB. The storage limit is 10 MB, but can be increased by requesting the "unlimitedStorage" permission
Expiry Data is cleared when session ends. Data is only cleared when the extension is removed.
Access Level By default, it's not exposed to content scripts. Is exposed to content scripts and is thus more susceptible to XSS (Cross-Site Scripting) attacks.
Efficiency Session storage is typically faster than local storage. Slower than local storage

Using chrome session storage example:

async function setData () {
    details = { var1: userinput1, var2:userinput2 }
    // note chrome.storage API supports both promises and callbacks
    await chrome.storage.session.set(details)
}

To access session storage from content scripts, you need to set permissions in the background script.

chrome.storage.session.setAccessLevel({ accessLevel: "TRUSTED_AND_UNTRUSTED_CONTEXTS", });

For more information on the chrome storage API, RTFM.

Bonus: Detecting Browser Events

You may need your extension to detect changes in a webpage. The MutationObserver interface provides the ability to watch for changes being made to the DOM tree. To accomplish this, use the constructor: MutationObserver(), which creates and returns a new MutationObserver and it can invoke a specified callback function when DOM changes occur. Say, for example, there is a proceed button on a webpage that is disabled for 30 seconds. To detect when the proceed button on the webpage is no longer disabled and then click on it:

const proceedButton = document.getElementById("proceed-btn");
const observer = new MutationObserver((mutations) => {
    mutations.forEach((mutation) => {
        if ( mutation.type === "attributes" && mutation.attributeName === "disabled" ) {
            proceedButton.click(); 
        }
    });
});

The mutation observer instance has three instance methods: disconnect(), observe(), and takeRecords(). You can use observe to activate the MutationObserver to begin receiving notifications when DOM changes occur. For example to observe the proceed button:

observer.observe(proceedButton,
    { attributes: true, attributeFilter: ["disabled"],
});

For more info, check out MDN Docs.
With the above introduction, you should now have the basics to start building your chrome extension, and automate the web.

Happy coding!

// back to all writing