Look Ma, no restarts!

An extension installed without restarting Firefox

This is a screenshot of some of my latest (and most exciting) work on my project to rewrite the extension manager. I’ve just implemented support for a special kind of extension that can install (and uninstall, and enable, disable, upgrade and anything else you can think of) without the user needing to restart Firefox. This is of course to allow add-ons developed on the Jetpack platform to install without restarts but the feature is going to be available to any extension author, there are just some restrictions to how these extensions work.

The precise spec for this isn’t final yet so I’m not going to show you precise examples but the basics are that unlike normal extensions the platform won’t load anything from the restart-less extensions except for one file. This simple JavaScript file will be called when the extension is loaded or unloaded allowing the extension to either set itself up or tear every trace of it out of the app. This may seem limited but there is actually very few things that an extension can’t do from this (and hopefully we’ll get those fixed), it just involves more manual work. Maybe we’ll simplify some of that in the future, but for now it’ll be pretty raw and ready for use. Of course the Jetpack platform basically does all the loading and unloading work for you…

19 thoughts on “Look Ma, no restarts!”

  1. Dave, I’m almost certain that you thought of that but just in case – please make sure that this can be used in a backwards-compatible way. In particular, I would like to use this feature from Adblock Plus while continuing to support Firefox 3.6. From your description this seems to be doable – in Firefox 3.6 all JavaScript files will be pulled in by an XPCOM component, in the future version it will be this simple JS file then. That simple JS file will hopefully run in its own context (BackstagePass?) and be loaded somewhere between profile-after-change and UI startup for regular initialization on browser startup. Then the only problem is tearing down overlays – the elements need to be removed manually I guess?

    1. Yeah the idea is that these extensions will still load in the normal way on versions of Firefox that don’t support this.

  2. Actually, now that I think about it – what you are describing means that no overlays will be applied automatically. Which means that you have to track new windows being opened and manually apply overlays to them. Some way to manipulate the internal overlays table would be better – analogous to what is usually done by chrome.manifest but with the ability to add/remove overlays dynamically while the application is executing (maybe some new methods on nsIToolkitChromeRegistry).

    1. Yeah this is part of what I meant about right now this being pretty raw and ready. Once this is in I expect we’ll start looking at things we can add to the platform to make using this kind of thing easier on developers.

  3. Blair McBride posted a link to the code and I got my answers from there. Suggestions:

    * Don’t use a regular object a scope for the bootstrap script. If that script tries to access global variables/functions it will get them from the scope of the extension manager module. As far as I know, the only way (from JS) to give this script a truly self-contained scope is using a Sandbox object: |let scope = new Components.utils.Sandbox(“chrome://global/content/”)|. Of course, the Sandbox object isn’t meant for that but it works well.

    * Don’t reload the bootstrap script every time you need to call one of its methods, make it persist. So rather than storing dir.persistentDescriptor in bootstrappedAddons, store the scopes of bootstrap scripts. This way the scope will only be released when the add-ons are disabled/uninstalled and replacing XPCOM components from “classic” extensions will be a lot simpler.

    1. Yep, the code there is just an early implementation, using a simple object was just a hack because there was no-one around on the weekend to remind me of the right way to do that 😉
      Not reloading the bootstrap is a good point, should be pretty simple to make that the case.

  4. Better late than never. This “feature” has been on Google Chrome for a long time. You better speed up your “copying” unless you (firefox) wanna stay relevant…

    1. Not quite, only newly created Chrome tabs get the extensions. Tabs that were running before an extension was installed don’t get the new extension, because of the very limited way Chrome extensions work.

    1. If someone were to fix the bugs relating to applying themes without restarting then yes we could switch this on for themes.

  5. Dave, thank you for implementing my suggestions – starts looking really good.

    Just out of curiosity: is there a particular reason you use |for (let i = 0; i < methods.length; i++)| rather than |for each (let method in methods)|? Somehow I always assumed that the latter is slightly faster because it immediately stores the member in a local variable rather than requiring you to access it by its index. But with TraceMonkey you cannot really know.

      1. I see. I prefer to keep Array.prototype alone and to strictly separate “arrays” and “maps”. But in your case it isn’t all under your control of course.

Comments are closed.