Running Extension Code In Another Process
In order to support running Jetpack-style extensions in another process, Firefox 4 has support for running arbitrary JavaScript code in a separate process. Although this code was designed primarily to support the Jetpack SDK, Firefox and extensions can use this support to run arbitrary code in a separate process.
Running code in a separate process has advantages similar to running code in a separate thread. The running code will not block the main Firefox user interface. An added advantage is crash protection: if the code causes a crash, it will not take down the entire browser. There may also be some performance benefits from separating the garbage collection heaps and avoiding XPCOM overhead.
The basic steps to start a subprocess and run code in it are as follows:
var process = Components.classes["@mozilla.org/jetpack/service;1"]. getService(Components.interfaces.nsIJetpackService).createJetpack(); process.evalScript("Put your JS here"); // When you are done with the process, you should explicitly destroy it. process.destroy();
Of course, running a script in another process isn’t that useful unless you can communicate with it. This is accomplished by passing messages back and forth. To send a message to the remote process, use process.sendMessage:
process.sendMessage("messageName", param...)
To receive messages from the remote process, register a receiver function:
process.registerReceiver("messageName, function(messageName, argument...) { ... });
The remote process has access to a similar set of global functions, as well as the ability to create sandboxes and use ctypes. For more information about the full capabilities, see the Mozilla Developer Center documentation. Note that code running in a jetpack-style process does not have access to XPCOM, because XPCOM is not started in the jetpack process; it runs code using only the JavaScript engine.
If an extension is using ctypes to work with third-party code or OS libraries, I strongly encourage that extension to consider running the code in a separate process for crash protection. If an extension has long-running or computationally expensive tasks, it might make sense to move those into a separate process as well. If nothing else, it will make it much easier to measure the CPU and memory usage of that code separate from the rest of Firefox.
December 3rd, 2010 at 7:01 pm
This is very cool!
I’m curious about the crash protection though – given that only JS code is running, shouldn’t that be immune to crashes anyhow? I guess it would protect against JS engine bugs. But it seems less significant than the other benefits mentioned (which are huge!), unless I am missing something?
December 3rd, 2010 at 8:13 pm
Cool stuff. Since this is really similar to web workers, is there any reason why it doesn’t use the same API? sendmessage could have been called postmessage pretty easily, no?
December 3rd, 2010 at 8:48 pm
We have a sorta similar messaging system with the IPC message manager. Would we want to harmonize these APIs?
For example, IPC message manager has “sendSyncMessage” and “sendAsyncMessage”. The Jetpack process has “callMessage” and “sendMessage”. Also, the way the message parameters are pass is different: JSON literal object in IPC versus individual parameters in Jetpack.
December 6th, 2010 at 3:03 am
nice to see firefox 4 support this.
December 6th, 2010 at 11:01 am
Azakai, that’s why I mentioned ctypes: it’s really easy to crash ctypes if you’re not careful.
sil/mfinkle: Obviously there are parallels here. I think that this API is better than the current message-manager names, and we should switch to these names (perhaps with backwards-compat sendSyncMessage/sendAsyncMessage). As for DOM workers, the actual mechanics are very different, because we don’t have windows or DOM events.
December 7th, 2010 at 1:43 pm
Benjamin, are there any other jetpack APIs exposed in that process? Are there plans to add more APIs to that context?
I’m thinking in the way of “oh, I can haz `node.js`-ish something on gecko’s js engine to do things on the side”.
December 14th, 2010 at 6:47 pm
Axel, I don’t understand the question. The primitives are limited to the ones that are documented, but you can run any JS you want in the process…