Bug 800112 - If I pave-over install Nightly while Nightly is running twice or more in a row, then nightly will always order a restart on every launch or uninstall. r=bbondy
authorRobert Strong <robert.bugzilla@gmail.com>
Fri, 12 Oct 2012 10:55:29 -0700
changeset 110179 90857937b601c194876922875486aedd7f6af69f
parent 110178 c9b7e55872c956a733b187167ab16ea2959e1f8f
child 110255 0be7bfea4744e871588a4248c0fe15213fb5d5ff
child 111114 ce28c1c2480028e6d4a83d5beb843fb2e18c1b36
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersbbondy
bugs800112
milestone19.0a1
Bug 800112 - If I pave-over install Nightly while Nightly is running twice or more in a row, then nightly will always order a restart on every launch or uninstall. r=bbondy
browser/installer/windows/nsis/stub.nsi
--- a/browser/installer/windows/nsis/stub.nsi
+++ b/browser/installer/windows/nsis/stub.nsi
@@ -59,20 +59,35 @@ Var DownloadSize
 Var HalfOfDownload
 Var DownloadReset
 Var ExistingTopDir
 Var SpaceAvailableBytes
 Var InitialInstallDir
 Var HandleDownload
 Var CanSetAsDefault
 Var TmpVal
+Var InstallCounterStep
 
 Var HEIGHT_PX
 Var CTL_RIGHT_PX
 
+!define DownloadIntervalMS 200 ; Interval for the download timer
+!define InstallIntervalMS 100 ; Interval for the install timer
+
+; Number of steps for the install progress.
+; This is 120 seconds with a 100 millisecond timer and a first step of 20 as
+; defined by InstallProgressFirstStep. This might not be enough when installing
+; on a slow network drive so it will fallback to downloading the full installer
+; if it reaches this number. The size of the install progress step increases
+; when the full installer finishes instead of waiting the entire 120 seconds.
+!define InstallProgresSteps 1220
+; The first step for the install progress bar. By starting with a large step
+; immediate feedback is given to the user.
+!define InstallProgressFirstStep 20
+
 ; On Vista and above attempt to elevate Standard Users in addition to users that
 ; are a member of the Administrators group.
 !define NONADMIN_ELEVATE
 
 !define CONFIG_INI "config.ini"
 
 !define MAX_PATH 260
 
@@ -309,16 +324,18 @@ FunctionEnd
 Function .onGUIEnd
   ${UnloadUAC}
 FunctionEnd
 
 Function .onUserAbort
   ${NSD_KillTimer} StartDownload
   ${NSD_KillTimer} OnDownload
   ${NSD_KillTimer} StartInstall
+  ${NSD_KillTimer} CheckInstall
+  ${NSD_KillTimer} FinishInstall
 
   Delete "$PLUGINSDIR\download.exe"
   Delete "$PLUGINSDIR\${CONFIG_INI}"
 FunctionEnd
 
 Function createDummy
 FunctionEnd
 
@@ -380,23 +397,20 @@ Function createIntro
   ${SetStretchedTransparentImage} $2 $PLUGINSDIR\appname.bmp $0
 
   ${NSD_CreateBitmap} 0 0 100% 100% ""
   Pop $2
   ${NSD_SetStretchedImage} $2 $PLUGINSDIR\bgintro.bmp $1
 
   GetDlgItem $0 $HWNDPARENT 1 ; Install button
   SendMessage $0 ${WM_SETTEXT} 0 "STR:$(INSTALL_BUTTON)"
+  ${NSD_SetFocus} $0
 
   GetDlgItem $0 $HWNDPARENT 2 ; Cancel button
   SendMessage $0 ${WM_SETTEXT} 0 "STR:$(CANCEL_BUTTON)"
-  ; Focus the Cancel button so tab stops will start from there.
-  ${NSD_SetFocus} $0
-  ; Kill the Cancel button's focus so pressing enter won't cancel the install.
-  SendMessage $0 ${WM_KILLFOCUS} 0 0
 
   GetDlgItem $0 $HWNDPARENT 3 ; Back and Options button
   SendMessage $0 ${WM_SETTEXT} 0 "STR:$(OPTIONS_BUTTON)"
 
   LockWindow off
   nsDialogs::Show
 
   ${NSD_FreeImage} $0
