Firefox for Android: Using the Android Emulator

Firefox for Android, both the XUL and Native versions, currently requires an ARMv7 CPU. We are looking into adding support for ARMv6, but the ARMv7 limitation had one painful drawback: We could not run Firefox on the Android emulator since it only supported ARMv6.

This is no longer true! The latest version of the Android SDK ships with ARMv7 images for the emulator.

Christian Holler (decoder on IRC) was kind enough to make a wiki page with instructions on setting up the emulator with ARMv7 support. As Christian points out, Firefox does not run at top speed in the emulator, but it’s a heck of a lot better than no “desktop” options at all. Oh yeah, the new native Android UI builds have no desktop counterparts, so the emulator is the only way to run those builds on a desktop machine.

Yes! The emulator runs Ice Cream Sandwich (ICS). Yes! Fennec needs to support the ActionBar on ICS 🙂

Firefox Android: Add-ons in a Native World

One of the first things I yelled about when we were debating switching to a native Android UI for Firefox was add-on support. Using a XUL-based UI meant add-ons were free. The Mozilla platform has support for add-ons baked right in. Moving to a native UI would surely kill our ability to support add-ons, right? Wrong!

Add-ons are an important part of the Firefox story. Native UI builds of Firefox support add-ons. There are some things an add-on developer needs to be aware:

  • The add-ons system is the same one used in other Mozilla applications. We did not invent a new add-on system.
  • Native UI builds are considered a new application and are not add-on compatible with the XUL versions. The application ID for native UI builds is: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
  • There is no visible XUL in the UI, so using overlays to try to add or change UI is useless.
  • There is a simple NativeWindow object that allows you to manipulate parts of the native Android UI.
  • Services like nsIPromptService and nsIAlertsService are implemented to use native Android UI.
  • Since overlays are useless for UI and JavaScript APIs are available for native UI, you should seriously consider just making a restartless add-on.

NativeWindow

We wanted to give add-on developers some APIs to manipulate the native Android UI, so we create a helper object called NativeWindow. The API is still young, but it gives you access to: Android Menu, Doorhanger Notifications, Context Menus (in web content) and Android popup toast alerts. The object is currently part of the main browser window, but we are considering moving it to a JS module. The basic API is here:


/*
 label: menu label
 icon: file:// or data: URI for an icon
 callback: JS function called when menu is tapped
 returns a menu ID that can be used to remove the menu
*/
menuID = NativeWindow.menu.add(label, icon, callback);
NativeWindow.menu.remove(menuID);

/*
 message: displayed text
 value: string based tag
 buttons: array of JS objects used to create buttons in the notification
 tabID: tab associated with this notification
 options: JS object that has 'persistence' and 'timeout' options
*/
NativeWindow.doorhanger.show(message, value, buttons, tabID, options);
NativeWindow.doorhanger.hide(value, tabID);

/*
 label: menu label
 selector: JS object that has a 'matches(element)' function. Used to show the menu.
 callback: JS function called when menu is tapped
 returns a menu ID that can be used to remove the menu
*/
menuID = NativeWindow.contextmenu.add(label, selector, callback);
NativeWindow.contextmenu.add(menuID);

/*
 message: displayed text
 duration: "short" or "long"; Used for alert timeout
*/
NativeWindow.toast.show(message, duration);

Some examples of what the API can do:

Doorhanger Notification


Menu Item


Context Menu Item


Toast Popup Alert


The NativeWindow API will continue to grow and mature, but I think even now it shows that add-ons can have first-class interactions with the native UI of Firefox. I am looking forward to developers trying it out and helping us push the API forward.

Firefox for Android: Native Android UI

You have probably seen some announcements and read some blog posts about Mozilla’s recent change in direction for Firefox Mobile on Android. We have decided to drop the XUL-based UI and re-build the application using native Android widgets. Here’s some of the rationale, from Johnathan’s newsgroup post:

  • Startup – A native UI can be presented much faster than a XUL based UI, since it can happen in parallel with Gecko startup. This means startup times in fractions of a second, versus several seconds for a XUL UI on some phones.
  • Memory Use – We believe a native UI will use significantly less memory.
  • Responsiveness – A native UI has the potential for beautiful panning and zooming performance.

