Just this week one of our intern heros, Shilpan Bagat landed a fancy new addon API for people in Fennec that we’re calling “page actions”. Essentially, they’re clickable indicators in the urlbar, a lot like what Desktop Firefox already has.

The API is pretty simple, so I thought it would be funner to show an example add-on using it here instead. So this is a short tutorial on adding a refresh button to the urlbar in Fennec. To start, we just have to fork the awesome skeleton add-on put together by mfinkle a bit ago (we’re going to update the skeleton with an example of pageactions soon too).

The skeleton has a pretty simple config file that we need to fixup with our add-on’s info, config_build.sh:

APP_NAME=“Refresher”

CHROME_PROVIDERS=

CLEAN_UP=1

ROOT_FILES=”bootstrap.js icon.png“

ROOT_DIRS=“chrome”

BEFORE_BUILD=

AFTER_BUILD=

PUSH_TO_DEVICE=1

ANDROID_APP_ID=org.mozilla.fennec

I bolded the bits I had to change. Namely, I added a name and an icon in the root directory (I added icon.png by stealing the current Fennec reload icon). I also needed an icon to show in th e urlbar, so I created a chrome directory. Finally, this API is only available in nightly builds, so I had to change the build script to install in Nightly instead of release Firefox. You don’t actually have to use that, or the adb install scripts. You can just host your add-on on a site (or even a dropbox account), and install from there. But its a nice quick turnaround if you do have adb installed.

I also updated install.rdf with my addon info, and added a chrome.manifest file:

content refresher chrome/

(there’s some sort of bug in the chrome resolveGeckoURI that doesn’t like chrome skins, I’m filing a bug to look into that). The meat of the addon is pretty simple. I removed everything in the skeleton addon between the isNativeFennec function and the windowListener.

We already have a refresh button on tablets, so I threw together a quick function to verify we’re not on a tablet:

function isPhone(window) {

return !window.BrowserApp.isTablet;

}

We also want to store our pageaction id, somewhere. Since we’re pretty isolated here in bootstrap.js, I just added a global to hold this. If you are doing something complex, its probably best practice to encapsulate this somehow:

var refreshItem = null;

In the loadIntoWindow function then, I want to register our page action. I’ve lucked out and picked something easy here. We can just add the page action here and never have to worry about updating it (until uninstall). For a more complex page action, you might listen to page loads, and update the action based on the url (for instance, we’re planning to add a page action for “Open in an app!”).

function loadIntoWindow(window) {

if (!window)

return;

if (isNativeUI() && isPhone(window)) {

refreshItem = window.NativeWindow.pageactions.add({

// This title is only shown if more than 2 page actions are shown and we overflow into a dropdown menu. This should be localized.

title: “Refresh”,

// An icon to show in the urlbar. Note, the resolveGeckoURI function here shouldn’t be necessary soon.

icon: window.resolveGeckoURI(“chrome://refresher/content/refresh.png”),

// function called when your icon is clicked

clickCallback: function() {

const reloadFlags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;

BrowserReloadWithFlags(window, reloadFlags);

},

// function called when your icon is long pressed. this will only work if you’re showing as an icon right now, and even then its not discover-able to anyone. You have no control over whether you icon is shown in overflow or not, and you should NOT rely on this.

longClickCallback: function() {

const reloadFlags = Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY | Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE;

BrowserReloadWithFlags(window, reloadFlags);

}

});

}

}

Finally, we need to do the actual reload. I stole this little tidbit from desktop Firefox’s reload logic:

function BrowserReloadWithFlags(window, flags) {

var webNav = window.BrowserApp.selectedTab.browser.webNavigation;

try {

var sh = webNav.sessionHistory;

if (sh)

webNav = sh.QueryInterface(Ci.nsIWebNavigation);

} catch (e) {

window.console.log(“error getting session history ” + e);

}

webNav.reload(flags);

}

Finally, when the addon is uninstalled, we need to remove our icon using the pageactions.remove api

function unloadFromWindow(window) {

if (!window)

return;

if (isNativeUI() && refreshItem)

window.NativeWindow.pageactions.remove(refreshItem);

}

Pretty simple! Once you’ve gotten your head wrapped around mobile development, its pretty easy to do nice stuff. We’ve added a few more API’s recently that I’m going to try and blog about soon (with companion neat-o addons where I can), but we’re really interested in what you can do with them, what you think you need, and how we can make the whole process easier.