Background Updates
This page describes the technical plan to move the process of applying the updates in Firefox to the background as opposed to at startup. In order to get a clear idea about the scope of the project, please see the Goals and Non-Goals sections below.
Contents
Goals
- Moving the update process to the background
- Initiating the update process as soon as an update is downloaded
- Being able to apply a newer update if Firefox was not restarted since the previous update was applied in the background
- Try to do as little as possible at startup
- Eliminate the progress bar UI that the current updater shows
Non-Goals
- Handling UAC prompts on Windows (covered in this project)
- Changing the frequency of checking for updates, our handling of major/minor updates, or the way we check for add-ons compatibility (covered in this project)
- Eliminating the UI we display in Item 2 (parts of it covered in this project)
- Changing how updates work on Android
- Downloading and/or apply update while Firefox is not running
- Any of the other projects falling under the "silent update" umbrella
Implementation
Background updates
Here is a proposal for how background updates will be implemented. Please note that the parts in italics explain what currently happens, and those parts are not changed under this proposal. They are only mentioned here for completeness.
- The process will start by Firefox checking for an update in the foreground or background.
- Once an update is found
- If the user needs to prompted for some reason, we show that prompt at the normal time. (e.g, on idle). If the user declines, we bail out.
- Otherwise, we go ahead and download the update (as a complete/partial MAR file).
- Once the download is finished, Firefox launches the updater binary in the background with the UI display disabled. Searching for new updates will be paused during this time.
- The target of the update will be known
FIREFOX_NEW
from now on.- On Windows, if Firefox is installed to "C:\path\to\Mozilla Firefox",
FIREFOX_NEW
will be "C:\path\to\Mozilla Firefox\updated". - On Mac, if Firefox is installed to "/path/to/Firefox.app",
FIREFOX_NEW
will be "/path/to/Firefox.app/Updated.app". In other words, the updated version of Firefox will be installed as a bundle inside the existing Firefox bundle. - On Linux, if Firefox is installed to a flat directory like "/path/to/firefox",
FIREFOX_NEW
will be "/path/to/firefox/updated". If it's installed in a non-flat directory structure (like /usr/bin for example), the details of whereFIREFOX_NEW
will be is TBD.
- On Windows, if Firefox is installed to "C:\path\to\Mozilla Firefox",
- The manifest file is the "update.status" file used by the updater service.
- The target of the update will be known
- The updater binary checks to see if there is an existing manifest file.
- If this file exists, and it contains "applied", its content is changed to "applying". Otherwise, the background update stops.
- The updater binary checks to see if there is an existing
FIREFOX_NEW
directory.- If this directory exists, it will be removed.
- The existing installation will be copied into
FIREFOX_NEW
. - The updater binary will go ahead and apply the update to the
FIREFOX_NEW
directory using the existing installation directory as the base. Any errors happening during this phase (such as running out of disk space or failing to write to disk) will be handled by the updater process by removing theFIREFOX_NEW
directory and aborting. The updater binary will also write to the manifest file "failed: n" where n is the reason code. - The updater binary will write "applied" to the manifest file.
- The updater binary will shutdown, and signal the Firefox main process.
- The Firefox main process will search for new updates when the next update interval is reached.
Firefox startup
The following needs to happen at Firefox startup time in order for the applied update to be used.
- Firefox checks for the manifest file in the installation directory. If it's not found, or its content does not equal "applied", then startup continues as normal.
- If the manifest file is found and its content is "applied", Firefox looks for the known
FIREFOX_NEW
directory. If that directory is not found, Firefox writes "failed: ERROR_CODE" to the manifest file and continues to startup as normal. - If the
FIREFOX_NEW
is found, Firefox "replaces" the existing installation direcotry with the newFIREFOX_NEW
directory, and removes theFIREFOX_NEW
directory, and restarts using the new binary. The details of this phase depends on the platform, and is documented below.
Replacing the existing installation
Windows
On Windows, it is not possible to remove or rename files and directories which are being used. In order to handle this, we need to add a little complexity.
- The Firefox executable will launch a helper application copied to somewhere outside of the installation directory, most likely the system's temporary directory.
- The helper application renames the existing installation directory to a new directory with ".tmp" appended to its path name. If the rename operation fails in the middle of the operation because of a file being open by another application, it reverts the change.
- If the first rename is successful, the helper app renames the
FIREFOX_NEW
directory to the name of the existing installation. If something goes wrong in this phase, theFIREFOX_NEW
directory and the one created in this phase are both removed and the ".tmp" directory is restored back to the state it was before the helper application was launched. - If the previous operation was successful, the helper app removes the ".tmp" diectory.
- At the end of its run, the helper app relaunches Firefox as a non elevated process from the path name of the existing installation, whatever it was.
Mac
On Mac, we basically move the Contents directory in the FIREFOX_NEW
directory over to the Contents directory in the existing installation, remove the now empty FIREFOX_NEW
directory, write "succeeded" to the manifest file, and restart Firefox.
Linux
On Linux, we basically move the FIREFOX_NEW
over the existing installation directory, write "succeeded" to the manifest file, and restart Firefox.
Considered alternatives
A number of other approaches have been considered before writing this proposal. One such approach is to make FIREFOX_NEW
live inside the existing installation directory. That will cause a lot of pain on Windows where we can't overwrite files that are currently open in another application.
We have also considered keeping two versions of Firefox in versioned side-by-side directory. That will also lead into a number of problems because the directory from which Firefox is going to be launched is going to change over and over again.
Downgrade
Firefox currently supports downgrading to older versions by installing an old installer over the new installation directory. The way that it works is that the Firefox installer first uninstalls the old version and then proceeds with the rest of the installation. This can be made possible in the face of background updates by relying on the uninstaller to know about the manifest file, and making the installer aware of the FIREFOX_NEW
directory. The uninstaller should remove the FIREFOX_NEW
directory as part of the uninstall process. The same handling is enough to correctly handle Firefox being uninstalled explicitly as well.