Search code examples
javascriptfirefoxfirefox-addonipcxpcom

The recommended way to run binary from Mozilla extension (with std I/O communication)?


I am developing a Firefox extension and would like to call an external binary from it. It would be great if I could use standard input/output to communicate, so I am looking for the best (and simplest) possible option. This is what I learnt so far:

  • nslProccess is not suitable, since I need to get string as a return value. nslProccess can provide exit codes only.
  • I could use XPCOM but I would prefer if I didn't need to modify code of the binary (it's C, BTW). I would also like to make the most portable solution possible.
  • Protozilla IPC looks like a solution, but I'm not sure if this project is maintained. Last commit was 10 years ago.

As I understood, this functionality is implemented in Enigmail, which uses command line gpg tool. Does anyone have some specifics on that?


Solution

  • From all I know, Enigmail uses a binary XPCOM component to achieve this, usually this isn't a viable solution for an extension. And communicating with another process via standard input/output isn't part of the Gecko platform. So I think that you have three options:

    1. Use js-ctypes to call the necessary OS functions directly. E.g. on Windows you would call CreateProcess and specify handles for the standard input/output in the lpStartupInfo parameter. Of course you would also have to use OS functions to work with the streams. This quickly gets very hairy if you need to support multiple operating systems.
    2. Use the shell to redirect output. See this answer on how running a command with the shell works on Windows, on Unix-like systems you would use "/bin/sh" instead of env.get("COMSPEC"). You could write the input data for your command line application into in.txt and then run the command foo < in.txt > out.txt - the output will be in out.txt when the command is done. Obviously, this will not work if you need to interact with the application while it is running.
    3. You could change the application to use a different IPC approach, one that is supported by the Gecko platform. Typically that would mean using TCP sockets bound to localhost. Or you turn it into a dynamic library (.dll on windows, .so on Unix-like systems) and communicate with it via js-ctypes.