Revision 30553 of Jetpack Processes

  • Revision slug: Jetpack_Processes
  • Revision title: Jetpack Processes
  • Revision id: 30553
  • Created:
  • Creator: Sheppy
  • Is current revision? No
  • Comment 59 words added
Tags: 

Revision Content

Jetpack processes are created by components that implement the {{ Interface("nsIJetpackService") }} interface, and their parent chrome process communicates with them via the {{ Interface("nsIJetpack") }} interface.

Note: The Jetpack service, provided by {{ interface("nsIJetpackService") }}, is not included by default in Firefox 4. It can be included in custom builds by using ENABLE_JETPACK_SERVICE at compile time. The service has not been thoroughly tested and debugged, and it has been decided not to include it in Firefox 4.

These processes are relatively lightweight, do not have access to XPCOM, and can innately do little other than compute. Messaging facilities that allow them to communicate with their parent chrome process are the only means by which they can be endowed with any real power.

Note: The above statement is not currently true, as js-ctypes is now provided to Jetpack processes as of bug 588563. A mechanism to optionally disable this feature has been proposed in bug 614351.

Privileged APIs

When script is evaluated in a Jetpack process via a call to {{ ifmethod("nsIJetpack","evalScript") }}, the script's global scope is endowed with the following privileged APIs:

sendMessage(aMessageName [, v1 [, v2 [, ...]]])
Similar to {{ ifmethod("nsIJetpack","sendMessage") }}, this function asynchronously sends a message to the chrome process.
callMessage(aMessageName [, v1 [, v2 [, ...]]])
This function is like sendMessage() but sends the message synchronously. It returns an Array whose elements are the return values of each receiver in the chrome process that was triggered by the message.
registerReceiver(aMessageName, aReceiver)
Similar to {{ ifmethod("nsIJetpack","registerReceiver") }}, this function registers a callback that is triggered when the chrome process sends a message with the given name.
unregisterReceiver(aMessageName, aReceiver)
Similar to {{ ifmethod("nsIJetpack","unregisterReceiver") }}, this function unregisters a callback previously registered with registerReceiver().
unregisterReceivers(aMessageName)
Similar to {{ ifmethod("nsIJetpack","unregisterReceivers") }}, this function unregisters all callbacks for the given message name.
createHandle()
Similar to {{ ifmethod("nsIJetpack","createHandle") }}, this function creates a new handle and returns it.
createSandbox()
This creates a new JavaScript sandbox and returns its global scope. This global scope does not contain privileged APIs, or any non-standard JavaScript objects for that matter, though new globals can be endowed by simply attaching them to the global scope as properties.
evalInSandbox(aSandbox, aScript)
Evaluates the given script contents in the given sandbox's global scope. At minimum, JavaScript 1.8.1 is used. Individual lines of the form //@line 1 "foo.js" can be used to specify filename and line number information for debugging purposes.
gc()
Synchronously performs garbage collection.

Handles

Messages that communicate between the browser and jetpack process may contain only serializable (JSON) data and handles. A handle can be used to provide context for messages. Either the browser or the jetpack implementation may create one.

A handle keeps any arbitrary properties attached to it alive, but those properties are not transmitted across the process boundary. These arbitrary properties are the primary means through which context can be provided for messages; for instance, if the handle is meant to represent a network request, an XMLHttpRequest instance can be attached to the handle on the chrome process.

Because a handle's existence crosses process boundaries and cross-process garbage collection does not exist, the lifetime of a handle needs to be controlled manually by code. By default, a handle is rooted in the JavaScript interpreter's garbage collector, meaning that even if a process throws it away, it will not be garbage collected unless the other process explicitly does something to indicate that it is no longer needed. If that other process does not do something explicit and simply removes all references to it, the handle remains rooted yet unreachable in both processes and a memory leak is created.

To prevent such memory leaks, a process can either invalidate a handle, immediately preventing it from being passed as a message argument, or it can unroot the handle, allowing it to be passed as a message argument until all references to it are removed, at which point it is garbage collected.

Handles have the following native methods and properties:

