Thursday 10 November 2011

Creating extension in chrome


What You Need to Know Before You Start

If you're comfortable putting together a web site—that is, you know a little HTML and are familiar with JavaScript—you can make a Chrome extension. If you're new to HTML and JavaScript, my beginner's guides for learning to code and how to make a web site are great starting points.
Beyond those two core competencies, there's really nothing special you need to know. Chrome extensions are delightfully easy to make if you've ever spent any time making web pages or hacking away with JavaScript, and even if you're only a beginner in those arenas, you can probably pull off a Chrome extension. So let's do just that.


Manifest.json: The Cornerstone of Your Chrome Extension

Every Chrome extension consists of, at minimum, a file called manifest.json, which defines the basics of your extension—its name, description, version number, what kind of extension it is (there are a handful of different things a Chrome extension can do, which we'll talk more about below), the permissions it needs to run (e.g., what web sites it needs access to), and so on.
So let's get started. Create a new folder—let's name it Hello World—and, using your favorite text editor, create a new text file called manifest.json. Copy and paste the following code into it:
{
  "name": "Hello World!",
  "version": "1.0",
  "description": "My first Chrome extension.",
  "browser_action": {
    "default_icon": "icon.png"
  }
}
The name, version, and description are all pretty self-explanatory, but browser_action is something new! The browser_action property tells Chrome that we're making an extension that will add a button to the toolbar. So far, all we've done is assign an icon to that button. Basically you're telling Chrome that your extension has an icon, called icon.png, and that it's located in the same folder as your manifest.json file. Of course, you don't have anicon.png file in your Hello World folder just yet, so let's fix that.
Download this tiny image (via) and copy it to your Hello World folder.
We haven't done much yet, but you've actually already made something you can test out, so let's do that. Point Chrome to chrome://extensions/, tick the Developer mode checkbox at the top-left of that window, then click the Load unpacked extension button. Point Chrome to your Hello World folder, click Select or OK (varies by operating system), Chrome will load up your stub of an extension, and you should see your little globe icon appear in your Chrome toolbar thusly:
If you try clicking your Hello World button, however, you'll notice it does an unsurprising amount of nothing. Let's fix that.

Creating a Browser Action, or, Wouldn't It Be Nice if That Button Did Something?

Open up your manifest.json file and add a popup action that points to an HTML file calledpopup.html, like so:
{
  "name": "Hello World!",
  "version": "1.0",
  "description": "My first Chrome extension.",
  "browser_action": {
    "default_icon": "icon.png",
    "popup": "popup.html"
  }
}
Note: The filenames don't matter as long as you're pointing Chrome to the right files—you could call it helloworld.html in manifest.json as long as you also named your filehelloworld.html.
Speaking of, you now need to create popup.html. So, once again, create an HTML file calledpopup.html and save it in your Hello World folder. Inside popup.html, simply add the text "Hello World!" (In theory you'd want to put some valid HTML markup in there, but it's not strictly necessary, so we're going to skip it here.)
Make sure you've saved manifest.jsonand popup.html, head back tochrome://extensions/, click the expand icon next to the Hello World extension in the Extension list, then click the Reload link (pictured at right).
Chrome will reload the extension using your updated code. Now click the button and get ready for the money shot!
Achievement unlocked! You've Hello World-ed your first Chrome extension. Nice work. Now let's take things up a notch. (If you had any trouble along the way, download my working Hello World.zip and compare it with yours.)

Where Do We Go From Here?

So Chrome can add buttons to your toolbar, you can click those buttons, and something can happen. Neato! You could stop your extension development here and have plenty of fun installing extensions on your friends' computers—add a little HTML image markup in place of the "Hello World!" text and you've unlocked a prankster's delight! Imagine the possibilities. Your unsuspecting friend clicks an alluring new button and—slam, goatse! Or toss in a YouTube video and... RICKROLL! (Or don't do this. Your friends won't thank you, but they might if they knew what you weren't subjecting them to.)
Impressing your friends with your sparkling sense of humor will only take you so far, though. You've probably seen the basic click-button-show-drop-down behavior in tons of different Chrome extensions before. But you've also seen extensions that perform very different tasks. If you take a gander at the Chrome Extension Developer's Guide, you'll see the familiar Browser Actions at the top of the list, but you'll also notice a ton of other things your extension can do, from creating desktop notifications or adding a keyword to the omnibox to creating an options page or performing actions that modify specific web pages. When you're ready to dive deep into extension development, you'll want to page through the developer documentation to get a feel for what your extension might take advantage of. You may also want to take a look at themanifest.json documentation to get a feel for some of your other options available to yourmanifest.json file.
For now, we're going to dive a little deeper into the browser actions. It's time to make yourself an RSS-reading and -notifying Chrome extension. So let's do it.

It's Time to Next Level This Hog

Now that you've safely navigated from zero to Hello World, we're going to pick up the pace a little. The "Hello World" extension didn't use a lick of JavaScript (apart from the JSON), and we didn't actually write any HTML, either. This section will rectify that.
First, let's take a look at the new and improved manifest.json we'll use for this extension:
{
  "name": "RSS Fetcher",
  "version": "0.1",

  "description": "Keep up with the latest from [insert web site here].",
  "icons": { "16" : "images/icon.png",
                        "48" : "images/48.png",
                        "128" : "images/128.png"},
  "homepage_url": "http://insert_web_site_here.com/",
        "background_page": "background.html",
        "permissions": [
          "http://insert_base_rss_url_here.com/*"
        ],
        "browser_action": {
    "default_icon": "images/icon.png",
    "default_title": "[INSERT WEB SITE NAME HERE] Fetcher",
    "default_popup": "popup.html"
  }
}
Let's quickly walk through what's new here.
  • First, you'll notice I've added icons. These are the icons that will display as the extension's icon in various places, including the Extensions page of your browser and in the Chrome Web Store should you decide to distribute your work.
  • homepage_url points to whatever site you want to associate with the extension you've written.
  • background_page is an HTML page that will run in the background constantly, allowing you to maintain a certain state or perform regular actions for different parts of your extension. In our extension, the background page will poll the RSS feed to see if anything new has been pushed to the feed.
  • permissions tells Chrome what special permissions you need access to. Chrome sandboxes extensions so they don't have access to all your browsing activity unless they request it (and you allow it). The permissions property allows you to set exactly what permissions you need. In our case, we need permission to load an RSS feed from a root URL, and we want to be able to create HTML 5 notifications when new items arrive.
You'll have noticed that our manifest.json file also calls for a lot of new files and folders, so instead of requiring you to set them all up yourself, you can download a basic, working version of this code that fetches from the Lifehacker RSS feed here.
(I've decided to include the images I used in the Lifehacker Notifier extension, but obviously you can swap out whatever images work for you.)
You'll also notice that I've included jQuery. If you're unfamiliar with jQuery, it's a JavaScript framework that makes doing a lot of things in JavaScript insanely easier. If you do anything on the web with JavaScript and you're not interesting in rebuilding the wheel and you are interested in saving a lot of time, you should learn to use jQuery. (Also, lucky you! The very cool web site Codeacademy just released an introductory guide to jQuery.)
This all may seem like it got complicated really quickly, but the main difference between our Hello World extension and this more complex RSS Fetcher is actually quite simple: Ourpopup.html file will now contain HTML and some JavaScript. Together, they'll actually do things beyond displaying "Hello World!" every time you click the button.
The other thing sets Chrome extension development apart from your everyday HTML and JavaScript is the Chrome extension APIs, which provide access to all kinds of functions that blur the line between your extension and the browser. So let's try a few basics.

How Our New Popup.html Works

The new popup.html file in our RSS fetching extension works like this: When you click the extension's button, it loads popup.html. When that loads, it passes a call tobackground.html, asking it to fetch our RSS feed. Once background.html has successfully fetched the feed, it passes the feed's XML back to popup.html, which then parses the feed into some friendly HTML, which it then displays inside the popup.

Message Passing Between Background.html and Popup.html

Because of various security sandboxing going on in Chrome, some parts of your extension can't access the same APIs or information that other parts of your extension can. To get around this, one common technique you'll need to employ in your Chrome extensions involves passing messages and data back and forth between different parts of your extension. To demonstrate the basics of how this works, I've put the method that fetches the RSS feed intobackground.html, and I call it from popup.html. In background.html, you'll notice thefetch_feed method:
function fetch_feed(url, callback) {
        var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function(data) {
      if (xhr.readyState == 4) {
        if (xhr.status == 200) {
          var data = xhr.responseText;
          callback(data);
        } else {
          callback(null);
        }
      }
    }
    // Note that any URL fetched here must be matched by a permission in
    // the manifest.json file!
    xhr.open('GET', url, true);
    xhr.send();
}
It's a very basic function that takes a URL and a callback function as parameters, fetches the feed, then passes it to the callback function. To listen to the other parts of your extension, we add this code:
function onRequest(request, sender, callback) {
        if (request.action == 'fetch_feed') {
         fetch_feed(request.url, callback);
       }
}

// Wire up the listener.
chrome.extension.onRequest.addListener(onRequest);
The last line, which uses the wonderfully useful chrome.extension API, tells the page to listen to requests from other parts of the extension. When it receives one, it's going to pass it to theonRequest function. As you can see, the onRequest function then checks to see if the request is asking for an action that it knows how to handle (in this case, a request to fetch a feed), and if it does, it calls that function.
Now let's jump over to the popup.html file. When it loads, the page is entirely empty. This is what kicks off changing that:
$(document).ready(function() {
        fetch_feed();
});
Our fetch_feed method then fires off this request:
function fetch_feed() {
        chrome.extension.sendRequest({'action' : 'fetch_feed', 'url' : 'http://lifehacker.com/index.xml'},
                function(response) {
                        display_stories(response);
                }
        );
}
As you might have guessed, chrome.extension.sendRequest sends out the request to other parts of your extension that may be listening. And as we know, background.html is listening for this exact request! So our request bounces from popup.html to background.html, which fetches the feed, then passes it back to popup.html, which then calls a function calleddisplay_stories, passing with it the response from background.html. The display stories function (which I won't step through here but which you can see in the source) then uses a little jQuery and JavaScript to parse the XML feed and render the stories in the popup.

Do you see how unbelievably easy this is???

I kid. Once you get the hang of it, though, making Chrome extensions actually is very easy, and very fun. (Obviously the complexity varies depending on what you want to make.) If you're comfortable with HTML and JavaScript (oh, and I guess CSS if you want to make it pretty), you can do so much, and the learning curve is pretty gentle. So go forth, intrepid coders, and make thee some awesome extensions!

Troubleshooting

You're great at everything (go you!), but you're going to stumble from time to time, particularly with your JavaScript. You'll find two invaluable tools to help debug. The first is console.log, which is a JavaScript method that writes text, objects, or whatever you pass it to Chrome's JavaScript console so you can catch where things may have gone wrong.
The second is Chrome's awesome Developer Tools—and more specifically, the JavaScript console and DOM inspector. You can pull up the console for your popup by right-clicking your extension's button and selecting Inspect popup. Likewise, you can pull up the Developer Tools for background.html by clicking the background.html link in the expanded view of the extension in chrome://settings/extensions.

Helpful Resources

All of my Chrome extension-building knowledge comes from Google's very thorough documentation and good ol' fashioned World Wide Web searches when I'd get stuck. So you should certainly check out:
  • The Official Google Chrome Extensions Developer's Guide: It's the starting point for everything you need to know, lays our all the various extension APIs you may want to use, and so on. If you know what kind of extension you want to make, I'd highly recommend taking an hour or so, reading through the docs, and taking notes/saving links whenever you stumble upon something that sounds like you'll need it to accomplish your extension goal.
  • Stack Overflow's Google Chrome Extension tag page is filled with great Q&As regarding Chrome extension development. If you're stumped by something, give StackOverflow a search, give the web at large a search, and if you can't find the answer, try posting your question to Stack Overflow. It's awesome.

No comments: