Hooking app exit in Firefox extensions

Posted by chetan on February 10, 2010 in development, work

I’ve spent the last few days since joining Better Advertising working on a new feature for a Firefox extension called Ghostery. We’ll be announcing the new feature soon, but until then I thought I’d share some of what I’ve learned so far.

I’ve never worked on an extension before but as it turns out, it’s really quite easy to pick up; some fairly simple XML (aka XUL) for composing the UI and JavaScript for the rest. One of the trickier bits has to do with scope. After doing some testing I figured out that the entry point into an extension is via the browser window; that is, your extension code will be executed each time you open a new window and that means that all your code is basically scoped to a single window.

In developing the new Ghostery feature I needed a way to run some code when the user quits Firefox. Luckily, the extension architecture is extremely flexible (if poorly documented at times) and I didn’t have to jump through any hoops to do it. Almost anything, it seems can be either chained or hooked in some way. In this case, the nsIObserverService gives us access to the necessary shutdown event to which we can attach an observer using a simple interface.

The problem, then, was that since our code is run every time a new window is created, I needed a way to register the hook only once to avoid firing multiple times on exit. My first thought was to try to register the hook outside of the window scope (e.g. using a different chrome overlay) but that appeared to be a dead end. Using a globally scoped variable as a lock was also a dead end. In the end I settled on something I already knew how to use: preferences. Essentially, I created a simple lock around a preference variable which, while I don’t need to store it between sessions, is in fact a global storage area that can be accessed from different windows.

Check out the code below for an example implementation. I left out the actual preferences code since it’s not crucial to understanding the solution.