Electrolysis/Jetpack: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
mNo edit summary
mNo edit summary
Line 16: Line 16:


In the chrome process:
In the chrome process:
   function onReady(callbackObj) {
   function onReady(callbackObj) {
     associateCallbackWithDOMDocumentLoaded(callbackObj.callback);
     associateCallbackWithDOMDocumentLoaded(callbackObj.callback);
Line 41: Line 40:
       let child = getCPOW(m.target);
       let child = getCPOW(m.target);
       JetpackEnv.Tabs.onReady(child.jetpack.Tabs.params[m.json.callback]);
       JetpackEnv.Tabs.onReady(child.jetpack.Tabs.params[m.json.callback]);
     }
     });


   Tabs = {
   Tabs = {
Line 51: Line 50:
In either instance, the chrome process will end up calling the CPOW callback using a CPOW document object (assuming content processes exist).
In either instance, the chrome process will end up calling the CPOW callback using a CPOW document object (assuming content processes exist).


Note that the solutions as described are currently un-implementable, because there's no way to pass the document object to the CPOW callback as a parameter.  We need chrome->jetpack CPOWs for that to work, and they don't exist yet.
Note that the solutions as described are currently un-implementable, because there's no way to pass the document object to the CPOW callback as a parameter.  We need chrome -> jetpack CPOWs for that to work, and they don't exist yet.


The upside is that jQuery should Just Work as soon as the chrome -> jetpack CPOWs do exist.
The upside is that jQuery should Just Work as soon as the chrome -> jetpack CPOWs do exist.


Please note that the above code is very much simplified from the actual implementation.  One complication is that <bsendAsyncMessage</b> is not accessible at document level.  Instead, you need code like the following to implement proxying:
Please note that the above code is very much simplified from the actual implementation.  One complication is that <b>sendAsyncMessage</b> is not accessible at document level.  Instead, you need code like the following to implement proxying:


From a script loaded into the remote jetpack process via loadFrameScript:
From a script loaded into the remote jetpack process via loadFrameScript:

Revision as of 04:46, 19 March 2010

In order to move Jetpack to an out-of-process implementation, a mixture of CPOWs and proxying appears to be necessary. I've encountered one main issue that must be considered:

Using callbacks

Given an API that allows the following:

   jetpack.tabs.onReady(
     function(doc) {
       $("#list", doc).appendChild(listElem);
     }
   }

Certain design choices are necessitated by the limitation of CPOWs - namely, functions cannot be sent directly between processes. Therefore, there are two choices:

1. any API that currently takes a callback must instead take an object with a named callback

In the chrome process:

 function onReady(callbackObj) {
   associateCallbackWithDOMDocumentLoaded(callbackObj.callback);
 }

In the Jetpack process, the jetpack.tabs object can theoretically be a CPOW to the chrome Tabs object, and everything should work fine.

2. any API that currently takes a callback can continue to do so, but must proxy the call

In the jetpack process:

 Tabs = {
   onReady: function(callback) {
     let uniqueSignature = new Date.time().toString();
     this.params[uniqueSignature] = callback;
     sendAsyncMessage("tabs.onReady", {callback: uniqueSignature});
   }
 }

In the chrome process:

 addMessageListener("tabs.onReady",
   function(m) {
     let child = getCPOW(m.target);
     JetpackEnv.Tabs.onReady(child.jetpack.Tabs.params[m.json.callback]);
   });
 Tabs = {
   onReady: function(callback) {
     associateCallbackWithDOMDocumentLoaded(callback);
   }
 }

In either instance, the chrome process will end up calling the CPOW callback using a CPOW document object (assuming content processes exist).

Note that the solutions as described are currently un-implementable, because there's no way to pass the document object to the CPOW callback as a parameter. We need chrome -> jetpack CPOWs for that to work, and they don't exist yet.

The upside is that jQuery should Just Work as soon as the chrome -> jetpack CPOWs do exist.

Please note that the above code is very much simplified from the actual implementation. One complication is that sendAsyncMessage is not accessible at document level. Instead, you need code like the following to implement proxying:

From a script loaded into the remote jetpack process via loadFrameScript:

 addEventListener("tabs.onReady",
   function(event) {
     var signature = event.getData("signature").QueryInterface(Components.interfaces.nsIVariant);
     sendAsyncMessage("tabs.onReady", {callback: signature});
   }, false, true);

In the Jetpack process implementation:

 Tabs = {
   onReady: function(callback) {
     let uniqueSignature = new Date.time().toString();
     this.params[uniqueSignature] = callback;
     
     var eventDoc = document.QueryInterface(Ci.nsIDOMDocumentEvent);
     var event = eventDoc.createEvent("datacontainerevents");
     var container = event.QueryInterface(Ci.nsIDOMDataContainerEvent);
     var variant = Cc["@mozilla.org/variant;1"].createInstance(Ci.nsIWritableVariant);
     variant.setAsAString(uniqueSignature);
     container.setData("signature", variant);
     event.initEvent("tabs.onReady", true, false);
     window.dispatchEvent(event);
   }
 }

Still, that's just an implementation detail.