Bug 1161661 - Provide progress and state feedback via the stub installer taskbar icon. r=bbondy
☠☠ backed out by 8f21d63b310a ☠ ☠
authorRobert Strong <robert.bugzilla@gmail.com>
Thu, 07 May 2015 10:35:00 -0700
changeset 274302 39fdaf04c690f52d18607fbfefc302fa795aacbb
parent 274301 f19f79a63cf2ba41229ffa0ff919085a05afd4ec
child 274303 de4f4de880fd428dce92c94ef168532f57dff547
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbondy
bugs1161661
milestone40.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1161661 - Provide progress and state feedback via the stub installer taskbar icon. r=bbondy
browser/installer/windows/nsis/installer.nsi
browser/installer/windows/nsis/stub.nsi
browser/installer/windows/nsis/uninstaller.nsi
toolkit/mozapps/installer/windows/nsis/common.nsh
--- a/browser/installer/windows/nsis/installer.nsi
+++ b/browser/installer/windows/nsis/installer.nsi
@@ -249,20 +249,17 @@ Section "-InstallStartCleanup"
 
   ; setup the application model id registration value
   ${InitHashAppModelId} "$INSTDIR" "Software\Mozilla\${AppName}\TaskBarIDs"
 
   ; Remove the updates directory for Vista and above
   ${CleanUpdateDirectories} "Mozilla\Firefox" "Mozilla\updates"
 
   ${RemoveDeprecatedFiles}
-
-  StrCpy $R2 "false"
-  StrCpy $R3 "false"
-  ${RemovePrecompleteEntries} "$R2" "$R3"
+  ${RemovePrecompleteEntries} "false"
 
   ${If} ${FileExists} "$INSTDIR\defaults\pref\channel-prefs.js"
     Delete "$INSTDIR\defaults\pref\channel-prefs.js"
   ${EndIf}
   ${If} ${FileExists} "$INSTDIR\defaults\pref"
     RmDir "$INSTDIR\defaults\pref"
   ${EndIf}
   ${If} ${FileExists} "$INSTDIR\defaults"
--- a/browser/installer/windows/nsis/stub.nsi
+++ b/browser/installer/windows/nsis/stub.nsi
@@ -66,16 +66,18 @@ Var DownloadReset
 Var ExistingTopDir
 Var SpaceAvailableBytes
 Var InitialInstallDir
 Var HandleDownload
 Var CanSetAsDefault
 Var InstallCounterStep
 Var InstallStepSize
 Var InstallTotalSteps
+Var ProgressCompleted
+Var ProgressTotal
 Var TmpVal
 
 Var ExitCode
 Var FirefoxLaunchCode
 
 ; The first three tick counts are for the start of a phase and equate equate to
 ; the display of individual installer pages.
 Var StartIntroPhaseTickCount
@@ -253,16 +255,17 @@ Var ControlRightPX
 !insertmacro GetLongPath
 !insertmacro GetPathFromString
 !insertmacro GetParent
 !insertmacro GetSingleInstallPath
 !insertmacro GetTextWidthHeight
 !insertmacro IsUserAdmin
 !insertmacro RemovePrecompleteEntries
 !insertmacro SetBrandNameVars
+!insertmacro ITBL3Create
 !insertmacro UnloadUAC
 
 VIAddVersionKey "FileDescription" "${BrandShortName} Stub Installer"
 VIAddVersionKey "OriginalFilename" "setup-stub.exe"
 
 Name "$BrandFullName"
 OutFile "setup-stub.exe"
 icon "setup.ico"
@@ -1288,16 +1291,19 @@ Function createInstall
   Pop $StartDownloadPhaseTickCount
 
   ${If} ${FileExists} "$INSTDIR\uninstall\uninstall.log"
     StrCpy $InstallTotalSteps ${InstallPaveOverTotalSteps}
   ${Else}
     StrCpy $InstallTotalSteps ${InstallCleanTotalSteps}
   ${EndIf}
 
+  ${ITBL3Create}
+  ${ITBL3SetProgressState} "${TBPF_INDETERMINATE}"
+
   ${NSD_CreateTimer} StartDownload ${DownloadIntervalMS}
 
   LockWindow off
   nsDialogs::Show
 
   ${NSD_FreeImage} $0
   ${NSD_FreeImage} $HwndBitmapBlurb1
   ${NSD_FreeImage} $HwndBitmapBlurb2
