Eli Grey

GTranslatifier

I have created a very simple Jetpack feature called GTranslatifier that adds a Google Translate icon to Firefox’s status bar for easy access to Google Translate services. Upon clicking the icon, one of the following things happen. If no text is selected in the tab currently being viewed, the page in the browser tab currently being viewed is translated into your native language. If the icon was left-clicked, the translated page will be loaded in the same tab. If the icon was middle-clicked or right-clicked the translated page is loaded in a new tab. If there is text selected in the current tab being viewed, a new tab is opened which has a translation of the selected text. If you are on a page translated using Google Translate, clicking the button will return you to the original page.

Edit Page Jetpack Feature

I have created a Jetpack feature called Edit Page to see what developing a Jetpack feature would be like. As the name implies, it lets you edit any web page in one click. Right clicking on the Edit Page button added to the status bar toggles spellcheck. To change the default spellcheck preference for the Jetpack feature, go to about:config and search for the jetpacks.editpage.spellcheck boolean preference to toggle it. The following is the code I used to implement version 0.1 of the Jetpack feature:

While creating this Jetpack feature, I ran into various quirks in the Jetpack platform:

  • Jetpack features are handled as JavaScript 1.6 and not 1.8 even though Firefox supports JavaScript 1.8. Update: This is due to a Firefox 3.0.x bug that is fixed in Firefox 3.5.
  • An HTML status bar widget added with jetpack.statusBar.append() is a complete HTMLDocument but it doesn’t support any features that involve the id attribute, like document.getElementById() and CSS’s #id syntax. This may be fixable by including a doctype in the HTML (I didn’t because it’s invalid E4X) but the point is that this is an HTML snippet, which should default to some HTML or XHTML doctype.
  • jetpack.notifications.show() doesn’t allow skipping options (passing null or undefined) without falling back on defaults (Prism’s API, platform.showNotification(), allows it). The following code should fix the function to allow this kind of use:
jetpack.notifications.show = function (message) {
    var body = message,
    title = "Jetpack Notification",
    icon = null; // Mozilla favicon is http://www.mozilla.org/favicon.ico
    if (typeof message == "object") {
        body = message.body;
        if ("title" in message) {
            title = message.title;
        }
        if ("icon" in message) {
            icon = message.icon;
        }
    }
    try {
        Components.classes['@mozilla.org/alerts-service;1']
          .getService(Components.interfaces.nsIAlertsService)
          .showAlertNotification(icon, title, body);
        return true;
    } catch (e) {
        console.log("Unable to display notification:", message);
        return false;
    }
};

Jetpack API

Mozilla Labs’ latest creation, Jetpack, is a great way to extend Firefox. It currently has a poorly documented API that doesn’t mention all of the public methods and fields. Due to Mozilla Labs’ decision of not putting the API documentation on MDC or the MozillaWiki, I cannot update the documentation myself. Therefore, I will list all of Jetpack’s documented and undocumented features as of version 0.1.2 in this blog post.

(Not) Assigning Properties

You can’t do things like jetpack.tabs.focused.contentWindow.foo = "bar". I find this much too restrictive, as it hinders a developer’s ability to make an API for a webpage to communicate with a jetpack to do things that need more privileges. Ironically, it seems that jetpacks have full access to Firefox’s XPCOM (Components.*, ect.) which means, with a little hacking, it may be possible to bypass this restriction. The follow code shows an example of getting an nsIAlertsService and using it instead of jetpack.notifications.show.

var body = "Some text",
title = "Notification",
icon = "http://code.eligrey.com/favicon.ico",
 
classObj = Components.classes['@mozilla.org/alerts-service;1'],
alertService = classObj.getService(Components.interfaces.nsIAlertsService);
 
alertService.showAlertNotification(icon, title, body);

(more…)