Electrolysis/Jetpack: Difference between revisions
m (Add clarification) |
m (Clarifications about existing CPOW limitations) |
||
| Line 48: | Line 48: | ||
} | } | ||
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 Jetpack CPOW callback using a content CPOW document object (assuming content processes exist). | ||
Note that the solutions as described are currently un-implementable, because there's no way to pass | Note that the solutions as described are currently un-implementable for certain circumstances, because there's no way to pass chrome objects to the CPOW callback as a parameter. We need reverse (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. | ||
Revision as of 16:59, 26 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 Jetpack CPOW callback using a content CPOW document object (assuming content processes exist).
Note that the solutions as described are currently un-implementable for certain circumstances, because there's no way to pass chrome objects to the CPOW callback as a parameter. We need reverse (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.
Accessing windows
Some jetpacks do things like the following:
var win = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator)
.getMostRecentWindow("navigator:browser");
I'm not yet sure what the best way to deal with this is. Perhaps create an API that wraps the window mediator and allows you to get specific window CPOWs in well-defined ways? Perhaps proxying the window mediator component to return CPOWs or something?