@@ -596,25 +610,20 @@ Function createOptions
       SendMessage $CheckboxInstallMaintSvc ${WM_SETFONT} $FontNormal 0
       ${NSD_Check} $CheckboxInstallMaintSvc
     ${EndIf}
   ${EndIf}
 !endif
 
   GetDlgItem $0 $HWNDPARENT 1 ; Install button
   SendMessage $0 ${WM_SETTEXT} 0 "STR:$(INSTALL_BUTTON)"
+  ${NSD_SetFocus} $0
 
   GetDlgItem $0 $HWNDPARENT 2 ; Cancel button
   SendMessage $0 ${WM_SETTEXT} 0 "STR:$(CANCEL_BUTTON)"
-  ; If the first control in the dialog is focused it won't display with a focus
-  ; ring on dialog creation when the Options button is clicked so just focus the
-  ; Cancel button so tab stops will start from there.
-  ${NSD_SetFocus} $0
-  ; Kill the Cancel button's focus so pressing enter won't cancel the install.
-  SendMessage $0 ${WM_KILLFOCUS} 0 0
 
   GetDlgItem $0 $HWNDPARENT 3 ; Back and Options button
   SendMessage $0 ${WM_SETTEXT} 0 "STR:$(BACK_BUTTON)"
 
   ${If} "$WasOptionsButtonClicked" != "true"
     ${If} "$CanWriteToInstallDir" == "false"
       MessageBox MB_OK|MB_ICONEXCLAMATION "$(WARN_WRITE_ACCESS)"
     ${ElseIf} "$HasRequiredSpaceAvailable" == "false"
@@ -756,18 +765,17 @@ Function createInstall
 
   ${NSD_CreateProgressBar} 103u 166u 157u 9u ""
   Pop $ProgressbarDownload
   ${NSD_AddStyle} $ProgressbarDownload ${PBS_MARQUEE}
   SendMessage $ProgressbarDownload ${PBM_SETMARQUEE} 1 10 ; start=1|stop=0 interval(ms)=+N
 
   ${NSD_CreateProgressBar} 260u 166u 84u 9u ""
   Pop $ProgressbarInstall
-  ${NSD_AddStyle} $ProgressbarInstall ${PBS_MARQUEE}
-  SendMessage $ProgressbarInstall ${PBM_SETMARQUEE} 0 10 ; start=1|stop=0 interval(ms)=+N
+  SendMessage $ProgressbarInstall ${PBM_SETRANGE32} 0 ${InstallProgresSteps}
 
   ${NSD_CreateBitmap} ${APPNAME_BMP_EDGE_DU} ${APPNAME_BMP_TOP_DU} \
                       ${APPNAME_BMP_WIDTH_DU} ${APPNAME_BMP_HEIGHT_DU} ""
   Pop $2
   ${SetStretchedTransparentImage} $2 $PLUGINSDIR\appname.bmp $0
 
   ${NSD_CreateBitmap} 0 0 100% 100% ""
   Pop $3
@@ -799,17 +807,17 @@ Function createInstall
 
   GetDlgItem $0 $HWNDPARENT 11
   SendMessage $0 ${WM_SETTEXT} 0 "STR:$(ONE_MOMENT)"
   SendMessage $0 ${WM_SETFONT} $FontNormal 0
   SetCtlColors $0 ${FOOTER_CONTROL_TEXT_COLOR_FADED} ${FOOTER_BKGRD_COLOR}
   ShowWindow $0 ${SW_SHOW}
 
   StrCpy $DownloadReset "false"
-  ${NSD_CreateTimer} StartDownload 500
+  ${NSD_CreateTimer} StartDownload ${DownloadIntervalMS}
 
   LockWindow off
   nsDialogs::Show
 
   ${NSD_FreeImage} $0
   ${NSD_FreeImage} $1
   ${NSD_FreeImage} $HwndBitmapBlurb1
   ${NSD_FreeImage} $HwndBitmapBlurb2