@@ -1310,16 +1316,31 @@ Function StartDownload
                 /CONNECTTIMEOUT 120 /RECEIVETIMEOUT 120 /END
   StrCpy $4 ""
   ${NSD_CreateTimer} OnDownload ${DownloadIntervalMS}
   ${If} ${FileExists} "$INSTDIR\${TO_BE_DELETED}"
     RmDir /r "$INSTDIR\${TO_BE_DELETED}"
   ${EndIf}
 FunctionEnd
 
+Function SetProgressBars
+  SendMessage $Progressbar ${PBM_SETPOS} $ProgressCompleted 0
+  ${ITBL3SetProgressValue} "$ProgressCompleted" "$ProgressTotal"
+FunctionEnd
+
+Function RemoveFileProgressCallback
+  IntOp $InstallCounterStep $InstallCounterStep + 2
+  System::Int64Op $ProgressCompleted + $InstallStepSize
+  Pop $ProgressCompleted
+  Call SetProgressBars
+  System::Int64Op $ProgressCompleted + $InstallStepSize
+  Pop $ProgressCompleted
+  Call SetProgressBars
+FunctionEnd
+
 Function OnDownload
   InetBgDL::GetStats
   # $0 = HTTP status code, 0=Completed
   # $1 = Completed files
   # $2 = Remaining files
   # $3 = Number of downloaded bytes for the current file
   # $4 = Size of current file (Empty string if the size is unknown)
   # /RESET must be used if status $0 > 299 (e.g. failure)
@@ -1328,16 +1349,17 @@ Function OnDownload
   ${If} $0 > 299
     ${NSD_KillTimer} OnDownload
     IntOp $DownloadRetryCount $DownloadRetryCount + 1
     ${If} "$DownloadReset" != "true"
       StrCpy $DownloadedBytes "0"
       ${NSD_AddStyle} $Progressbar ${PBS_MARQUEE}
       SendMessage $Progressbar ${PBM_SETMARQUEE} 1 \
                   $ProgressbarMarqueeIntervalMS ; start=1|stop=0 interval(ms)=+N
+      ${ITBL3SetProgressState} "${TBPF_INDETERMINATE}"
     ${EndIf}
     InetBgDL::Get /RESET /END
     StrCpy $DownloadSizeBytes ""
     StrCpy $DownloadReset "true"
 
     ${If} $DownloadRetryCount >= ${DownloadMaxRetries}
       StrCpy $ExitCode "${ERR_DOWNLOAD_TOO_MANY_RETRIES}"
       ; Use a timer so the UI has a chance to update
@@ -1385,18 +1407,19 @@ Function OnDownload
     StrCpy $DownloadSizeBytes "$4"
     System::Int64Op $4 / 2
     Pop $HalfOfDownload
     System::Int64Op $HalfOfDownload / $InstallTotalSteps
     Pop $InstallStepSize
     SendMessage $Progressbar ${PBM_SETMARQUEE} 0 0 ; start=1|stop=0 interval(ms)=+N
     ${RemoveStyle} $Progressbar ${PBS_MARQUEE}
     System::Int64Op $HalfOfDownload + $DownloadSizeBytes
-    Pop $R9
-    SendMessage $Progressbar ${PBM_SETRANGE32} 0 $R9
+    Pop $ProgressTotal
+    StrCpy $ProgressCompleted 0
+    SendMessage $Progressbar ${PBM_SETRANGE32} $ProgressCompleted $ProgressTotal
   ${EndIf}
 
   ; Don't update the status until after the download starts
   ${If} $2 != 0
   ${AndIf} "$4" == ""
     Return
   ${EndIf}
 
@@ -1443,22 +1466,23 @@ Function OnDownload
           ${NSD_CreateTimer} StartDownload ${DownloadIntervalMS}
         ${EndIf}
         Return
       ${EndIf}
 
       LockWindow on
       ; Update the progress bars first in the UI change so they take affect
       ; before other UI changes.
