commit d79ae7ad4ede83346a710a0125ce40e16bc2dff8
parent d4927b88663c8cfac60eb8a3c5fddbe843ce4af4
Author: Chris DuPuis <cdupuis@mozilla.com>
Date: Fri, 17 Oct 2025 21:48:47 +0000
Bug 1992115 - part 1: Desktop Launcher install-on-update on shared install r=bytesized,browser-installer-reviewers
Split up the handling of installing the Desktop Launcher in the
post-update process into separate functions for elevated vs.
unelevated instances. These two instances also need to be aware
of each other, which is now handled by a new registry key
entry.
Differential Revision: https://phabricator.services.mozilla.com/D268598
Diffstat:
2 files changed, 123 insertions(+), 93 deletions(-)
diff --git a/browser/app/desktop-launcher/docs/index.rst b/browser/app/desktop-launcher/docs/index.rst
@@ -39,6 +39,25 @@ At update time:
- NO: Do nothing
+
+In elevated installer, we will delete the public shortcut and record the event if:
+ - It exists
+ - We haven't deleted it before
+ - This is a stub installed Firefox
+
+In the unelevated installer, we will delete the user shortcut and record the event if:
+ - There is a user shortcut (i.e. this is a personal install)
+ - We haven't deleted it before
+ - This is a stub installed Firefox
+
+In the unelevated installer, we will install the desktop launcher and record the event if:
+ - It is already installed OR
+ - It wasn't previously installed
+ - There is or was a shortcut (shared or personal)
+ - The installation type is "stub"
+
+
+
FAQ
===
diff --git a/browser/installer/windows/nsis/shared.nsh b/browser/installer/windows/nsis/shared.nsh
@@ -46,6 +46,10 @@
${EndIf}
${EndIf}
+ !ifdef DESKTOP_LAUNCHER_ENABLED
+ Call OnUpdateDesktopLauncherHandler
+ !endif
+
; Update the name/icon/AppModelID of our shortcuts as needed, then update the
; lastwritetime of the Start Menu shortcut to clear the tile icon cache.
; Do this for both shell contexts in case the user has shortcuts in multiple
@@ -298,57 +302,34 @@ ${RemoveDefaultBrowserAgentShortcut}
; relative to the shell var context. Caller is expected to call
; SetShellVarContext to set the shell var context.
; Args: none
-; Return value is pushed onto the stack: "true" if the shortcut
-; is found, "false" otherwise
+; Return value is pushed onto the stack: "1" if the shortcut
+; is found, "0" otherwise
Function IsDesktopShortcutPresent
- Push $0
+ Push $0 ; will be used to store the result
+ Push $1 ; will be used as a temp variable
+ StrCpy $0 "0"
+
${If} ${FileExists} "$DESKTOP\${BrandShortName}.lnk"
ShellLink::GetShortCutArgs "$DESKTOP\${BrandShortName}.lnk"
- Pop $0
- ${If} "$0" == ""
+ Pop $1
+ ${If} "$1" == ""
+ ; Let's see if we can find out anything about the shortcut
ShellLink::GetShortCutTarget "$DESKTOP\${BrandShortName}.lnk"
- Pop $0
- ${GetLongPath} "$0" $0
- ${If} "$0" == "$INSTDIR\${FileMainEXE}"
- Pop $0 ; restore the register
- Push "true" ; result
- Return
+ Pop $1
+ ${GetLongPath} "$1" $1
+ ${If} "$1" == "$INSTDIR\${FileMainEXE}"
+ ; We had permission to look at the shortcut properties and its target was the Firefox executable
+ StrCpy $0 "1" ; set the result to 1
+ ${ElseIf} "$1" == ""
+ ; Most likely case is that we don't have permission to read the shortcut properties, so just report that it exists
+ StrCpy $0 "1" ; set the result to 1
${EndIf}
${EndIf}
${EndIf}
- Pop $0 ; restore the register
- Push "false"
-FunctionEnd
-
-; Looks for the desktop launcher app in the $DESKTOP directory
-; relative to the shell var context. Caller is expected to call
-; SetShellVarContext to set the shell var context.
-; Args: none
-; Return value is pushed onto the stack: "true" if the shortcut
-; is found, "false" otherwise
-Function IsDesktopLauncherPresent
- ${If} ${FileExists} "$DESKTOP\${BrandShortName}.exe"
- Push "true"
- ${Else}
- Push "false"
- ${EndIf}
+ Pop $1 ; restore the register
+ Exch $0 ; restore the register and place result on the stack
FunctionEnd
-; Looks at the user's registry keys to see if the value
-; indicating that we had ever installed the desktop launcher
-; is set.
-Function WasDesktopLauncherEverInstalled
- Push $0
- ReadRegDWORD $0 HKCU "Software\Mozilla\${BrandFullNameInternal}" DesktopLauncherAppInstalled
- ${IfNot} ${Errors}
- ${AndIf} $0 == "1"
- Pop $0 ; restore register
- Push "true"
- ${Else}
- Pop $0 ; restore register
- Push "false"
- ${EndIf}
-FunctionEnd
; Installs the desktop launcher and sets a registry key to show that we did it.
Function InstallDesktopLauncher
@@ -361,65 +342,98 @@ Function InstallDesktopLauncher
${EndIf}
FunctionEnd
-; When updating from a pre-launcher version to a version that includes the launcher, we
-; want to install the desktop launcher for users if it seems like they might benefit
-; from it, and don't install it if it seems like they won't.
-Function OnUpdateDesktopLauncherHandler
- Var /GLOBAL UserLauncherExists
- Var /GLOBAL UserShortcutExists
- Var /GLOBAL SharedShortcutExists
- Var /GLOBAL LauncherEverInstalled
- Var /GLOBAL InstallationType
- Push $0 ; Used to store original shell var context
+Function OnUpdateDesktopLauncher_HKLM
+ ; This is elevated. In this instance, we won't be installing the desktop launcher, but we may be deleting the shared shortcut
+ Push $0
+ Push $1
+ ; Have we deleted the shared shortcut before?
+ StrCpy $0 "0"
+ ReadRegDWORD $0 HKLM "Software\Mozilla\${BrandFullNameInternal}" "UpdaterDeletedShortcut"
+ Call IsDesktopShortcutPresent
+ Pop $1
+ ${If} $0 != "1"
+ ${AndIf} $1 != "0"
+ ; shared shortcut exists, and we haven't deleted it before. So let's delete it now.
+ Delete "$DESKTOP\${BrandShortName}.lnk"
+ WriteRegDWORD HKLM "Software\Mozilla\${BrandFullNameInternal}" "UpdaterDeletedShortcut" "1"
+ ${EndIf}
+ Pop $1
+ Pop $0
+FunctionEnd
- ; First let's find out whether the shortcut or launcher is present (or ever
- ; installed) in the current user's Desktop folder
- ${SwapShellVarContext} current $0
- Call IsDesktopLauncherPresent
- Pop $UserLauncherExists
+Function OnUpdateDesktopLauncher_HKCU
+ ; If there is a desktop launcher installed, call InstallDesktopLauncher (this is how the launcher gets updated)
+ ${If} ${FileExists} "$DESKTOP\${BrandShortName}.exe"
+ Call InstallDesktopLauncher
+ ; Early return
+ Return
+ ${EndIf}
+
+ Push $0
+ Push $1
+ Push $2
+ Push $3
+
+ ; $0 is 1 if a shortcut is found in user's desktop or 0 otherwise
+ StrCpy $0 "0"
+ ; $1 is 1 if there was a "recently deleted" shortcut or 0 otherwise
+ StrCpy $1 "0"
+ ; $2 is 1 if the desktop launcher was ever installed or 0 otherwise
+ StrCpy $2 "0"
+ ; $3 is 1 if a shortcut is found in shared desktop or 0 otherwise
+ StrCpy $3 "0"
+
+ ; see if there is a shortcut on the user's own desktop
Call IsDesktopShortcutPresent
- Pop $UserShortcutExists
- Call WasDesktopLauncherEverInstalled
- Pop $LauncherEverInstalled
+ Pop $0
- ; Next, let's find out whether the shortcut is installed in the shared
- ; Desktop folder
+ ; see if there is a shortcut in the shared desktop folder
SetShellVarContext all
Call IsDesktopShortcutPresent
- Pop $SharedShortcutExists
+ Pop $3
+ SetShellVarContext current
- ; Now, let's figure out what type of installer was used.
- Push "$INSTDIR\installation_telemetry.json"
- Call GetInstallationType
- Pop $InstallationType
+ ReadRegDWORD $1 HKLM "Software\Mozilla\${BrandFullNameInternal}" "UpdaterDeletedShortcut"
+ ReadRegDWORD $2 HKCU "Software\Mozilla\${BrandFullNameInternal}" "DesktopLauncherAppInstalled"
- ; Now that we know the state of the installation, we can decide what to do
- ${If} $UserLauncherExists == "true"
- ; This is the update case. The user already has the launcher, so
- ; we install the current version over it to ensure that it is
- ; up-to-date.
- SetShellVarContext current
- Call InstallDesktopLauncher
- ${ElseIf} $InstallationType != "stub"
- ; If it's not a stub installer, we don't want to replace the shortcut.
- ; Leave it as-is.
- ${ElseIf} $UserShortcutExists == "true"
- ${AndIf} $LauncherEverInstalled == "false"
- ; Remove the shortcut and add the launcher
- SetShellVarContext current
+ ${If} $2 == "1"
+ ; We previously installed desktop launcher. Don't reinstall
+ ${ElseIf} $0 == "1"
+ ; There was a shortcut on the user's desktop. Delete it and install launcher
+ Delete "$DESKTOP\${BrandShortName}.lnk"
Call InstallDesktopLauncher
- Call DeleteDesktopShortcut ; delete the shortcut from the user's own Desktop
- ${ElseIf} $SharedShortcutExists == "true"
- ${AndIf} $LauncherEverInstalled == "false"
- ; Remove the shortcut and add the launcher
- SetShellVarContext current
+ ${ElseIf} $1 == "1"
+ ${OrIf} $3 == "1"
+ ; This block covers these two cases:
+ ; - If the elevated post-update script runs before the unelevated one, then it will have deleted the shortcut and set the UpdaterDeletedShortcut regkey.
+ ; - Or, if the unelevated script is running now befor the elevated one, then there will still be a shortcut in the shared location.
+ ; In either case, we need to install the desktop launcher now. It's the responsibility of the elevated post-update script to delete
+ ; the shared shortcut, and that is implemented in OnUpdateDesktopLauncher_HKLM
Call InstallDesktopLauncher
- SetShellVarContext all
- Call DeleteDesktopShortcut ; delete the shortcut from the public Desktop
${EndIf}
- ; Restore original shell var context and register
- ${SetShellVarContextToValue} $0
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+FunctionEnd
+
+Function OnUpdateDesktopLauncherHandler
+ Push $0
+ Push "$INSTDIR\installation_telemetry.json"
+ Call GetInstallationType
+ ; Pop the result from the stack into $0
+ Pop $0
+ ${If} $0 == "stub"
+ ${If} $RegHive == "HKLM"
+ SetShellVarContext all
+ Call OnUpdateDesktopLauncher_HKLM
+ ${Else}
+ SetShellVarContext current
+ Call OnUpdateDesktopLauncher_HKCU
+ ${EndIf}
+ ${EndIf}
+ ; Restore $0 to its original value
Pop $0
FunctionEnd
@@ -1730,9 +1744,6 @@ FunctionEnd
${LogDesktopShortcut} "${BrandShortName}.lnk"
!endif
${EndUnless}
-!ifdef DESKTOP_LAUNCHER_ENABLED
- Call OnUpdateDesktopLauncherHandler
-!endif
!macroend
!define CreateShortcutsLog "!insertmacro CreateShortcutsLog"