Hi, my name is Brian Kennish. I'm a developer advocate on the Google Chrome
team. And I'm going to show you how to build Google
Chrome Extensions. We'll start out with an overview of extension
building. Then, we'll walk through some code and put
together an example step by step. But before we get to the technical stuff,
let's talk about what extensions are. Google Chrome Extensions are mostly small
programs that add bits of functionality to Google Chrome.
They install instantly without a browser restart. And, like Google Chrome, they update silently
when new versions are available. We designed the extension system with web
developers in mind. If you can create webpages, you know pretty
much all you need to know to create Google Chrome extensions.
In fact, extensions are implemented with nothing but standard web technologies -- HTML, CSS,
JavaScript, and so on. An extension is a compressed directory -- a
signed zip, to be exact -- with a bunch of web files in it.
The one file every extension has to have is a manifest file.
It's also the one file that has to have a particular name, which is "manifest.json".
As the name implies, the manifest file is JSON-formatted data -- specifically, metadata
that describes the extension, lists permissions, and points to the extension's other components.
Those components are what give the extension its functionality.
An extension includes one or more of the following components.
Browser actions and page actions are the two UI surfaces the extension system ships with
initially. A browser action appears in the toolbar of
every tab. A page action selectively appears in the omnibox
and can be toggled on or off for each tab. An extension can only have one UI surface
or the other. We'd like to encourage extension developers
to be as minimal in their design decisions as the Google Chrome team is.
Content scripts are arbitrary CSS and JavaScript that are injected into selected pages.
They're similar to user scripts and can be used as a UI alternative to browser and page
actions. Background pages are long-running scripts
that help you manage state and coordinate tasks across extension components.
As an extension gets more complex, it tends to need a background page.
In addition to these components that are specific to Google Chrome Extensions, you can bundle
any other web files with your extension -- images, JavaScript libraries, Flash movies, whatever
it is your extension needs. The extension API is small and easy to learn.
It currently defines about 40 objects and 40 methods.
"chrome" is the name of the top-level object automatically exposed to all extensions.
The API is split into six modules, which are represented by objects contained in the "chrome"
object. "chrome.extension" has properties and methods
that let you send messages to communicate between extension components and resolve the
URLs of extension files. "chrome.browserAction" lets you set the appearance
of browser actions and their badges, which are mini text areas overlaid on browser actions.
"chrome.pageAction" lets you enable and disable page actions.
"chrome.windows" lets you open, close, look up, and update browser windows.
It requires "tabs" permission in your manifest file.
That's not a typo -- windows and tabs are so closely related they share a common permission.
"chrome.tabs" lets you perform the same actions on tabs.
It also requires "tabs" permission. And "chrome.bookmarks" lets you read from
and write to the user's bookmark tree and requires "bookmarks" permission.
Now, let's try this stuff out by iteratively developing an extension.
Our extension will be a Google Chrome Twitter client, which we'll call Chritter.
First, we'll give the extension a basic, “hello world”-type UI.
Of course, we need a manifest file. In it, we specify the extension's name, version
number, description, and icon. For the UI part, we're going to pick a browser
action because, well, we want our tweets handy at all times!
We populate the browser-action fields with an icon that will appear in the toolbar, a
tooltip that will appear when the user mouses over the icon, and a popup bubble that will
appear when the user clicks on the icon. For now, the popup is a trivial HTML file.
After installing our extension, we get -- as advertised -- an icon, a tooltip, and a popup.
The popup asks: "Wouldn't it be nice to see some tweets here?"
And I think it would be nice, so let's add some!
We'll do so by fetching Twitter's public timeline with XMLHttpRequest.
Back in our manifest file, we ask for permission to make cross-origin requests to twitter.com
so we can access Twitter's API. We ask for "tabs" permission, as well, so
we can open UI links in new tabs. And in our popup file, we beef up the HTML
by inserting a title and a template to present the attributes of each tweet -- a link to
the user's profile, their image and name, and the tweet itself.
We also have new JavaScript for retrieving and displaying the timeline.
When the load event fires, we run an "init" function to grab references to the different
template elements via XPath. That function hands control over to another
function to do the XHR work. "getTweets" issues a simple request for a
JSON feed, and in turn, hands control over to the callback function "processTweets".
The processing function deserializes the incoming JSON using V8's builtin JSON support and stores
the result in an array. Iterating through the array of tweets, the
"update" function assigns each template attribute and appends the marked-up tweet to the popup.
Our extension has a lot more going on now, with a polished UI and the most recent public
tweets to show off. Our implementation isn't ideal, though.
As a last step, let's improve the extension's performance and functionality by refactoring
our code. Namely, we should turn our popup into a dumb
view so it only knows how to update its display and offload the rest of the work to a background
page. We'll go ahead and add a background page to
our manifest. Then, we can strip the XHR code out of our
popup. In place of that code, we throw in a reference
to the background page, which is returned by the "getBackgroundPage" method.
The popup doesn't collect tweets anymore, so we use the background reference to iterate
through the available tweets instead. We move the XHR code to its new digs in the
background page, but not without a couple upgrades.
I mentioned we could improve performance and functionality and here's where we will.
Since the background page isn't tied to any DOM event, the page can fetch tweets on a
continuous loop. That way, we can batch tweets up and have
them ready before the user even invokes the popup.
We specify a frequency for fetching -- 10 seconds for demo purposes -- and manage the
process with the "setInterval" method. While we're at it, we can also spiff up the
UI. We now have a variable number of batched tweets,
which is a perfect candidate for display with a browser-action badge.
We style the badge with "setBadgeBackgroundColor" and pass in the number of unread tweets with
"setBadgeText". Our extension doesn't look a whole lot different
right away. But if we let it think for a bit, we see a
badge that dynamically updates the tweet count. The popup should work identically, although
we potentially have a lot more tweets to scroll through now.
While this version of Chritter makes for a nice toy, there are some features we'd want
to add for it to be truly useful. On the top of that list would be incorporating
the user's friend timeline -- rather than the public timeline -- which would require
baking OAuth into the extension. Things can get a little hairy there.
Luckily, we've already done the heavy lifting for you and have an example of Chritter with
OAuth support. We also have a further example that handles
custom autoupdating. To download that code, the code you just saw,
and more, go to code.google.com/chrome/extensions. Thanks for watching and have fun building
Google Chrome Extensions!