@@ -819,17 +827,17 @@ FunctionEnd
 Function leaveInstall
 # Need a ping?
 FunctionEnd
 
 Function StartDownload
   ${NSD_KillTimer} StartDownload
   InetBgDL::Get "${URLStubDownload}" "$PLUGINSDIR\download.exe" /END
   StrCpy $4 ""
-  ${NSD_CreateTimer} OnDownload 500
+  ${NSD_CreateTimer} OnDownload ${DownloadIntervalMS}
   ${If} ${FileExists} "$INSTDIR\${TO_BE_DELETED}"
     RmDir /r "$INSTDIR\${TO_BE_DELETED}"
   ${EndIf}
 FunctionEnd
 
 Function OnDownload
   InetBgDL::GetStats
   # $0 = HTTP status code, 0=Completed
@@ -841,52 +849,55 @@ Function OnDownload
   # When status is $0 =< 299 it is handled by InetBgDL
   ${If} $0 > 299
     ${NSD_KillTimer} OnDownload
     ${If} "$DownloadReset" != "true"
       ${NSD_AddStyle} $ProgressbarDownload ${PBS_MARQUEE}
       SendMessage $ProgressbarDownload ${PBM_SETMARQUEE} 1 10 ; start=1|stop=0 interval(ms)=+N
     ${EndIf}
     InetBgDL::Get /RESET /END
-    ${NSD_CreateTimer} StartDownload 500
+    ${NSD_CreateTimer} StartDownload ${DownloadIntervalMS}
     StrCpy $DownloadReset "true"
     StrCpy $DownloadSize ""
     Return
   ${EndIf}
 
   ${If} "$DownloadReset" == "true"
     StrCpy $DownloadReset "false"
   ${EndIf}
 
   ${If} $DownloadSize == ""
   ${AndIf} $4 != ""
     StrCpy $DownloadSize $4
     System::Int64Op $4 / 2
     Pop $HalfOfDownload
-    SendMessage $ProgressbarDownload ${PBM_SETMARQUEE} 0 50 ; start=1|stop=0 interval(ms)=+N
+    SendMessage $ProgressbarDownload ${PBM_SETMARQUEE} 0 0 ; start=1|stop=0 interval(ms)=+N
     ${RemoveStyle} $ProgressbarDownload ${PBS_MARQUEE}
     SendMessage $ProgressbarDownload ${PBM_SETRANGE32} 0 $DownloadSize
   ${EndIf}
 
   ; Don't update the status until after the download starts
   ${If} $2 != 0
   ${AndIf} $4 == ""
     Return
   ${EndIf}
 
   ${If} $IsDownloadFinished != "true"
     ${If} $2 == 0
       ${NSD_KillTimer} OnDownload
       StrCpy $IsDownloadFinished "true"
+      ; The first step of the install progress bar is determined by the
+      ; InstallProgressFirstStep define and provides the user with immediate
+      ; feedback.
+      StrCpy $InstallCounterStep ${InstallProgressFirstStep}
       LockWindow on
       ; Update the progress bars first in the UI change so they take affect
       ; before other UI changes.
       SendMessage $ProgressbarDownload ${PBM_SETPOS} $DownloadSize 0
-      ${NSD_AddStyle} $ProgressbarDownload ${PBS_MARQUEE}
-      SendMessage $ProgressbarInstall ${PBM_SETMARQUEE} 1 10 ; start=1|stop=0 interval(ms)=+N
+      SendMessage $ProgressbarInstall ${PBM_SETPOS} $InstallCounterStep 0
       ShowWindow $LabelDownloadingInProgress ${SW_HIDE}
       ShowWindow $LabelInstallingToBeDone ${SW_HIDE}
       ShowWindow $LabelInstallingInProgress ${SW_SHOW}
       ShowWindow $LabelDownloadingDown ${SW_SHOW}
       ShowWindow $LabelBlurb2 ${SW_HIDE}
       ShowWindow $BitmapBlurb2 ${SW_HIDE}
       ShowWindow $LabelBlurb3 ${SW_SHOW}
       ShowWindow $BitmapBlurb3 ${SW_SHOW}
