Graphene On Gecko Without B2G

Recently, I’ve been experimenting with a reimplementation of Graphene on Gecko that doesn’t require B2G. Graphene is a desktop runtime for HTML apps, and Browser.html uses it to run on Servo. There’s a Gecko implementation of Graphene that is based on B2G, but it isn’t maintained and appears to have bitrotted. It also entrains all of B2G, although Browser.html doesn’t use many B2G features.

My reimplementation is minimal. All it does is load a URL in a native window and expose a few basic APIs (including <iframe mozbrowser>). But that’s enough to run Browser.html. And since Browser.html is a web app, it can be loaded from a web server (with this change that exposes <iframe mozbrowser> to https: URLs).

I forked browserhtml/browserhtml to mykmelez/browserhtml, built it locally, and then pushed the build to my GitHub Pages website at Then I forked mozilla/gecko-dev to mykmelez/graphene-gecko and reimplemented Graphene in it. I put the implementation into embedding/graphene/, but I could have put it anywhere, including in a separate repo, per A Mozilla App Outside Central.

To try it out, clone, build, and run it:

git clone
cd graphene-gecko
./mach build && ./mach run

You’ll get a native window with Browser.html running in Graphene:

Graphene on Gecko


A Mozilla App Outside Central

After forking gecko-dev again for an experiment, I wondered if there was a better way to create a Mozilla app outside the mozilla-central repository. After all, that repository, mirrored as mozilla/gecko-dev on GitHub, is huge. And forking the same repo twice to the same GitHub account (or organization) requires cumbersome workarounds (and workarounds for the workarounds in some cases).

Plus, Mozilla apps don’t necessarily need to modify Gecko. But even when they do, they could share a single fork, with branches for each app, if there was a way to create a Mozilla app that imported gecko-dev as a dependency without having to live inside a fork of gecko-dev itself.

So I created an example app that does just that. It happens to use a shallow Git submodule to import gecko-dev, but it could use a Git subtree or any other dependency management tool.

The build process touches only one file in the gecko-dev subdirectory: it creates a symlink to the parent (app) directory to work around the limitation that Mozilla app directories must be subdirectories of gecko-dev.

To try it for yourself, clone the mykmelez/mozilla-app repo and build it:

git clone --recursive --shallow-submodules
cd mozilla-app/
./mach build && ./mach run

You should see a window like this:

Mozilla app window

And your clone will contain the app’s files, the gecko-dev submodule directory, and an obj directory containing the built app:

> ls
LICENSE  app.mozbuild  components   gecko-dev  modules    moz.configure  obj
app      branding  mach  mozconfig


The app builds Gecko from source, so you still need Mozilla build prerequisites. On some platforms, you can install these via ./mach bootstrap.

I’ve only tested it on Mac, but it probably works on Linux, and it probably doesn’t work on Windows (because of the symlink).

Although the Mozilla application framework is mature and robust, it isn’t explicitly generalized for use beyond Firefox anymore, and it could change or break at any time.


Continuous Integration of Positron with TaskCluster

I recently enabled continuous integration of Positron using TaskCluster’s support for GitHub repositories. I’ve used Travis CI to integrate other GitHub projects, but Positron is too large for Travis to build without timing out, since it builds all of Gecko. So I needed an alternative.

Caveat: TaskCluster only supports GitHub repositories in the mozilla organization or another org that is explicitly configured for it, as described by Setting up Taskcluster with a Github Organization. So it won’t work with your personal fork.

Also, while the Positron repository is based on gecko-dev, I didn’t use GitHub’s “fork” feature to create it, since GitHub won’t let you fork a repo to another repo in the same organization. Instead, I created a new repository and then copied gecko-dev’s commits to it, as described in Copy/fork a git repo on github into same organization.

(I also had to push the copied commits to GitHub in batches, as described in Github remote push pack size exceeded. And I had to push the first batch via special syntax, per Pushing a large github repo fails with “unable to push to unqualified destination: master”.)

To enable CI, I first created this Docker image, based on Ubuntu 14.04 (Trusty), that includes the Mozilla build toolchain and dependencies installed by Gecko’s script. The image also includes the taskcluster-vcs utility, which caches gecko-dev and clones from the cache so that TaskCluster pulls from GitHub are lighter-weight.

Here’s the Dockerfile for that image:

FROM ubuntu:trusty

RUN apt-get update -y && \
    apt-get install -y \
      curl \
      git \
      nodejs \
      nodejs-legacy \
      npm \
      python \

RUN npm install -g taskcluster-vcs

RUN wget -O && \
    python --no-interactive --application-choice=browser