-      SendMessage $Progressbar ${PBM_SETPOS} $DownloadSizeBytes 0
+      StrCpy $ProgressCompleted "$DownloadSizeBytes"
+      Call SetProgressBars
       System::Int64Op $InstallStepSize * ${InstallProgressFirstStep}
       Pop $R9
-      SendMessage $Progressbar ${PBM_SETSTEP} $R9 0
-      SendMessage $Progressbar ${PBM_STEPIT} 0 0
-      SendMessage $Progressbar ${PBM_SETSTEP} $InstallStepSize 0
+      System::Int64Op $ProgressCompleted + $R9
+      Pop $ProgressCompleted
+      Call SetProgressBars
       ShowWindow $LabelDownloading ${SW_HIDE}
       ShowWindow $LabelInstalling ${SW_SHOW}
       ShowWindow $LabelBlurb2 ${SW_HIDE}
       ShowWindow $BitmapBlurb2 ${SW_HIDE}
       ShowWindow $LabelBlurb3 ${SW_SHOW}
       ShowWindow $BitmapBlurb3 ${SW_SHOW}
       ; Disable the Cancel button during the install
       GetDlgItem $5 $HWNDPARENT 2
@@ -1535,17 +1559,18 @@ Function OnDownload
       ; from creating a taskbar shortcut (Bug 791613).
       ${GetShortcutsLogPath} $0
       Delete "$0"
       ; Workaround to prevent pinning to the taskbar.
       ${If} $CheckboxShortcutOnBar == 0
         WriteIniStr "$0" "TASKBAR" "Migrated" "true"
       ${EndIf}
 
-      ${RemovePrecompleteEntries} $Progressbar $InstallCounterStep
+      GetFunctionAddress $0 RemoveFileProgressCallback
+      ${RemovePrecompleteEntries} $0
 
       ; Delete the install.log and let the full installer create it. When the
       ; installer closes it we can detect that it has completed.
       Delete "$INSTDIR\install.log"
 
       ; Delete firefox.exe.moz-upgrade and firefox.exe.moz-delete if it exists
       ; since it being present will require an OS restart for the full
       ; installer.
@@ -1564,17 +1589,18 @@ Function OnDownload
         LockWindow on
         ShowWindow $LabelBlurb1 ${SW_HIDE}
         ShowWindow $BitmapBlurb1 ${SW_HIDE}
         ShowWindow $LabelBlurb2 ${SW_SHOW}
         ShowWindow $BitmapBlurb2 ${SW_SHOW}
         LockWindow off
       ${EndIf}
       StrCpy $DownloadedBytes "$3"
-      SendMessage $Progressbar ${PBM_SETPOS} $3 0
+      StrCpy $ProgressCompleted "$DownloadedBytes"
+      Call SetProgressBars
     ${EndIf}
   ${EndIf}
 FunctionEnd
 
 Function OnPing
   InetBgDL::GetStats
   # $0 = HTTP status code, 0=Completed
   # $1 = Completed files
@@ -1603,17 +1629,19 @@ Function CheckInstall
     ; Close the handle that prevents modification of the full installer
     System::Call 'kernel32::CloseHandle(i $HandleDownload)'
     StrCpy $ExitCode "${ERR_INSTALL_TIMEOUT}"
     ; Use a timer so the UI has a chance to update
     ${NSD_CreateTimer} DisplayDownloadError ${InstallIntervalMS}
     Return
   ${EndIf}
 
-  SendMessage $Progressbar ${PBM_STEPIT} 0 0
+  System::Int64Op $ProgressCompleted + $InstallStepSize
+  Pop $ProgressCompleted
+  Call SetProgressBars
 
   ${If} ${FileExists} "$INSTDIR\install.log"
     Delete "$INSTDIR\install.tmp"
     CopyFiles /SILENT "$INSTDIR\install.log" "$INSTDIR\install.tmp"
 
     ; The unfocus and refocus that happens approximately here is caused by the
     ; installer calling SHChangeNotify to refresh the shortcut icons.
 
@@ -1627,39 +1655,40 @@ Function CheckInstall
       System::Call 'kernel32::CloseHandle(i $HandleDownload)'
       Rename "$INSTDIR\install.tmp" "$INSTDIR\install.log"
       Delete "$PLUGINSDIR\download.exe"
       Delete "$PLUGINSDIR\${CONFIG_INI}"
       System::Call "kernel32::GetTickCount()l .s"
       Pop $EndInstallPhaseTickCount
       System::Int64Op $InstallStepSize * ${InstallProgressFinishStep}
       Pop $InstallStepSize
