Making Chrome Extensions

Nowadays, we see a large use of browsers on a day-to-day basis. Due to this, browser developers have created support for extensions, which are basically add-ons to the browser, enhance the user's experience. At a very basic level, a Chrome extension is just some HTML, CSS and JavaScript that allows you to add some functionality to Chrome through some of the JavaScript APIs Chrome exposes. An extension is basically just a web page that is hosted within Chrome and can access some additional APIs. Extensions can interact with web pages or servers using content scripts or cross-origin XMLHttpRequest. Extensions can also interact programmatically with browser features such as bookmarks and tabs.This article will be primarily discussing how to make extensions for Google Chrome, but one can easily do so for other browsers as well.

Contents

The Basics

Each extension has the following files:

  • Manifest File - This contains basic information of the app, which lets Chrome know the author, API Key, injected scripts etc.
  • HTML Files - These will be the containers for your Javascript. Unless your extension is a theme, it will have at least one HTML file.
  • Javascript Files (optional) - These would handle the events triggered by the user, and make the app responsive.
  • Others - Resources like image files, fonts, etc.

While you're working on your extension, you put all these files into a single folder. When you distribute your extension, the contents of the folder are packaged into a special ZIP file that has a .crx suffix. If you upload your extension using the Chrome Developer Dashboard, the .crx file is created for you.

Architecture

Many extensions have a background page, an invisible page that holds the main logic of the extension. An extension can also contain other pages that present the extension's UI. If an extension needs to interact with web pages that the user loads (as opposed to pages that are included in the extension), then the extension must use a content script.

The Background Page

The background.html file is to essentialy include any JS code that controls the behaviour of the extension, and needs to run independently of user action. There are two types of background pages, persistent background pages and event pages. The former is always open, whereas the latter only reacts to certain events as defined. Both have their pros and cons, and this link does a good job of explaining what to use when in more detail.

UI Pages

These pages basically contain the extension's UI. Examples include popups, or an options page which customizes the functioning of the extensions (similar to AdBlock). The cool thing about an extensions is that within an extension, all the HTML files can access each other's DOMs,and can invoke functions on each other.

Content Scripts

These scripts are for interacting with the webpage the browser is on.Content scripts can read details of the web pages the browser visits, and they can make changes to the pages. In the following figure, the content script can read and modify the DOM for the displayed web page. It cannot, however, modify the DOM of its parent extension's background page.Think of a content script as part of that loaded page, not as part of the extension it was packaged with

Chrome APIs

In addition to having access to all the APIs that web pages and apps can use, extensions can also use Chrome-only APIs (often called chrome.* APIs) that allow tight integration with the browser. For example, any extension or web app can use the standard window.open() method to open a URL. But if you want to specify which window that URL should be displayed in, your extension can use the Chrome-only tabs.create method instead. This allows for more control over the behaviour of the extension. An exhaustive compilation of the various chrome.* APIs, their supported versions, and usages are available on this link. When going through the list, one will see the terms asynchronous and callback often. These are better explained below -

Synchronous and Asynchronous Methods

In contrast to normal programming methods, chrome.* API methods do not wait for the result of the method before moving on to the next instruction, but instead move on immediately. To access the output data, one needs to define a corresponding callback function, and pass it as an argument to the method.That callback is executed later (potentially much later), sometime after the method returns.
For Example, we consider the signature of the chrome.tabs.create function:

chrome.tabs.create(object createProperties, function callback)

This function would initiate the creation of a new tab subject to some properties, and when it's done, the callback function will be called. In the meantime, the extension is not idle, and continues executing instructions. For a better understanding of synchronous and asynchronous functions, this answer on StackOverflow does a good job of clarifying.

Example: Using a Callback

Say you want to navigate the user's currently selected tab to a new URL. To do this, you need to get the current tab's id (using tabs.query) and then make that tab go to the new URL (using tabs.update).
If query() were synchronous, you might write code like this:

1 //THIS CODE DOESN'T WORK
2 var tab = chrome.tabs.query({'active': true}); //WRONG!!!
3 chrome.tabs.update(tab.id, {url:newUrl});
4 someOtherFunction();

That approach fails because query() is asynchronous. It returns without waiting for its work to complete, and it doesn't even return a value (although some asynchronous methods do).To fix the preceding code, you must use that callback parameter. The following code shows how to define a callback function that gets the results from query() (as a parameter named tab) and calls update().

1 //THIS CODE WORKS
2 chrome.tabs.query({'active': true}, function(tabs) {
3 chrome.tabs.update(tabs[0].id, {url: newUrl});
4 });
5 someOtherFunction();

In this example, the lines are executed in the following order: 2, 5, 3. The callback function specified to query() is called (and line 3 executed) only after information about the currently selected tab is available, which is sometime after query() returns. Although update() is asynchronous, this example doesn't use its callback parameter, since we don't do anything about the results of the update.

Getting Started

What better place to start than Google's own tutorial?(link here). This is a really good tutorial, but does assume one has basic knowledge of HTML and JavaScript.