aboutsummaryrefslogtreecommitdiff
path: root/tools/addon-sdk-1.3/packages/api-utils/docs/e10s.md
blob: 3e2f047facac01f441e5e8fe740669ebc0a379dc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
<span class="aside">
For a high-level overview of out-of-process add-ons, see the
[Out-of-Process Add-ons][] internals guide.
</span>

The `e10s` module allows add-ons to execute in a separate process from Firefox
itself.

## Adapters ##

As explained in the [Out-of-Process Add-ons][] internals guide, an *e10s
adapter* is the primary mechanism through which chrome functionality is exposed
to add-on processes. It is a single piece of code evaluated *twice*&mdash;once
in each process&mdash;and typically has 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. */
    };

In the above code, the `chrome` global is only visible to this code when it is
executed in the add-on process. It is an instance of `ChromeProcess`.

The `register()` function, on the other hand, is only defined and called in the
chrome process, and the `addon` argument passed to it is an instance of
`AddonProcess`.

`ChromeProcess` and `AddonProcess` instances come in pairs, and represent
opposite sides of an inter-process communication mechanism.

  [Out-of-Process Add-ons]: dev-guide/module-development/e10s.html

## Events ##

Chrome and add-on processes can asynchronously send arbitrary events to each
other. The <code>[EventEmitter][]</code> interface has been overloaded to make
handling these events simple and intuitive. For instance, here's a trivial e10s
adapter that uses events:

    if (this.chrome) {
      exports.sendFoo = function(x) {
        chrome.send('foo', x);
      };
    } else exports.register = function register(addon) {
      addon.on('foo', function(type, x) {
        console.log("foo called with argument", x);
      });
    };

  [EventEmitter]: packages/api-utils/docs/events.html

## Remote Function Calls ##

The add-on process can synchronously call a function on the chrome process, but
not vice versa. Here's a trivial example of an e10s adapter using this
mechanism:

    if (this.chrome) {
      exports.bar = function(x) {
        return chrome.call('bar', x);
      };
    } else exports.register = function register(addon) {
      addon.registerCall('bar', function(name, x) {
        return x * 3;
      });
    };

## Arguments ##

When sending events or calling functions in another process, the chrome and
add-on processes are allowed to send JSON-serializable arguments. Additionally,
they can send a special type of object called a *handle*. See the
[MDN Handle Documentation][] for more information on these.

Here's a simple example of a handle being used to remember a callback function
on the add-on side:

    if (this.chrome) {
      exports.baz = function(callback) {
        var handle = chrome.createHandle();
        handle.callback = callback;
        chrome.send('baz', handle);
      };
      chrome.on('bazCallback', function(name, handle) {
        try { handle.callback(); } except (e) { console.exception(e); }
        handle.invalidate();
      });
    } else exports.register = function register(addon) {
      addon.on('baz', function(name, handle) {
        require('timer').setTimeout(function() {
          addon.send('bazCallback', handle);
        }, 1000);
      });
    };

  [MDN Handle Documentation]: https://developer.mozilla.org/en/Jetpack_Processes#Handles

<api name="ChromeProcess">
@class
  In an add-on process, this represents the parent chrome process. This class is
  a singleton and has no constructor. It is automatically injected into the
  global scope of all `-e10s-adapter` modules as the `chrome` object.

<api name="on">
@method
  Registers an event listener with the chrome process.
@param type {string}
  The type of event to listen for.
@param listener {function}
  The listener function that handles the event. Its first argument is always
  `type`, and additional arguments vary depending on the event's originating
  `addon.send()` call in the chrome process.
</api>

<api name="removeListener">
@method
  Removes an event listener from the chrome process.
@param type {string}
  The type of event for which `listener` was registered.
@param listener {function}
  The listener function that was registered.
</api>

<api name="send">
@method
  Sends an event asynchronously to the chrome process. Any additional arguments
  after `type` are passed as arguments to event listeners in the chrome process.
@param type {string}
  The type of event to send.
</api>

<api name="call">
@method
  Synchronously calls a remote function in the chrome process and returns its
  result. Any additional arguments after `name` are passed as arguments to the
  function in the chrome process.
@param name {string}
  The name of the function to call.
</api>

<api name="createHandle">
@method
  Creates a [handle][] object, which can be passed to the chrome process via
  `send()` or `call()`.

  [handle]: https://developer.mozilla.org/en/Jetpack_Processes#Handles
</api>

</api>

<api name="AddonProcess">
@class
  In the chrome process, this represents a child add-on process.

<api name="AddonProcess">
@constructor
  Creates a new add-on process.

@param options {object}
  An optional object with the following keys, all of which are optional:

  @prop [console] {object}
    An object whose interface corresponds to that of the `console` global. All
    logging messages to the `console` object of the addon will be redirected to
    this object. If this object isn't provided, then the global `console` object
    of the chrome process will be used.
</api>

<api name="destroy">
@method
  Terminates the add-on process.
</api>

<api name="on">
@method
  Registers an event listener with the add-on process.
@param type {string}
  The type of event to listen for.
@param listener {function}
  The listener function that handles the event. Its first argument is always
  `type`, and additional arguments vary depending on the event's originating
  `chrome.send()` call in the add-on process.
</api>

<api name="registerCall">
@method
  Registers a synchronous call handler with the add-on process.
@param name {string}
  The name of the function.
@param handler {function}
  The call handler. Its first argument is always `name`, and additional
  arguments vary depending on the call's originating `chrome.call()` invocation
  in the add-on process. The handler's return value is also passed back to the
  original caller in the add-on process.
</api>

<api name="send">
@method
  Sends an event asynchronously to the add-on process. Any additional arguments
  after `type` are passed as arguments to event listeners in the add-on process.
@param type {string}
  The type of event to send.
</api>

<api name="createHandle">
@method
  Creates a [handle][] object, which can be passed to the add-on process via
  `send()`.

  [handle]: https://developer.mozilla.org/en/Jetpack_Processes#Handles
</api>

</api>