-      SendMessage $Progressbar ${PBM_SETSTEP} $InstallStepSize 0
       ${NSD_CreateTimer} FinishInstall ${InstallIntervalMS}
     ${EndUnless}
   ${EndIf}
 FunctionEnd
 
 Function FinishInstall
   ; The full installer has completed but the progress bar still needs to finish
   ; so increase the size of the step.
   IntOp $InstallCounterStep $InstallCounterStep + ${InstallProgressFinishStep}
   ${If} $InstallTotalSteps < $InstallCounterStep
     StrCpy $InstallCounterStep "$InstallTotalSteps"
   ${EndIf}
 
   ${If} $InstallTotalSteps != $InstallCounterStep
-    SendMessage $Progressbar ${PBM_STEPIT} 0 0
+    System::Int64Op $ProgressCompleted + $InstallStepSize
+    Pop $ProgressCompleted
+    Call SetProgressBars
     Return
   ${EndIf}
 
   ${NSD_KillTimer} FinishInstall
 
-  SendMessage $Progressbar ${PBM_GETRANGE} 0 0 $R9
-  SendMessage $Progressbar ${PBM_SETPOS} $R9 0
+  StrCpy $ProgressCompleted "$ProgressTotal"
+  Call SetProgressBars
 
   ${If} "$CheckboxSetAsDefault" == "1"
     ${GetParameters} $0
     ClearErrors
     ${GetOptions} "$0" "/UAC:" $0
     ${If} ${Errors} ; Not elevated
       Call ExecSetAsDefaultAppUser
     ${Else} ; Elevated - execute the function in the unelevated process
@@ -1930,16 +1959,20 @@ Function LaunchAppFromElevatedProcess
   ; Set the current working directory to the installation directory
   ${GetParent} "$0" $1
   SetOutPath "$1"
   Exec "$\"$0$\""
 FunctionEnd
 
 Function DisplayDownloadError
   ${NSD_KillTimer} DisplayDownloadError
+  ; To better display the error state on the taskbar set the progress completed
+  ; value to the total value.
+  ${ITBL3SetProgressValue} "100" "100"
+  ${ITBL3SetProgressState} "${TBPF_ERROR}"
   MessageBox MB_OKCANCEL|MB_ICONSTOP "$(ERROR_DOWNLOAD)" IDCANCEL +2 IDOK +1
   StrCpy $OpenedDownloadPage "1" ; Already initialized to 0
 
   ${If} "$OpenedDownloadPage" == "1"
     ClearErrors
     ${GetParameters} $0
     ${GetOptions} "$0" "/UAC:" $1
     ${If} ${Errors}
--- a/browser/installer/windows/nsis/uninstaller.nsi
+++ b/browser/installer/windows/nsis/uninstaller.nsi
@@ -392,19 +392,17 @@ Section "Uninstall"
   ${un.CleanVirtualStore}
 
   ; Only unregister the dll if the registration points to this installation
   ReadRegStr $R1 HKCR "CLSID\{0D68D6D0-D93D-4D08-A30D-F00DD1F45B24}\InProcServer32" ""
   ${If} "$INSTDIR\AccessibleMarshal.dll" == "$R1"
     ${UnregisterDLL} "$INSTDIR\AccessibleMarshal.dll"
   ${EndIf}
 
-  StrCpy $R2 "false"
-  StrCpy $R3 "false"
-  ${un.RemovePrecompleteEntries} "$R2" "$R3"
+  ${un.RemovePrecompleteEntries} "false"
 
   ${If} ${FileExists} "$INSTDIR\defaults\pref\channel-prefs.js"
     Delete /REBOOTOK "$INSTDIR\defaults\pref\channel-prefs.js"
   ${EndIf}
   ${If} ${FileExists} "$INSTDIR\defaults\pref"
     RmDir /REBOOTOK "$INSTDIR\defaults\pref"
   ${EndIf}
   ${If} ${FileExists} "$INSTDIR\defaults"
