Firefox Mobile – Managing Profiles

Last week we were talking about the need for private browsing, or something like it, in Firefox Mobile. Even though you might not share your phone with other people, you might share a tablet – especially the “family tablet”, sitting there on the coffee table. Private browsing is an obtrusive system, at least as implemented in Mozilla, and it’s doubtful we could add it for Firefox Mobile in time for the upcoming release. Also, private browsing doesn’t really satisfy the sharing use case for tablets.

Firefox has the concept of profiles, which could be useful for sharing. From the Firefox Support site:

Firefox saves your personal information such as bookmarks, passwords, and user preferences in a set of files called your profile, which is stored in a separate location from the Firefox program files. You can have multiple Firefox profiles, each containing a separate set of user information. The Profile Manager allows you to create, remove, rename, and switch profiles.

The built-in Profile Manager, used in desktop Firefox, isn’t really a good fit for mobile, so I made a simple, restartless add-on for managing profiles in Firefox Mobile, called Mobile Profiles. From the Preferences panel, you can add, remove and switch profiles.

I’m thinking about adding support for password protecting profiles and clearing private data when closing Firefox. Let me know what you think.

Development Details

I found the restartless, bootstrapped system I have been playing with worked well for this add-on. The nsIToolkitProfileService handles most of the heavy lifting. The UI is a little more complicated than my original trivial example, but I still only have two (2) files in my XPI. View the source here.

Without XUL overlays, I had to add the UI using DOM operations (createElement and setAttribute). Not a big deal, but it got tedious, so I made a little helper function:


function $x(aDocument, aElement, aAttributes) {
  if (typeof(aElement) == "string")
    aElement = aDocument.createElement(aElement);
  for (attribute in aAttributes)
    aElement.setAttribute(attribute, aAttributes[attribute]);
  return aElement;
}

Using this helper means adding elements via DOM is a little less syntax:


let itemManage = $x(window.document, "setting", {
  "id": "prefs-mobileprofiles-profiles",
  "title": "User Profiles",
  "desc": "Add, remove or switch profiles",
  "class": "setting-group",
  "type": "control"
});

I could probably make the helper function be a little more useful by adding some features you’d find in HTML DOM builders, but it’s good enough for now. I’ll probably add a chrome.manifest so I can support normal localization using properties files.

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.

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!

Updating Add-ons in Firefox Mobile 1.1

In previous versions of Firefox Mobile, you could check for and install updates for your add-ons by pressing the “Update” button in the Add-ons Manager. This meant that you could check whenever and as often as you wanted, but, if you didn’t really want to manage these things manually, you could find yourself without the latest versions.

Desktop versions of Firefox will prompt you that a new version of an add-on is available. Maybe this prompt is enough for you to actually update the add-on, maybe it isn’t. Maybe you find the whole process annoying and/or boring.

In Firefox Mobile 1.1, we introduce automatic add-on upgrades. Once a day, Firefox will check your add-ons for an update and if an update is found, we download and install the new version. If you’re interested, you can go to the Add-ons Manager and see what add-ons have been updated. If you’re eager to use the new add-on, you can restart. In the future, some add-ons may not even need a restart.

Of course, you can still use the “Update” button to force add-ons to update right away, without waiting for the next automatic check.

If you want to turn off automatic add-on updates, you can use about:config and set extensions.autoupdate.enabled to false. If you’d like to change the timing for automatic updates, set extensions.autoupdate.interval to a different number of seconds.

Firefox Mobile 1.1 Beta 1 and Add-ons

With Firefox 1.1 Beta 1 for Maemo ready to go and the final release not far away, now is an excellent time for add-on developers to update their add-ons. Obviously, Mozilla wants as many add-ons as possible to be compatible with the latest version of Firefox Mobile.

AMO (addons.mozilla.org) is ready for add-ons to set maxVersion to 1.1.*

Please test your add-on before bumping the version. You can use the nightly builds for Maemo, as well as the desktop versions to help test. Here are a few things to keep in mind while testing add-ons:

  • Site Menu: The site menu was redesigned and uses different XUL and JS. If your add-on adds a command to the site menu, please check out the changes and update your code.
  • Context Menu: Long taps (or right clicks on desktop) will display a context menu, but only limited targets are allowed (images, links and mailto: links). If your add-on can benefit form the context menu, use it. But use it wisely.
  • Startup: When starting the browser, the Awesomebar Screen is no longer shown. A true Start Page system is now used. Adjust your add-on startup process if needed.
  • Portrait Mode: Firefox for Maemo (and Android) now supports dynamic portrait/landscape orientation. Make sure your add-on works well in both orientations.
  • Theme Breakage: Check to make sure the add-on is not including the chrome://global/content/global.css stylesheet. It will break the mobile platform CSS. An easy way to see this breakage is to look at the toggle buttons in Preferences UI. If those buttons look like checkboxes, the CSS is broken. This seems to be very common for new add-ons.
  • Check for Errors: When testing the add-on, launch the browser from a terminal and use | fennec –jsconsole | to open the JS Error Console. Make sure no errors appear in the console while testing the add-on.

If you have any questions, please use Mozilla IRC and join the #mobile channel. Use mibbit if you don’t have an IRC client. I’ll be there (mfinkle), as will many other helpful people who can help answer your questions.

Fennec 1.1 Context Menus

Fennec 1.1 now supports context menus. Using a long tap (aka tap-n-hold), or right-click on desktop versions, you can get a context menu to appear.

We intentional designed the context menu system to be simple and minimalistic. We do not want large context menus with many, many commands. Currently, context menus are only displayed if the user long-taps on a link or an image. Technically, not all links will activate the context menu. javascript: links, for example will not activate the context menu.

Fennec 1.1 will only ship with two context menu commands: Open Link in New Tab and Save Image.

Add-ons can extend the context menu. Just overlay the context menu list of commands, which is in the XUL. Each command must have a type attribute and only 3 types are recognized: link, image, mailto.

The context menu system will automatically show/hide commands based on where the user long-taps. Under normal circumstances, the add-on will not need to worry about showing or hiding the context menu command:

  • If an image is tapped, only type="image" commands will be shown.
  • If the element is an image inside a link, both types of commands will be shown.
  • If no link or image is picked, no context menu will be shown at all.

Yes, this is a bit restrictive, but that’s the way we want context menus to work for now. Feedback is always appreciated and Mozilla IRC (#mobile channel) is available to help answer questions.