Another major change is a move away from multi-process architecture (e10s) as well. The web content process was great for stabiilty, keeping crashes from taking down the entire application, but it also increased our memory usage and created some performance issues. In the new application, Gecko is running in a separate thread, not a separate process.

Quite simply everything you see is a native Android widget. Even the web content is displayed in a native view, very similar to the multi-process layers system we previously used. This allows us to asynchronously pan and zoom the web content, without waiting for the browser to scroll or zoom the actual content.

Even though the UI is completely implemented in native widgets, there is still a lot of JavaScript around, it’s just not visible. JavaScript is the perfect binding language into the Gecko platform and we are still using it for many of the same tasks. If you have ever built a browser using XUL, take a look at the browser,js file and you will see some familiar code. Because we have such a strong JavaScript binding layer, we can support add-ons in much the same way as a XUL-based application. More on that in a future blog post.

A few more details on how these three systems interact can be found in this basic architecture document. There is some details on the simple messaging system we use to allow the JavaScript and Java systems to communicate too.

The current nightlies are very usable, and support Flash (yes they do!) – so go grab the APK and try it out yourself.

Firefox Mobile – Send Performance Data

Firefox Mobile recently hooked up the same performance data telemetry system used by desktop Firefox. If you use the Nightly version of Firefox Mobile, you can start sending anonymous performance data back to Mozilla. We will use this data to improve future versions of Firefox Mobile.

It’s really easy to use and is completely anonymous. Once you enable the feature, everything happens in the background. To enable, go to the Feedback panel and make sure Send performance data is toggled on.

While you’re there, send us some feedback on Firefox Mobile as well.

Add-ons: Binary Components and js-ctypes

Lots of discussion going on recently about the affect of 6 week development cycles on binary XPCOM components in add-ons. I don’t want to re-hash those discussions, but Daniel Glazman brought up an interesting point in a comment on Wladimir’s post. Wladimir was suggesting binary component developers start moving to js-ctypes. Daniel pointed out that there are two classes of binary XPCOM components:

  • XPCOM wrappers around 3rd-party binary libraries: We use this model for exposing external binary functionality into JavaScript so add-ons and applications can access the libraries. Using js-ctypes should provide a simple, non-breaking way to expose the libraries. You create a simple JavaScript wrapper in a JavaScript XPCOM component. We need more examples of using js-ctypes to do this, but it works.
  • Pure binary XPCOM components built only using the Mozilla platform: Sometimes the functionality you want to expose is actually locked away in the Mozilla platform itself. Maybe there is no public nsIXxx interface or the existing interface has a [noscript] attribute on a property of method. This model shouldn’t be required anymore, in my opinion. Mozilla is pushing JavaScript based components and we should be exposing as much as possible to chrome JavaScript. I would encourage add-on developers to file bugs and lobby to expose binary-only parts of the Mozilla platform to chrome JavaScript.

JavaScript ctypes has come a long, long way since it was started back in 2007. Let’s start leveraging it more. The ctypes model has been used quite effectively in other languages.

Firefox for Mobile: What’s New in Mobile Aurora 7?

The latest Firefox Mobile Aurora 7 release has many of the same great features as Firefox Desktop Aurora 7. The new memory optimizations make running Firefox on Android much more pleasant, with fewer browser session restarts.

