diff --git a/browser/components/shell/src/nsWindowsShellService.cpp b/browser/components/shell/src/nsWindowsShellService.cpp index 56f5dc56203d..0a1a94f86dea 100644 --- a/browser/components/shell/src/nsWindowsShellService.cpp +++ b/browser/components/shell/src/nsWindowsShellService.cpp @@ -262,6 +262,9 @@ nsWindowsShellService::ShortcutMaintenance() { nsresult rv; + // XXX App ids were updated to a constant install path hash, + // XXX this code can be removed after a few upgrade cycles. + // Launch helper.exe so it can update the application user model ids on // shortcuts in the user's taskbar and start menu. This keeps older pinned // shortcuts grouped correctly after major updates. Note, we also do this diff --git a/browser/installer/windows/nsis/defines.nsi.in b/browser/installer/windows/nsis/defines.nsi.in index 3e92d99cde5b..73e3a50e1ffb 100644 --- a/browser/installer/windows/nsis/defines.nsi.in +++ b/browser/installer/windows/nsis/defines.nsi.in @@ -1,19 +1,8 @@ #filter substitution -# Win7: AppVendor, AppName, and AppVersion must match the application.ini values -# of Vendor, Name, and Version. These values are used in registering shortcuts -# with the taskbar. ExplicitAppUserModelID registration when the app launches is -# handled in widget/src/windows/WinTaskbar.cpp. - -!define AppVendor "Mozilla" +# These defines should match application.ini settings !define AppName "Firefox" !define AppVersion "@APP_VERSION@" -#ifdef HAVE_64BIT_OS -; differentiate 64-bit builds, we do the same in widget. -!define AppUserModelID "${AppVendor}.${AppName}.${AppVersion}.Win64" -#else -!define AppUserModelID "${AppVendor}.${AppName}.${AppVersion}" -#endif !define GREVersion @MOZILLA_VERSION@ !define AB_CD "@AB_CD@" diff --git a/browser/installer/windows/nsis/installer.nsi b/browser/installer/windows/nsis/installer.nsi index 9402645bcbed..43aee4111d9d 100755 --- a/browser/installer/windows/nsis/installer.nsi +++ b/browser/installer/windows/nsis/installer.nsi @@ -37,6 +37,7 @@ # Required Plugins: # AppAssocReg http://nsis.sourceforge.net/Application_Association_Registration_plug-in # ApplicationID http://nsis.sourceforge.net/ApplicationID_plug-in +# CityHash http://mxr.mozilla.org/mozilla-central/source/other-licenses/nsis/Contrib/CityHash # ShellLink http://nsis.sourceforge.net/ShellLink_plug-in # UAC http://nsis.sourceforge.net/UAC_plug-in @@ -107,6 +108,7 @@ VIAddVersionKey "OriginalFilename" "setup.exe" !insertmacro CreateRegKey !insertmacro GetPathFromString !insertmacro GetParent +!insertmacro InitHashAppModelId !insertmacro IsHandlerForInstallDir !insertmacro IsPinnedToTaskBar !insertmacro LogDesktopShortcut @@ -319,6 +321,9 @@ Section "-Application" APP_IDX ${EndIf} ${EndIf} + ; setup the application model id registration value + ${InitHashAppModelId} "$INSTDIR" "Software\Mozilla\${AppName}\TaskBarIDs" + ${RemoveDeprecatedKeys} ; The previous installer adds several regsitry values to both HKLM and HKCU. @@ -433,7 +438,8 @@ Section "-Application" APP_IDX ShellLink::SetShortCutWorkingDirectory "$SMPROGRAMS\${BrandFullName}.lnk" \ "$INSTDIR" ${If} ${AtLeastWin7} - ApplicationID::Set "$SMPROGRAMS\${BrandFullName}.lnk" "${AppUserModelID}" + ${AndIf} "$AppUserModelID" != "" + ApplicationID::Set "$SMPROGRAMS\${BrandFullName}.lnk" "$AppUserModelID" ${EndIf} ${LogMsg} "Added Shortcut: $SMPROGRAMS\${BrandFullName}.lnk" ${Else} @@ -447,7 +453,8 @@ Section "-Application" APP_IDX ShellLink::SetShortCutWorkingDirectory "$DESKTOP\${BrandFullName}.lnk" \ "$INSTDIR" ${If} ${AtLeastWin7} - ApplicationID::Set "$DESKTOP\${BrandFullName}.lnk" "${AppUserModelID}" + ${AndIf} "$AppUserModelID" != "" + ApplicationID::Set "$DESKTOP\${BrandFullName}.lnk" "$AppUserModelID" ${EndIf} ${LogMsg} "Added Shortcut: $DESKTOP\${BrandFullName}.lnk" ${Else} diff --git a/browser/installer/windows/nsis/shared.nsh b/browser/installer/windows/nsis/shared.nsh index 5208d8fc5824..905d49f5724b 100755 --- a/browser/installer/windows/nsis/shared.nsh +++ b/browser/installer/windows/nsis/shared.nsh @@ -44,6 +44,10 @@ ${RegCleanMain} "Software\Mozilla" ${RegCleanUninstall} ${UpdateProtocolHandlers} + + ; setup the application model id registration value + ${InitHashAppModelId} "$INSTDIR" "Software\Mozilla\${AppName}\TaskBarIDs" + ; Win7 taskbar and start menu link maintenance Call FixShortcutAppModelIDs @@ -190,7 +194,8 @@ ${If} ${FileExists} "$DESKTOP\${BrandFullName}.lnk" ShellLink::SetShortCutWorkingDirectory "$DESKTOP\${BrandFullName}.lnk" "$INSTDIR" ${If} ${AtLeastWin7} - ApplicationID::Set "$DESKTOP\${BrandFullName}.lnk" "${AppUserModelID}" + ${AndIf} "$AppUserModelID" != "" + ApplicationID::Set "$DESKTOP\${BrandFullName}.lnk" "$AppUserModelID" ${EndIf} ${Else} SetShellVarContext current ; Set $DESKTOP to the current user's desktop @@ -200,7 +205,8 @@ ShellLink::SetShortCutWorkingDirectory "$DESKTOP\${BrandFullName}.lnk" \ "$INSTDIR" ${If} ${AtLeastWin7} - ApplicationID::Set "$DESKTOP\${BrandFullName}.lnk" "${AppUserModelID}" + ${AndIf} "$AppUserModelID" != "" + ApplicationID::Set "$DESKTOP\${BrandFullName}.lnk" "$AppUserModelID" ${EndIf} ${EndIf} ${EndUnless} @@ -214,7 +220,8 @@ ShellLink::SetShortCutWorkingDirectory "$SMPROGRAMS\${BrandFullName}.lnk" \ "$INSTDIR" ${If} ${AtLeastWin7} - ApplicationID::Set "$SMPROGRAMS\${BrandFullName}.lnk" "${AppUserModelID}" + ${AndIf} "$AppUserModelID" != "" + ApplicationID::Set "$SMPROGRAMS\${BrandFullName}.lnk" "$AppUserModelID" ${EndIf} ${Else} SetShellVarContext current ; Set $SMPROGRAMS to the current user's Start @@ -225,7 +232,8 @@ ShellLink::SetShortCutWorkingDirectory "$SMPROGRAMS\${BrandFullName}.lnk" \ "$INSTDIR" ${If} ${AtLeastWin7} - ApplicationID::Set "$SMPROGRAMS\${BrandFullName}.lnk" "${AppUserModelID}" + ${AndIf} "$AppUserModelID" != "" + ApplicationID::Set "$SMPROGRAMS\${BrandFullName}.lnk" "$AppUserModelID" ${EndIf} ${EndIf} ${EndUnless} @@ -753,7 +761,9 @@ ${If} ${FileExists} "$SMPROGRAMS\$1" ShellLink::SetShortCutWorkingDirectory "$SMPROGRAMS\$1" \ "$INSTDIR" - ApplicationID::Set "$SMPROGRAMS\$1" "${AppUserModelID}" + ${If} "$AppUserModelID" != "" + ApplicationID::Set "$SMPROGRAMS\$1" "$AppUserModelID" + ${EndIf} ${EndIf} ${EndUnless} ${EndUnless} @@ -835,8 +845,9 @@ ShellLink::SetShortCutWorkingDirectory "$SMPROGRAMS\${BrandFullName}.lnk" \ "$INSTDIR" ${If} ${AtLeastWin7} + ${AndIf} "$AppUserModelID" != "" ApplicationID::Set "$SMPROGRAMS\${BrandFullName}.lnk" \ - "${AppUserModelID}" + "$AppUserModelID" ${EndIf} ${EndIf} ${EndIf} @@ -942,7 +953,6 @@ !macroend !define PushFilesToCheck "!insertmacro PushFilesToCheck" - ; Sets this installation as the default browser by setting the registry keys ; under HKEY_CURRENT_USER via registry calls and using the AppAssocReg NSIS ; plugin for Vista and above. This is a function instead of a macro so it is @@ -986,7 +996,10 @@ FunctionEnd ; Helper for updating the shortcut application model IDs. Function FixShortcutAppModelIDs - ${UpdateShortcutAppModelIDs} "$INSTDIR\${FileMainEXE}" "${AppUserModelID}" $0 + ${If} ${AtLeastWin7} + ${AndIf} "$AppUserModelID" != "" + ${UpdateShortcutAppModelIDs} "$INSTDIR\${FileMainEXE}" "$AppUserModelID" $0 + ${EndIf} FunctionEnd ; The !ifdef NO_LOG prevents warnings when compiling the installer.nsi due to diff --git a/browser/installer/windows/nsis/uninstaller.nsi b/browser/installer/windows/nsis/uninstaller.nsi index a052b1e2f4c1..b0a771059de1 100755 --- a/browser/installer/windows/nsis/uninstaller.nsi +++ b/browser/installer/windows/nsis/uninstaller.nsi @@ -36,6 +36,7 @@ # Required Plugins: # AppAssocReg http://nsis.sourceforge.net/Application_Association_Registration_plug-in +# CityHash http://mxr.mozilla.org/mozilla-central/source/other-licenses/nsis/Contrib/CityHash # ShellLink http://nsis.sourceforge.net/ShellLink_plug-in # UAC http://nsis.sourceforge.net/UAC_plug-in @@ -92,6 +93,7 @@ VIAddVersionKey "OriginalFilename" "helper.exe" !insertmacro ElevateUAC !insertmacro GetLongPath !insertmacro GetPathFromString +!insertmacro InitHashAppModelId !insertmacro IsHandlerForInstallDir !insertmacro IsPinnedToTaskBar !insertmacro LogDesktopShortcut @@ -117,6 +119,7 @@ VIAddVersionKey "OriginalFilename" "helper.exe" !insertmacro un.DeleteShortcuts !insertmacro un.GetLongPath !insertmacro un.GetSecondInstallPath +!insertmacro un.InitHashAppModelId !insertmacro un.ManualCloseAppPrompt !insertmacro un.ParseUninstallLog !insertmacro un.RegCleanAppHandler @@ -229,13 +232,23 @@ Section "Uninstall" RmDir "$APPDATA\Mozilla" ${EndIf} + ; setup the application model id registration value + ${un.InitHashAppModelId} "$INSTDIR" "Software\Mozilla\${AppName}\TaskBarIDs" + SetShellVarContext current ; Set SHCTX to HKCU ${un.RegCleanMain} "Software\Mozilla" ${un.RegCleanUninstall} ${un.DeleteShortcuts} ; Unregister resources associated with Win7 taskbar jump lists. - ApplicationID::UninstallJumpLists "${AppUserModelID}" + ${If} ${AtLeastWin7} + ${AndIf} "$AppUserModelID" != "" + ApplicationID::UninstallJumpLists "$AppUserModelID" + ${EndIf} + + ; Remove any app model id's stored in the registry for this install path + DeleteRegValue HKCU "Software\Mozilla\${AppName}\TaskBarIDs" "$INSTDIR" + DeleteRegValue HKLM "Software\Mozilla\${AppName}\TaskBarIDs" "$INSTDIR" ClearErrors WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" "Write Test" @@ -577,6 +590,10 @@ FunctionEnd # Initialization Functions Function .onInit + ; We need this set up for most of the helper.exe operations. + !ifdef AppName + ${InitHashAppModelId} "$INSTDIR" "Software\Mozilla\${AppName}\TaskBarIDs" + !endif ${UninstallOnInitCommon} FunctionEnd diff --git a/toolkit/mozapps/installer/windows/nsis/common.nsh b/toolkit/mozapps/installer/windows/nsis/common.nsh index b7adb2baf809..86eba4999d48 100755 --- a/toolkit/mozapps/installer/windows/nsis/common.nsh +++ b/toolkit/mozapps/installer/windows/nsis/common.nsh @@ -1139,9 +1139,9 @@ Function CheckIfRegistryKeyExists ; stack: main key, key - Exch $R9 ; main key - Exch 1 - Exch $R8 ; key + Exch $R9 ; main key, stack: old R9, key + Exch 1 ; stack: key, old R9 + Exch $R8 ; key, stack: old R8, old R9 Push $R7 Push $R6 Push $R5 @@ -1162,10 +1162,9 @@ Pop $R5 Pop $R6 - Pop $R7 - Exch $R8 - Exch 1 - Exch $R9 + Pop $R7 ; stack: old R8, old R9 + Pop $R8 ; stack: old R9 + Exch $R9 ; stack: result FunctionEnd !verbose pop @@ -4831,8 +4830,13 @@ ClearErrors ${GetOptions} "$R0" "/UpdateShortcutAppUserModelIds" $R2 IfErrors hideshortcuts +1 - ${UpdateShortcutAppModelIDs} "$INSTDIR\${FileMainEXE}" "${AppUserModelID}" $R2 - StrCmp "$R2" "true" finish +1 ; true indicates that shortcuts have been updated + StrCpy $R2 "" +!ifmacrodef InitHashAppModelId + ${If} "$AppUserModelID" != "" + ${UpdateShortcutAppModelIDs} "$INSTDIR\${FileMainEXE}" "$AppUserModelID" $R2 + ${EndIf} +!endif + StrCmp "$R2" "false" +1 finish ; true indicates that shortcuts have been updated Quit ; Nothing initialized so no need to call OnEndCommon ; Require elevation if the user can elevate @@ -6675,3 +6679,121 @@ Pop ${_RESULT} !verbose pop !macroend + +/** + * Retrieve if present or generate and store a 64 bit hash of an install path + * using the City Hash algorithm. On return the resulting id is saved in the + * $AppUserModelID variable declared by inserting this macro. InitHashAppModelId + * will attempt to load from HKLM/_REG_PATH first, then HKCU/_REG_PATH. If found + * in either it will return the hash it finds. If not found it will generate a + * new hash and attempt to store the hash in HKLM/_REG_PATH, then HKCU/_REG_PATH. + * Subsequent calls will then retreive the stored hash value. On any failure, + * $AppUserModelID will be set to an empty string. + * + * Registry format: root/_REG_PATH/"_EXE_PATH" = "hash" + * + * @param _EXE_PATH + * The main application executable path + * @param _REG_PATH + * The HKLM/HKCU agnostic registry path where the key hash should + * be stored. ex: "Software\Mozilla\Firefox\TaskBarIDs" + * @result (Var) $AppUserModelID contains the app model id. + */ +!macro InitHashAppModelId + !ifndef ${_MOZFUNC_UN}InitHashAppModelId + !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN} + !insertmacro ${_MOZFUNC_UN_TMP}GetLongPath + !undef _MOZFUNC_UN + !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP} + !undef _MOZFUNC_UN_TMP + + !ifndef InitHashAppModelId + Var AppUserModelID + !endif + + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + !define ${_MOZFUNC_UN}InitHashAppModelId "!insertmacro ${_MOZFUNC_UN}InitHashAppModelIdCall" + + Function ${_MOZFUNC_UN}InitHashAppModelId + ; stack: apppath, regpath + Exch $R9 ; stack: $R9, regpath | $R9 = apppath + Exch 1 ; stack: regpath, $R9 + Exch $R8 ; stack: $R8, $R9 | $R8 = regpath + Push $R7 + + ${If} ${AtLeastWin7} + ${${_MOZFUNC_UN}GetLongPath} "$R9" $R9 + ClearErrors + ReadRegStr $R7 HKLM "$R8" "$R9" + ${If} ${Errors} + ClearErrors + ReadRegStr $R7 HKCU "$R8" "$R9" + ${If} ${Errors} + ; If it doesn't exist, create a new one and store it + CityHash::GetCityHash64 "$R9" + Pop $AppUserModelID + ${If} $AppUserModelID == "error" + GoTo end + ${EndIf} + ClearErrors + WriteRegStr HKLM "$R8" "$R9" "$AppUserModelID" + ${If} ${Errors} + ClearErrors + WriteRegStr HKLM "$R8" "$R9" "$AppUserModelID" + ${If} ${Errors} + StrCpy $AppUserModelID "error" + ${EndIf} + ${EndIf} + ${EndIf} + ${EndIf} + ${EndIf} + + end: + ${If} "$AppUserModelID" == "error" + StrCpy $AppUserModelID "" + ${EndIf} + + ClearErrors + Pop $R7 + Exch $R8 + Exch 1 + Exch $R9 + FunctionEnd + + !verbose pop + !endif +!macroend + +!macro InitHashAppModelIdCall _EXE_PATH _REG_PATH + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + Push "${_REG_PATH}" + Push "${_EXE_PATH}" + Call InitHashAppModelId + !verbose pop +!macroend + +!macro un.InitHashAppModelIdCall _EXE_PATH _REG_PATH + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + Push "${_REG_PATH}" + Push "${_EXE_PATH}" + Call un.InitHashAppModelId + !verbose pop +!macroend + +!macro un.InitHashAppModelId + !ifndef un.InitHashAppModelId + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + !undef _MOZFUNC_UN + !define _MOZFUNC_UN "un." + + !insertmacro InitHashAppModelId + + !undef _MOZFUNC_UN + !define _MOZFUNC_UN + !verbose pop + !endif +!macroend diff --git a/toolkit/mozapps/installer/windows/nsis/makensis.mk b/toolkit/mozapps/installer/windows/nsis/makensis.mk index 57a3ce58fcf3..59e74fe66e7e 100644 --- a/toolkit/mozapps/installer/windows/nsis/makensis.mk +++ b/toolkit/mozapps/installer/windows/nsis/makensis.mk @@ -57,6 +57,7 @@ CUSTOM_NSIS_PLUGINS = \ AccessControl.dll \ AppAssocReg.dll \ ApplicationID.dll \ + CityHash.dll \ InvokeShellVerb.dll \ ShellLink.dll \ UAC.dll \