@@ -959,20 +970,27 @@ Function OnDownload
       Delete "$0"
       ; Workaround to prevent pinning to the taskbar.
       ${If} $CheckboxShortcutOnBar == 0
         WriteIniStr "$0" "TASKBAR" "Migrated" "true"
       ${EndIf}
 
       ${OnStubInstallUninstall}
 
-      Exec "$\"$PLUGINSDIR\download.exe$\" /INI=$PLUGINSDIR\${CONFIG_INI}"
-      ; Close the handle that prevents modification of the full installer
-      System::Call 'kernel32::CloseHandle(i $HandleDownload)'
-      ${NSD_CreateTimer} StartInstall 1000
+      ; 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 if it exists since it being present will
+      ; require an OS restart for the full installer.
+      Delete "$INSTDIR\${FileMainEXE}.moz-upgrade"
+
+      ; Flicker happens less often if a timer is used between updates of the
+      ; progress bar.
+      ${NSD_CreateTimer} StartInstall ${InstallIntervalMS}
     ${Else}
       ${If} $HalfOfDownload != "true"
       ${AndIf} $3 > $HalfOfDownload
         StrCpy $HalfOfDownload "true"
         LockWindow on
         ShowWindow $LabelBlurb1 ${SW_HIDE}
         ShowWindow $BitmapBlurb1 ${SW_HIDE}
         ShowWindow $LabelBlurb2 ${SW_SHOW}
@@ -980,66 +998,119 @@ Function OnDownload
         LockWindow off
       ${EndIf}
       SendMessage $ProgressbarDownload ${PBM_SETPOS} $3 0
     ${EndIf}
   ${EndIf}
 FunctionEnd
 
 Function StartInstall