There are also a few mobile specific changes:

  • Text selection in web content: Long tap in a web page and start selection text using the familiar Android-style drag handles. Since Firefox does not use Android widgets, we had to implement this feature ourselves and there is still some additional work to do in order to make it more robust.
  • Session history within a tab is saved and restored: If Firefox needs to restore the session, each tab’s back/forward history is restored as well.
  • Language selection at initial startup: Choose you language right away, instead of wading through screens in a language you might not be able to read. If the Android OS is set to a language Firefox has bundled, the selection screen is skipped and you are taken to the Firefox Home page. If you really wanted to pick a different language, there is a “Choose Language” button on Firefox Home too, but only on the initial startup.
  • Added a ‘Quit’ action to the Android menu: This was a frequent feature request and low risk to the UI so we added it.
  • Text selection in action:


    Quit menu:


    Of course, Mobile Aurora 7 also has the features and optimizations found in the upcoming Firefox for Mobile 6 Beta release. Things like startup and painting speedups, Gingerbread theme, Android menu improvements and more. We’ll post more details about Firefox for Mobile 6 Beta soon.

    Mobile Aurora 7 is not in the Android Market. We are considering publishing it along with the Beta and Final releases. Until then, install the latest Mobile Aurora from this download page.

Firefly – Remote JS Shell for Firefox Mobile

A long time ago, in May 2008, I posted about a remote JS shell add-on I was building. I had been tinkering with a few existing projects (JSSH, SD Connect and MozRepl) but wanted to build something small, lightweight and mainly focused on helping add-on / XUL developers interact with JS running in a separate application. I tried to get the protocol closer to that used by Opera DragonFly and Crossfire, but I never had the time to get it exactly right. When I started work on Firefox Mobile, I used the add-on to interact with Firefox running on a mobile device from my desktop machine. Unfortunately, I never felt the UI and the code were good enough for a public release.

Recently, I dusted off the code, converted to restartless add-ons and made a very simple in-content UI. I say add-ons, because there are two: a probe, and a shell. You install the probe into Firefox Mobile and install the shell into Firefox Desktop (or Firefox Mobile running on a desktop – it’s up to you).

Shell

The shell is implemented as an in-content about: page [1]. After installing the shell, navigate to “about:firefly” and you’ll see the simple UI. The shell can act as a listening server or you can connect to a relay server. The listening server is simplest, so start with that.. You start the server on a specific TCP port. Once started, the shell waits for a probe to connect.

Probe

The probe is simple. After installing it, you just point it at an instance of the shell by entering the IP address and port. You can connect and disconnect from the “Remote Debugging” preferences. That’s all you need to do with the probe.

Starting a Session

Once the probe has connected to a shell, you can enter JavaScript commands into the simplistic shell UI, the code is sent to the probe and evaluated in a sandbox running in the application. Because it’s a sandbox, the probe injects some helper properties and methods:

  • window – The active chrome window. With this object, you have full access to the window’s JS and DOM.
  • firefly – Injected API with some special utility methods:
    • getWindow(type) – Returns the chrome window of a given type.
    • getWindows() – Returns an array of all open windows.
    • inspectJS(object) – Lists all properties and functions associated with a given JS object.
    • inspectDOM(selector or element) – Dumps the markup for a given DOM element. You can pass a CSS selector string or a real DOM element to the method.

Examples

Since we are talking about Firefox Mobile, you should be familiar with the internal chrome UI code before starting to poke around. The main browser.js has a Browser object that acts like a manager for the open tabs, so let’s play with it:

URL of active tab:
window.Browser.selectedBrowser.currentURI.spec

Add a new tab:
window.Browser.addTab("http://mozilla.org", true)

Inspect the active tab JS object:
firefly.inspectJS(window.Browser.selectedTab)

