HOWTO: Calling into Mozilla C internals from JavaScript

July 13, 2012 § 13 Comments

I have been using js-ctypes to call into libxul from JavaScript, to I figured I should share the recipe.

Several versions ago, Firefox, Thunderbird and other applications using the Mozilla Platform (aka Gecko) started shipping with js-ctypes, a very powerful foreign function interface for JavaScript. Using this mechanism, privileged JavaScript code can call into native libraries. Since then, js-ctypes has been used to implement all sorts of tools, from interaction with MacOS X GUI to direct calls to the Linux kernel to scripting Dalvik, the Android JVM.

One of the interesting and less-known features of js-ctypes is that you can also use it to call into Gecko internals. You can use it to script a number of previously inaccessible Gecko features. I personally use it to permit access the Unicode conversion primitives of Gecko, and to help me with serialization of js-ctypes values, but there is no reason to not use it for other things, such as testing native libxul code from JavaScript.

Caveat This is a hack. Doing this may void your warranty. Also, if I were reviewing an add-on that depends on this, I would reject it. You have been warned.

Let’s see how. At the time of this writing, the following steps require a recent Nightly build of Firefox/Thunderbird/… but the feature should be available shortly to released versions.

Import js-ctypes and OS.Constants.

Components.utils.import("resource://gre/modules/ctypes.jsm");

Components.classes["@mozilla.org/net/osfileconstantsservice;1"].
 getService(Components.interfaces.nsIOSFileConstantsService).
 init();

If your code is executed in a worker thread, this extract is not required.

If you are running an older version of Firefox (i.e. anything except a recent Nightly), you will need to replace the references to nsIIOSFileConstantsService/OS.Constants with more verbose calls to xpcom, and this will work only on the main thread.

Open libxul

libxul is the native library that contains the Gecko internals. To open it,

let libxul = ctypes.open(OS.Constants.Path.libxul);

Play with it!

You are basically done. Now, you can import any C function (or a number of C++ functions, with a little more effort) to JavaScript. Let’s see how to import function DumpJSStack, for instance. This function is part of the JavaScript Virtual Machine. As its name implies, it prints the JavaScript stack. Not very useful for us at this stage, as JavaScript can print its own stack quite easily, but a good way to test our toy.

The definition of DumpJSStack is the following:

extern "C" void DumpJSStack()

In other words, this function takes no argument, returns nothing and is designed to be called from C (or from js-ctypes). This makes it an ideal candidate to import it with js-ctypes:

let dumpJSStack = libxul.declare("DumpJSStack",
  ctypes.default_abi,
  /*return*/ ctypes.void_t);

We can now use the function as if it were a regular JS function:

dumpJSStack();

(prints some information about how you got to this point – works only from the main thread)

Play with it: printf_stderr

We can similarly import function printf_stderr, which is often quite useful for debugging:

extern "C" void printf_stderr(char* fmt, ...);

To import it:

let printf_stderr = libxul.declare("printf_stderr",
 ctypes.default_abi,
 /*return*/ ctypes.void_t,
 /*fmt*/ ctypes.char.ptr,
 /* ... */ "...");

More features

There are many more features that can be accessed through libxul and that go beyond the scope of this blog entry. Let us simply list a few of them.

What about:

  • walking the native stack using NS_StackWalk? see file nsStackWalk.h for more details;
  • interacting with other processes using PR_CreateProcess, PR_WaitProcess, PR_KillProcess? see prprocess.h for more details;
  • using the built-in cryptographic features of the Mozilla Platform? see nss/* for more details;

and certainly more…

Note that, by opposition to XPCOM-based calls, most js-ctypes based calls work from all threads.

About these ads

§ 13 Responses to HOWTO: Calling into Mozilla C internals from JavaScript

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

What’s this?

You are currently reading HOWTO: Calling into Mozilla C internals from JavaScript at Il y a du thé renversé au bord de la table.

meta

Follow

Get every new post delivered to your Inbox.

Join 32 other followers

%d bloggers like this: