Electrolysis/Jetpack: Difference between revisions

replaced content w/ link to jetpack processes page on MDN
(→‎External Resources: linked to bug 556846)
(replaced content w/ link to jetpack processes page on MDN)
 
Line 1: Line 1:
In order to move [[Labs/Jetpack|Jetpack]] to an out-of-process implementation, a mixture of [[Electrolysis/CPOW|CPOWs]], [[XPConnect_Chrome_Object_Wrappers|COWs]] and proxying appears to be necessary.
The information on this wiki page was out-of-date and has been removed; see [https://developer.mozilla.org/en/Jetpack_Processes Jetpack Processes] on MDN for the latest information.
 
== Three contexts ==
 
When a Jetpack is implemented in a separate process, there will be at least three kinds of JS execution contexts:
 
=== Jetpack context ===
 
The jetpack JS itself will run in the jetpack process.
 
Predefined globals:
 
* <code>require()</code>
 
=== implementation-jetpack context ===
 
Part of the jetpack implementation runs in the jetpack process. It uses COW-type wrappers to expose functions and properties to the jetpack context. It also has some core functions which allow it to send synchronous or asynchronous messages to the browser process.
 
Predefined globals:
* <code>jetpack</code> - the jetpack context global, used to create <code>jetpack.require</code>
* <code>sendMessage("messageName" [, data]);</code> - sends asynchronously, no return value
* <code>callMessage("messageName" [, data]);</code> - sends synchronously, has return value
* <code>createHandle(object[, parentHandle]);</code> - returns handle object
* other special globals as necessary, e.g. ctypes would be exposed entirely within the jetpack process and wouldn't need to communicate with chrome
* <code>registerReceiver(messageName, func)</code> - incoming messages of the specified name
* <code>wrap(object)</code> - create a COW
 
=== implementation-chrome context ===
 
The rest of the jetpack implementation would live in the chrome process, primarily in a JS module. A method would exist (via XPCOM?) to bootstrap a jetpack:
 
<code>var ajetpack = createJetpackProcess();</code>
 
* <code>ajetpack.sendMessage("messageName" [, data]);</code> - only async messages are allowed
* <code>ajetpack.createHandle(object [, parentHandle]);</code>
* <code>ajetpack.loadImplementation(uri);</code> - load a script into the jetpack implementation context
* <code>ajetpack.loadUserScript(uri);</code> - load a script into the jetpack context
* <code>ajetpack.registerReceiver(messageName, func)</code>
 
=== Messages and 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 a handle. A handle keeps its associated JS object alive, and has the following properties:
 
* <code>handle.object</code> - the JS object associated with the handle
* <code>handle.parent</code> - the parent handle of the object, if any
* <code>handle.destroy()</code> - destroy the handle so that is is no longer valid
* <code>handle.isValid</code> - boolean, is this handle still valid?
 
A handle that is created without a parent stays alive until it is explicitly destroyed.
 
When a handle is created, a "parent handle" may be specified: a handle becomes invalid when its parent is destroyed. 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.
 
Either process may destroy a handle when it is no longer useful. For each handle type jetpack uses, the jetpack implementation should decide which side of the conversation is typically responsible for destroying a handle.
 
=== Example ===
 
This is a barebones example of how [[Labs/Jetpack/Reboot/JEP/109|JEP 109]], the request module, could be implemented:
 
Jetpack:
 
<pre>const Request = require("request").Request;
new Request({
url:      "http://example.com/",
onComplete: function() console.log(this.response.text)
}).get();</pre>
 
implementation-jetpack:
 
<pre>function jp_request(r)
{
  this._onComplete = r.onComplete;
  // ... set up the rest of this._stuff
}
jp_request.prototype = {
  __exposedProps__ = {'__call__': 'r', 'get': 'r', 'response': 'r'},
 
  get: function() {
    // create a cross-process handle for messsages relating to this request
    this._handle = createHandle(this);
    // send the browser a message to kick things off
    sendMessage("request_get", {url: this._url, handle: this._handle});
  },
 
  _handleResponse: function(data) {
    // Firefox just sent us data. Save it in this.response and then...
    this._onComplete();
  },
};
registerReceiver("request_done", function(data) {
  data.handle.object._handleResponse(data);
});
 
// Now hook up jetpack.require
jetpack.require = function(package) {
  switch (package) {
  "request":
    return { Request: jp_request };
  }
};</pre>
 
implementation-chrome:
 
<pre>var ajetpack = createJetpackProcess();
 
ajetpack.registerReceiver("request_get", function(data) {
  // perhaps do some kind of domain validation here based on jetpack metadata?
  var r = new XMLHttpRequest(data.uri, ...);
  r.addEventListener("load", function() {
    ajetpack.sendMessage("request_done", {
    responseText: r.responseText,
    handle: data.handle,
    });
  });
});
 
ajetpack.loadImplementation("chrome://jetpack/content/jetpack-implementation.js");
ajetpack.loadUserScript("resource://jetpack-repository/myjetpack.js");
</pre>
 
=== Unresolved Issues ===
 
This proposal doesn't really deal with jetpack-to-content communication at all, for pagemods, etc.  That's an easier question, in some ways: we can use CPOWs, and that already basically works. What we don't know is how to bootstrap it: given a jetpack and a content winow in chrome, how do we set up the machinery for jetpack/content communication?
 
cjones needs this for cross-process layers as well.  The basic idea will be that, in the chrome process, some code will do
<code>contentProcessParent.Bridge(jetpackParent, PJetpackContent)</code>
which will asynchronously open a new channel between the content and jetpack processes.  The new channel will talk <code>PJetpackContent</code> (or whatever that's called).  Haven't worked out the notification bits or how the new <code>PJetpackContent</code> top-level actors will be created, but probably the content and jetpack top-levels will get an <code>OnBridge()</code> notification and perhaps that will be where the actors will be required to be created.
 
== External Resources ==
 
* [https://developer.mozilla.org/en/Multi-Process_Architecture/Jetpack Multi-process Jetpack] on MDC
* {{bug|556846}} - Investigate multi-process Jetpack
874

edits