Bootstrapped Add-ons

Bootstrapped, also known as ‘restartless’, add-ons are a new class of add-ons for Gecko 2 (Firefox 4) which are installed, upgraded, enabled, and disabled all without an aplication restart. They can be identified by the presence of the em:bootstrapped flag in install.rdf. Rather than a chrome.manifest, these add-ons have a file called bootstrap.js in their root folder which is responsible for all startup and shutdown procedures of the add-on.


There are several challenges to reviewing bootstrapped add-ons when compared to traditional add-ons, the foremost being that we expect bootstrapped add-ons to leave as little trace of their presence as feasible when they are disabled. The following is a list of some of the more common actions which require cleanup when the add-on is disabled.

Component registration
Bootstrapped add-ons must manually register their components with the component manager (Components.manager) via the nsIComponentRegistrar.registerFactory method. These registrations must be removed at shutdown via a complimentary nsIComponentRegistrar.unregisterFactory call.
Category registration
Components and actions are often registered with the category manager via the nsICategoryManager.addCategoryEntry method. The fourth argument to this method should always be false and all such registrations must be removed at shutdown via a complimentary nsICategoryManager.deleteCategoryEntry call.
Various observers
Observers may be added via several methods, including nsIObserverService.addObserver, nsIWindowWatcher.registerNotification, and nsIPrefBranch2.addObserver. Similar event listeners may be added by means such as nsIWindowMediator.addListener. Whenever you come across one of these methods, or any objects implementing the nsIObserver interface or providing an observe method, you should make certain that these observers are removed via the appropriate method when the add-on is disabled.
resource: package registration
Many bootstrapped add-ons register resource: URI packages via the nsIResProtocolHandler.setSubstitution method. These substitutions must be cleared at shutdown by another call to the setSubstitution method with a null second argument.
DOM node additions
Any DOM nodes which are added to existing windows, including script and style nodes, must be removed when the add-on is disabled. Any attribute changes to existing nodes must likewise be undone. An exception may be made for injections into content pages so long as they continue to function when the add-on is disabled and further injections do not occur thereafter.
DOM event listeners
Any DOM event listeners added via the nsIDOMEventTarget.addEventListener property to existing nodes must be removed when the add-on is disabled. Listeners added to DOM nodes created by the add-on may be left intact since the nodes in question must be removed from the document at shutdown in any case.
The Stylesheet Service
Any stylesheets registered via nsIStyleSheetService.loadAndRegisterSheet must be reversed via a complimentary call to nsIStyleSheetService.unregisterSheet at add-on shutdown.
New windows and tabs
Any new windows and tabs containing content provided by the add-on, including documents provided by about: pages, resource: packages, and custom protocols, should be closed by the add-on when it is disabled.
JavaScript properties
JavaScript properties added to any DOM nodes or globals must be removed by bootstrapped add-ons at shutdown. New constants or non-configurable properties may not be added to existing objects.
JavaScript modules
Due to bug 564674, it is currently impossible to destroy JavaScript module globals once a module has been loaded. This means that all JavaScript modules must be cleared of any newly created objects on add-on shutdown to minimize leaked memory. Further, because compiled module code is cached, modules must be loaded from a different directory and via a different URL whenever their contents have changed between upgrades or they will continue to utilize their previous contents.
String bundles
The nsIStringBundleService is often used to access localized strings from property files. Because the string bundle service maintains a cache of recently accessed string bundles, the nsIStringBundleService.flushBundles method should be called on shutdown whenever a bootstrapped add-on creates a string bundle instance from a file provided by the add-on itself. This is not, however, necessary when the service is used exclusively to access property files provided by the platform.
Chrome registration
It is possible for bootstrapped add-ons to register chrome packages via the nsIComponentRegistrar.autoRegister method. Since there is no way to remove these registrations without a full restart, this method is not allowed for bootstrapped add-ons.

Testing procedures

Bootstrapped add-ons are expected to pass the same tests as any other class of add-on. Due to their special properties, however, the following additional testing procedures are recommended. No errors or untoward console output should appear during the course of any of these tests.