Outreachy : Understanding my project and contributing to Mozilla

Nupur Baghel
Jun 23 · 7 min read

Do you want to contribute to Mozilla, but feel scared and unaware where to start? Are you enthusiastic to help but maybe feeling a little lost? Or you want to know what working at a project here feels like? Yes? This blog presents my emotions and journey so far, and explains in detail the work I am doing as part of an Outreachy intern with the Interoperability Team at Mozilla.

Snapshot of Bugzilla showing Mozilla projects

The Very Beginning O_o

At a first glance, reading project descriptions and trying to understand the work happening inside can be quite daunting. The technology stack can be almost 100% new to you, which may feel like jumping over and finding a better match. Yet, the fact remains that every community and project will have something or the other which is “strikingly new and alien” to offer.

Me and that unknown tech stack staring at each other! (Credits: Giphy.com)

This exactly describes my situation when I first started contributing to Mozilla last year. Mozilla offered a wide variety of projects each differing in its requirements and I decided to contribute to Servo, the browser layout engine. I had a fair amount of understanding of JavaScript, HTML and CSS. But, to understand and make my first pull request, I needed to learn the “Rust programming language”. Fast forward to this year, I am working as a part of the Interoperability team and still learning new concepts on Rust such as how to build new crates and modules. I am also in the process of learning to use Mercurial, which is a version control system like Git. The next section, will explain more on my work.

Project Details

Marionette is a remote protocol that lets out-of-process programs communicate with, instrument, and control Gecko-based browsers, such as Firefox and Fennec. Currently, the code for the Marionette protocol resides in the geckodriver crate, which is Mozilla’s WebDriver implementation for Firefox. The following figure, demonstrates this -

Current state of system

The client sends a request ( a WebDriver command) which is received by the geckodriver.

Internally, the Marionette-specific code converts it into the format required by Marionette server.

The response returned by server is received by the geckodriver and converted back to the WebDriver response format to be sent to the client.

The aim of my project is to move the Marionette code out of the geckodriver to a separate crate (which we call a library), because of several motivating factors such as :

  1. Supporting interchangeable back ends. This allows us to use a different protocol instead of Marionette in future.
  2. Improvement in parts of Gecko-code. This will replace hard-coded JSON definitions with generalized serde traits. Thus, providing more safety by utilizing Rust’s type system.

Hence, the new system will look like the following -

Final state of system

This figure explains the role of the Marionette as a separate crate. The geckodriver receives the command sent by the client. It next forwards this command to the Marionette Library which defines its serde traits.

The library sends back the serialized version of the command to the geckodriver, which is then sent to the Marionette server. The response process also proceeds in a similar manner with the library performing de-serialization of response.

In simple terms, I am building a Rust library from scratch. The library will define several structs and types which are used during the request and response phases of the client communicating with the browser. For example, a command to find body tag in the current webpage. This library will enable to improve upon safety concerns and ease the tight coupling between geckodriver and marionette protocol.

What did I find confusing in my project?

If you are still unable to make head or tail about my project, don’t be scared. After all, Rome wasn’t built in a day…! All good things take time to be completed. I continue to have millions of doubts on a daily basis and am still in the process of understanding better. For instance,

  • How to create a crate ? What are its essential elements ?
  • How does a crate differ from a module ? Also, how to create a module ?
  • Where should the library be located ? Should it be a separate crate or just a sub-crate ? (It will be a sub-crate for now inside the geckodriver)
  • I have created a file, but cargo doesn’t compile it, no errors, nothing. Did I miss something ?
  • I am defining types which are already present in WebDriver. Should I reuse them or redefine them? (And then I tried reusing them as an experiment)
  • The commands belong to different namespaces, should we keep them in the same file or as multiple files ?
  • Hmm, actually, where should I start 🤔!!!

How can you contribute ?

I am sure, you must be pumped up by now to make one of your own contributions to Open Source and Mozilla 💪 Here is Mozilla’s own blog for new contributors -> https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Introduction

Since reading all of this can make you feel out of place, I am going to explain certain aspects of this directly to you.

1. The first step is to understand that while some repositories of Mozilla are hosted on GitHub, others such as Firefox and this project’s code base are hosted on Mercurial. So, install Mercurial on your system.

2. The repository which we will be working on is called mozilla-central. To get the source code for mozilla-central and place it in a folder named firefox-source, use the following commands, also available in this doc:

hg clone https://hg.mozilla.org/mozilla-central/ firefox-source
cd firefox-source

NOTE: If you wish to work on multiple repositories, you should consider getting code for the Unified Firefox Repository instead. Further instructions have been written considering mozilla-central only.

3. Use the following command to set up a development environment. This will install Homebrew and all the necessary dependencies needed for working on all code in Gecko. Gecko is the web browser engine used in Firefox.

./mach bootstrap

4. When it asks you whether you want to have an artifact or a full build, you should choose an artifact build (Option 1). This saves you from having to build Firefox locally which can take a long time.

Please choose the version of Firefox you want to build:
1. Firefox for Desktop Artifact Mode
2. Firefox for Desktop
3. GeckoView/Firefox for Android Artifact Mode
4. GeckoView/Firefox for Android
Your choice: 1

While this is in process, it will ask if you want to optimally configure Mercurial. You can safely choose No.

NOTE: If you are building this repository for the first time, you will need to create a file named mozconfig in the top level directory (firefox-source for us) and place the following 2 lines in that file.

# Automatically download and use compiled C++ components:
ac_add_options --enable-artifact-builds

5. Run the following commands to set the configuration and ensure everything is set up properly. (Installation of Rust is required for the second step: https://www.rust-lang.org/tools/install)

./mach configure
./mach build testing/geckodriver
  1. Mozilla uses Bugzilla as the platform for reporting bugs. Click here to view the list of bugs in geckodriver. You can also work on any other component : https://bugzilla.mozilla.org/describecomponents.cgi
  2. The next step is to find a bug of your interest and write a comment expressing your intent to solve. Once you get a positive reply from the reporter or any other community member, you are good to start.
  3. Once you are ready with the patch of the bug, you need to submit it using Phabricator, which is used by Mozilla for ensuring better security. First create an account on Bugzilla using username and password option. Then, enable two factor authentication using TOTP on Google Authenticator. Finally, make an account on the Phabricator portal.
  4. Each commit requires using a proper format to be followed. View these restrictions here. Each commit message contains a bug ID, one line description and handle of reviewer. Consider an example,
Bug 577872 - Create WebM versions of Ogg reftests. r=kinetik

5. Once, you have added all the files and committed your task, use the following command to push your changes to Phabricator :

moz-phab

6. Tada! You have submitted your first patch. You may be asked to do some changes before the patch gets accepted. Instead of creating a new commit, just make changes to your code, edit the same commit and push the changes again. (make sure you select only the required changes, when asked after running moz-phab).

hg amend
moz-phab
When your patch gets accepted :’) (Credits: Giphy.com)

Hurrah, its time to celebrate! That was hard work, pat on your back 😍!

More doubts? Feel free to ask me(nupur on IRC) or anyone from the #interop team on IRC ( We are all really friendly :P ) Also find me on Linked-In and Twitter. Adios!

Nupur Baghel

Written by

Machine Learning Enthusiast | Open Source programmer | Upcoming Data Scientist 👩‍🔬