September 08, 2005
Mozilla Exec extension - finally working...

This is like Dashboard and Konfabulator, but for Firefox and Linux. A bit more like Dashboard actually - it combines the HTML/CSS/JS rendering with strong integration with the operating system. The main function of the extension is executing native code, and capturing the output or passing an input stream. Later, I want to integrate it with the kde/gnome app launchers, and start creating nice interfaces for everything that I usually do in the command line.

The firefox built-in support for executing OS commands is very weak - nsIProcess allows execution of a command, but there is no way to access the input and output streams. My extension is adding the pipes to control the streams - but the tricky part is how to make them work non-blocking, using async callbacks, like in Dashboard. Probably the 'right' way would be to use the event system, but I didn't find enough docs and it is pretty complex.

The solution I use may seem like a hack, but it works pretty well. Here's a short description for people who have similar problem:

  • create a nsIPipe. This is not a regular OS pipe, but works the same way allowing communication between mozilla threads. It also has built-in support for async notifications. That's the main driver.
  • create the regular OS pipe, that communicates with the process. Wrap it in an InputSteam - or copy the FDInputStream from my extension. It's weird that mozilla doesn't have such thing built-in. To get things working properly, you should wrap this in a BufferedInputStream.
  • use nsIAsyncStreamCopier to copy from the BufferedInputStream to the output end of the internal nsIPipe.
  • the AsyncInputStream end of the pipe can be used to generate nsIInputStreamCallback.
The nsIAsyncStreamCopier will do the copy in a separate thread. Unfortunately, javascript in mozilla can't be used from that thread - so I use the nsIPipe to get the data back to the javascript thread. The XMLHttpRequest seems to be using events for error and progress, and for all other handlers seems to do some magic with the javascript stack - but I couldn't get this to work, similar code constantly fails. I  guess the thread used by the AsyncStreamCopier is not properly initialized. I also didn't want to manually create the thread and deal with low level events - I may try later, just to understand how things work, but the docs and comments in code are far from perfect.

Not sure where to publish the extension  ( well, I need to clean it first ), but I already started to automate my command-line tools with html interfaces, and I really like it.

Posted by costin at September 08, 2005 10:09 PM
Disabled due to spam. Click on the link to post a comment, it'll be sent in email ( and thus usual mail spam filters and blacklist applied ). It may be made accessible later on, but code needs to be written for that. Comments