invalidate()
Invalidates the handle. Either process may invalidate a handle when it is no longer useful.
createHandle()
Creates a child handle which becomes invalid when its parent does. This is useful for associating handles to the lifetime of a particular window, context menu, or other element, and helping ensure that they do not leak.
parent
The parent handle of the object, if any. Read-only.
isValid
Whether the handle is still valid or not. Read-only.
isRooted
Whether the handle is GC rooted or not. Read-write.
onInvalidate
A callback to call when the handle is garbage collected, either through an explicit call to invalidate() or being unrooted and then unreachable. The callback is only called from the process that the handle was not garbage collected in. Read-write.

Special Messages

core:process-error(context)
When the jetpack process crashes, this message is sent to the parent. If a crash report minidump is available, the context.dumpID property will list the minidump ID of the crash report that was collected.
core:exception(error)
When an exception occurs in a Jetpack script and is not caught, this message is sent to the parent. The error object contains the following properties: fileName, lineNumber, and message.

History

See {{ Bug("556846") }} and {{ Bug("578821") }} for details.

Sample Code

For example code, check out the {{ source("js/jetpack/tests/unit/","unit tests") }}.

See also

  • {{ Interface("nsIJetpackService") }}
  • {{ Interface("nsIJetpack") }}

Revision Source