Then I replaced the upstream .taskcluster.yml file with one that clones and builds Positron when a developer submits a pull request or lands a change. .taskcluster.yml is like .travis.yml, but for TaskCluster. Here’s that file:

version: 0
    name: "Positron"
    description: "continuous integration for Positron"
    owner: "{{ }}"
    source: "{{ event.head.repo.url }}"
    - provisionerId: "{{ taskcluster.docker.provisionerId }}"
      workerType: "{{ taskcluster.docker.workerType }}"
              env: true
                  - pull_request.opened
                  - pull_request.synchronize
                  - pull_request.reopened
                  - push
          maxRunTime: 7200 # seconds (i.e. two hours)
          image: "mykmelez/docker-build-positron:latest"
              - "/bin/bash"
              - "--login"
              - "-c"
              - "tc-vcs checkout repo $GITHUB_HEAD_REPO_URL $GITHUB_HEAD_BRANCH &&
                 cd repo/ && SHELL=/bin/bash ./mach build"
          name: "checkoutandbuild"
          description: "check out and build the repository"
          owner: "{{ }}"
          source: "{{ event.head.repo.url }}"

Finally, I added TaskClusterRobot to the list of collaborators in the repo’s Settings > Collaborators & teams list, giving it Write permissions, so it can annotate pull requests with icons representing the state of the job, just like Travis does:

Screen Shot of GitHub PR with CI annotations

Et voilà, continuous integration for Positron!

(Once Positron starts running Node and Electron tests, I’ll add tasks to run those tests and report their results.)


Project Positron

Along with several colleagues, I recently started working on Project Positron, an effort to build an Electron-compatible runtime on top of the Mozilla technology stack (Gecko and SpiderMonkey). Mozilla has long supported building applications on its stack, but the process is complex and cumbersome. Electron development, by comparison, is a dream. We aim to bring the same ease-of-use to Mozilla.

Positron development is proceeding along two tracks. In the SpiderNode repository, we’re working our way up from Node, shimming the V8 API so we can run Node on top of SpiderMonkey. Ehsan Akhgari details that effort in his Project SpiderNode post.

In the Positron repository, we’re working our way down from Electron, importing Electron (and Node) core modules, stubbing or implementing their native bindings, and making the minimal necessary changes (like basing the <webview> element on <iframe mozbrowser>) so we can run Electron apps on top of Gecko. Eventually we aim to join these tracks, even though we aren’t yet sure exactly where the last spike will be located.

It’s early days. As Ehsan noted, SpiderNode doesn’t yet link the Node executable successfully, since we haven’t shimmed all the V8 APIs it accesses. Meanwhile, Positron supports only a tiny subset of the Electron and Node APIs.

Nevertheless, we reached a milestone today: the tip of the Positron trunk now runs the Electron Quick Start app described in the Electron tutorial. That means it can open a BrowserWindow, hook up a DevTools window to it (with Firefox DevTools integration contributed by jryans), and handle basic application lifecycle events. We’ve imported that app into the Positron repository as our “hello world” example.

Clone and build Positron to see it in action!



New Year, New Blogware

Four score and many moons ago, I decided to move this blog from Blogger to WordPress. The transition took longer than expected, but it’s finally done.

If you’ve been following along at the old address,, now’s the time to update your address book! If you’ve been going to, however, or you read the blog on Planet Mozilla, then there’s nothing to do, as that’s the new address, and Planet Mozilla has been updated to syndicate posts from it.


Introducing PluotSorbet

PluotSorbet is a J2ME-compatible virtual machine written in JavaScript. Its goal is to enable users you run J2ME apps (i.e. MIDlets) in web apps without a native plugin. It does this by interpreting Java bytecode and compiling it to JavaScript code. It also provides a virtual filesystem (via IndexedDB), network sockets (through the TCPSocket API), and other common J2ME APIs, like Contacts.

The project reuses as much existing code as possible, to minimize its surface area and maximize its compatibility with other J2ME implementations. It incorporates the PhoneME reference implementation, numerous tests from Mauve, and a variety of JavaScript libraries (including jsbn, Forge, and FileSaver.js). The virtual machine is originally based on node-jvm.

PluotSorbet makes it possible to bring J2ME apps to Firefox OS. J2ME may be a moribund platform, but it still has non-negligible market share, not to mention a number of useful apps. So it retains residual value, which PluotSorbet can extend to Firefox OS devices.

PluotSorbet is also still under development, with a variety of issues to address. To learn more about PluotSorbet, check out its README, clone its Git repository, peruse its issue tracker, and say hello to its developers in!