Writing a Google Chrome Extension

Chrome Extensions JavaScript

A couple of weeks ago I released Seesponsive, my first Google Chrome Extension. While it’s not going to win any awards it was a fun project to learn about building an extension.

It lets you see how a website behaves at different screen sizes, and in particular which CSS media queries it uses to control its layout at those sizes.

The Seesponsive action button and the toolbar that is added when it is activated on a website.

The Seesponsive action button and the toolbar that is added when it is activated on a website.

It adds a button (an “action button” in Chrome speak) to Chrome’s toolbar. Click this button and the extension kicks in. It adds a toolbar to the top of the page with two simple actions – Shrink and Grow. They let you animate the screen width that the website sees.

If the website uses media queries to adapt its layout you’ll see them appear in the toolbar as they are matched and unmatched. It’s a simple way to observe how the website behaves, before you dive into the code to see how it hangs together.

For example you can see in the video below that on packdog.com the header video gets replaced with a static image as the page shrinks to mobile device sizes. That can help the page load faster on mobile networks.

But CSS Media queries are a whole other topic in themselves that I’ll cover at a later date. This article is all about building Chrome extensions. I’m going to explain how Seesponsive is constructed and the challenges I faced along the way in getting it to work. At the same time you’ll learn the main building blocks needed to write your own extensions.

A plan of attack

It was pretty easy to come up with the initial plan. I needed to simulate the browser’s window size changing over time in order to have a website’s media queries kick in and have its layout change in front of the user. While the extension could resize the entire browser window dynamically, this would be quite distracting and perhaps quite annoying. Apart from that, I wanted to show additional overlaid information to the user and that wouldn’t be possible if the whole screen shrunk.

So I went with displaying the website in an iFrame. This effectively gives you an encapsulated browser window. When the size of the iFrame changes the web page within it sees a different window size. Throwing together a quick proof I concept I verified that this indeed resulted in different media queries kicking in as I varied the width of the iFrame.

Inspired by this proof of concept I set off to make a fully fledged extension.

The simplest extension

Chrome Extensions are coded in HTML and JavaScript. Each extension has a manifest file (manifest.json) which is simply a configuration file that tells Chrome about the extension and points to the various pieces that make it up. Here’s the first part of Seesponsive’s manifest file:

{
  "manifest_version": 2,

  "name": "Seesponsive",
  "description": "Interactively see how a website's layout changes responsively",
  "version": "1.0",

  "browser_action": {
    "default_icon": "icon19.png",
    "default_title": "Seesponsive"
  },

  // -- snip -- //
}

The first few properties are fairly self explanatory – they describe and version the extension. For now we’re interested in just the browser_action property. This tells Chrome that our extension should have an action button in the toolbar to the right of the Omnibox. You can give the button a title (that gets displayed as a tooltip) and a 19 by 19 pixel icon.

Load the extension with just these properties included and your button magically appears as shown in the previous screenshot.

A brief diversion into packaging

You might have noticed that I’ve glossed over how you actually load your extension. Let’s quickly cover that off. In fact it’s straightforward to load and reload your extension during development.

When downloaded from the Chrome Store your extension is delivered as a cryptograhically signed .CRX archive. That’s great for end users but it would be a pain to have to archive and sign your extension every time you make a change. Luckily Chrome lets you load your extension as an exploded archive during development. It’s as simple as enabling development mode from the Extensions screen and pointing Chrome at your extension’s source folder.

To load an unpacked extension, from the extensions screen enable developer mode and browse to the source for your extensions

To load an unpacked extension, from the extensions screen enable developer mode and browse to the source for your extensions

Once you’ve loaded your extension you can work through the familiar test, edit, reload cycle web development cycle. Some smart souls have even figured out how to get a live reload workflow happening. I’ll cover that in a future article.

A “hello world” button

The next step was to hook up the action button to actually do something. Turns out that’s relatively simple too. Chrome lets you add an event listener to your action button that gets called when the button is clicked. Let’s hook it up to simply log to the console.

// Add a listener to our action button
chrome.browserAction.onClicked.addListener(function() {
    console.log("Hello responsive world!");
});

Note that the chrome namespace is used for all extension related methods.

That all seems pretty easy but where do you stick that code? It’s time to introduce background scripts.

Background and event scripts

Background and event scripts are JavaScript scripts that contain your extension’s code. They run in a separate process and are not linked to a particular tab or browser window. To tell Chrome about your script you use the background property in your manifest file.

{
  // -- snip -- //

  "background": {
    "script" : "event_page.js",
    "persistent": false
  }

  // -- snip -- //
}

The difference between a background script and an event script is that background scripts persist as long as your extension is loaded whereas event scripts are loaded in response to various events and unloaded when no longer needed.

Event scripts are a newer feature and they are preferable in most cases since they minimise the resources your extension consumes. Switching between background and event scripts is simply a matter of toggling the persistent flag in the manifest.

Adding your event listener for the action button to your event script you can finally get your button to respond. Note that the path you provide to your script and other resources is relative to your extension’s root folder.

Next steps

That’s the basics out of the way. In the next part of this series I’ll introduce content scripts which let you inject your own scripts into a web page so that they execute in the same context.