--- a/toolkit/mozapps/installer/windows/nsis/common.nsh
+++ b/toolkit/mozapps/installer/windows/nsis/common.nsh
@@ -1636,18 +1636,18 @@
     ExecWait '"$SYSDIR\regsvr32.exe" /s /u "${DLL}"'
     ${EnableX64FSRedirection}
   ${Else}
     UnRegDLL "${DLL}"
   ${EndIf}
 
 !macroend
 
-!define RegisterDLL `!insertmacro RegisterDLL`
-!define UnregisterDLL `!insertmacro UnregisterDLL`
+!define RegisterDLL "!insertmacro RegisterDLL"
+!define UnregisterDLL "!insertmacro UnregisterDLL"
 
 
 ################################################################################
 # Macros for retrieving existing install paths
 
 /**
  * Finds a second installation of the application so we can make informed
  * decisions about registry operations. This uses SHCTX to determine the
@@ -4327,34 +4327,31 @@
 !macro OnInstallUninstallCall
   !verbose push
   !verbose ${_MOZFUNC_VERBOSE}
   Call OnInstallUninstall
   !verbose pop
 !macroend
 
 /**
- * Parses the precomplete file to remove an installation's files and directories.
- *
- * @param   _PROGRESSBAR
- *          The progress bar to update using PBM_STEPIT. Can also be "false" if
- *          updating a progressbar isn't needed.
- * @param   _INSTALL_STEP_COUNTER
- *          The install step counter to increment. The variable specified in
- *          this parameter is also updated. Can also be "false" if a counter
- *          isn't needed.
- * $R2 = false if all files were deleted or moved to the tobedeleted directory.
+ * Parses the precomplete file to remove an installation's files and
+ * directories.
+ *
+ * @param   _CALLBACK
+ *          The function address of a callback function for progress or "false"
+ *          if there is no callback function.
+ *
+ * $R3 = false if all files were deleted or moved to the tobedeleted directory.
  *       true if file(s) could not be moved to the tobedeleted directory.
- * $R3 = Path to temporary precomplete file.
- * $R4 = File handle for the temporary precomplete file.
- * $R5 = String returned from FileRead.
- * $R6 = First seven characters of the string returned from FileRead.
- * $R7 = Temporary file path used to rename files that are in use.
- * $R8 = _PROGRESSBAR
- * $R9 = _INSTALL_STEP_COUNTER
+ * $R4 = Path to temporary precomplete file.
+ * $R5 = File handle for the temporary precomplete file.
+ * $R6 = String returned from FileRead.
+ * $R7 = First seven characters of the string returned from FileRead.
+ * $R8 = Temporary file path used to rename files that are in use.
+ * $R9 = _CALLBACK
  */
 !macro RemovePrecompleteEntries
 
   !ifndef ${_MOZFUNC_UN}RemovePrecompleteEntries
     !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
     !insertmacro ${_MOZFUNC_UN_TMP}GetParent
     !insertmacro ${_MOZFUNC_UN_TMP}TrimNewLines
     !insertmacro ${_MOZFUNC_UN_TMP}WordReplace
@@ -4363,146 +4360,133 @@
     !undef _MOZFUNC_UN_TMP
 
     !verbose push
     !verbose ${_MOZFUNC_VERBOSE}
     !define ${_MOZFUNC_UN}RemovePrecompleteEntries "!insertmacro ${_MOZFUNC_UN}RemovePrecompleteEntriesCall"
 
     Function ${_MOZFUNC_UN}RemovePrecompleteEntries
       Exch $R9
-      Exch 1
-      Exch $R8
+      Push $R8
       Push $R7
       Push $R6
       Push $R5
       Push $R4
       Push $R3
-      Push $R2
 
       ${If} ${FileExists} "$INSTDIR\precomplete"
-        StrCpy $R2 "false"
+        StrCpy $R3 "false"
 
         RmDir /r "$INSTDIR\${TO_BE_DELETED}"
         CreateDirectory "$INSTDIR\${TO_BE_DELETED}"
-        GetTempFileName $R3 "$INSTDIR\${TO_BE_DELETED}"
-        Delete "$R3"
-        Rename "$INSTDIR\precomplete" "$R3"
+        GetTempFileName $R4 "$INSTDIR\${TO_BE_DELETED}"
+        Delete "$R4"
+        Rename "$INSTDIR\precomplete" "$R4"
 
         ClearErrors
         ; Rename and then remove files
