Building Firefox Hub Add-ons for Firefox for Android

The Firefox Hub APIs allow add-ons to add new panels to the Firefox for Android home page, where users normally find their top sites, bookmarks and history. These APIs were introduced in Firefox 30, but there are more features and bug fixes in Firefox 31 and 32. You can already find some of these add-ons on addons.mozilla.org, and there is some boilerplate code on github to help you get started.

image01
image00

Overview

There are two main parts to building a Firefox Hub add-on: creating a home panel, and storing data to show in that panel. Home panels consist of different views, each of which displays data from a given dataset.

Creating a new home panel

To create a home panel, first use the Home.panels API to register a panel. The register API takes a panel id and an options callback function as parameters. This options callback is called to dynamically generate an options object whenever a panel is installed or updated, which allows for dynamic locale changes.

function optionsCallback() {
  return {
    title: "My Panel",
    views: [{
      type: Home.panels.View.LIST,
      dataset: "my.dataset@mydomain.org"
    }]
  };
}

Home.panels.register("my.panel@mydomain.org", optionsCallback);

You must always register any existing panels on startup, but the first time you want the panel to actually appear on the user’s home page (e.g. when your add-on is installed), you also need to explicitly install the panel.

Home.panels.install("my.panel@mydomain.org");

You can modify the options callback function to customize the way data is displayed in your panel. For example, you can choose to display your data in a grid or a list, customize the view that is displayed when no data is available, or choose to launch an intent when the user taps on one of the items.

Storing data for the panel

To actually show something in your new home panel, use the HomeProvider API to store data. This API allows you to asynchronously save and delete data, as well as register a callback to allow the browser to periodically sync your data for you.

The HomeProvider API gives you access to HomeStorage objects, which you can interact with to save and delete data from a given dataset. These methods are designed to be used with Task.jsm to execute asynchronous transactions within a task.

let storage = HomeProvider.getStorage("my.dataset@mydomain.org");
Task.spawn(function() {
  yield storage.save(items);
}).then(null, Cu.reportError);

In Firefox 31, we expanded the save API to support replacing existing data for you, which is convenient for periodically refreshing your dataset.

function refreshDataset() {
  let items = fetchItems();
  Task.spawn(function() {
        yield storage.save(items, { replace: true });
  }).then(null, Cu.reportError);
}

HomeProvider.addPeriodicSync("my.dataset@mydomain.org", 3600,
refreshDataset);

This code snippet will ensure that our dataset is refreshed once every 3600 seconds (1 hour).

What’s new in Firefox 32 Beta

In addition to bug fixes, Firefox 32 also adds a few more features to the set of Firefox Hub APIs.

Refresh handler

In addition to support for periodically updating data, we also added support for “pull to refresh”, which gives users the power to manually refresh panel data. To take advantage of this feature, you can add an onrefresh property to your view declaration.

function optionsCallback() {
  return {
    title: "My Panel",
    views: [{
      type: Home.panels.View.LIST,
      dataset: "my.dataset@mydomain.org",
      onrefresh: refreshDataset
    }]
  };
}

With this new line added, swiping down on your panel will trigger a refresh indicator and call the refreshDataset function. The refresh indicator will disappear after a save call is made for that dataset.

Authentication view

We added support for an authentication view, to make it easier for your add-on to use data that requires authentication. This view includes space for text and an image, as well as a button that triggers an authentication flow. To use this feature, you can add an auth property to your panel declaration.

function optionsCallback() {
  return {
    title: "My Panel",
    views: [{
      type: Home.panels.View.LIST,
      dataset: "my.dataset@mydomain.org"
    }],
    auth: {
     authenticate: function authenticate() {
        // … do some stuff to authenticate the user …
       Home.panels.setAuthenticated("my.panel@mydomain.org", true);
     },
     messageText: "Please log in to see your data",
     buttonText: "Log in"
   }
  };
}

By default, the authentication view will appear when your panel is first installed, and the authenticate function will be called when the user taps the button in the view. It is up to you to call setAuthenticated(true) when the user successfully completes an authentication flow, and you can also call setAuthenticated(false) when a user becomes unauthenticated. This authentication state will persist between app runs, so it is up to you to reset it if you need to.

Future work

We have ideas about ways to expand these APIs, but please let us know if there is anything you would like to see! We’re also always looking for new contributors to Firefox for Android, and we’d love to help you get started writing patches.

About Margaret Leibovic

Margaret is a developer on the Firefox for Android team at Mozilla. She loves the web, open source, and helping people get involved with Mozilla. You can find her on IRC as margaret.

More articles by Margaret Leibovic…

About Chris Heilmann

Evangelist for HTML5 and open web. Let's fix this!

More articles by Chris Heilmann…


4 comments

  1. pd

    Unfortunately, unless I’m very much mistaken, Firefox has practically no market share on Android. Even the dodgy “Android Browser” still had a lot of share but Firefox doesn’t.

    My own personal experience of significant annoying bugs with Firefox on Android suggests people can’t be blamed for not using it. For example, there’s a case where web pages simply do not display anything at all. The tab list has a thumbnail of the page, but select that ‘tab’ displays absolutely nothing but a white background. Even reloading the page doesn’t fix this problem.

    Then there’s the way Firefox on Android destroys sessions and nukes home screen bookmark favicons, replacing them with the Firefox icon, when upgrading. Yippee!

    It’s also way too easy to close a tab from the list that you didn’t actually want to close, yet no visual UI for how to undo that, though I guess at least you can find the same tab/page after clumsily opening a new tab, typing in some sort or string and it appearing in the history.

    All told not a great experience.

    What is Mozilla doing to force Google into giving alternative browsers access to the “Internet” shortcut amongst the precious “Phone | Contacts | Messaging | … | Apps” section of the Android home screen? This is clearly similar, but worse, to Microsoft’s anti-competitive preferential treatment on Windows, back in the day, for Internet Explorer. It’s all very well complaining that developers are using quasi-standard webkit CSS selector prefixes when writing web pages for mobile, but why shouldn’t they when there’s no non-webkit browser on *either* mobile platform? Maybe a little less resources/attention should be devoted to conquering the third world smartphone market share and a little more to influencing the first world browser market share?

    Having finally rooted my Android device, at least I could get rid of the awful “Android Browser” from my phone, including the shortcut down the bottom of the home screen! :) Unfortunately every time Firefox gets too buggy I now have to use Chrome.

    July 25th, 2014 at 03:02

    1. Robert Nyman [Editor]

      To my knowledge, Firefox is the highest rated web browser in the Google Play store with over one million votes. That said, we naturally believe it would be a good thing to reach more users on Android.

      This post is specifically about building panels for the home page in Firefox on Android, though, so I’d like the commenting here to stay on topic.

      For any bug you have in Firefox on Android, please talk to the Firefox on Android support and/or file a bug for Firefox on Android.

      July 25th, 2014 at 10:38

  2. Hu

    Wouldn’t it be interesting to have one common API for all Firefox (Desktop,Android,…) so that we can write those panels once and it could run everywhere. Having this Firefox Hub on the desktop when opening a new tab would be great.

    July 27th, 2014 at 02:15

    1. Margaret Leibovic

      Yes, that would be very interesting! We started developing this as an experimental feature on Android, but we would definitely be interested in working with the desktop team to add similar support to desktop Firefox.

      In the meantime, I imagine someone could write a shim library to add support for these APIs to desktop Firefox. I think that would be a fun exercise for a desktop Firefox add-on hacker, since you would just have to implement your own Home.jsm and HomeProvider.jsm.

      July 28th, 2014 at 07:35

Comments are closed for this article.