Bootstrap Jones – Adventures in Restartless Add-ons

We recently landed some code in Firefox Mobile to better handle restartless (bootstrapped) add-ons. Turns out, Dietrich made a non-Jetpack add-on using the SDK and tried unsuccessfully to install it into Firefox Mobile. In the process of getting everything working, I decided to make a simple restartless add-on we could use as a testcase. It’s a copy of Dietrich’s original add-on, without any SDK usage. I’ve not taken the SDK plunge yet. The experience was interesting, educational and slightly enjoyable. The process of testing the install / uninstall and enable / disable mechanism without a restart left me as giddy as a schoolboy.

I’ve decided to approach any future add-on development using the bootstrapped system. If I find a reason why it’s not possible, them I’ll switch back to the traditional XUL overlay approach. Below is the code from the testcase I created. There are only two (2) files! install.rdf and bootstrap.js. That’s it!

The install.rdf has the basic stuff along with the em:bootstrap flag that turns on the magic. My bootstrap.js file has the basic bootstrap methods, but only two, startup and shutdown, needed to be implemented. I added some code to handle adding and removing my add-on UI on demand. All I do is implement the loadIntoWindow and unloadFromWindow methods. Pretty easy, especially for lightweight add-ons.

Notice how I am using a data: URI for a button image, so I don’t need to package the file and add a chrome.manifest.

Just to be clear, I am not using Jetpack or the SDK. Firefox Mobile doesn’t really support Jetpack yet. This is just a simple bootstrapped, restartless add-on. I’m in the process of using this system for a bigger add-on, so I might need to make some adjustments. I’ll let you know how it goes.

install.rdf




    
        bootstrapdemo@starkravingfinkle.org
        2
        Bootstrap Jones
        1.0
        true
        Mark 'Bootstrap' Finkle
        
            
                {a23983c0-fd0e-11dc-95ff-0800200c9a66}
                4.0b4pre
                4.*
            
        
    

bootstrap.js


var Cc = Components.classes;
var Ci = Components.interfaces;

function loadIntoWindow(window) {
  if (!window) return;

  // Get the anchor for "overlaying" but make sure the UI is loaded
  let forward = window.document.getElementById("tool-forward");
  if (!forward) return;

  // Place the new button after the last button in the top set
  let anchor = forward.nextSibling;

  let button = window.document.createElement("toolbarbutton");
  button.setAttribute("id", "tool-homebutton");
  button.setAttribute("label", "Home");
  button.setAttribute("class", "button-control");
  button.style.listStyleImage = "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAo0lEQVR42u3VMQrCMBSA4Q7uOnsNB4%2FR0cM6ZPYyyRRIGhAzly5CNQrfD49Alhe%2BJdMkSZIk6d1ijMdSyryelNJp710hhMPWrpzzeRjAsiyX1tpzPf3%2B%2BgnsrV211hsAAAAAAAAAAAAAAAAAAAAAAACA0QDfHAAAAPweQH%2FUo5%2F3PafvCn4BAAAAAAAAAAAAAAAAAAAAAAAAAADGAkiSJOmPewEpGDS2TaImnAAAAABJRU5ErkJggg%3D%3D)";

  button.addEventListener("click", function() {
    window.Browser.loadURI("about:home");
  }, false);

  anchor.parentNode.insertBefore(button, anchor);
}

function unloadFromWindow(window) {
  if (!window) return;
  let button = window.document.getElementById("tool-homebutton");
  if (button)
    button.parentNode.removeChild(button);
}

/*
 bootstrap.js API
*/

var windowListener = {
  onOpenWindow: function(aWindow) {
    // Wait for the window to finish loading
    let domWindow = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
    domWindow.addEventListener("load", function() {
      domWindow.removeEventListener("load", arguments.callee, false);
      loadIntoWindow(domWindow);
    }, false);
  },
  onCloseWindow: function(aWindow) { },
  onWindowTitleChange: function(aWindow, aTitle) { }
};

function startup(aData, aReason) {
  let wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);

  // Load into any existing windows
  let enumerator = wm.getEnumerator("navigator:browser");
  while (enumerator.hasMoreElements()) {
    let win = enumerator.getNext().QueryInterface(Ci.nsIDOMWindow);
    loadIntoWindow(win);
  }

  // Load into any new windows
  wm.addListener(windowListener);
}