-        FileOpen $R4 "$R3" r
+        FileOpen $R5 "$R4" r
         ${Do}
-          FileRead $R4 $R5
+          FileRead $R5 $R6
           ${If} ${Errors}
             ${Break}
           ${EndIf}
 
-          ${${_MOZFUNC_UN}TrimNewLines} "$R5" $R5
+          ${${_MOZFUNC_UN}TrimNewLines} "$R6" $R6
           ; Replace all occurrences of "/" with "\".
-          ${${_MOZFUNC_UN}WordReplace} "$R5" "/" "\" "+" $R5
+          ${${_MOZFUNC_UN}WordReplace} "$R6" "/" "\" "+" $R6
 
           ; Copy the first 7 chars
-          StrCpy $R6 "$R5" 7
-          ${If} "$R6" == "remove "
+          StrCpy $R7 "$R6" 7
+          ${If} "$R7" == "remove "
             ; Copy the string starting after the 8th char
-            StrCpy $R5 "$R5" "" 8
+            StrCpy $R6 "$R6" "" 8
             ; Copy all but the last char to remove the double quote.
-            StrCpy $R5 "$R5" -1
-            ${If} ${FileExists} "$INSTDIR\$R5"
+            StrCpy $R6 "$R6" -1
+            ${If} ${FileExists} "$INSTDIR\$R6"
               ${Unless} "$R9" == "false"
-                IntOp $R9 $R9 + 2
-              ${EndUnless}
-              ${Unless} "$R8" == "false"
-                SendMessage $R8 ${PBM_STEPIT} 0 0
-                SendMessage $R8 ${PBM_STEPIT} 0 0
+                Call $R9
               ${EndUnless}
 
               ClearErrors
-              Delete "$INSTDIR\$R5"
+              Delete "$INSTDIR\$R6"
               ${If} ${Errors}
-                GetTempFileName $R7 "$INSTDIR\${TO_BE_DELETED}"
-                Delete "$R7"
+                GetTempFileName $R8 "$INSTDIR\${TO_BE_DELETED}"
+                Delete "$R8"
                 ClearErrors
-                Rename "$INSTDIR\$R5" "$R7"
+                Rename "$INSTDIR\$R6" "$R8"
                 ${Unless} ${Errors}
-                  Delete /REBOOTOK "$R7"
+                  Delete /REBOOTOK "$R8"
 
                   ClearErrors
                 ${EndUnless}
 !ifdef __UNINSTALL__
                 ${If} ${Errors}
-                  Delete /REBOOTOK "$INSTDIR\$R5"
-                  StrCpy $R2 "true"
+                  Delete /REBOOTOK "$INSTDIR\$R6"
+                  StrCpy $R3 "true"
                   ClearErrors
                 ${EndIf}
 !endif
               ${EndIf}
             ${EndIf}
-          ${ElseIf} "$R6" == "rmdir $\""
+          ${ElseIf} "$R7" == "rmdir $\""
             ; Copy the string starting after the 7th char.
-            StrCpy $R5 "$R5" "" 7
+            StrCpy $R6 "$R6" "" 7
             ; Copy all but the last two chars to remove the slash and the double quote.
-            StrCpy $R5 "$R5" -2
-            ${If} ${FileExists} "$INSTDIR\$R5"
+            StrCpy $R6 "$R6" -2
+            ${If} ${FileExists} "$INSTDIR\$R6"
               ; Ignore directory removal errors
-              RmDir "$INSTDIR\$R5"
+              RmDir "$INSTDIR\$R6"
               ClearErrors
             ${EndIf}
           ${EndIf}
         ${Loop}
-        FileClose $R4
+        FileClose $R5
 
         ; Delete the temporary precomplete file
-        Delete /REBOOTOK "$R3"
+        Delete /REBOOTOK "$R4"
 
         RmDir /r /REBOOTOK "$INSTDIR\${TO_BE_DELETED}"
 
         ${If} ${RebootFlag}
-        ${AndIf} "$R2" == "false"
+        ${AndIf} "$R3" == "false"
           ; Clear the reboot flag if all files were deleted or moved to the
           ; tobedeleted directory.
           SetRebootFlag false
         ${EndIf}
       ${EndIf}
 
       ClearErrors
 
