Skip to main content

installer

Architecture, conventions and pitfalls of the Firefox Windows installers (stub, full, helper/uninstaller, MSI, MSIX) built with NSIS. Use when reading, writing, reviewing or debugging .nsi/.nsh files, anything under browser/installer/windows/ or toolkit/mozapps/installer/windows/nsis/, NSIS plugins in other-licenses/nsis/, or installer/uninstall telemetry.

ソース情報

リポジトリ
mozilla/firefox-aidev-plugins
ソースの最終更新活動
2026年9月24日 16:42
検出された SKILL.md の言語
英語
スター
12
フォーク
17

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

ファイルエクスプローラー
7 ファイル

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
installer
description
Architecture, conventions and pitfalls of the Firefox Windows installers (stub, full, helper/uninstaller, MSI, MSIX) built with NSIS. Use when reading, writing, reviewing or debugging .nsi/.nsh files, anything under browser/installer/windows/ or toolkit/mozapps/installer/windows/nsis/, NSIS plugins in other-licenses/nsis/, or installer/uninstall telemetry.
# Firefox Windows Installer The Firefox installer gets users running Firefox as quickly and reliably as possible while integrating it into the Windows system. It is built on the NSIS (Nullsoft Scriptable Install System) framework, which compiles scripts in its custom language (plus native C++ plugins) into executable installers. We build four installer types: Stub Installer, Full Installer, MSI package (wraps the full installer), and MSIX package. There is also helper.exe (uninstaller + post-update + shortcuts). Read `references/build-and-test.md` before building or testing changes, `references/telemetry.md` before touching install/uninstall pings, `references/full-installer-options.md` for the full installer's CLI/INI surface, `references/file-map.md` to locate a script/include/doc by topic, `references/uac.md` before touching elevation logic, and `references/stub-installer.md` before touching the stub's HTML/CSS/JS UI or the WebBrowser plugin. --- # 1. Architecture ## 1.1 Stub installer The default installer most users see. A tiny download (200-300 KB) that downloads and runs the full installer silently. It offers no options except an optional profile cleanup prompt for returning users. - Main script: `browser/installer/windows/nsis/stub.nsi` - Structure is unusual for NSIS: one empty section, no predefined pages; all work is in two custom pages (`createProfileCleanup` and `createInstall`) - GUI is built with HTML/CSS/JS rendered via the Windows `IWebBrowser2` control (IE-based), driven by the custom WebBrowser NSIS plugin ### Execution flow 1. `.onInit` checks system requirements, selects 32/64-bit, looks for existing install to pave over, displays UAC prompt, initializes variables and GUI 2. `createProfileCleanup` optionally offers profile cleanup (same as about:support refresh) 3. `createInstall` draws the download/install UI, starts a blurb rotation timer, runs `StartDownload` 4. `StartDownload` kicks off the InetBgDl plugin for background download, starts `OnDownload` timer (200ms) 5. `OnDownload` checks download status, retries on failure, updates progress bar, verifies and runs the full installer when complete 6. `CheckInstall` waits for the full installer to exit, deletes the file 7. `FinishInstall` copies post-signing data, waits for the app to launch (requesting profile cleanup if selected) 8. Once the app is running and has shown a window, the stub sends its ping and exits ### Architecture selection 64-bit is selected only if: (1) 64-bit OS, (2) strictly more than 2 GB RAM, (3) no incompatible third-party software. Otherwise 32-bit. ### Install scope Automatically selected based on privileges. Rejecting the UAC prompt results in a per-user installation. No UI for this choice. ### Install location Looks for existing same-channel installation with matching architecture to pave over. If none found, uses a hard-coded default based on architecture, scope, and channel. ### Profile cleanup Shown when helpful. Two variants: "paveover" (overwriting existing install) and "reinstall" (new install). Triggers the same refresh as about:support. Decision logic: 1. Find default Firefox profile; if none, skip 2. Look for existing same-channel installation via registry 3. Check if default profile's last-used version is 2+ versions behind current; if so, show prompt ### GUI and WebBrowser plugin IE8 rendering mode, limited image/font formats, fixed window size, and the `ShowPage`/`RegisterCustomFunction`/`CreateTimer` WebBrowser plugin API used to drive the HTML/CSS/JS UI — see `references/stub-installer.md`. ## 1.2 Full installer The "real" installer that does the actual work. Uses a traditional wizard interface. Can be launched by the stub or standalone. Produces setup.exe (30-40 MB). - Main script: `browser/installer/windows/nsis/installer.nsi` - Heavy lifting in `toolkit/mozapps/installer/windows/nsis/common.nsh` - Writes `installation_telemetry.json` to the install location (read by Firefox for telemetry) — see `references/telemetry.md` - If not launched by the stub, sends an install ping on exit — see `references/telemetry.md` - Can access NSIS plugins written in C++ - Full CLI/INI option surface: `references/full-installer-options.md` ## 1.3 Helper (helper.exe) Contains the uninstaller, a post-update routine, and default browser/shortcut utilities. Two main files: `uninstaller.nsi` (entry point + uninstall logic) and `shared.nsh` (other functions). ### Uninstaller Philosophy: remove everything the installer creates, nothing it doesn't. - Removes all installer-created registry entries (including very old versions) - Deletes known application files using the `precomplete` file (auto-generated list of all app files) - Leaves the install directory if any unknown files remain - Runs maintenance service uninstaller if this was the only Firefox using it - Cancels any BITS jobs for this installation - Uploads the uninstall ping — see `references/telemetry.md` - Profiles and user-generated files are NOT removed ### PostUpdate Runs after an update via `/PostUpdate` switch. Maintains system integration objects (version numbers in registry, shortcut renaming, maintenance service updates, DLL registration). Key facts: - Runs after its own code has been updated, so changes take effect immediately in the first build containing a patch - Runs twice: once elevated (HKLM entries) and once as regular user (HKCU entries) - Windows-only; cannot fix things up on other platforms ### Default browser and shortcut handling - `/ShowShortcuts` — add application to Open With - `/HideShortcuts` — remove application from Open With - `/SetAsDefaultAppGlobal` — make default browser (system-wide) - `/SetAsDefaultAppUser` — make default browser (invoked by Firefox preferences) On Windows 10+, SetAsDefault commands only write necessary registry entries since the settings app controls defaults. ShowShortcuts/HideShortcuts are never called (SPAD control panel no longer exists). ## 1.4 MSI package A Windows Installer package for enterprise deployment. NOT a "true" MSI — it wraps the full installer. The full installer runs inside the MSI just as if launched normally. Built with WiX tools from `browser/installer/windows/msi/installer.wxs`. - Build: `./mach repackage msi` - Most of the WiX file passes MSI properties through as CLI arguments to the full installer - Cannot uninstall Firefox via standard MSI tools (limitation of the wrapper approach) ## 1.5 MSIX package A full participant in the Windows modern app packaging system. Distributed, installed, updated, repaired, and uninstalled entirely via that system. Firefox's built-in updater is always disabled in MSIX. Better than MSI for Windows 10+ enterprise deployment. - Build: `./mach repackage msix` - Can build unsigned packages with `--unsigned` (Windows 11 only) - Can sign locally with `--sign` or `./mach repackage sign-msix` - Channel-specific paths and assets (branding-aware) - Langpacks included as distribution extensions in shippable builds - `resources.pri` generated with `makepri.exe` from Windows SDK --- # 2. File locations Installer scripts and includes live under `browser/installer/windows/nsis/` (browser-level) and `toolkit/mozapps/installer/windows/nsis/` (toolkit-level shared utilities in `common.nsh`), with NSIS plugins in `other-licenses/nsis/Plugins/`, branding in `browser/branding/*/branding.nsi`, and docs in `browser/installer/windows/docs/`. See `references/file-map.md` for the full breakdown by script, include, branding, build config, localization, plugins, UI content, repackaging, and tests. --- # 3. NSIS language guide ## 3.1 Variables - Declared with `Var VarName` at the top of files, outside any section or function - Avoid `Var /GLOBAL` inside sections/functions; it works but is non-idiomatic - All variables are global, mutable, and only known at install-time - Access with `$VarName` syntax - Key built-in variables: `$INSTDIR` (install directory), `$EXEDIR` (executable directory) ## 3.2 Defines (symbols) - Compile-time constants, accessed with `${DefineName}` syntax - `!undef` a define when no longer needed to prevent accidental reuse - Key defines: `${BrandFullName}` (product name), `${FileMainEXE}` (main exe name) - `${GetLongPath}` returns the correctly formatted full path for a file ## 3.3 Registers - NSIS has registers `$0`-`$9` and `$R0`-`$R9` for temporary storage - Registers are global — a value set in a macro/function persists after execution - CRITICAL: always push registers before use and pop after, in FILO order, to avoid clobbering - Use registers in ascending order: `$0`, then `$1`, `$2`, `$3`, etc. (same for `$R0`, `$R1`, `$R2`, ...) - Convention: use `$R9` for macro return values ## 3.4 Functions vs macros - **Functions**: for code invoked repeatedly; cannot take arguments directly; use slightly less disk space - **Macros**: copy-paste code at invocation site; can take arguments; beware of variable clobbering since the code is inlined - Prefer macros when arguments are needed - Convention: define a `!define MacroName "!insertmacro MacroName"` shorthand so callers use `${MacroName}` syntax - Functions cannot take arguments natively; use stack Push/Pop or global variables instead ## 3.5 Parameter passing and return values - Stack-based: parameters pushed onto stack, functions use `Exch` and `Pop` - Push/Pop must follow FILO (First In Last Out) order - Return values: assign to a register (convention: `$R9`) or a user variable - Macros have no built-in return mechanism; use registers or global variables ## 3.6 LogicLib and conditional logic `${If}`, `${ElseIf}`, `${Else}`, `${EndIf}`, `${Unless}` are LogicLib macros that simplify conditional logic (replacing raw IntCmp/StrCmp gotos). Key constraint: LogicLib does NOT work recursively — a macro meant to be used as a right-hand operand of `${If}` cannot itself use `${If}` internally. For such macros, use raw `IntCmp`, `StrCmp`, or similar comparison instructions instead. ## 3.7 Conditional compilation - `!ifdef`, `!ifndef`, `!if`, `!else`, `!endif` for compile-time conditionals - `IfFileExists` for runtime file checks - `defines.nsi.in` uses `@VARIABLE@` substitution (Mozilla build system preprocessor) - Key defines: `MOZ_MAINTENANCE_SERVICE`, `MOZ_BITS_DOWNLOAD`, `MOZ_DEFAULT_BROWSER_AGENT`, `HAVE_64BIT_BUILD`, `_ARM64_` ## 3.8 Error handling - Check errors with `${If} ${Errors}` after operations - Use `IfFileExists` before file operations - Call `ClearErrors` at the start of functions/macros that check the error flag - `ClearErrors` can mask bugs if used carelessly; use with caution - Registry operations should handle missing keys gracefully - Common pattern: try HKLM, check errors, fall back to HKCU --- # 4. Codebase conventions ## 4.1 Naming - Standard macros: `${MacroName}` (e.g., `${SetHandlers}`, `${TouchStartMenuShortcut}`) - Uninstaller-only variants MUST use the `un.` prefix (e.g., `un.CheckForFilesInUse`) - If a macro is used in both installer and uninstaller, place it in `shared.nsh` and create both prefixed and unprefixed variants - Functions are called with `Call FunctionName` or `Call un.FunctionName` ## 4.2 Registry operations - Two main root keys: HKLM (system-wide, admin) and HKCU (current user only) - NSIS auto-creates parent keys when writing subkeys/values - Common value types: REG_SZ (string) and REG_DWORD (32-bit integer) - Write default value of a key by using empty string as value name - HKLM writes may fail in unelevated installs; always write fallback code for HKCU - Use `ClearErrors` before operations that may fail, then check `${If} ${Errors}` - Prefer commands that take an explicit root key argument over relying on `SetShellVarContext` ## 4.3 SetShellVarContext - `SetShellVarContext all` makes shell folder constants (`$DESKTOP`, `$SMPROGRAMS`, etc.) resolve to all-users paths AND sets `SHCTX` to HKLM for registry operations - `SetShellVarContext current` makes them resolve to current-user paths AND sets `SHCTX` to HKCU - It affects BOTH file system paths and registry operations (via the `SHCTX` root key) - Misreading or forgetting to restore the context is a common source of bugs - When possible, favor registry commands that explicitly take a root key (HKLM/HKCU) over relying on `SHCTX` - If you must use it, always restore it to the expected value after your operation - `control_utils.nsh` provides helpers: `${SetShellVarContextToValue}` and `${SwapShellVarContext}` ## 4.4 Code style - Keep lines reasonable in length - Use `; comment` style for inline comments (not `# comment`) - Section organization follows: PreInit -> Init -> InstallTypes -> Pages -> Sections -> Functions - Delete files with `Delete`, not `RMDir` (which is for directories) --- # 5. UAC and elevation All installer scripts declare `RequestExecutionLevel user` — they do NOT request admin at startup. Elevation is lazy, via the UAC plugin (`${ElevateUAC}`/`${UnloadUAC}` in common.nsh), and degrades gracefully to HKCU if declined or unavailable. After elevation, scripts test-write to HKLM to decide `$RegHive` (HKLM or HKCU) and set `SetShellVarContext` accordingly. When elevated code needs to run a user-level operation (e.g. shortcuts), it uses the dual-context pattern: detect the `/UAC:` flag with `${GetOptions}`, and if present, call `UAC::ExecCodeSegment` on a `GetFunctionAddress` of the user-level function instead of calling it directly. See `references/uac.md` for the full UAC plugin function reference, the elevation flow, the dual-context code pattern, and how elevation differs between the full installer, stub installer, and uninstaller.
GitHubで見る