diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /browser/installer/windows/docs | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'browser/installer/windows/docs')
-rw-r--r-- | browser/installer/windows/docs/FullConfig.rst | 83 | ||||
-rw-r--r-- | browser/installer/windows/docs/FullInstaller.rst | 14 | ||||
-rw-r--r-- | browser/installer/windows/docs/Helper.rst | 39 | ||||
-rw-r--r-- | browser/installer/windows/docs/InstallerBuild.rst | 55 | ||||
-rw-r--r-- | browser/installer/windows/docs/MSI.rst | 9 | ||||
-rw-r--r-- | browser/installer/windows/docs/MSIX.rst | 226 | ||||
-rw-r--r-- | browser/installer/windows/docs/StubArch.rst | 18 | ||||
-rw-r--r-- | browser/installer/windows/docs/StubConfig.rst | 36 | ||||
-rw-r--r-- | browser/installer/windows/docs/StubGUI.rst | 52 | ||||
-rw-r--r-- | browser/installer/windows/docs/StubInstaller.rst | 13 | ||||
-rw-r--r-- | browser/installer/windows/docs/WebBrowserAPI.rst | 35 | ||||
-rw-r--r-- | browser/installer/windows/docs/index.rst | 21 |
12 files changed, 601 insertions, 0 deletions
diff --git a/browser/installer/windows/docs/FullConfig.rst b/browser/installer/windows/docs/FullConfig.rst new file mode 100644 index 0000000000..37dd9e8f0c --- /dev/null +++ b/browser/installer/windows/docs/FullConfig.rst @@ -0,0 +1,83 @@ +============================ +Full Installer Configuration +============================ + +.. note:: + + This page applies to the ``.exe`` full installer. If you want to run or deploy the :doc:`MSI package <MSI>`, refer to the instructions on `the support web page for it <https://support.mozilla.org/kb/deploy-firefox-msi-installers>`_ instead; the command-line options documented here won't work. + +Command-line Options +-------------------- + +The full installer provides a number of options that can be used either from the GUI or from the command line. The following command line options are accepted. The list is valid for Firefox 62 and later. Prior to Firefox 62, only ``/S`` and ``/INI`` are accepted, and ``/StartMenuShortcut`` is not available in INI files, only the plural ``/StartMenuShortcuts`` works (even though only one shortcut is created). + +The presence of **any** command-line option implicitly enables silent mode (see the ``/S`` option). + +Each option must start with a ``/`` as shown, ``-`` or ``--`` are not supported. Short names for the options are not provided; all names must be spelled out. + +For options that accept ``true`` or ``false``, ``=true`` can be left off to get the same effect. That is, ``/DesktopShortcut`` and ``/DesktopShortcut=true`` both enable the desktop shortcut. + +``/S`` + Silent installation. This option doesn't open the GUI, instead running the installation in the background using all the default settings. It's useful as part of a script for configuring a new system, for example. + + For backwards compatibility, this option can also be spelled ``-ms``. + +``/InstallDirectoryPath=[path]`` + Absolute path specifying the complete install location. This directory does not need to exist already (but it can). + + If ``InstallDirectoryName`` is set, then this setting will be ignored. + +``/InstallDirectoryName=[name]`` + Name of the installation directory to create within Program Files. For example, if ``InstallDirectoryName`` is set to ``Firefox Release``, then the installation path will be something like ``C:\Program Files\Firefox Release``. The Program Files path used will be the correct one for the architecture of the application being installed and the locale/configuration of the machine; this setting is mainly useful to keep you from having to worry about those differences. + + If this is set, then ``InstallDirectoryPath`` will be ignored. + +``/TaskbarShortcut={true,false}`` + Set to ``false`` to disable pinning a shortcut to the taskbar. ``true`` by default. + +``/DesktopShortcut={true,false}`` + Set to ``false`` to disable creating a shortcut on the desktop. ``true`` by default. + +``/StartMenuShortcut={true,false}`` + Set to ``false`` to disable creating a Start menu shortcut. ``true`` by default. + + For backwards compatibility, this option can also be spelled ``/StartMenuShortcuts`` (plural), however only one shortcut is ever created in the Start menu per installation. + +``/PrivateBrowsingShortcut={true,false}`` + Set to ``false`` to disable creating a private browsing shortcut in the start menu. ``true`` by default. + +``/MaintenanceService={true,false}`` + Set to ``false`` to disable installing the Mozilla Maintenance Service. This will effectively prevent users from installing Firefox updates if they do not have write permissions to the installation directory. ``true`` by default. + +``/RemoveDistributionDir={true,false}`` + Set to ``false`` to disable removing the ``distribution`` directory from an existing installation that's being paved over. By default this is ``true`` and the directory is removed. + +``/PreventRebootRequired={true,false}`` + Set to ``true`` to keep the installer from taking actions that would require rebooting the machine to complete, normally because files are in use. This should not be needed under normal circumstances because no such actions should be required unless you're paving over a copy of Firefox that was running while the installer was trying to run, and setting this option in that case may result in an incomplete installation. ``false`` by default. + +``/OptionalExtensions={true,false}`` + Set to ``false`` to disable installing any bundled extensions that are present. Normally none of these exist, except in special distributions of Firefox such as the one produced by Mozilla China or by other partner organizations. ``true`` by default. + +``/RegisterDefaultAgent={true,false}`` + Set to ``false`` to disable creating a recurring scheduled task to run the default browser agent. There are other ways (a policy and a pref) to disable the actions that the agent takes; this option is provided for tightly-controlled environments where even a + scheduled task that simply exits immediately is undesirable. + +``/INI=[absolute path to .ini file]`` + Read configuration from an .ini file. All settings should be placed into one section, called ``[Install]``, and use the standard INI syntax. All settings are optional; they can be included or left out in any combination. Order does not matter. + + The available settings in the .ini file are the same as the command line options, except for ``/S`` and ``/INI`` (of course). They should be set with the same syntax described above for command line use. + + For any option provided both in an .ini file and on the command line, the value found on the command line will be used. This allows command line options to override .ini settings. + + Here's an example of a valid .ini file for use with this option:: + + [Install] + ; Semicolons can be used to add comments + InstallDirectoryName=Firefox Release + DesktopShortcut=false + StartMenuShortcuts=true + MaintenanceService=false + OptionalExtensions=false + +``/ExtractDir=[directory]`` + Extract the application files to the given directory and exit, without actually running the installer. No other options may be supplied along with ``ExtractDir``, and ``ExtractDir`` is not available for use in .ini files. diff --git a/browser/installer/windows/docs/FullInstaller.rst b/browser/installer/windows/docs/FullInstaller.rst new file mode 100644 index 0000000000..fcfa60371e --- /dev/null +++ b/browser/installer/windows/docs/FullInstaller.rst @@ -0,0 +1,14 @@ +============== +Full Installer +============== + +The full installer is actually responsible for installing the browser; it's what the stub launches in order to do the "real" installing work, but it's also available separately. It uses a traditional "wizard" interface design, as is (somewhat) natively supported by NSIS. It can also be :doc:`configured <FullConfig>` to launch in a silent mode, suitable for scripting or managed deployments. + +The full installer's main script is `installer.nsi <https://searchfox.org/mozilla-central/source/browser/installer/windows/nsis/installer.nsi>`_, but most of the heavy lifting is done by the shared functions in `common.nsh <https://searchfox.org/mozilla-central/source/toolkit/mozapps/installer/windows/nsis/common.nsh>`_. + +If it was not launched by the :doc:`StubInstaller`, an :ref:`Install Ping` is sent when the installer exits. + +The installer writes ``installation_telemetry.json`` to the install location, this is read by Firefox in order to send a telemetry event, see the event definition in `Events.yaml <https://searchfox.org/mozilla-central/source/toolkit/components/telemetry/Events.yaml>`_ (category ``installation``, event name ``first_seen``) for a description of the properties. There is also an ``install_timestamp`` property, which is saved in the profile to determine whether there has been a new installation; this is not sent as part of the ping. + +.. toctree:: + FullConfig diff --git a/browser/installer/windows/docs/Helper.rst b/browser/installer/windows/docs/Helper.rst new file mode 100644 index 0000000000..de69e12e27 --- /dev/null +++ b/browser/installer/windows/docs/Helper.rst @@ -0,0 +1,39 @@ +====== +Helper +====== +helper.exe contains the uninstaller, plus a routine that's run by the application updater after it applies an update, as well as a few utilities used for default browser handling and shortcut maintenance. It mainly consists of two files, uninstaller.nsi_, which is the main script and contains the entry point and the uninstall logic, and shared.nsh_, which contains most of the logic for the other functions. + +Uninstaller +----------- +The uninstaller may be the most straightforward of the installer components. The only complexity comes from a need to avoid accidentally removing any user files that may have found their way into the installation directory; the general philosophy of the uninstaller is to remove everything that the installer creates, and nothing that it doesn't. + +* Any registry entries the installer would have created are removed, even ones only used by very old installer versions. +* All the files that the uninstaller knows were created by the installer or are owned by the application are deleted, or flagged for deletion on reboot if any are in use. There are a few hard-coded directories that are known to be safe to delete (for example, the distribution directory, and any temporary directories created by the updater). For a list of application files that are safe to uninstall, we read a file from the application directory called ``precomplete``. This file is mainly used to tell the updater what it should do to clean out the directory when applying a complete update (one that replaces all application files), but that means it contains a handy auto-generated list of all application files, so it can be reused for uninstallation. +* If the application directory is empty after that, then it is removed, but it's left alone if any files are still present. +* If the copy of Firefox that was just uninstalled is the only one that was using the maintenance service, the maintenance service uninstaller is also run. +* Any BITS jobs from this installation of Firefox are cancelled. +* The first :ref:`"uninstall" ping` found is uploaded, and all uninstall pings are deleted (for this installation). + +Note that profiles and any other user-generated files (e.g., crash reports) are specifically not uninstalled. + +PostUpdate +---------- +At the end of an application update cycle, after the new files are in place, the updater invokes the helper with the ``/PostUpdate`` command-line switch. The PostUpdate function fills a grab bag of responsibilities which are all focused around maintaining system integration objects created by the installer. For example, a number of registry entries contain the version number, so that has to be changed on updates. If the branding name of the application changes and shortcuts have to be renamed, that's done here as well. For one counterexample, changing icons does not require any code in PostUpdate, or anywhere else; new icons are automatically picked up by the shell. The PostUpdate function also keeps the maintenance service up to date. + +It's important to remember that PostUpdate is, indeed, post-update. It doesn't run until after its own code has already been updated. This makes it really the only phase of the update process where changes can go into affect immediately in the first build that contains a patch, instead of having to wait for the next update after that. This makes it a good place to put anything that needs to be done before the new version of the application can run; this includes things like registering DLL's, which the installer also handles, but that PostUpdate has to take care of for existing installations. + +PostUpdate actually runs two times after each update: once in an elevated context, and once as a regular user who performed the update. Both runs do similar work - the main difference being that we update HKLM registry entries are updated by the elevated instance, while HKCU ones are updated by the non-elevated instance. + +It's also important to remember that PostUpdate, being part of the installer code, only exists on Windows, so it can't be used to fix things up on other platforms the same way. + +Default Browser and Shortcut Handling +------------------------------------- +Windows versions older than 10 contain a control panel called Set Program Access and Defaults, or SPAD. As the name suggests, this was the UI for setting default programs for classes of activities ("web browser" or "e-mail client" for example), as the Windows 10 default program settings page is, but it also controls program "access," which is typically defined as whether or not shortcuts for the program exist. To support this interface, an application has to register a set of commands that the interface can invoke to hide or show the shortcuts, and to have the application make itself the default. We implement these actions in helper.exe; they're triggered by invoking it with the command-line switches ``/ShowShortcuts``, ``/HideShortcuts``, or ``/SetAsDefaultAppGlobal``. + +The helper also implements the ``/SetAsDefaultAppUser`` switch, which is invoked by the "Make Default" button in the Firefox preferences UI. + +On Windows 10 neither SetAsDefaultAppUser nor SetAsDefaultAppGlobal is effective because the default programs settings can only be modified by the Windows settings app. However they do still write the registry entries that are needed to get us an entry in the system default browser menu, should those entries not already exist (the installer always creates them, but running Firefox without having run the installer is supported). ShowShortcuts and HideShortcuts are never called on Windows 10 because the SPAD control panel no longer exists. + + +.. _uninstaller.nsi: https://searchfox.org/mozilla-central/source/browser/installer/windows/nsis/uninstaller.nsi +.. _shared.nsh: https://searchfox.org/mozilla-central/source/browser/installer/windows/nsis/shared.nsh diff --git a/browser/installer/windows/docs/InstallerBuild.rst b/browser/installer/windows/docs/InstallerBuild.rst new file mode 100644 index 0000000000..a98e819d8c --- /dev/null +++ b/browser/installer/windows/docs/InstallerBuild.rst @@ -0,0 +1,55 @@ +=============== +Installer Build +=============== + +How to build the installers +--------------------------- + +The easiest way to build an installer in your local tree is to run ``mach package``. The finished installers will be in ``$OBJDIR/dist/install/sea/``. You have to have a build of the application already done before that will work, but `artifact builds <https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Artifact_builds>`_ are supported, so that can save you a lot of time if you're only doing installer work. + +You'll also need to be on a Windows machine; the installer build depends on tools that aren't available for other platforms. + +Stub installer +~~~~~~~~~~~~~~ + +The stub installer probably won't be built by default in a local tree; normally unless the build has been set to use one of the official update channels, only the full installer is built. If you need to work on the stub installer, you can override the default and get one built along with the full installer by adding ``export MOZ_STUB_INSTALLER=1`` to your mozconfig. + +Uninstaller +~~~~~~~~~~~ + +The uninstaller is built as part of the main application build, not the installer target, so ``mach build`` is what will get you an uninstaller. You'll find it at ``$OBJDIR/dist/bin/uninstaller/helper.exe``. + +Branding +~~~~~~~~ + +By default local builds use "unofficial" branding, which somewhat resembles a previous version of the Nightly branding, but is designed not to resemble any official channel too closely. + +But sometimes you'll need to test installers that are built using one or more of the official channel branding configurations, perhaps to try out different strings, make sure different sets of art look good, or to test behavior around installing multiple channels at the same time. + +You can build installers (and the entire application) with official branding by adding ``ac_add_options --with-branding=browser/branding/{nightly|aurora|official}`` to your mozconfig (the default branding is ``browser/branding/unofficial``). + +Build process +------------- + +.. note:: + + If you intend to distribute your build to others, you'll want to add + ``export WIN32_REDIST_DIR=<CRT_LOCATION>`` in your ``mozconfig``. The CRT location + will vary depending on your Visual Studio version. At the time of writing, this would look like: + ``export WIN32_REDIST_DIR="/c/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Redist/MSVC/14.28.29325/x86/Microsoft.VC142.CRT"``. + +Both the full and stub installers are built through a similar process, which is summarized here along with references to the relevant bits of code. + +Most of this procedure is done in `makensis.mk <https://searchfox.org/mozilla-central/source/toolkit/mozapps/installer/windows/nsis/makensis.mk>`_ and in the `mach repackage <https://searchfox.org/mozilla-central/rev/2b9779c59390ecc47be7a70d99753653d8eb5afc/python/mozbuild/mozbuild/mach_commands.py#2166>`_ command. + +0. A prerequisite is for the application to be in a packaged state, so ``mach package`` first creates a release-style package and puts it in ``$OBJDIR/dist/firefox``. +1. All required files are copied into the instgen directory. This includes .nsi and .nsh script files, plugin DLL files, image and icon files, and the 7-zip SFX module and its configuration files. +2. The NSIS scripts are compiled, resulting in setup.exe and setup-stub.exe (if building the stub is enabled). +3. The 7-zip SFX module is run through UPX. +4. The application files and the full installer setup.exe are compressed together into one 7-zip file. +5. The stub installer is compressed into its own 7-zip file. +6. The (UPX-packed) 7-zip SFX module, the correct configuration data, and the 7-zip file containing the application files and setup.exe are concatenated together. This results in the final full installer. +7. The (still UPX-packed) 7-zip SFX module, the correct configuration data, and the 7-zip file containing the stub installer are concatenated together. This results in the final stub installer. + + +If this is an official build running on Mozilla automation infrastructure, then after this the installers will be signed, like other build products. Release engineering owns that process, it's not within the scope of this documentation. diff --git a/browser/installer/windows/docs/MSI.rst b/browser/installer/windows/docs/MSI.rst new file mode 100644 index 0000000000..9e5f30a711 --- /dev/null +++ b/browser/installer/windows/docs/MSI.rst @@ -0,0 +1,9 @@ +=========== +MSI Package +=========== + +We provide a `Windows Installer <https://wikipedia.org/wiki/Windows_Installer>`_ MSI package for the convenience of administrators deploying Firefox in their organizations. The primary documentation for how to obtain and use these packages is hosted on `the Mozilla support web site <https://support.mozilla.org/kb/deploy-firefox-msi-installers>`_. + +Our MSI packages are not "true" Windows Installer packages; they don't actually contain any installable components and don't register any product. They simply wrap the :doc:`full installer <FullInstaller>`, which performs the installation just as if it had been run normally. The main reason for this is the difficulty of adapting Firefox's existing update mechanisms to fit the way that Windows Installer would expect things to be done. + +The MSI package is built for every release along with the other package formats using the command ``./mach repackage msi``. That command invokes the `WiX tools <https://wixtoolset.org/>`_ to build the package from `a normal WiX XML file <https://searchfox.org/mozilla-central/source/browser/installer/windows/msi/installer.wxs>`_, after filling in a few variables to customize the package for that particular Firefox build. The majority of the WiX file is concerned with passing parameters through from MSI properties to command-line arguments for the full installer to use; the rest is boilerplate to satisfy the minimum requirements for something that WiX will build and the Windows Installer system will load and run without errors. diff --git a/browser/installer/windows/docs/MSIX.rst b/browser/installer/windows/docs/MSIX.rst new file mode 100644 index 0000000000..771ea6c061 --- /dev/null +++ b/browser/installer/windows/docs/MSIX.rst @@ -0,0 +1,226 @@ +MSIX Package +============ + +Firefox MSIX packages are full participants in the "modern" Windows +app packaging system. They are distributed, installed, updated, +repaired, and uninstalled entirely using that system. This gives +administrators lots of deployment options, and also grants complete +control over when and how application updates are rolled out +(Firefox's built-in updater is always fully disabled in MSIX +packages). This stands in contrast to Firefox MSI packages, which +mostly work against the Windows Installer framework rather than with +it, and therefore are missing a lot of important functionality; for +example, tools that install MSI packages generally cannot uninstall +Firefox [#]_. This means the MSIX package may well be the better +option for deploying to Windows 10 and up. + +In automation +------------- + +The ``repackage-msix`` and ``repackage-shippable-l10n-msix`` tasks +repackage the ZIP packages produced by signed build tasks into MSIX +packages. The ``shippable-l10n`` variants depend on Linux64 builds and +localization tasks to produce signed langpacks, which are incorporated +into the MSIX package as distribution extensions. (This is the same +approach taken by ``snap`` and ``flatpak`` Linux packages.) + +The ``repackage-signing-msix`` and +``repackage-signing-shippable-l10n-msix`` tasks sign the MSIX packages +produced by the repackage tasks. + +Signing in automation +~~~~~~~~~~~~~~~~~~~~~ + +MSIX packages are signed by the same certificates that sign binaries for +other jobs. In practice, this means that try builds are signed with the +```Mozilla Fake CA`` +certificate `MozFakeCA_2017-10-13.cer <https://raw.githubusercontent.com/mozilla-releng/OpenCloudConfig/3493a608bf700b68a54ff2fd506f33373bb87a04/userdata/Configuration/Mozilla%20Maintenance%20Service/MozFakeCA_2017-10-13.cer>`__. +In order to install try builds locally, you must trust this certificate. +**For your own security, it's best to do this in Windows Sandbox or a +Virtual Machine**. To do so run the following in an elevated +(administrator) Powershell: + +:: + + $ Import-Certificate -FilePath "MozFakeCA_2017-10-13.cer" -Cert Cert:\LocalMachine\Root\ + ... + Thumbprint Subject + ---------- ------- + FA056CEBEFF3B1D0500A1FB37C2BD2F9CE4FB5D8 CN=Mozilla Fake CA + +The ``shippable-l10n`` MSIX variants incorporate signed langpacks. These +in turn are signed with the same certificate. Firefox knows about this +certificate but does not trust it by default. To trust it, set the +hidden Gecko boolean preference + +:: + + xpinstall.signatures.dev-root=true + +Sadly, it's not possible to set preferences via a ``distribution.ini`` +early enough to impact loading the signed langpacks (see `Bug +1721764 <https://bugzilla.mozilla.org/show_bug.cgi?id=1721764>`__), and +once the signed langpacks fail to load once, they will not be reloaded +(see `Bug +1721763 <https://bugzilla.mozilla.org/show_bug.cgi?id=1721763>`__). This +make testing the first-run experience challenging. What can be done is +to install the MSIX package (perhaps using +``Add-AppxPackage -Path ...``) and determine the profile directory +(using ``about:support``). Uninstall the MSIX package (perhaps using +``Get-AppxPackage | Where -Property Name -like "Mozilla.*" | Remove-AppxPackage``). +Delete the contents of the profile directory entirely, but add a file +``user.js`` containing: + +:: + + user_pref("xpinstall.signatures.dev-root", true); + user_pref("extensions.logging.enabled", true); + +Reinstall the MSIX package and the signed langpacks should now be loaded +(slowly!) and available after first startup. + +Local developer builds +---------------------- + +``mach repackage msix`` lets you repackage a Firefox package (or +directory) into an MSIX/App Package. The main complication is that an +App Package contains channel-specific paths and assets, and therefore +needs to be branding-aware, much as an Android package needs to be +branding-aware. + +Usage +~~~~~ + +The tool is designed to repackage ZIP archives produced in automation. +Start looking for official builds at locations like: + +========== ========================================================================================================================== +Channel URL +========== ========================================================================================================================== +Release https://archive.mozilla.org/pub/firefox/candidates/88.0.1-candidates/build1/win64/en-US/firefox-88.0.1.zip +Beta https://archive.mozilla.org/pub/firefox/candidates/89.0b15-candidates/build1/win64/en-US/firefox-89.0b15.zip +Devedition https://archive.mozilla.org/pub/devedition/candidates/89.0b15-candidates/build1/win64/en-US/firefox-89.0b15.zip +Nightly https://archive.mozilla.org/pub/firefox/nightly/2021/05/2021-05-21-09-57-54-mozilla-central/firefox-90.0a1.en-US.win64.zip +========== ========================================================================================================================== + +Repackage using commands like: + +:: + + $ ./mach repackage msix \ + --input firefox-88.0.1.zip \ + --channel=official \ + --arch=x86_64 \ + --verbose + +Or package a local developer build directly with ``mach repackage msix``: + +:: + + $ ./mach repackage msix + +This command will do its best to guess your channel and other necessary +information. You can override these with options like ``--channel`` +(see the ``--help`` text for all supported options). + +Paths to tools can be set via environment variables. In order, searched +first to searched last: + +1. the tool name, like ``MAKEAPPX`` or ``SIGNTOOL`` +2. searching on ``PATH`` +3. searching under ``WINDOWSSDKDIR`` +4. searching under ``C:/Program Files (x86)/Windows Kits/10`` + +If you are cross compiling from Linux or macOS you will need a +compiled version of `Mozilla's fork of Microsoft's msix-packaging +<https://github.com/mozilla/msix-packaging/tree/johnmcpms/signing>`__ +tools. + +Linux users can obtain a prebuilt version with: + +:: + + $ ./mach artifact toolchain --from-build linux64-msix-packaging + +After `bug 1743036 <https://bugzilla.mozilla.org/show_bug.cgi?id=1743036>`__ +is fixed, macOS and Windows users will have a similar option. + +Signing locally +~~~~~~~~~~~~~~~ + +The repackaged MSIX files produced are not signed by default. In +automation, Mozilla's signing service signs the repackaged MSIX files. +For local testing, you can sign them with a self-signed certificate by +adding ``--sign`` to ``mach repackage msix``, or with commands like: + +:: + + $ ./mach repackage sign-msix --input test.msix --verbose + +Or sign them yourself following `Microsoft's self-signed certificate +instructions <https://docs.microsoft.com/en-us/windows/msix/package/create-certificate-package-signing#create-a-self-signed-certificate>`__. + +Signing Certificates +^^^^^^^^^^^^^^^^^^^^ + +Mach will create the necessary signing keys and certificates for you +and reuse them for subsequent signings. Before your locally signed +builds can be installed you will need to install the correct +certificate to the Windows Root Store. This can be done with a command +like: + +:: + + $ powershell -c 'Import-Certificate -FilePath mycert.cer -Cert Cert:\LocalMachine\Root\' + +The exact command to run will be shown if you run ``./mach repackage`` +with ``--verbose``. + +You _may_ choose to sign in a different manner, with a key and certificate +you create yourself, but Windows requires that the Subject of the certificate +match the Publisher found in the MSIX's AppxManifest.xml. If you choose +to go this route, ensure that you pass ``--publisher`` to +``./mach repackage msix`` to set that correctly. + +For developers +~~~~~~~~~~~~~~ + +Updating the MSIX template +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +MSIX is an "open format" in one sense: the MSIX container format is +specified at https://github.com/Microsoft/msix-packaging. It is +categorically *not* an open format in another sense: many of the +contained files are proprietary binary formats (``.reg`` -- registry +hive files) or undocumented (``.pri`` files -- resource index files). + +Generally the MSIX packaging code tries to avoid requiring such files +that can't be built from sources. Where they are truly required, it +tries to use a single such file independent of branding and other +configuration, checked into the source tree. + +resources.pri +''''''''''''' + +Generate a new ``resources.pri`` file on a Windows machine using +``makepri.exe`` from the Windows SDK, like: + +:: + + $ makepri.exe new \ + -IndexName firefox \ + -ConfigXml browser/installer/windows/msix/priconfig.xml \ + -ProjectRoot browser/branding/official/msix \ + -OutputFile browser/installer/windows/msix/resources.pri \ + -Overwrite + +The choice of channel (i.e., +``browser/branding/{official,aurora,beta,nightly,unofficial}``) should +not matter. + +.. [#] The MSI has to be limited in this way because of the difficulty + of migrating existing installations into MSI and adding support + for it to Firefox's update pipeline. MSIX does not have these + constraints, because the partially virtualized file system that + these kinds of apps run in makes install migration impossible + and unnecessary. diff --git a/browser/installer/windows/docs/StubArch.rst b/browser/installer/windows/docs/StubArch.rst new file mode 100644 index 0000000000..2ab8bc65dc --- /dev/null +++ b/browser/installer/windows/docs/StubArch.rst @@ -0,0 +1,18 @@ +=========================== +Stub Installer Architecture +=========================== + +The stub is called a stub because it doesn't actually install anything. It's just a GUI frontend that downloads and runs the full installer in silent mode. The exact full installer that will be downloaded isn't baked into the stub; the channel and the locale (which are baked in) are sent in a request to the Bouncer service, which uses that information to redirect to the URL of the specific full installer file. + +The main stub installer source code file is `stub.nsi <https://searchfox.org/mozilla-central/source/browser/installer/windows/nsis/stub.nsi>`_. Even though the stub installer doesn't install anything, it's still built on NSIS. This means the structure of stub.nsi is a bit odd for an NSIS script. There's only one section, and it's empty, and there are no predefined pages used (including no instfiles page, which we get a warning from the compiler about). The work is all done in two custom pages, createProfileCleanup and createInstall, and the functions called by those two pages. Also, the stub's dialogs are built using HTML and the Windows WebBrowser control (based on Internet Explorer); see :doc:`this page <StubGUI>` for details about that. + +The basic execution flow is this: + +1. .onInit checks basic system requirements, determines whether we should install a 64-bit or a 32-bit build, looks for an existing installation that we should try to pave over, displays a UAC prompt, and initializes lots of variables and GUI objects. +2. createProfileCleanup determines if a profile cleanup prompt should be offered (see the ShouldPromptForProfileCleanup function), and calls the web control to draw the UI for that if so. +3. createInstall draws the UI for the download/install page, again using the web control, kicks off the periodic timer that swaps out the blurb text every few seconds (if the branding includes that), and runs StartDownload. +4. StartDownload invokes the InetBgDl plugin to begin the full installer download on a background thread. It then starts a periodic timer for the OnDownload function. +5. Every time OnDownload runs (every 200 ms), it checks the status of the background download, retries or restarts if the download has failed, updates the progress bar if the download is still running, and verifies and runs the full installer if the download is complete. +6. CheckInstall waits for the full installer to exit, then deletes the file. +7. FinishInstall copies the post-signing data, then waits for the application to launch, requesting it perform profile cleanup if that option was selected. +8. Once the installed application is running and has shown a window (or if another copy was already running), the stub sends its ping and then exits. diff --git a/browser/installer/windows/docs/StubConfig.rst b/browser/installer/windows/docs/StubConfig.rst new file mode 100644 index 0000000000..caf414a5fd --- /dev/null +++ b/browser/installer/windows/docs/StubConfig.rst @@ -0,0 +1,36 @@ +============================ +Stub Installer Configuration +============================ + +The stub installer doesn't offer many options to the user, most of its configuration is automatic and implicit. But there are two things the user can control, and here we'll discuss those and the automated settings. + +Architecture +------------ +The stub installer automatically selects whether to install a 32-bit or a 64-bit build of Firefox. 64-bit will be selected only if these conditions all pass: + +1. The operating system is a 64-bit build. +2. The system has enough physical memory installed. Currently an amount strictly greater than 2 GB is required (that is, exactly 2 GB is not considered enough). +3. No third-party software that is incompatible with the 64-bit build is present on the system. + +If any of the above conditions is not satisfied, a 32-bit build is installed. + +Scope +----- +We support creating the installation in either a machine or a per-user scope. This affects whether application files, shortcuts, and registry entries are created in locations that are accessible to any user on the machine or locations that are specific to a particular user. Even in the full installer there is no UI for configuring which scope is selected; instead both installers automatically select a scope based on whether they have the privileges needed to perform a machine scope installation. This means a user with those privileges can effectively control the scope by the selection they make in the Windows UAC prompt; rejecting it will mean that the installer doesn't see that user as an administrator and will perform a per-user installation. + +Install Location +---------------- +The user doesn't have any control over the install location used by the stub. To determine the location that will be used, first the stub looks for any existing installations of the same channel of Firefox. If it finds one of those and the architecture of that installation is the same as the one that's been selected for the new one, then the path for the new install will be set to the same as that install, effectively overwriting it. This allows the stub to be used as a repair method for broken installations. If there isn't any existing installation fitting those criteria, then a hard-coded default is selected based on the architecture, scope, and channel. + +Profile Cleanup +--------------- +If the stub installer detects that this could be a helpful thing to do, it will start off the installation by offering to clean up the user's Firefox profile. This is the same cleanup that's triggered by the "refresh" button in about:support, and it's performed by the same Firefox code (the stub really just asks the browser to do the cleanup using a command-line parameter, it doesn't try to perform the operation itself). The user can control whether this cleanup is done by toggling a checkbox that's shown before the installation begins. + +There are two variations of the profile cleanup prompt that can be shown to the user, one that appears if the new installation would overwrite an existing one (the "paveover" prompt) and another if it would be a new installation (the "reinstall" prompt). The only difference is the text that the user sees, the two function identically. + +This is the procedure that determines when one of the two cleanup prompts is shown: + +1. Look for the current default Firefox profile. If there are no profiles or none is set as the default, don't show either prompt. +2. Look for an existing installation by searching the registry for any copies of Firefox that are registered for potential file type associations. If none exist, show the reinstall prompt. +3. Check if the existing installation is for the same channel that's being installed now. If not, don't show either prompt. +4. Check the version of Firefox that the default profile we found in step 1 was last used with. This information comes from the profile's compatibility.ini file. If that version is more than 2 versions behind the current version, show the paveover prompt. Otherwise, don't show either prompt. Information about the current version is taken from `<https://product-details.mozilla.org/1.0/firefox_versions.json>`_. diff --git a/browser/installer/windows/docs/StubGUI.rst b/browser/installer/windows/docs/StubGUI.rst new file mode 100644 index 0000000000..4e285f5e2e --- /dev/null +++ b/browser/installer/windows/docs/StubGUI.rst @@ -0,0 +1,52 @@ +================== +Stub Installer GUI +================== + +The stub installer's primary GUI is built using the web platform, rendered by the native Windows browser control ``IWebBrowser2``, which is based on Internet Explorer (Microsoft never updated it to use Edge [#1]_). + +This is all driven by a custom NSIS plugin, called WebBrowser. The plugin's source code can be found in the directory ``other-licenses/nsis/Contrib/WebBrowser``, and its public API is documented :doc:`here <WebBrowserAPI>`. The plugin implements the COM interfaces needed to host the IWebBrowser2 object and embed it using OLE into the dialog provided by NSIS. It also provides an implementation of timers [#2]_, and supports making NSIS functions callable from JavaScript running inside the web page. + +Note that not 100% of the stub UI is built using WebBrowser; we also have message boxes which use `the Windows TaskDialog function <https://docs.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-taskdialog>`_, invoked from NSIS code using the standard System plugin. + +Changing the UI +=============== + +For each of the two main pages, there is one HTML file (which also contains the JavaScript for the page) and one CSS file. + +The HTML file for each page is always the same regardless of the branding, so it's kept in the ``installer`` directory next to ``stub.nsi``. These files should be updated if elements need to be added or removed from the page, or if features requiring JavaScript are being implemented or changed. + +Each branding directory (``/browser/branding/*``) contains a CSS file for each page, which specifies how the page should be laid out and rendered. These are normal CSS files and can easily be modified to change or redesign one or both pages for any or all brandings. Currently there are two completely different layouts, one for release and another for all other brandings, and the two differ only in this CSS file and in the background image file (also in the branding directory). + +Constraints +=========== + +The most severe constraint on the web UI is that the browser engine must be configured to run in Internet Explorer 8 mode. This is because the installer must run correctly on an unpatched Windows 7 installation with no service packs or other updates, and that is the version of IE that such an installation provides. That means this constraint can only be relaxed if Firefox's OS support changes to exclude unpatched Windows 7 (i.e., either dropping Windows 7 entirely or requiring Service Pack 1). + +Image assets (meaning only the background image at the moment) can be any format IE8 can open, including JPEG, GIF, or PNG, but any newer formats like WebP won't work. SVG isn't supported until IE9. + +Fonts should be limited to those that a default Windows 7+ installation provides, which may vary based on locale (it is possible to specify a specific font to use for a certain locale). + +The size of the window is difficult to change, and doing so would affect all brandings and require redesigning the background art, so changing that should be avoided. + +Care should be taken to make sure that accessibility is maintained, and best practices for web accessibility should be followed. For example, the installing page contains a progress bar. Normally, and in keeping with best practices, this would be implemented using a ``<progress>`` element, but IE8 doesn't support those, so it has to be built manually out of divs instead. Because this is an inherently inaccessible design, appropriate ARIA attributes are used so that the control is presented to accessibility tools as a real progress bar. + +Technical Details +================= + +Custom Functions +---------------- + +Custom functions provide a foreign function interface that allows JavaScript running in the web page to invoke NSIS functions. Since the installer logic is all handled in NSIS, this is necessary for the UI to be able to determine the state of the installation, relay any settings to the installer, etc. Custom functions always take a single argument on the NSIS stack, and return a single value on the NSIS stack (this design is mostly for convenience, to avoid needing the C++ glue layer to handle different numbers of intended arguments or return values). + +The implementation of custom functions is basically glue between the NSIS ExecuteCodeSegment mechanism (which allows executing NSIS functions from native plugin code) and the web browser control's support for IDispatch (which allows invoking native code from JavaScript). Connecting those two things together allows us to run NSIS code from within JavaScript. + +To make an NSIS function available to JavaScript, the NSIS script must call the plugin's ``RegisterCustomFunction`` export, passing it the address (as obtained from the ``GetFunctionAddress`` instruction) and the name that the function should be exposed to JavaScript under. This call has to happen after the call to ``Init`` and before ``ShowPage``. The plugin wraps that address in a native C++ function, and passes it to the WebBrowser control to register with its IDispatch implementation. That code allocates a ``DISPID`` for the new function and associates it with the given name. Later, when JavaScript invokes a function by that name, our ``IDispatch::Invoke`` calls the wrapper function with the argument that was passed in by JavaScript (if any), and makes sure the return value gets relayed back to JavaScript as well. + + + +.. [#1] There is currently a new control called `WebView2 <https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2>`_ in development which uses the Chrome-based Edge engine, but it's unfinished as of this writing and would only work on machines with Chrome-based Edge installed anyway. + +.. [#2] Previously, the stub installer's UI was based on nsDialogs, and used its timer implementation, so when nsDialogs was removed an alternative was needed. The replacement timers don't strictly need to be provided by the WebBrowser plugin, but it was the convenient place to put those functions. + +.. toctree:: + WebBrowserAPI diff --git a/browser/installer/windows/docs/StubInstaller.rst b/browser/installer/windows/docs/StubInstaller.rst new file mode 100644 index 0000000000..112c036d24 --- /dev/null +++ b/browser/installer/windows/docs/StubInstaller.rst @@ -0,0 +1,13 @@ +============== +Stub Installer +============== + +The stub installer is the default installer interface that most users installing Firefox will see. It's a tiny download (200-300 KB), so it gets the user into the product experience quickly. It's also a highly streamlined experience; there are no options or prompts offered, except in the case of a returning user (see Profile Cleanup). Running the stub installer immediately starts downloading and installing the browser, and automatically runs the new installation and exits when it's done. + +An :ref:`Install Ping` is sent when the stub exits. + + +.. toctree:: + StubConfig + StubArch + StubGUI diff --git a/browser/installer/windows/docs/WebBrowserAPI.rst b/browser/installer/windows/docs/WebBrowserAPI.rst new file mode 100644 index 0000000000..2b16ea0178 --- /dev/null +++ b/browser/installer/windows/docs/WebBrowserAPI.rst @@ -0,0 +1,35 @@ +===================== +WebBrowser Plugin API +===================== + +This page lists all the functions exported from the WebBrowser plugin and explains how to use them. + +``ShowPage`` + This function takes one parameter: the URL or file path to be displayed. It returns nothing. + + ``ShowPage`` will block until the page is closed, either by closing the window or by something like sending the parent dialog a "go to page" message. + + Dialog item 1018 will be taken over as the control to display the web page in, so if you're using a custom dialog template, be sure it contains a control with that ID. + + ``file:`` URL's are supported, but passing in just the file path also works. Relative paths are supported but should be avoided because the stub installer's working directory isn't necessarily predictable or meaningful. Web (HTTP or HTTPS) URL's can be used, but the security restrictions the browser control is configured with will prevent most resource files from being downloaded, so they are unlikely to be very useful. + +``RegisterCustomFunction`` + This function allows an NSIS function to be called from JavaScript. + + This function takes two parameters, the function address, as obtained from the ``GetFunctionAddress`` instruction, and then a string containing the name of the function to be exposed to JavaScript. It returns nothing. + + ``RegisterCustomFunction`` should be called before ``ShowPage`` (which will block anyway). + + JavaScript can invoke this function by the assigned name under the global ``external`` object (that's part of the design of the control and isn't something we can change). The NSIS function will receive a single parameter on the NSIS stack (whether it needs one or not) and is expected to return a single value on the NSIS stack (whether it needs to or not) which will become the return value from the JavaScript function. + + Currently only strings, integers, and booleans are supported as parameter types; anything else will result in the NSIS function being passed an empty string. More types could be added if needed. The return type will always be passed back to JavaScript directly as a string, and any conversions needed must be performed in JS. + +``CreateTimer`` + This function creates an interval timer and invokes a callback at each interval. + + This function takes two parameters, the function address of the timer callback, as obtained from the ``GetFunctionAddress`` instruction, and then the timer interval in milliseconds. It returns a handle which can later be passed to ``CancelTimer``. + +``CancelTimer`` + This function stops running a timer that was started by ``CreateTimer``. + + It takes the handle that ``CreateTimer`` returned, and returns nothing. diff --git a/browser/installer/windows/docs/index.rst b/browser/installer/windows/docs/index.rst new file mode 100644 index 0000000000..5cc72902d9 --- /dev/null +++ b/browser/installer/windows/docs/index.rst @@ -0,0 +1,21 @@ +========= +Installer +========= + +The main role of the Firefox installer is to get a user running Firefox as quickly and reliably as possible, while taking all necessary steps to make Firefox an integrated part of the system. + +It turns out that the only platform where we need an installer in order to accomplish all of that is Windows. So we only develop and ship and installer for Windows, and on other platforms we distribute a package in a non-executable format typical of applications distributed on that platform. + +Currently, the installers are built on the `NSIS <http://nsis.sourceforge.net/Main_Page>`_ installer framework. This is a Windows-only framework which compiles scripts written in its custom language (along with some native plugins) into an executable installer. + +We build four different kinds of installers, the :doc:`Stub Installer <StubInstaller>`, the :doc:`Full Installer <FullInstaller>`, an :doc:`MSI package <MSI>` which wraps the full installer, and an :doc:`MSIX package <MSIX>`. The stub is the default installer intended for most individual users, the full installer and MSI are aimed at power users and administrators who need more control, and the MSIX is aimed at enterprise users who need to control deployment. + +There's also another installer-related program, which is called :doc:`helper.exe <Helper>`. It's also written in NSIS and has a few different jobs that involve maintaining things that the installer sets up, including the uninstaller and a post-update routine. + +.. toctree:: + InstallerBuild + StubInstaller + FullInstaller + MSI + MSIX + Helper |