-      Pop $R2
       Pop $R3
       Pop $R4
       Pop $R5
       Pop $R6
       Pop $R7
-      Exch $R8
-      Exch 1
+      Pop $R8
       Exch $R9
     FunctionEnd
 
     !verbose pop
   !endif
 !macroend
 
-!macro RemovePrecompleteEntriesCall _PROGRESSBAR _INSTALL_STEP_COUNTER
+!macro RemovePrecompleteEntriesCall _CALLBACK
   !verbose push
-  Push "${_PROGRESSBAR}"
-  Push "${_INSTALL_STEP_COUNTER}"
+  Push "${_CALLBACK}"
   !verbose ${_MOZFUNC_VERBOSE}
   Call RemovePrecompleteEntries
-  Pop ${_INSTALL_STEP_COUNTER}
   !verbose pop
 !macroend
 
-!macro un.RemovePrecompleteEntriesCall _PROGRESSBAR _INSTALL_STEP_COUNTER
+!macro un.RemovePrecompleteEntriesCall _CALLBACK
   !verbose push
   !verbose ${_MOZFUNC_VERBOSE}
-  Push "${_PROGRESSBAR}"
-  Push "${_INSTALL_STEP_COUNTER}"
+  Push "${_CALLBACK}"
   Call un.RemovePrecompleteEntries
-  Pop ${_INSTALL_STEP_COUNTER}
-  Pop $0
   !verbose pop
 !macroend
 
 !macro un.RemovePrecompleteEntries
   !ifndef un.RemovePrecompleteEntries
     !verbose push
     !verbose ${_MOZFUNC_VERBOSE}
     !undef _MOZFUNC_UN
@@ -7323,16 +7307,165 @@
     !insertmacro InitHashAppModelId
 
     !undef _MOZFUNC_UN
     !define _MOZFUNC_UN
     !verbose pop
   !endif
 !macroend
 
