Blog


Simple Extensions in Firefox 3

It was fascinating to watch the unveiling of Firefox 3 last week. I'm pleased that, in some small way, my contributions helped to bring this browser out the door.

Firefox 3: Download Day Results

First 24 hours: 8.3 million downloads, 69 downloads/second, 20 Gb/s Peak Transfer

While I generally focus on issues tangential to JavaScript code, at Mozilla - like testing, performance analysis, specifications, standards, bug hunting, speaking, demos, and blogging - some of my code is live within the browser, and that makes me quite happy.

One of my first tasks at Mozilla was to, with Mark Finkle, develop a JavaScript API for performing common interactions typically desired by extension developers, called: FUEL. This is a pure-JavaScript implementation that sits as a proxy inbetween the developer and the various, traditional, XPCOM-style ways of performing actions.

If you're interested in learning more about FUEL I've collected a number of links and examples:

The Development of FUEL

FUEL was created over the course of a couple months, in early 2007, by Mark Finkle and I. Mark had much-better knowledge of Mozilla's APIs and I had good knowledge of JavaScript and API design - the match worked out nicely. I've written a couple blog posts on FUEL and so has Mark.

You can also see the features and code that went into FUEL 0.1 and FUEL 0.2 in Bugzilla.

FUEL, Today

Today FUEL lives in Firefox 3 (meaning that you can use it to develop Firefox extensions) and is part of the core Mozilla platform (meaning that portions of the API will be available in any Mozilla-based application that is built). For example you can even use a FUEL-like API in Thunderbird (called 'STEEL'). Here are some of the best resources for getting started with FUEL in Firefox 3:



Here are some of my favorite example of FUEL in action. It was very important to me that the most-common actions take no more than a single line of code to perform - with even complex actions keeping nice and trim.

Open, and activate, a new tab pointing to Google.com

Application.browser.open("http://google.com/").active = true;

Close the active browser tab

Application.browser.activeTab.close();

Close all tabs that mention Google

Application.browser.tabs.forEach(function(tab){
  if ( tab.url.match(/google/) )
    tab.remove();
});

Add a new bookmark pointing to Mozilla

Application.bookmarks.add("Mozilla", "http://mozilla.org/");

Remove all bookmarks pointing to Google.com

Application.bookmarks.all.forEach(function(cur){
  if ( cur.url.match(/google.com/) )
    cur.remove();
});

FUEL, Future

Development is still going strong on FUEL. There's a Google Summer of Code student working on extending the API and porting it to more parts of the platform (along with backwards support for Firefox 2!). We'll probably end up seeing this in Firefox 3.1 (the next version of Firefox, due out later this year).

If you have any questions concerning how to use FUEL, or to develop Firefox extensions in general, your best bet would probably be to join the #extdev IRC channel on irc.mozilla.org. Lots of knowledgeable people hang out there and will be more-than-capable of answering any questions that you might have.

Once again, I'm terribly excited by the final release of Firefox 3 - here's hoping to many more excellent releases to come!

Tags: extensions, firefox, mozilla, javascript

Fuel 0.2 Progress

In case you missed it, Fuel 0.1 recently landed in Firefox 3.0a4.

Fuel 0.1 focused on building a solid foundation for further development; laying a good application and events layer, and building out Preference management. Much of our original plan was scaled back due to the nature of how JavaScript APIs need to be written using XPCOM and IDLs. In a nutshell: Dynamically-generated properties are out, as are optional arguments, and arguments that contains non-primitive objects (arrays, objects, regexps, etc.).

The plan for Fuel 0.2 is pretty well defined at this point. We're on track to have it land in Firefox 3.0a5.

Specifically, Fuel 0.2 is going to be dealing with two things: Browser tabs and Bookmarks. We have a fairly-complete version of the Fuel 0.2 API up, this will be on top of the existing Fuel 0.1 API.

If you're curious what this new code is going to look like, here's some examples from our current plan:

NOTE All of the following is subject to change - please view the final plan and API before attempting to use.

Browser

Open, and activate, a new tab

Application.browser.open("http://google.com/").active = true;

Open, and activate, a tab just after the current tab

var tab = Application.browser.open("http://google.com/");
Application.browser.insertBefore( tab, Application.browser.activeTab.next );
tab.active = true;

or:

var tab = Application.browser.open("http://google.com/");
tab.index = Application.browser.activeTab + 1;
tab.active = true;

Move the active tab to be the first tab

Application.browser.insertBefore(
  Application.browser.activeTab,
  Application.browser.tabs[0]
);

