Bug 986081 - Allow backing out of closing the stub installer. r?agashlin draft
authorMatt Howell <mhowell@mozilla.com>
Wed, 21 Mar 2018 10:39:38 -0700
changeset 774959 3d6a7739b9f023f46110815f819a797798c71921
parent 774958 1f0c819ec9e8076a63cbbd8087836de438e79300
push id104576
push usermhowell@mozilla.com
push dateThu, 29 Mar 2018 22:01:29 +0000
reviewersagashlin
bugs986081
milestone61.0a1
Bug 986081 - Allow backing out of closing the stub installer. r?agashlin Currently, clicking the close button or otherwise trying to exit the Windows stub installer always ends up canceling the installation. This patch prompts the user to either continue or cancel the installation. MozReview-Commit-ID: 4KMgCcyjTnv
browser/installer/windows/nsis/stub.nsi
browser/locales/en-US/installer/nsisstrings.properties
toolkit/mozapps/installer/windows/nsis/common.nsh
--- a/browser/installer/windows/nsis/stub.nsi
+++ b/browser/installer/windows/nsis/stub.nsi
@@ -544,24 +544,40 @@ Function .onUserAbort
   ${NSD_KillTimer} OnDownload
   ${NSD_KillTimer} CheckInstall
   ${NSD_KillTimer} FinishInstall
   ${NSD_KillTimer} DisplayDownloadError
   ${NSD_KillTimer} NextBlurb
   ${NSD_KillTimer} ClearBlurb
 
   ${If} "$IsDownloadFinished" != ""
-    Call DisplayDownloadError
+    ; Go ahead and cancel the download so it doesn't keep running while this
+    ; prompt is up. We'll resume it if the user decides to continue.
+    InetBgDL::Get /RESET /END
+
+    ${ShowTaskDialog} $(STUB_CANCEL_PROMPT_HEADING) \
+                      $(STUB_CANCEL_PROMPT_MESSAGE) \
+                      $(STUB_CANCEL_PROMPT_BUTTON_CONTINUE) \
+                      $(STUB_CANCEL_PROMPT_BUTTON_EXIT)
+    Pop $0
+    ${If} $0 == 1002
+      ; The cancel button was clicked
+      Call LaunchHelpPage
+      Call SendPing
+    ${Else}
+      ; Either the continue button was clicked or the dialog was dismissed
+      Call StartDownload
+    ${EndIf}
   ${Else}
     Call SendPing
   ${EndIf}
 
-  ; Aborting the abort will allow SendPing which is called by
-  ; DisplayDownloadError to hide the installer window and close the installer
-  ; after it sends the metrics ping.
+  ; Aborting the abort will allow SendPing to hide the installer window and
+  ; close the installer after it sends the metrics ping, or allow us to just go
+  ; back to installing if that's what the user selected.
   Abort
 FunctionEnd
 
 Function DrawBackgroundImage
   ${NSD_CreateBitmap} 0 0 100% 100% ""
   Pop $HwndBgBitmapControl
 
   ; If the scaling factor is 100%, use the 1x image; the 2x images scaled down
@@ -1680,32 +1696,33 @@ FunctionEnd
 Function DisplayDownloadError
   ${NSD_KillTimer} DisplayDownloadError
   ${NSD_KillTimer} NextBlurb
   ${NSD_KillTimer} ClearBlurb
   ; 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_CONT)" IDCANCEL +2 IDOK +1
-  StrCpy $OpenedDownloadPage "1" ; Already initialized to 0
+  Call LaunchHelpPage
+  Call SendPing
+FunctionEnd
 
-  ${If} "$OpenedDownloadPage" == "1"
-    ClearErrors
-    ${GetParameters} $0
-    ${GetOptions} "$0" "/UAC:" $1
-    ${If} ${Errors}
-      Call OpenManualDownloadURL
-    ${Else}
-      GetFunctionAddress $0 OpenManualDownloadURL
-      UAC::ExecCodeSegment $0
-    ${EndIf}
+Function LaunchHelpPage
+  StrCpy $OpenedDownloadPage "1" ; Already initialized to 0
+  ClearErrors
+  ${GetParameters} $0
+  ${GetOptions} "$0" "/UAC:" $1
+  ${If} ${Errors}
+    Call OpenManualDownloadURL
+  ${Else}
+    GetFunctionAddress $0 OpenManualDownloadURL
+    UAC::ExecCodeSegment $0
   ${EndIf}
-
-  Call SendPing
 FunctionEnd
 
 Function OpenManualDownloadURL
   ExecShell "open" "${URLManualDownload}${URLManualDownloadAppend}"
 FunctionEnd
 
 Function ShouldPromptForProfileCleanup
   Call GetLatestReleasedVersion
--- a/browser/locales/en-US/installer/nsisstrings.properties
+++ b/browser/locales/en-US/installer/nsisstrings.properties
@@ -38,10 +38,15 @@ WARN_MIN_SUPPORTED_OSVER_MSG=Sorry, $Bra
 WARN_MIN_SUPPORTED_CPU_MSG=Sorry, $BrandShortName can't be installed. This version of $BrandShortName requires a processor with ${MinSupportedCPU} support. Please click the OK button for additional information.
 WARN_MIN_SUPPORTED_OSVER_CPU_MSG=Sorry, $BrandShortName can't be installed. This version of $BrandShortName requires ${MinSupportedVer} or newer and a processor with ${MinSupportedCPU} support. Please click the OK button for additional information.
 WARN_WRITE_ACCESS_QUIT=You don't have access to write to the installation directory
 WARN_DISK_SPACE_QUIT=You don't have sufficient disk space to install.
 WARN_MANUALLY_CLOSE_APP_LAUNCH=$BrandShortName is already running.\n\nPlease close $BrandShortName prior to launching the version you have just installed.
 
 ERROR_DOWNLOAD_CONT=Hmm. For some reason, we could not install $BrandShortName.\nChoose OK to start over.
 