-  ${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
-  ${AndIf} ${FileExists} "$INSTDIR\uninstall\uninstall.log"
-    Delete "$INSTDIR\uninstall\uninstall.tmp"
-    CopyFiles /SILENT "$INSTDIR\uninstall\uninstall.log" "$INSTDIR\uninstall\uninstall.tmp"
+  ${NSD_KillTimer} StartInstall
+
+  IntOp $InstallCounterStep $InstallCounterStep + 1
+  LockWindow on
+  SendMessage $ProgressbarInstall ${PBM_SETPOS} $InstallCounterStep 0
+  LockWindow off
+
+  Exec "$\"$PLUGINSDIR\download.exe$\" /INI=$PLUGINSDIR\${CONFIG_INI}"
+  ${NSD_CreateTimer} CheckInstall ${InstallIntervalMS}
+FunctionEnd
+
+Function CheckInstall
+  IntOp $InstallCounterStep $InstallCounterStep + 1
+  ${If} $InstallCounterStep >= ${InstallProgresSteps} 
+    ${NSD_KillTimer} CheckInstall
+    ; Close the handle that prevents modification of the full installer
+    System::Call 'kernel32::CloseHandle(i $HandleDownload)'
+    MessageBox MB_OKCANCEL|MB_ICONSTOP "$(ERROR_DOWNLOAD)" IDCANCEL +2 IDOK 0
+    ExecShell "open" "${URLManualDownload}"
+    ; The following will exit the installer
+    SetAutoClose true
+    StrCpy $R9 2
+    Call RelativeGotoPage
+    Return
+  ${EndIf}
+
+  SendMessage $ProgressbarInstall ${PBM_SETPOS} $InstallCounterStep 0
+
+  ${If} ${FileExists} "$INSTDIR\install.log"
+    Delete "$INSTDIR\install.tmp"
+    CopyFiles /SILENT "$INSTDIR\install.log" "$INSTDIR\install.tmp"
+
+    ; When the full installer completes the installation the install.log will no
+    ; longer be in use.
     ClearErrors
-    Delete "$INSTDIR\uninstall\uninstall.log"
+    Delete "$INSTDIR\install.log"
     ${Unless} ${Errors}
-      CopyFiles /SILENT "$INSTDIR\uninstall\uninstall.tmp" "$INSTDIR\uninstall\uninstall.log"
-      ${NSD_KillTimer} StartInstall
-      Delete "$INSTDIR\uninstall\uninstall.tmp"
+      ${NSD_KillTimer} CheckInstall
+      ; Close the handle that prevents modification of the full installer
+      System::Call 'kernel32::CloseHandle(i $HandleDownload)'
+      Rename "$INSTDIR\install.tmp" "$INSTDIR\install.log"
       Delete "$PLUGINSDIR\download.exe"
       Delete "$PLUGINSDIR\${CONFIG_INI}"
-
-      ${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
-          GetFunctionAddress $0 ExecSetAsDefaultAppUser
-          UAC::ExecCodeSegment $0
-        ${EndIf}
-      ${EndIf}
-
-      ${If} $CheckboxShortcutOnBar == 1
-        ${If} ${AtMostWinVista}
-          ClearErrors
-          ${GetParameters} $0
-          ClearErrors
-          ${GetOptions} "$0" "/UAC:" $0
-          ${If} ${Errors}
-            Call AddQuickLaunchShortcut
-          ${Else}
-            GetFunctionAddress $0 AddQuickLaunchShortcut
-            UAC::ExecCodeSegment $0
-          ${EndIf}
-        ${EndIf}
-      ${EndIf}
-
-      Call LaunchApp
-
-      ; The following will exit the installer
-      SetAutoClose true
-      StrCpy $R9 2
-      Call RelativeGotoPage
+      ${NSD_CreateTimer} FinishInstall ${InstallIntervalMS}
     ${EndUnless}
   ${EndIf}
 FunctionEnd
 
+Function FinishInstall
+  ; The full installer has complete but we still need to finish the progress
+  ; bar so increase the size of the step
+  IntOp $InstallCounterStep $InstallCounterStep + 10
+  ${If} ${InstallProgresSteps} < $InstallCounterStep
+    StrCpy $InstallCounterStep "${InstallProgresSteps}"
+  ${EndIf}
+
+  SendMessage $ProgressbarInstall ${PBM_SETPOS} $InstallCounterStep 0
+  ${If} ${InstallProgresSteps} != $InstallCounterStep
+    Return
+  ${EndIf}
+
+  ${NSD_KillTimer} FinishInstall
+
+  ${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
+      GetFunctionAddress $0 ExecSetAsDefaultAppUser
+      UAC::ExecCodeSegment $0
+    ${EndIf}
+  ${EndIf}
+
+  ${If} $CheckboxShortcutOnBar == 1
+    ${If} ${AtMostWinVista}
+      ClearErrors
+      ${GetParameters} $0
+      ClearErrors
+      ${GetOptions} "$0" "/UAC:" $0
+      ${If} ${Errors}
+        Call AddQuickLaunchShortcut
+      ${Else}
+        GetFunctionAddress $0 AddQuickLaunchShortcut
+        UAC::ExecCodeSegment $0
+      ${EndIf}
+    ${EndIf}
+  ${EndIf}
+
+  ${If} ${FileExists} "$INSTDIR\${FileMainEXE}.moz-upgrade"
+    Delete "$INSTDIR\${FileMainEXE}"
+    Rename "$INSTDIR\${FileMainEXE}.moz-upgrade" "$INSTDIR\${FileMainEXE}"
+  ${EndIf}
+
+  Call LaunchApp
+
+  ; The following will exit the installer
+  SetAutoClose true
+  StrCpy $R9 2
+  Call RelativeGotoPage
+FunctionEnd
+
 Function OnBack
   StrCpy $WasOptionsButtonClicked "true"
   StrCpy $R9 1 ; Goto the next page
   Call RelativeGotoPage
   ; The call to Abort prevents NSIS from trying to move to the previous or the
   ; next page.
   Abort
 FunctionEnd