Loading a native library in Firefox via the Add-ons SDK
Thursday, October 2nd, 2014Contact: mar10 a krutt punto org
In this tutorial we are going to discover how to use a small c library written by ourselves inside Firefox.
This tutorial assumes that you have a working GNU/Linux distribution with a gcc environment installed. Here we use Ubuntu, however all the steps must work for any POSIX system in which the Add-ons SDK runs.
Requirements:
- A working gcc compiler. I am using gcc 4.8.2
- A text editor
- Firefox. I am using Firefox 32.0.3
- The Add-ons SDK installed. I am using Add-on SDK 1.17
Please go to Mozilla Add-ons SDK to get familiar with the SDK and specially with the cfx tool.
We could use any system library (shared object) in order to demonstrate how to use the Add-ons SDK. However I prefer the long way. We start by coding our own c-library. After that, we will start with the add-on.
Step 1: Preparing the directories
Open a terminal, and create a working directory, i.e. do something like:
mkdir example example/c example/add-on
After that, you would have the following directories:
. |- example |-- add-on |-- c
Step 2: Creating the library
We need to write some C code in order to produce a shared object. Copy the following to a file named example.c
inside the c directory:
#include <stdio.h> int sum( int a, int b ) { int c; FILE *f; c = a+b; f = fopen("output.txt", "a"); fprintf(f, "%d + %d = %d\n", a, b, c); fclose(f); return c; }
This code just prints the sum of two numbers. Each time this function is called, it will append a new line to file output.txt
.
Compile it with the following commands:
gcc -Wall -Wextra -std=c89 --pedantic -fPIC -c example.c -o example.o gcc -shared example.o -o libexample.so
After that, you will have something like this:
. |-- example |-- add-on |-- c |-- example.c |-- example.o |-- libexample.so
From a terminal at the example
directory, run the following:
file c/libexample.so
you would see this:
c/libexample.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=..., not stripped
Note that now we have a shared object (libexample.so
) that must be installed in the target system in order to be consumed by Firefox.
Step 3: Installing the library
In order to use the library in our target system, we must install it. Assuming that you are at the example directory, do this:
sudo cp c/libexample.so /usr/lib sudo chmod 0755 /usr/lib/libexample.so
If everything went fine, you must have libexample.so
in /usr/lib
. Now do this:
sudo ldconfig ldconfig -p | grep example
You must see something like this:
libexample.so (libc6,x86-64) => /usr/lib/libexample.so
This means that you have successfully installed libexample.so
, and that your system will be able to load libexample.so
when asked by an application.
Step 4: Testing the library
Create a file named example/c/main.c
with the following content:
#include <stdio.h> int sum( int a, int b ); int main() { int ret; ret = sum(1, 2); printf("1 + 2 = %d\n", ret); return 0; }
Go to example/c
. Compile main.c
, as follows:
gcc -Wall -Wextra -std=c89 --pedantic -c main.c -o main.o
And now, link the object file (main.o
) with the library:
gcc main.o -lexample -o main
Use the ldd
command to review the new executable file:
ldd main
You must see something like this:
linux-vdso.so.1 => (0x00007fff02fc1000) libexample.so => /usr/lib/libexample.so (0x00007f4c82181000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4c81dbb000) /lib64/ld-linux-x86-64.so.2 (0x00007f4c823a8000)
Run the executable:
./main
It must print 1 + 2 = 3
.
Step 5: Creating the add-on
Here we make use of the Add-ons SDK. Go to the add-on
directory and run:
cfx init
This command will create a template for the add-on. Your add-on
directory now have the following structure:
. |-- example |-- add-on | |-- data | |-- lib | | |-- main.js | |-- package.json | |-- test | |-- test-main.js |-- c |-- example.c |-- example.o |-- libexample.so |-- main |-- main.c |-- main.o
Customizing packaje.json
Open the packaje.json
file, you will see this:
{ "name": "add-on", "title": "add-on", "id": "jid1-k4igzLTBAsNAew", "description": "a basic add-on", "author": "", "license": "MPL 2.0", "version": "0.1" }
You can change the information contained in packaje.json
. These fields will be visible inside the Firefox’s add-ons manager.
For example, you could put this in the packaje.json
file:
{ "name": "mar10_add-on", "title": "add-on example", "id": "jid1-k4igzLTBAsNAew", "description": "a basic add-on", "author": "mar10", "license": "MPL 2.0", "version": "0.1a" }
The value of the "name"
field will be used by the cfx
tool to name the xpi
add-on file.
Open the main.js
file and copy this:
/* import js-ctypes */ var {Cu} = require("chrome"); var {ctypes} = Cu.import("resource://gre/modules/ctypes.jsm", null); /* Open the library */ try { var libexample = ctypes.open("libexample.so"); /* * remember that our c-function is of the form: * int sum( int a, int b ) */ var sum = libexample.declare("sum", /* function name */ ctypes.default_abi, /* call ABI */ ctypes.int, /* return type */ ctypes.int, /* argument type */ ctypes.int); /* argument type */ var num_a = 1; var num_b = 2; var ret = sum( num_a, num_b); console.log("Result: " + num_a + " + " + num_b + " = " + ret ); libexample.close(); } catch (e) { console.log("Error while loading lib: " + e); }
Run the following command:
cfx run
You will see something like this:
console.log: mar10_add-on: Result: 1 + 2 = 3
Perhaps you will find more information coming from Firefox, i.e. some GLib-GObject
warnings. Don’t pay attention to those messages.
At the same directory, you will find the output.txt
file with the same information you just saw at the terminal!
To create the xpi
file, run the following command at the example/add-on
directory:
cfx xpi
This creates the mar10_add-on.xpi
file. Now you can import this add-on to Firefox.
Step 6: Importing the add-on to Firefox
Just press Ctrl+O
to launch the open file dialog. Select the xpi
file and
click open
. In my case the add-on is mar10_add-on.xpi
.
A new window will appear. Click Install Now
.
Go to the Add-ons manager and click on Extensions
:
Now click on More
over our recently installed add-on, you will see something like this:
Once the add-on is installed, our library libexample.so
is executed each time Firefox is initiated, inclusive at the moment the add-on was installed!!!
Now write the following command:
cat output.txt
The content of output.txt
must be: 1 + 2 = 3
, awesome!!!. Each time you start Firefox, you will append a new line with the same content to output.txt
.
Step 7: Running Firefox
Run Firefox from a terminal:
/usr/bin/firefox
The output.txt
file will be created inside the directory that you use to call Firefox.
If you run Firefox by clicking over an icon in the desktop or via another graphic element, the output.txt
file will be created at $HOME
directory.
Final remarks
As you can see, this add-on is almost useless. There is no interaction with the browser, or with the user. However, now you are able to compile and load native libraries in Firefox!!!
See also
Download
Here you can get the code of this tutorial.
License
Copyright (C) 2014 mar10
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license can be found here.