If you’re interested in using Firefly, you can install the add-ons from here:
Shell: firefly-shell
Probe: firefly-probe (mobile shortcut: http://bit.ly/irvpjc)

Source code:
Shell
Probe

Next Steps

  • Add access to the web content running in the child process. Firefox Mobile is multi-process, so you can’t directly access the web content from the main process.
  • Add a pretty output for the inspectXXX helpers. Instead of just dumping the simple text output into the HTML, we could make the output more dynamic – think Firebug panels.
  • Add helpers to do more profiling and data collection. Many times I want to know what is happening on the device. Things like CPU and memory usage or why the profile data is exploding.

Bug reports and feature requests welcome.

[1] Yep, an about: page in a restartless add-on. It wasn’t too hard. I am using a resource: alias for the external CSS file and the favicon. I could have just move the CSS into the XHTML file and used a data: URI for the favicon.

Firefox for Mobile: Channels and Branding

I mentioned that Firefox for Mobile (codenamed Fennec) has adopted the same rapid release system as used for development of desktop Firefox. The new system creates four (4) channels, each with possible releases: Nightly, Aurora, Beta and Final. With Fennec, you can have all four channels installed on your device at the same time. The installs do not share any files or data – they are completely isolated from each other.

Fennec has adopted new branding for releases. First up is the Nightly channel. As with desktop Firefox, the Nightly channel is our bleeding edge and the new branding has landed there first. If you install or update and existing nightly release of Fennec, you’ll see the new logos and naming. Don’t be alarmed – it’s the same Fennec you know and love, just with a new name and logo.

The branding consistency with desktop Firefox will also trickle into our Aurora channel soon. Firefox for Mobile beta branding will deviate slightly from desktop Firefox. The logos and title will contain “Beta” text to avoid confusion when both final releases and beta releases are installed on the same device.

Firefox for Mobile: Rapid Release Process

By now you are probably aware that desktop Firefox has moved to a rapid release system, utilizing several new code repositories and a focused strategy for creating releases in a timely manner.

Like desktop Firefox and Thunderbird, mobile Firefox has decided to adopt the same schedule-driven release plan. Currently, mobile is building “Fennec 6.0a1” nightly builds from mozilla-central. We plan to create an Aurora branding and start creating “Fennec Aurora 5.0a2” nightly builds from mozilla-aurora. While desktop Firefox is looking to create a significant user base on Aurora, Mobile is not actively promoting Aurora, since our user base is smaller and we’d like to focus user testing on the nightly release. We will re-evaluate this position as our user base grows.

Since we are sticking to the same release schedule as desktop Firefox, we will be releasing a mobile “Firefox 5 Beta 1” on or around May 17th. Normally, we would be building the beta from mozilla-beta, but we hit a snag for this cycle and will be using a one-time only fallback repository. In order to make sure things go smoothly, we’ll do a pre-beta build sometime next week, ahead of the official beta.

The plan is to put the beta releases in the Android Market. The beta releases will install alongside the final releases, but will have beta-specific branding, to minimize confusion with the final releases. Desktop Firefox has a channel-switcher, allowing users to easily move between Aurora and Beta channels. Mobile has no plans to create a switcher. Each release has it’s own profile and run separate from any other installed releases.

Zippity Update – Telemetry

I updated Zippity, our crowd sourcing data collection system, to add support for memory and CPU data telemetry. What is memory and CPU data telemetry you ask? Basically, we send data about the current Firefox Mobile memory and CPU usage patterns to Zippity. There are two ways to send the data:

  • Manually push a button: This might be a handy way to report metrics when you think Firefox Mobile is running slow on your phone.
  • Silently on idle once a day: During an idle moment, Zippity scans the metrics. This gives us data on the Firefox Mobile resting state. Hopefully we don’t see large CPU usage. Just install the Zippity add-on, and you start sending data – no additional work for you!

Why send this data you ask? We care a lot of the performance of Firefox Mobile, and we want to better understand how Firefox Mobile is running on your phone. We run a lot of tests at Mozilla, but these tests sometimes don’t compare well to the real world. For example, I have no performance issues running Firefox Mobile on my Nexus One, but we get lots of feedback from users that the performance is too slow on their phones. We need to run tests and collect data from Firefox Mobile running on your phone.

What kind of data is sent you ask? Firefox Mobile has a built-in memory reporting system and Zippity will enumerate that system to get detailed memory usage data. We also use the Linux /proc system to get information about the CPU usage. We only check the Firefox main and child processes. We don’t log any information about other processes. Thanks to Brad Lassey and Taras Glek for helping me get the data collected. Here is an example of the JSON formatted data sent to Zippity:

{
    "product": "Fennec 6.0a1",
    "os": "Android",
    "buildid": "20110416004121",
    "type": "metrics",
    "date": 1303152081000,
    "testkey": "telemetry-v1",
    "appid": "{a23983c0-fd0e-11dc-95ff-0800200c9a66}",
    "device": "Nexus One",
    "userkey": "",
    "osversion": "REL (10)",
    "data": {
        "reason": "manual",
        "malloc/allocated": 32377108,
        "malloc/mapped": 34603008,
        "malloc/committed": 34603008,
        "malloc/dirty": 77824,
        "js/gc-heap": 5242880,
        "js/string-data": 514630,
        "js/mjit-code": 88500,
        "storage/sqlite/pagecache": 4536536,
        "storage/sqlite/other": 1050816,
        "storage/permissions.sqlite/LookAside_Used": 29,
        "storage/permissions.sqlite/Cache_Used": 99208,
        "storage/permissions.sqlite/Schema_Used": 1272,
        "storage/permissions.sqlite/Stmt_Used": 5744,
        "storage/extensions.sqlite/LookAside_Used": 438,
        "storage/extensions.sqlite/Cache_Used": 428248,
        "storage/extensions.sqlite/Schema_Used": 6928,
        "storage/extensions.sqlite/Stmt_Used": 119024,
        "gfx/surface/image": 1088248,
        "images/chrome/used/raw": 0,
        "images/chrome/used/uncompressed": 1025124,
        "images/chrome/unused/raw": 0,
        "images/chrome/unused/uncompressed": 3648,
        "images/content/used/raw": 0,
        "images/content/used/uncompressed": 2144,
        "images/content/unused/raw": 4168,
        "images/content/unused/uncompressed": 8288,
        "layout/all": 563338,
        "storage/places.sqlite/LookAside_Used": 143,
        "storage/places.sqlite/Cache_Used": 428488,
        "storage/places.sqlite/Schema_Used": 11704,
        "storage/places.sqlite/Stmt_Used": 44152,
        "content/canvas/2d_pixel_bytes": 81120,
        "storage/cookies.sqlite/LookAside_Used": 14,
        "storage/cookies.sqlite/Cache_Used": 165000,
        "storage/cookies.sqlite/Schema_Used": 1816,
        "storage/cookies.sqlite/Stmt_Used": 0,
        "storage/formhistory.sqlite/LookAside_Used": 14,
        "storage/formhistory.sqlite/Cache_Used": 197920,
        "storage/formhistory.sqlite/Schema_Used": 1656,
        "storage/formhistory.sqlite/Stmt_Used": 0,
        "storage/addons.sqlite/LookAside_Used": 152,
        "storage/addons.sqlite/Cache_Used": 296616,
        "storage/addons.sqlite/Schema_Used": 4280,
        "storage/addons.sqlite/Stmt_Used": 29152,
        "storage/search.sqlite/LookAside_Used": 20,
        "storage/search.sqlite/Cache_Used": 99192,
        "storage/search.sqlite/Schema_Used": 1216,
        "storage/search.sqlite/Stmt_Used": 1840,
        "shmem/allocated": 0,
        "shmem/mapped": 0,
        "storage/index.sqlite/LookAside_Used": 148,
        "storage/index.sqlite/Cache_Used": 296656,
        "storage/index.sqlite/Schema_Used": 3032,
        "storage/index.sqlite/Stmt_Used": 51704,
        "uptime": 159848,
        "process": {
            "parent": {
                "user": 13,
                "system": 2,
                "rss": 77456
            },
            "child": {
                "user": 22,
                "system": 2,
                "rss": 25132
            },
            "cpu": 57
        }
    }
}

You can now access Metrics charts on Zippity to view the data. Trying to find ways to visualize the data isn’t easy. There is a lot of data. The charts are simple for now. The data point tooltip shows more detailed information.

Visit Zippity from your phone and install the add-on today. Thanks for using Zippity to help us collect data to make Firefox Mobile better.