or:

Application.browser.activeTab.index = 0;

Close the active tab

Application.browser.activeTab.close();

Do something when the active tab loads

Application.browser.activeTab.events.addListener( "load", function(){
  this.query("#foo div")
});

Change the URL in the active tab

Application.browser.activeTab.url = "http://mozilla.org/";

Close all Google-related tabs

Application.browser.tabs.forEach(function(tab){
  if ( tab.url.match(/google/) )
    tab.remove();
});

Re-use a tab, or open a new one

var url = "http://google.com/";
Application.browser.tabs.some(function(tab){
  if ( tab.url == url )
    return tab.active = true;
}) || Application.browser.open( url ).active = true;

Stop the user from opening any new tabs

Application.browser.events.addListener( "TabOpen", function(e){
  e.target.close();
});

Bookmarks

Log the title of all top-level bookmarks:

Application.bookmarks.all.forEach(function(cur){
  console.log( "title", cur.title );
});

Add a new bookmark:

Application.bookmarks.add("Mozilla", "http://mozilla.org/");

Remove all bookmarks that point to Google:

Application.bookmarks.all.forEach(function(cur){
  if ( cur.url.match(/google.com/) )
    cur.remove();
});

Add a new bookmark, if one doesn't already exist:

var url = "http://google.com/";
Application.bookmarks.all.some(function(cur){
  if ( cur.url == url )
    return true;
}) || Application.bookmarks.add( "Google", url );

If you're interested in tracking our progress on Fuel 0.2, feel free to CC yourself on the tracking ticket for it. If all goes well, this should be in your hands by the time the Firefox 3.0 betas are rolling out. I'm really excited to see some new applications come out that are built on this code.

Tags: javascript, extensions, firefox, mozilla, programming, fuel

Hacking Digg With Firebug and jQuery

This is an adaptation of a presentation that I gave while at Mashup Camp Boston. We're going to take an introductory look at the Firebug Firefox Extension and the jQuery JavaScript Library - combining the two to build a reusable bookmarklet that can manipulate Digg Posts and Comments.

Click video to begin (14:39 Minutes long, 59MB):


Download: Right-click this link and select Save As... in order to download a copy of your own. (59MB)

Bookmarklets:
In the presentation, I refer to a bookmarklet that you can use to introduce jQuery into a web page. Drag these bookmarklets to your Bookmark toolbar to use them.

  1. » jQuerify « - Introduce jQuery into any web page.
  2. » Fix Digg « - The final bookmarklet that we made to remove all buried comments from a Digg post.

Related Links:

If you enjoyed this screencast, don't forget to Digg it up!

Update: If you wish to use Greasemonkey instead of a bookmarklet, then by all means, please do so. You can use the ability to quickly analyze and inspect a page that Firebug and jQuery affords you, using the results to build a Greasemonkey script, instead of a simple bookmarklet. I only really intended this to be a quick introduction to the subject, so please feel free to explore it more!

More Tips: Here are some more jQuery selectors that you can use on a Digg Post:

  • $("li.c-bury > div").remove(); - Remove all buried comments, but none of the direct replies.
  • $("div.c-body").show(); - Show all comments, even ones that've been buried.

Tags: firefox, bookmarklets, programming, extensions, javascript, jquery, firebug, digg, mozilla

Serious Greasemonkey Security Problems

If you haven't been keeping up on the recent security concerns with Greasemonkey - now's a good time to jump in. I had no idea that the problems where 'that bad' until today. I assumed that it was only possible to do something malicious within a user script, not outside of it (due to bad scoping issues). At least, until, this post caught my eye.

Uninstall Greasemonkey altogether. At this point, I don't trust having it on my computer at all. I would think that whoever is in charge of addons.mozilla.org should immediately remove the Greasemonkey XPI and post a large warning in its place advising people to uninstall it. --Mark

Backtracking through the entire security thread brings up quite a few serious problems. Currently, it's possible to do the following things:

Do not fear! - Headway is already being made. The main concern is that it's possible to access all of the above data outside of a user script's scope. Once this is resolved (and the afformentioned hack may just do that) then Greasemonkey will be back on the fast-track.

Tags: bugs, greasemonkey, firefox, extensions, security

Current Projects

jQuery JavaScript Library

jQuery

Comprehensive DOM, Event, Animation, and Ajax JavaScript Library.

Recent Projects

Pro JavaScript Techniques

JavaScript Book

The best techniques for professional JavaScript. Published by Apress.


Hosting provided by the cool dudes at Engine Yard.