Search code examples
javascriptfirefoxfirefox-addonfirefox-addon-sdk

Force restart on install and upgrade of Firefox Add-on-SDK based extension


I have Firefox Jetpack Add-on-SDK based extension that is built not in the best way - after reinstall some old XPCOM components are hanging in memory and it is unable to register new one. So, I need to force browser restart on extension update/install. I know older version does this by default, but this one is restartless.

So my question is: how can I force the browser to restart on extension upgrade? I have looked into package.json and found nothing.


Solution

  • My expectation is that you are basically SOL if your desire is to try to mark your Add-on SDK extension as non-restartless. The Add-on SDK produces a restartless extension that uses the standard restartless startup methods. So, effectively anytime you create an Add-on SDK add-on you have really created a restartless add-on that is wrapped by the Add-on SDK.

    You could change, in the install.rdf file created when you jpm xpi, the following line:
    <em:bootstrap>true</em:bootstrap>
    to
    <em:bootstrap>false</em:bootstrap>
    which would cause your extension to be seen as a non-restartless add-on. It would be treated by Firefox and Mozilla Add-ons as an extension which requires a restart to be enabled/disabled.

    However, doing so would cause your add-on to not function. The entry points to your add-on would never be called.

    Thus, you must force the restart on your own.

    You will need to store a preference that indicates that you have, or have not, restarted (i.e. so that you do not end up restarting continuously). See:

    You should open a dialog/panel (MDN add-on SDK panel API) with the user to inform them that a restart is required in order for your add-on to function and provide them with the option to restart at that time, or to wait. See: Addon SDK way to make a dialog

    In one of my add-ons, Change Profile's Window Icons, there is the need to restart in order to have changes take full effect (not restarting only results in partial effect). I inform the user of that need and provide the option for them to do so from the options dialog. The dialog looks like:
    Change Profile's Icon Options Dialog

    In this dialog, the button Accept changes and Restart Firefox will do what it says, and restart Firefox. The code I use to restart Firefox is:

    window.opener.content.document.getElementById('cmd_restartApp').doCommand();
    

    This uses the restart capability that is built into Firefox to perform the restart. Thus, there is no need to keep that code updated if there are changes in the exact methodology of how a restart must be performed, or any housekeeping associated with doing so.

    How, exactly, you would call that function depends on the context you are in when you want to do so. In part, this will depend on how you implement informing the user that a restart is required and provide them the option to do so now or later. Given that you have not specified this in the question, it is not possible to tell you exactly the code that you need to use in order to cause the restart. However, in general, you will need a reference to one of the base Firefox windows. You can obtain that reference by any of a variety of methods depending on how you are implementing the interaction with the user.

    One way would be:

    if (window === null || typeof window !== "object") {
        //If you do not already have a window reference, you need to obtain one:
        //  Add/remove a "/" to comment/un-comment the code appropriate for your add-on type.
        //* Add-on SDK:
        var window = require('sdk/window/utils').getMostRecentBrowserWindow();
        //*/
        /* Overlay and bootstrap (from almost any context/scope):
        var window=Components.classes["@mozilla.org/appshell/window-mediator;1"]
                             .getService(Components.interfaces.nsIWindowMediator)
                             .getMostRecentWindow("navigator:browser");        
        //*/
    }
    if (typeof document === "undefined") {
        //If there is no document defined, get it
        var document = window.content.document;
    }
    
    //Then restart:
    document.getElementById('cmd_restartApp').doCommand();
    

    Portions of the above code were copied from other answers of mine, including this one, or from an extension I wrote.