From 17601890520a13bbbeeb0d71a6157ee3ee942e68 Mon Sep 17 00:00:00 2001 From: "rob_strong@exchangecode.com" Date: Sat, 20 Oct 2007 15:56:49 -0700 Subject: [PATCH] Bug 398434 - Provide option to remove profiles during uninstall. r=sspitzer, blocking-firefox3=beltzner --- .../installer/windows/nsis/uninstaller.nsi | 52 +++++- .../locales/en-US/installer/custom.properties | 7 + .../mozapps/installer/windows/nsis/common.nsh | 150 ++++++++++++++++++ 3 files changed, 201 insertions(+), 8 deletions(-) diff --git a/browser/installer/windows/nsis/uninstaller.nsi b/browser/installer/windows/nsis/uninstaller.nsi index a41d42ee93ea..1cd04a6458c0 100755 --- a/browser/installer/windows/nsis/uninstaller.nsi +++ b/browser/installer/windows/nsis/uninstaller.nsi @@ -42,8 +42,6 @@ ; Set verbosity to 3 (e.g. no script) to lessen the noise in the build logs !verbose 3 -RequestExecutionLevel user - ; 7-Zip provides better compression than the lzma from NSIS so we add the files ; uncompressed and use 7-Zip to create a SFX archive of it SetDatablockOptimize on @@ -67,9 +65,19 @@ Var TmpVal !include MUI.nsh !include TextFunc.nsh !include WinMessages.nsh -!include WinVer.nsh !include WordFunc.nsh +; WinVer.nsh was added in the same release that RequestExecutionLevel so check +; if ___WINVER__NSH___ is defined to determine if RequestExecutionLevel is +; available. +!include /NONFATAL WinVer.nsh +!ifdef ___WINVER__NSH___ + RequestExecutionLevel user +!else + !warning "Installer will be created without Vista compatibility.$\n \ + Upgrade your NSIS installation to at least version 2.22 to resolve." +!endif + !insertmacro StrFilter !insertmacro WordReplace @@ -102,6 +110,7 @@ VIAddVersionKey "FileDescription" "${BrandShortName} Helper" !insertmacro un.ChangeMUIHeaderImage !insertmacro un.CleanVirtualStore +!insertmacro un.DeleteRelativeProfiles !insertmacro un.GetLongPath !insertmacro un.GetSecondInstallPath !insertmacro un.ManualCloseAppPrompt @@ -153,9 +162,7 @@ ShowUnInstDetails nevershow !insertmacro MUI_UNPAGE_WELCOME ; Uninstall Confirm Page -!define MUI_PAGE_CUSTOMFUNCTION_SHOW un.showConfirm -!define MUI_PAGE_CUSTOMFUNCTION_LEAVE un.leaveConfirm -!insertmacro MUI_UNPAGE_CONFIRM +UninstPage custom un.preConfirm un.leaveConfirm ; Remove Files Page !insertmacro MUI_UNPAGE_INSTFILES @@ -200,6 +207,11 @@ Section "Uninstall" ClearErrors ${EndIf} + ${MUI_INSTALLOPTIONS_READ} $0 "unconfirm.ini" "Field 3" "State" + ${If} "$0" == "1" + ${un.DeleteRelativeProfiles} "Mozilla\Firefox" + ${EndIf} + SetShellVarContext current ; Set SHCTX to HKCU ${un.RegCleanMain} "Software\Mozilla" ${un.RegCleanUninstall} @@ -362,17 +374,41 @@ Function un.preWelcome ${EndIf} FunctionEnd -Function un.showConfirm +Function un.preConfirm ${If} ${FileExists} "$INSTDIR\distribution\modern-header.bmp" ${AndIf} $hHeaderBitmap == "" Delete "$PLUGINSDIR\modern-header.bmp" CopyFiles /SILENT "$INSTDIR\distribution\modern-header.bmp" "$PLUGINSDIR\modern-header.bmp" ${un.ChangeMUIHeaderImage} "$PLUGINSDIR\modern-header.bmp" ${EndIf} + + !insertmacro un.createUnConfirmINI + !insertmacro MUI_HEADER_TEXT "$(UN_CONFIRM_PAGE_TITLE)" "$(UN_CONFIRM_PAGE_SUBTITLE)" + ; The Summary custom page has a textbox that will automatically receive + ; focus. This sets the focus to the Install button instead. + !insertmacro MUI_INSTALLOPTIONS_INITDIALOG "unconfirm.ini" + GetDlgItem $0 $HWNDPARENT 1 + ${MUI_INSTALLOPTIONS_READ} $1 "unconfirm.ini" "Field 4" "HWND" + SetCtlColors $1 0x000000 0xFFFFEE + ShowWindow $1 ${SW_HIDE} + System::Call "user32::SetFocus(i r0, i 0x0007, i,i)i" + !insertmacro MUI_INSTALLOPTIONS_SHOW FunctionEnd -; Checks if the app being uninstalled is running. Function un.leaveConfirm + ${MUI_INSTALLOPTIONS_READ} $0 "unconfirm.ini" "Settings" "State" + StrCmp $0 "3" +1 continue + ${MUI_INSTALLOPTIONS_READ} $0 "unconfirm.ini" "Field 3" "State" + ${MUI_INSTALLOPTIONS_READ} $1 "unconfirm.ini" "Field 4" "HWND" + StrCmp $0 1 +1 +3 + ShowWindow $1 ${SW_SHOW} + Abort + + ShowWindow $1 ${SW_HIDE} + Abort + + continue: + ; Try to delete the app executable and if we can't delete it try to find the ; app's message window and prompt the user to close the app. This allows ; running an instance that is located in another directory. If for whatever diff --git a/browser/locales/en-US/installer/custom.properties b/browser/locales/en-US/installer/custom.properties index da0174a92752..0a40a69564fc 100755 --- a/browser/locales/en-US/installer/custom.properties +++ b/browser/locales/en-US/installer/custom.properties @@ -81,6 +81,13 @@ WARN_UNSUPPORTED_MSG=Sorry, ${BrandShortName} can't be installed. This version o WARN_RESTART_REQUIRED_UNINSTALL=Your computer must be restarted to complete a previous uninstall of ${BrandShortName}. Do you want to reboot now? ERROR_CREATE_DIRECTORY=Error creating directory:\n\n$0\n\nClick Cancel to stop the installation or\nRetry to try again. +UN_CONFIRM_PAGE_TITLE=Uninstall ${BrandFullName} +UN_CONFIRM_PAGE_SUBTITLE=Remove ${BrandFullName} from your computer. +UN_CONFIRM_UNINSTALLED_FROM=${BrandShortName} will be uninstalled from the following location: +UN_CONFIRM_CLICK=Click Uninstall to continue. +UN_REMOVE_PROFILES=&Remove my ${BrandShortName} personal data and customizations +UN_REMOVE_PROFILES_DESC=This will permanently remove your bookmarks, saved passwords, cookies and customizations. You may wish to keep this information if you plan on installing another version of ${BrandShortName} in the future. + STATUS_INSTALL_APP=Installing ${BrandShortName}... STATUS_INSTALL_LANG=Installing Language Files (${AB_CD})... STATUS_INSTALL_OPTIONAL=Installing Optional Components... diff --git a/toolkit/mozapps/installer/windows/nsis/common.nsh b/toolkit/mozapps/installer/windows/nsis/common.nsh index a5d4d28458c1..ac92936ead15 100755 --- a/toolkit/mozapps/installer/windows/nsis/common.nsh +++ b/toolkit/mozapps/installer/windows/nsis/common.nsh @@ -534,6 +534,54 @@ WriteINIStr "$PLUGINSDIR\summary.ini" "Field 3" Bottom "150" !macroend +!macro un.createUnConfirmINI + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Settings" NumFields "5" + + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Type "label" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Text "$(UN_CONFIRM_UNINSTALLED_FROM)" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Left "0" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Right "-1" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Top "5" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Bottom "15" + + ; XXXrstrong - a side affect of using a READONLY textbox is if the path is + ; longer than the visible area of the textbox it will display the characters + ; at the end and the beginning of the path will be hidden. Since the path has + ; to be greater than 74 characters in length I'm not going to spend any + ; cycles trying to come up with a workaround. + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" Type "text" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" State "$INSTDIR" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" Left "0" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" Right "-1" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" Top "17" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" Bottom "30" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" flags "READONLY" + + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Type "checkbox" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Text "$(UN_REMOVE_PROFILES)" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Left "0" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Right "-1" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Top "40" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Bottom "50" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" State "0" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" flags "NOTIFY" + + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Type "text" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" State "$(UN_REMOVE_PROFILES_DESC)" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Left "0" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Right "-1" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Top "52" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Bottom "120" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" flags "MULTILINE|READONLY" + + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 5" Type "label" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 5" Text "$(UN_CONFIRM_CLICK)" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 5" Left "0" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 5" Right "-1" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 5" Top "130" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 5" Bottom "150" +!macroend + /** * DEPRECATED - use GetParent instead. */ @@ -3042,6 +3090,108 @@ !endif !macroend +/** + * Deletes all relative profiles specified in an application's profiles.ini and + * performs various other cleanup. + * + * @param _REL_PROFILE_PATH + * The relative path to the profile directory. + * + * $R6 = value of IsRelative read from profiles.ini + * $R7 = value of Path to profile read from profiles.ini + * $R8 = counter for reading profiles (e.g. Profile0, Profile1, etc.) + * $R9 = _REL_PROFILE_PATH + */ +!macro DeleteRelativeProfiles + + !ifndef ${_MOZFUNC_UN}DeleteRelativeProfiles + !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN} + !insertmacro ${_MOZFUNC_UN_TMP}WordReplace + !undef _MOZFUNC_UN + !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP} + !undef _MOZFUNC_UN_TMP + + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + !define ${_MOZFUNC_UN}DeleteRelativeProfiles "!insertmacro ${_MOZFUNC_UN}DeleteRelativeProfilesCall" + + Function ${_MOZFUNC_UN}DeleteRelativeProfiles + Exch $R9 + Push $R8 + Push $R7 + Push $R6 + + SetShellVarContext current + StrCpy $R8 -1 + + loop: + IntOp $R8 $R8 + 1 ; Increment the counter. + ReadINIStr $R7 "$APPDATA\$R9\profiles.ini" "Profile$R8" "Path" + IfErrors end +1 + + ; Only remove relative profiles + ReadINIStr $R6 "$APPDATA\$R9\profiles.ini" "Profile$R8" "IsRelative" + StrCmp "$R6" "1" +1 loop + + ; Relative paths in profiles.ini use / as a separator + ${${_MOZFUNC_UN}WordReplace} "$R7" "/" "\" "+" $R7 + + IfFileExists "$LOCALAPPDATA\$R9\$R7" +1 +2 + RmDir /r "$LOCALAPPDATA\$R9\$R7" + IfFileExists "$APPDATA\$R9\$R7" +1 +2 + RmDir /r "$APPDATA\$R9\$R7" + GoTo loop + + end: + ; Remove profiles directory under LOCALAPPDATA (e.g. cache, etc.) since + ; they are at times abandoned. + RmDir /r "$LOCALAPPDATA\$R9\Profiles" + RmDir /r "$APPDATA\$R9\Crash Reports" + Delete "$APPDATA\$R9\profiles.ini" + Delete "$APPDATA\$R9\console.log" + Delete "$APPDATA\$R9\pluginreg.dat" + + Pop $R6 + Pop $R7 + Pop $R8 + Exch $R9 + FunctionEnd + + !verbose pop + !endif +!macroend + +!macro DeleteRelativeProfilesCall _REL_PROFILE_PATH + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + Push "${_REL_PROFILE_PATH}" + Call DeleteRelativeProfiles + !verbose pop +!macroend + +!macro un.DeleteRelativeProfilesCall _REL_PROFILE_PATH + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + Push "${_REL_PROFILE_PATH}" + Call un.DeleteRelativeProfiles + !verbose pop +!macroend + +!macro un.DeleteRelativeProfiles + !ifndef un.DeleteRelativeProfiles + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + !undef _MOZFUNC_UN + !define _MOZFUNC_UN "un." + + !insertmacro DeleteRelativeProfiles + + !undef _MOZFUNC_UN + !define _MOZFUNC_UN + !verbose pop + !endif +!macroend + ################################################################################ # Macros for parsing and updating the uninstall.log and removed-files.log