function shutdown(aData, aReason) {
  // When the application is shutting down we normally don't have to clean up any UI changes
  if (aReason == APP_SHUTDOWN) return;

  let wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);

  // Stop watching for new windows
  wm.removeListener(windowListener);

  // Unload from any existing windows
  let enumerator = wm.getEnumerator("navigator:browser");
  while (enumerator.hasMoreElements()) {
    let win = enumerator.getNext().QueryInterface(Ci.nsIDOMWindow);
    unloadFromWindow(win);
  }
}

function install(aData, aReason) { }

function uninstall(aData, aReason) { }

Firefox Mobile – A Few Add-ons

In addition to working on Firefox Mobile, I like to tinker around with building add-ons too. Not surprising I guess, since I seem to go on and on about how to build them.

Anyway, I have a few add-ons that you might find useful – either installed in Firefox Mobile or as examples you can rip apart and use to build your own add-ons.

Mobile Tools

Mobile Tools is a collection of a few utilities that might be useful when debugging mobile webpages. You’ll find commands for viewing page source and basic page info. Both open in new tabs. Page source shows the web page’s raw HTML content. You can zoom and pan through the source just like any other web page. Page info shows some simple bits of information about the web page:

Mobile Tools also supports window.console a little better than the built-in native support, including:

  • String formatting in logging methods (%s, %d, %i, %f)
  • dir and dirxml
  • Simplified trace
  • group and groupEnd
  • time and timeEnd

Start Page Plus

The built-in start page, Firefox Start, is pretty, loads fast and has some nice features. We can always add more! Start Page Plus adds a few sections to the standard Firefox Start page:

  • Favorites: A list of bookmarks you want displayed on the start page. Just tag a bookmark with “start” and it appears on the start page.
  • Local Search: Quickly find various types of places near you with a simple tap. Includes food, hotels, gas, movie theaters and your own location – shown on Google Maps. This feature does use the built-in geolocation feature.
  • Local Twitter: Shows tweets happening near you. You don’t need to be logged into Twitter. The stream is based on your location.

Use the add-on options to show and hide sections as well as move them around the page. You can also set the zone used to pull in tweets from Twitter.

Firefox Mobile and window.console Support

Desktop Firefox added native support for a subset of the window.console API. It’s a subset in that only the following API methods are supported:

  • console.log(arguments)
  • console.info(arguments)
  • console.warn(arguments)
  • console.error(arguments)

Also, the Firebug string formatting features are not supported yet.

Last night we turned on basic support in Firefox Mobile too. It’s basic in the sense that the window.console is merely forwarded to the Error Console.

Mobile Add-on Development

I was part of this year’s Add-on Con event, presenting some information on building add-ons for Firefox Mobile. Learning how to work in multiple processes can be tricky at first, but once you get used to working with messages, it gets easier. The information was also relevant for Firefox Desktop, since multiple processes will show up there in a future release. Felipe Gomes is working very hard on getting that project jump started.

In addition to the presentation, I made some video tutorials on building Firefox Mobile add-ons, including a multi-process add-on. Fellow Mozillian, Sara Yap, encouraged me to add some code to the page to allow subtitling. I am excited to see how that works out.

