Menu

Restartless Addons - Lessons learned

At first I thought building a restartless addon is an easy task, but it's not.

The whole restartless stuff looks as if someone stopped half way. The Interfaces are badly designed, you have to use ugly hacks and there is only little to no documentation.

Let's summarize what I stumbled upon.

Minimum Gecko 8.0

Before restartless can be considers as broken and unusable. Why? It neither supports chrome or resource urls! So you need to define you own resource urls protocol. But various components like the Account manager can't handle this kind of urls. No workarounds possible, simply broken. But the good news is Gecko 8.0 introduced chrome urls for restartless...

XPCOM Components

Despite other statement you can use XPCOM Components with restartless. You might remember Gecko 2.0 introduced a shiny new way to register components? You can forget about that, and go back to your Gecko 1.x code. You have to register the old school way a factory. But keep in mind everything you registered you also need to unload.

Overlays

Overlays are not supported. So you end up using window listeners to wait for new windows. And the either load overlay dynamically or inject you Dom elements directly. But be warned loading overlay dynamically has various side effects. So I suggest to always use the hard way an insert DOM elements manually. As a positive side effect cleanup is way easier.

I actually expected Mozilla had added some helpers to make live easier. But there is nothing no documentation, no examples and no hints what you should do an what you should not do. One of the few usable Examples is here Playing with windows in restartless (bootstrapped) extensions

nsIWindowMediator

nsIWindowMediator is good for detecting new windows, but do not attempt to use it's onCloseWindow Listerner Method. The onCloseWindow is fired before(!) a window's onunload event! When you unload in the onCloseWindow Method an Module, all your onunload events relying on this Module possibly will fail.

The workaround is to use your own implementation and detect manually when a window is closed. When nsIWindowMediator detects a new Window, just add a unload listener. This listener will fire upon unload and gives you a chance for a clean shutdown.

See (SieveOverlayManager.jsm)[http://sourceforge.net/p/managesieve/code/ci/master/tree/src/sieve%40mozdev.org/chrome/chromeFiles/content/modules/overlays/SieveOverlayManager.jsm] for a live example.

Locales

It's impossible to use DTD Files and string bundles are broken. String bundles are cached, and this cache is not flushed upon update. One way is to bypass this cache by calling createBundle for every string you need.

Tabtypes & Interfaces

There are many interfaces like tabmail. They offer an add method but no remove. So you can add new tabtypes but you cannot remove them. There is simply no such method. So you endup having to restarting in order to update your restartless addon...

(SieveOverlayManager.jsm)[http://sourceforge.net/p/managesieve/code/ci/master/tree/src/sieve%40mozdev.org/chrome/chromeFiles/content/modules/overlays/SieveOverlayManager.jsm] implements removeTabType() It's a workaround to remove tabmodes on the fly. Be warned it's a hack.

Style sheets

You have to call upon load document.createProcessingInstruction() and add it to the document. And remove it upon unload.

Toolbar buttons

Just look at the code an you'll see the mess (SieveOverlayManager.jsm)[http://sourceforge.net/p/managesieve/code/ci/master/tree/src/sieve%40mozdev.org/chrome/chromeFiles/content/modules/overlays/SieveOverlayManager.jsm].

First of all you need to add a tooblar button to the palette. As the palette is already fully loaded adding is not enought. You need to manually insert the button into the toolbars at the right position.

Import vs Unload

Components.utils.mport and Components.utils.unload follows a singleton pattern. They do not pair up like a constructor and deconstructor. You can call import as often as you want, there will be only one module loaded into memory. But you can call unload only once per module! If you call it your module will be immediately removed.

One way to get around this is just loading all modules upon startup and removing them upon shutdown. If your restartless module is big but seldomly used you end up wasting megabytes of memory for noting. A good example how a bad interface design bloats the memory usage and why Gecko applications need by design so much memory.

The other way is implementing a collector mechanism. As context I am using Chrome windows. So I started with implemented a wrapper around import.
When you need a module you call this wrapper pass the url and the window. Internally it maintains a list with keeps book on which modules are used in which windows. If the wrapper detects a window is closed, it loops though these lists and checks for modules without any windows associated. Finally calls unload to remove these. It's simple but very efficient.

During normal runtime the sieve extension just adds four modules to you memory. Two of these are xpcom modules, one is the collector and one the bootstrap compartment. That as little as you can get. If you open the script editor you will have roughly 20 modules in memory, but they will be gone as soon as you close the editor window...

If you are interested how it works, check out
(SieveOverlayManager.jsm)[http://sourceforge.net/p/managesieve/code/ci/master/tree/src/sieve%40mozdev.org/chrome/chromeFiles/content/modules/overlays/SieveOverlayManager.jsm]

But don't ask me why Mozilla did not implement an ship such or a similar mechanism.

Summary

I actually do not understand why Mozilla did such a lousy job with restartless addons. It seems to me that Mozilla hired a professional code monkey to hack this part. This contractor just implemented all basic requirement without ever thinking about what a potential user might need and what not. Just fulfilling the requirement - the typical way how software development works in a big company.

Mozilla should have invested more resources in restartless. They should focus on building more solid and clean apis as well as a good documentation. This would improve code quality and Firefox would be less memory hungry and I suppose become better and faster.

I personally get more and more the impression Mozilla is currently mismanaged. It's run like a big company but the management is not capable of generating new product ideas and visions. They are currently just reusing ideas that worked out for others and are struggling to re implement those. To be honest they are currently just copying Google...

Posted by Thomas Schmid 2012-07-13 Labels: mozilla restartless thunderbird bootstrap bootstraped

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.