+################################################################################
+# Helpers for taskbar progress
+
+!ifndef CLSCTX_INPROC_SERVER
+  !define CLSCTX_INPROC_SERVER  1
+!endif
+
+!define CLSID_ITaskbarList {56fdf344-fd6d-11d0-958a-006097c9a090}
+!define IID_ITaskbarList3 {ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf}
+!define ITaskbarList3->SetProgressValue $ITaskbarList3->9
+!define ITaskbarList3->SetProgressState $ITaskbarList3->10
+
+/**
+ * Creates a single uninitialized object of the ITaskbarList class with a
+ * reference to the ITaskbarList3 interface. This object can be used to set
+ * progress and state on the installer's taskbar icon using the helper macros
+ * in this section.
+ */
+!macro ITBL3Create
+
+  !ifndef ${_MOZFUNC_UN}ITBL3Create
+    Var ITaskbarList3
+
+    !verbose push
+    !verbose ${_MOZFUNC_VERBOSE}
+    !define ${_MOZFUNC_UN}ITBL3Create "!insertmacro ${_MOZFUNC_UN}ITBL3CreateCall"
+
+    Function ${_MOZFUNC_UN}ITBL3Create
+      ; Setting to 0 allows the helper macros to detect when the object was not
+      ; created.
+      StrCpy $ITaskbarList3 0
+      ; Don't create when running silently.
+      ${Unless} ${Silent}
+        ; This is only supported on Win 7 and above.
+        ${If} ${AtLeastWin7}
+          System::Call "ole32::CoCreateInstance(g '${CLSID_ITaskbarList}', \
+                                                i 0, \
+                                                i ${CLSCTX_INPROC_SERVER}, \
+                                                g '${IID_ITaskbarList3}', \
+                                                *i .s)"
+          Pop $ITaskbarList3
+        ${EndIf}
+      ${EndUnless}
+    FunctionEnd
+
+    !verbose pop
+  !endif
+!macroend
+
+!macro ITBL3CreateCall
+  !verbose push
+  !verbose ${_MOZFUNC_VERBOSE}
+  Call ITBL3Create
+  !verbose pop
+!macroend
+
+!macro un.ITBL3CreateCall _PATH_TO_IMAGE
+  !verbose push
+  !verbose ${_MOZFUNC_VERBOSE}
+  Call un.ITBL3Create
+  !verbose pop
+!macroend
+
+!macro un.ITBL3Create
+  !ifndef un.ITBL3Create
+    !verbose push
+    !verbose ${_MOZFUNC_VERBOSE}
+    !undef _MOZFUNC_UN
+    !define _MOZFUNC_UN "un."
+
+    !insertmacro ITBL3Create
+
+    !undef _MOZFUNC_UN
+    !define _MOZFUNC_UN
+    !verbose pop
+  !endif
+!macroend
+
+/**
+ * Sets the percentage completed on the taskbar process icon progress indicator.
+ *
+ * @param   _COMPLETED
+ *          The proportion of the operation that has been completed in relation
+ *          to _TOTAL.
+ * @param   _TOTAL
+ *          The value _COMPLETED will have when the operation has completed.
+ *
+ * $R8 = _COMPLETED
+ * $R9 = _TOTAL
+ */
+!macro ITBL3SetProgressValueCall _COMPLETED _TOTAL
+  Push ${_COMPLETED}
+  Push ${_TOTAL}
+  ${CallArtificialFunction} ITBL3SetProgressValue_
+!macroend
+
+!define ITBL3SetProgressValue "!insertmacro ITBL3SetProgressValueCall"
+!define un.ITBL3SetProgressValue "!insertmacro ITBL3SetProgressValueCall"
+
+!macro ITBL3SetProgressValue_
+  Exch $R9
+  Exch 1
+  Exch $R8
+  ${If} ${AtLeastWin7}
+  ${AndIf} $ITaskbarList3 <> 0
+    System::Call "${ITaskbarList3->SetProgressValue}(i$HWNDPARENT, l$R8, l$R9)"
+  ${EndIf}
+  Exch $R8
+  Exch 1
+  Exch $R9
+!macroend
+
+; Normal state / no progress bar
+!define TBPF_NOPROGRESS       0x00000000
+; Marquee style progress bar
+!define TBPF_INDETERMINATE    0x00000001
+; Standard progress bar
+!define TBPF_NORMAL           0x00000002
+; Red taskbar button to indicate an error occurred
+!define TBPF_ERROR            0x00000004
+; Yellow taskbar button to indicate user attention (input) is required to
+; resume progress
+!define TBPF_PAUSED           0x00000008
+
+/**
+ * Sets the state on the taskbar process icon progress indicator.
+ *
+ * @param   _STATE
+ *          The state to set on the taskbar icon progress indicator. Only one of
+ *          the states defined above should be specified.
+ *
+ * $R9 = _STATE
+ */
+!macro ITBL3SetProgressStateCall _STATE
+  Push ${_STATE}
+  ${CallArtificialFunction} ITBL3SetProgressState_
+!macroend
+
+!define ITBL3SetProgressState "!insertmacro ITBL3SetProgressStateCall"
+!define un.ITBL3SetProgressState "!insertmacro ITBL3SetProgressStateCall"
+
+!macro ITBL3SetProgressState_
+  Exch $R9
+  ${If} ${AtLeastWin7}
+  ${AndIf} $ITaskbarList3 <> 0
+    System::Call "${ITaskbarList3->SetProgressState}(i$HWNDPARENT, i$R9)"
+  ${EndIf}
+  Exch $R9
+!macroend
 
 ################################################################################
 # Helpers for the new user interface
 
 !ifndef MAXDWORD
   !define MAXDWORD 0xffffffff
 !endif
 
@@ -7425,17 +7558,17 @@
   ${NSD_AddExStyle} $R0 ${WS_EX_TRANSPARENT}|${WS_EX_TOPMOST}
 
   Pop $R0
   Pop $2
   Pop $1
   Exch $0
   Pop ${HANDLE}
 !macroend
-!define SetStretchedTransparentImage `!insertmacro __SetStretchedTransparentImage`
+!define SetStretchedTransparentImage "!insertmacro __SetStretchedTransparentImage"
 
 /**
  * Removes a single style from a control.
  *
  * _HANDLE the handle of the control
  * _STYLE  the style to remove
  */
 !macro _RemoveStyle _HANDLE _STYLE