Mozilla is currently running a contest for mobile add-ons – The Firefox Mobile Add-ons Cup. Get your add-on entered as soon as possible. Join Mozilla IRC (#mobile or #mobileaddons) if you have questions about building your add-on.

Firefox Mobile keeps getting better and better. I recently acquired a Samsung Galaxy Tab and I have to say, Firefox is awesome on the Tab.

Add-on Training at Add-on Con

I’ll be taking part in the Training Day portion of Add-on Con this year. Firefox Mobile has made the jump to a multi-process architecture and many aspects of add-on development have changed. Sure, this could be a little scary. Yes, you will need to learn some new tricks. Of course, we’ll be here to help you. My session at Add-on Con will be all about building add-ons that work in a multi-process architecture.

As a developer on the Front-end team of Firefox Mobile, I can tell you that we had to go through the same kind of code changes. Check out some documentation we have for working with multi-process. I’ve also started to build some video tutorials on the subject too. They won’t win any Oscar’s, but might give you a better understanding of what’s changing.

Even if building add-ons for Firefox Mobile isn’t your cup of tea, it’s probably a good idea to pay attention. Rumor has it that desktop Firefox is moving to multi-process soon too.

Hope to see you at Add-on Con. Don’t forget the Mozilla Party!

Fennec 4.0 – New and Notable

Just Too Damn Good to be a Version 2.0

in case you haven’t heard yet, Firefox for mobile (Fennec) is bumping it’s version numbering to more closely match desktop releases of Firefox. This means “Firefox 2.0b1 for Android & Maemo” is becoming “Firefox 4.0b1 for Android & Maemo” and will be released as “Firefox 4 for Android and Nokia N900“. We are aligning mobile Firefox and desktop Firefox since the web rendering engines used in both browsers are the same. Treating them as the same version seemed like the right thing to do.

Any add-ons hosted on addons.mozilla.org (AMO) that are marked as compatible for Fennec 2.0b1pre will automatically be bumped to support Fennec 4.0b1pre. If your add-on worked in Fennec 2.0b1pre, it will work fine in Fennec 4.0b1pre.

Goodbye Tiles, Hello Browser

Desktop Firefox uses a XUL to display web content. The user manipulates the browser element when clicking, scrolling, dragging or typing. The same was not true in Fennec. In order to achieve acceptable panning and zooming performance, Fennec 1.0 started using a set of tiles to render the web content – which was still loaded into hidden elements. It was a complex system with many quirks to go along with the performance improvements.

Thankfully, a lot of platform work in graphics, layout and multi-process has happened since Fennec 1.0 and recently we removed the tiles and switched back to use only elements to render web content. The front-end code is much cleaner and more simple. In addition, it’s much faster than the previous code so panning and zooming are even better than before.

Go try a nightly release for yourself: Android or Maemo

Note to the faint of heart: Nightly release contain bugs – don’t be frightened when you encounter them. Tell us about them instead!

Fennec 2.0 – New and Notable

It’s been a while since I posted about news things happening in Fennec and now I have a backlog! Let’s jump right into the list of new features you’ll find in the Fennec 2.0 nightlies:

  • Awesomescreen: The Awesomebar Awesomescreen redesign merges the existing Search and Bookmark UIs while adding History and Desktop (via Sync) into a single UI. It’s part of our goal to keep data close to you when you need it. The Awesomescreen is all about helping you navigate to the pages you want, as fast as you can.
  • Moved Search Providers: The list of search providers was moved from the bottom of the Awesomescreen results to a button on the right side of the URL bar. This was done to maximize the available space fro the Awesomescreen results.
  • SiteMenu and ContextMenu APIs: We made it a lot easier for add-ons to extend the SiteMenu and ContextMenu by adding real APIs around the functionality.
  • Awesomescreen Badging: We added the ability to “badge” URLs shown in the Awesomescreen with helpful meta data, like unread inbox counts. We also added an API to the feature so add-ons could add badging to any URL (website), not just the ones we built into Fennec.
  • More Context Menus: We added support for more context menus (long tap menus) in places like Bookmark list, Awesomescreen results and the element in web content.
  • Android Notifications: We use the native notification system on Android for things like downloads, add-on installations and application updates.
  • Right-to-Left Support: We made the Fennec support RTL locales much better than it did, and we also want to make sure we don’t break RTL locales as we land new features.

The Future of JavaXPCOM

This is a public service announcement for those people interested in the future of JavaXPCOM. JavaXPCOM has been disabled and will likely to removed from the Mozilla source tree in the future. See Benjamin Smedberg’s newsgroup post for more details.

Please follow up (add comments) to the newsgroup post.

Fennec 2.0 – Now with Firefox Sync Builtin

The Mozilla Labs team has been working very hard to move the core part of Firefox Sync (nee Weave Sync) into the main Mozilla source repository. They finished a few days ago. Now any Mozilla application can start to use the core features of Firefox Sync without requiring the user to install an add-on. The system is built right into the application.

The Mobile team integrated the basic user interface for Firefox Sync directly into Fennec. Now you can synchronize your tabs, history, bookmarks, form data and passwords – desktop to mobile device and back again – without installing an add-on!

If you’re using a nightly Fennec 2.0a1pre build, take a look in the preferences area for the Sync settings. We’re not finished yet. Plans for Fennec 2.0 include re-organizing the UI for accessing remote-synced tabs.