# Out-of-Process Add-ons #

Early infrastructure for allowing add-ons to execute in a separate process from
Firefox itself is now available in the Add-on SDK.

## Motivation ##

Add-ons are awesome, but like any software, they have the ability to behave in
unexpected ways. An add-on that's gone rogue should have as little ability to
negatively affect the rest of the user's browsing experience as possible; one
way to achieve this is by running the add-on's code in a separate process.

These separate processes are relatively lightweight, don't have access to XPCOM,
and are provided messaging facilities that allow them to communicate with their
parent chrome process.

## The Big Picture ##

![Multi-Process Architecture](media/twitter-widget.png)

The above diagram is a simplified depiction of what happens when a hypothetical
add-on using the `widget` module is loaded.

First, the add-on loader initializes the add-on and loads `main.js` in a
separate process. We call this the *add-on process*.

When `main.js` calls `require("widget")`, the add-on process sends a message to
the chrome process and awaits a reply.

The chrome process then notices that the `widget` module requires chrome
privileges and therefore won't work properly if sent to the add-on process for
evaluation. So it looks for an *e10s adapter* for the module by appending
`-e10s-adapter` to the module's name and searching for it.

This causes `widget-e10s-adapter.js` to be found and imported as the
`widget-e10s-adapter` module in the chrome process. The *exact same code* is
also returned to the add-on process for evaluation as the `widget` module in its
world, and its exports are returned by `require()`. In other words, different
sides of the message-passing boundary between the two processes are contained in
the same adapter file, which is typically of the following form:

    if (this.chrome) {
      /* We're being evaluated in the add-on process. Export the
       * module's API, proxying all calls to the chrome process
       * as necessary. */
    } else exports.register = function register(addon) {
      /* We're being evaluated in the chrome process.
       * Set up chrome process listeners to communicate with
       * the given add-on process. */
    };

More details on the above code can be found in the documentation for the
<code>[e10s][]</code> module.

Note that this only describes what happens when a module requiring chrome
privileges *and* having an e10s adapter is requested by code in the add-on
process.

### Other Cases ###

If the add-on process code attempts to import a chrome-privileged module that
does *not* have an e10s adapter, an access denied exception is thrown.

If the add-on process code attempts to import a module that does *not*
explicitly require chrome privileges, the code for the module is sent to the
add-on process and evaluated there, just like the `main` module.

### Double Loading ###

If both a module in the chrome process *and* a module in the add-on process
request the same module that doesn't require chrome privileges, it is actually
loaded *twice*: once in each process. This means that modules which intend to
provide singleton-like functionality may need an e10s adapter to proxy calls
into a single process.

## Usage ##

To enable out-of-process add-on functionality, simply pass the `--e10s` option
to `cfx`. At present, this is only intended for SDK platform developers who are
porting core SDK modules to work in out-of-process add-ons.

Once these modules have been ported and the infrastructure is production-ready,
we will be removing the `--e10s` option, as it will become the new default
environment for add-ons to run in. We may decide to introduce a `--no-e10s`
option at that time, to allow add-on authors to use the in-process architecture
if absolutely necessary.

For more detailed information on the usage of the e10s APIs, see the
<code>[e10s][]</code> module.

## Internals ##

Code for the creation and bootstrapping of the add-on process is contained in
the <code>[e10s][]</code> module, which uses the
<code>[nsIJetpackService][]</code> and <code>[nsIJetpack][]</code> XPCOM
interfaces to create a [Jetpack process][] and send
<code>[bootstrap-remote-process.js][]</code> to it for evaluation. The `e10s`
module also contains most of the `require()` logic for the add-on process.

[e10s]: packages/api-utils/docs/e10s.html

[bootstrap-remote-process.js]: packages/api-utils/data/bootstrap-remote-process.js
[nsIJetpackService]: https://developer.mozilla.org/en/nsIJetpackService
[nsIJetpack]: https://developer.mozilla.org/en/nsIJetpack
[Jetpack process]: https://developer.mozilla.org/en/Jetpack_Processes