+STUB_CANCEL_PROMPT_HEADING=Do you want to install $BrandShortName?
+STUB_CANCEL_PROMPT_MESSAGE=If you cancel, $BrandShortName will not be installed.
+STUB_CANCEL_PROMPT_BUTTON_CONTINUE=Install $BrandShortName
+STUB_CANCEL_PROMPT_BUTTON_EXIT=Cancel
+
 VERSION_32BIT=32-bit $BrandShortName
 VERSION_64BIT=64-bit $BrandShortName
--- a/toolkit/mozapps/installer/windows/nsis/common.nsh
+++ b/toolkit/mozapps/installer/windows/nsis/common.nsh
@@ -7524,16 +7524,106 @@
   Pop $2
   Pop $1
   Exch $0
   Pop ${HANDLE}
 !macroend
 !define SetStretchedImageOLE "!insertmacro __SetStretchedImageOLE"
 
 /**
+ * Display a task dialog box with custom strings and button labels.
+ *
+ * The task dialog is highly customizable. The specific style being used here
+ * is similar to a MessageBox except that the button text is customizable.
+ * MessageBox-style buttons are used instead of command link buttons; this can
+ * be made configurable if command buttons are needed.
+ *
+ * See https://msdn.microsoft.com/en-us/library/windows/desktop/bb760544.aspx
+ * for the TaskDialogIndirect function's documentation, and links to definitions
+ * of the TASKDIALOGCONFIG and TASKDIALOG_BUTTON structures it uses.
+ *
+ * @param INSTRUCTION  Dialog header string; use empty string if unneeded
+ * @param CONTENT      Secondary message string; use empty string if unneeded
+ * @param BUTTON1      Text for the first button, the one selected by default
+ * @param BUTTON2      Text for the second button
+ *
+ * @return One of the following values will be left on the stack:
+ *         1001 if the first button was clicked
+ *         1002 if the second button was clicked
+ *         2 (IDCANCEL) if the dialog was closed
+ *         0 on error
+ */
+!macro _ShowTaskDialog INSTRUCTION CONTENT BUTTON1 BUTTON2
+  !ifndef SIZEOF_TASKDIALOGCONFIG_32BIT
+    !define SIZEOF_TASKDIALOGCONFIG_32BIT 96
+  !endif
+  !ifndef TDF_ALLOW_DIALOG_CANCELLATION
+    !define TDF_ALLOW_DIALOG_CANCELLATION 0x0008
+  !endif
+  !ifndef TDF_RTL_LAYOUT
+    !define TDF_RTL_LAYOUT 0x02000
+  !endif
+  !ifndef TD_WARNING_ICON
+    !define TD_WARNING_ICON 0x0FFFF
+  !endif
+
+  Push $0 ; return value
+  Push $1 ; TASKDIALOGCONFIG struct
+  Push $2 ; TASKDIALOG_BUTTON array
+  Push $3 ; dwFlags member of the TASKDIALOGCONFIG
+
+  StrCpy $3 ${TDF_ALLOW_DIALOG_CANCELLATION}
+  !ifdef ${AB_CD}_rtl
+    IntOp $3 $3 | ${TDF_RTL_LAYOUT}
+  !endif
+
+  ; Build an array of two TASKDIALOG_BUTTON structs
+  System::Call "*(i 1001, \
+                  w '${BUTTON1}', \
+                  i 1002, \
+                  w '${BUTTON2}' \
+                  ) p.r2"
+  ; Build a TASKDIALOGCONFIG struct
+  System::Call "*(i ${SIZEOF_TASKDIALOGCONFIG_32BIT}, \
+                  p $HWNDPARENT, \
+                  p 0, \
+                  i $3, \
+                  i 0, \
+                  w '$(INSTALLER_WIN_CAPTION)', \
+                  p ${TD_WARNING_ICON}, \
+                  w '${INSTRUCTION}', \
+                  w '${CONTENT}', \
+                  i 2, \
+                  p r2, \
+                  i 1001, \
+                  i 0, \
+                  p 0, \
+                  i 0, \
+                  p 0, \
+                  p 0, \
+                  p 0, \
+                  p 0, \
+                  p 0, \
+                  p 0, \
+                  p 0, \
+                  p 0, \
+                  i 0 \
+                  ) p.r1"
+  System::Call "comctl32::TaskDialogIndirect(p r1, *i 0 r0, p 0, p 0)"
+  System::Free $1
+  System::Free $2
+
+  Pop $3
+  Pop $2
+  Pop $1
+  Exch $0
+!macroend
+!define ShowTaskDialog "!insertmacro _ShowTaskDialog"
+
+/**
  * Removes a single style from a control.
  *
  * _HANDLE the handle of the control
  * _STYLE  the style to remove
  */
 !macro _RemoveStyle _HANDLE _STYLE
   Push $0