<p>Jetpack processes are created by components that implement the {{ Interface("nsIJetpackService") }} interface, and their parent chrome process communicates with them via the {{ Interface("nsIJetpack") }} interface.</p>
<div class="note"><strong>Note:</strong> The Jetpack service, provided by {{ interface("nsIJetpackService") }}, is not included by default in Firefox 4. It can be included in custom builds by using <code>ENABLE_JETPACK_SERVICE</code> at compile time. The service has not been thoroughly tested and debugged, and it has been decided not to include it in Firefox 4.</div>
<p>These processes are relatively lightweight, do not have access to XPCOM, and can innately do little other than compute. Messaging facilities that allow them to communicate with their parent chrome process are the only means by which they can be endowed with any real power.</p>
<div class="note"><strong>Note:</strong> The above statement is not currently true, as <a href="/en/js-ctypes" title="https://developer.mozilla.org/en/js-ctypes">js-ctypes</a> is now provided to Jetpack processes as of <a class=" link-https" href="https://bugzilla.mozilla.org/show_bug.cgi?id=588563" title="https://bugzilla.mozilla.org/show_bug.cgi?id=588563">bug 588563</a>. A mechanism to optionally disable this feature has been proposed in <a class=" link-https" href="https://bugzilla.mozilla.org/show_bug.cgi?id=614351" title="https://bugzilla.mozilla.org/show_bug.cgi?id=614351">bug 614351</a>.</div>
<h2 name="Privileged_APIs">Privileged APIs</h2>
<p>When script is evaluated in a Jetpack process via a call to {{ ifmethod("nsIJetpack","evalScript") }}, the script's global scope is endowed with the following privileged APIs:</p>
<dl> <dt><code>sendMessage(aMessageName [, v1 [, v2 [, ...]]])</code></dt> <dd>Similar to {{ ifmethod("nsIJetpack","sendMessage") }}, this function asynchronously sends a message to the chrome process.</dd> <dt><code>callMessage(aMessageName [, v1 [, v2 [, ...]]])</code></dt> <dd>This function is like <code>sendMessage()</code> but sends the message synchronously. It returns an <code>Array</code> whose elements are the return values of each receiver in the chrome process that was triggered by the message.</dd> <dt><code>registerReceiver(aMessageName, aReceiver)</code></dt> <dd>Similar to {{ ifmethod("nsIJetpack","registerReceiver") }}, this function registers a callback that is triggered when the chrome process sends a message with the given name.</dd> <dt><code>unregisterReceiver(aMessageName, aReceiver)</code></dt> <dd>Similar to {{ ifmethod("nsIJetpack","unregisterReceiver") }}, this function unregisters a callback previously registered with <code>registerReceiver()</code>.</dd> <dt><code>unregisterReceivers(aMessageName)</code></dt> <dd>Similar to {{ ifmethod("nsIJetpack","unregisterReceivers") }}, this function unregisters all callbacks for the given message name.</dd> <dt><code>createHandle()</code></dt> <dd>Similar to {{ ifmethod("nsIJetpack","createHandle") }}, this function creates a new <a href="#Handles">handle</a> and returns it.</dd> <dt><code>createSandbox()</code></dt> <dd>This creates a new JavaScript sandbox and returns its global scope. This global scope does <em>not</em> contain privileged APIs, or any non-standard JavaScript objects for that matter, though new globals can be endowed by simply attaching them to the global scope as properties.</dd> <dt><code>evalInSandbox(aSandbox, aScript)</code></dt> <dd>Evaluates the given script contents in the given sandbox's global scope. At minimum, JavaScript 1.8.1 is used. Individual lines of the form <code>//@line 1 "foo.js"</code> can be used to specify filename and line number information for debugging purposes.</dd> <dt><code>gc()</code></dt> <dd>Synchronously performs garbage collection.</dd>
</dl>
<h2 name="Handles">Handles</h2>
<p>Messages that communicate between the browser and jetpack process may contain only serializable (JSON) data and <em>handles</em>. A handle can be used to provide context for messages. Either the browser or the jetpack implementation may create one.</p>
<p>A handle keeps any arbitrary properties attached to it alive, but those properties are not transmitted across the process boundary. These arbitrary properties are the primary means through which context can be provided for messages; for instance, if the handle is meant to represent a network request, an <code>XMLHttpRequest</code> instance can be attached to the handle on the chrome process.</p>
<p>Because a handle's existence crosses process boundaries and cross-process garbage collection does not exist, the lifetime of a handle needs to be controlled manually by code. By default, a handle is rooted in the JavaScript interpreter's garbage collector, meaning that even if a process throws it away, it will not be garbage collected unless the other process explicitly does something to indicate that it is no longer needed. If that other process does not do something explicit and simply removes all references to it, the handle remains rooted yet unreachable in both processes and a memory leak is created.</p>
<p>To prevent such memory leaks, a process can either <em>invalidate</em> a handle, immediately preventing it from being passed as a message argument, or it can <em>unroot</em> the handle, allowing it to be passed as a message argument until all references to it are removed, at which point it is garbage collected.</p>
<p>Handles have the following native methods and properties:</p>
<dl> <dt><code>invalidate()</code></dt> <dd>Invalidates the handle. Either process may invalidate a handle when it is no longer useful.</dd> <dt><code>createHandle()</code></dt> <dd>Creates a child handle which becomes invalid when its parent does. This is useful for associating handles to the lifetime of a particular window, context menu, or other element, and helping ensure that they do not leak.</dd> <dt><code>parent</code></dt> <dd>The parent handle of the object, if any. Read-only.</dd> <dt><code>isValid</code></dt> <dd>Whether the handle is still valid or not. Read-only.</dd> <dt><code>isRooted</code></dt> <dd>Whether the handle is GC rooted or not. Read-write.</dd> <dt><code>onInvalidate</code></dt> <dd>A callback to call when the handle is garbage collected, either through an explicit call to <code>invalidate()</code> or being unrooted and then unreachable. The callback is only called from the process that the handle <em>was not</em> garbage collected in. Read-write.</dd>
</dl>
<h2 name="History">Special Messages</h2>
<dl> <dt>core:process-error(context)</dt> <dd>When the jetpack process crashes, this message is sent to the parent. If a crash report minidump is available, the <span style="font-family: Courier New;">context.dumpID</span> property will list the minidump ID of the crash report that was collected.</dd> <dt>core:exception(error)</dt> <dd>When an exception occurs in a Jetpack script and is not caught, this message is sent to the parent. The error object contains the following properties: <span style="font-family: Courier New;">fileName</span>, <span style="font-family: Courier New;">lineNumber</span>, and <span style="font-family: Courier New;">message</span>.</dd>
</dl>
<h2 name="History">History</h2>
<p>See {{ Bug("556846") }} and {{ Bug("578821") }} for details.</p>
<h2 name="Sample_Code">Sample Code</h2>
<p>For example code, check out the {{ source("js/jetpack/tests/unit/","unit tests") }}.</p>
<h2 name="See_also">See also</h2>
<ul> <li>{{ Interface("nsIJetpackService") }}</li> <li>{{ Interface("nsIJetpack") }}</li>
</ul>
Revert to this revision