Bug 1512039 - Allow the stub installer to detect and download the AArch64 Windows build. r=agashlin
authorMatt Howell <mhowell@mozilla.com>
Thu, 10 Jan 2019 23:09:01 +0000
changeset 510463 47b94d26f8a57c50298b284342f270151d273ed5
parent 510462 36802e2a349090305f53f7ef345bfe6a3f324243
child 510464 585a078ac5b3ffa4d19fbe5eddecfbb4fefa3ea7
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersagashlin
bugs1512039
milestone66.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 1512039 - Allow the stub installer to detect and download the AArch64 Windows build. r=agashlin This patch also removes the last vestiges of the old architecture dropdown structure, and removes a use of GetBinaryTypeW because it doesn't seem to return a useful result for any ARM ISA. Differential Revision: https://phabricator.services.mozilla.com/D14811
browser/branding/aurora/branding.nsi
browser/branding/nightly/branding.nsi
browser/branding/official/branding.nsi
browser/branding/unofficial/branding.nsi
browser/installer/windows/nsis/stub.nsi
browser/locales/en-US/installer/nsisstrings.properties
--- a/browser/branding/aurora/branding.nsi
+++ b/browser/branding/aurora/branding.nsi
@@ -10,18 +10,19 @@
 # instead of BrandFullName and typically should not be modified.
 !define BrandFullNameInternal "Firefox Developer Edition"
 !define BrandShortName        "Firefox Developer Edition"
 !define BrandFullName         "Firefox Developer Edition"
 !define CompanyName           "mozilla.org"
 !define URLInfoAbout          "https://www.mozilla.org"
 !define HelpLink              "https://support.mozilla.org"
 
-!define URLStubDownload32 "https://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-devedition-latest"
-!define URLStubDownload64 "https://download.mozilla.org/?os=win64&lang=${AB_CD}&product=firefox-devedition-latest"
+!define URLStubDownloadX86 "https://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-devedition-latest"
+!define URLStubDownloadAMD64 "https://download.mozilla.org/?os=win64&lang=${AB_CD}&product=firefox-devedition-latest"
+!define URLStubDownloadAArch64 "https://download.mozilla.org/?os=win64-aarch64&lang=${AB_CD}&product=firefox-devedition-latest"
 !define URLManualDownload "https://www.mozilla.org/${AB_CD}/firefox/installer-help/?channel=aurora&installer_lang=${AB_CD}"
 !define URLSystemRequirements "https://www.mozilla.org/firefox/system-requirements/"
 !define Channel "aurora"
 
 # The installer's certificate name and issuer expected by the stub installer
 !define CertNameDownload   "Mozilla Corporation"
 !define CertIssuerDownload "DigiCert SHA2 Assured ID Code Signing CA"
 
--- a/browser/branding/nightly/branding.nsi
+++ b/browser/branding/nightly/branding.nsi
@@ -9,18 +9,19 @@
 # BrandFullNameInternal is used for some registry and file system values
 # instead of BrandFullName and typically should not be modified.
 !define BrandFullNameInternal "Nightly"
 !define BrandFullName         "Firefox Nightly"
 !define CompanyName           "mozilla.org"
 !define URLInfoAbout          "https://www.mozilla.org"
 !define HelpLink              "https://support.mozilla.org"
 
-!define URLStubDownload32 "https://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-nightly-latest"
-!define URLStubDownload64 "https://download.mozilla.org/?os=win64&lang=${AB_CD}&product=firefox-nightly-latest"
+!define URLStubDownloadX86 "https://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-nightly-latest"
+!define URLStubDownloadAMD64 "https://download.mozilla.org/?os=win64&lang=${AB_CD}&product=firefox-nightly-latest"
+!define URLStubDownloadAArch64 "https://download.mozilla.org/?os=win64-aarch64&lang=${AB_CD}&product=firefox-nightly-latest"
 !define URLManualDownload "https://www.mozilla.org/${AB_CD}/firefox/installer-help/?channel=nightly&installer_lang=${AB_CD}"
 !define URLSystemRequirements "https://www.mozilla.org/firefox/system-requirements/"
 !define Channel "nightly"
 
 # The installer's certificate name and issuer expected by the stub installer
 !define CertNameDownload   "Mozilla Corporation"
 !define CertIssuerDownload "DigiCert SHA2 Assured ID Code Signing CA"
 
--- a/browser/branding/official/branding.nsi
+++ b/browser/branding/official/branding.nsi
@@ -14,18 +14,19 @@
 !define URLInfoAbout          "https://www.mozilla.org"
 !define URLUpdateInfo         "https://www.mozilla.org/firefox/${AppVersion}/releasenotes"
 !define HelpLink              "https://support.mozilla.org"
 
 ; The OFFICIAL define is a workaround to support different urls for Release and
 ; Beta since they share the same branding when building with other branches that
 ; set the update channel to beta.
 !define OFFICIAL
-!define URLStubDownload32 "https://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-latest"
-!define URLStubDownload64 "https://download.mozilla.org/?os=win64&lang=${AB_CD}&product=firefox-latest"
+!define URLStubDownloadX86 "https://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-latest"
+!define URLStubDownloadAMD64 "https://download.mozilla.org/?os=win64&lang=${AB_CD}&product=firefox-latest"
+!define URLStubDownloadAArch64 "https://download.mozilla.org/?os=win64-aarch64&lang=${AB_CD}&product=firefox-latest"
 !define URLManualDownload "https://www.mozilla.org/${AB_CD}/firefox/installer-help/?channel=release&installer_lang=${AB_CD}"
 !define URLSystemRequirements "https://www.mozilla.org/firefox/system-requirements/"
 !define Channel "release"
 
 # The installer's certificate name and issuer expected by the stub installer
 !define CertNameDownload   "Mozilla Corporation"
 !define CertIssuerDownload "DigiCert SHA2 Assured ID Code Signing CA"
 
--- a/browser/branding/unofficial/branding.nsi
+++ b/browser/branding/unofficial/branding.nsi
@@ -9,18 +9,19 @@
 # BrandFullNameInternal is used for some registry and file system values
 # instead of BrandFullName and typically should not be modified.
 !define BrandFullNameInternal "Mozilla Developer Preview"
 !define BrandFullName         "Mozilla Developer Preview"
 !define CompanyName           "mozilla.org"
 !define URLInfoAbout          "https://www.mozilla.org"
 !define HelpLink              "https://support.mozilla.org"
 
-!define URLStubDownload32 "https://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-latest"
-!define URLStubDownload64 "https://download.mozilla.org/?os=win64&lang=${AB_CD}&product=firefox-latest"
+!define URLStubDownloadX86 "https://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-latest"
+!define URLStubDownloadAMD64 "https://download.mozilla.org/?os=win64&lang=${AB_CD}&product=firefox-latest"
+!define URLStubDownloadAArch64 "https://download.mozilla.org/?os=win64-aarch64&lang=${AB_CD}&product=firefox-latest"
 !define URLManualDownload "https://www.mozilla.org/${AB_CD}/firefox/installer-help/?channel=release&installer_lang=${AB_CD}"
 !define URLSystemRequirements "https://www.mozilla.org/firefox/system-requirements/"
 !define Channel "unofficial"
 
 # The installer's certificate name and issuer expected by the stub installer
 !define CertNameDownload   "Mozilla Corporation"
 !define CertIssuerDownload "DigiCert SHA2 Assured ID Code Signing CA"
 
--- a/browser/installer/windows/nsis/stub.nsi
+++ b/browser/installer/windows/nsis/stub.nsi
@@ -26,17 +26,16 @@ ManifestDPIAware true
 
 Var Dialog
 Var Progressbar
 Var ProgressbarMarqueeIntervalMS
 Var CheckboxSetAsDefault
 Var CheckboxShortcuts
 Var CheckboxSendPing
 Var CheckboxInstallMaintSvc
-Var DroplistArch
 Var LabelBlurb
 Var BgBitmapImage
 Var HwndBgBitmapControl
 Var CurrentBlurbIdx
 Var CheckboxCleanupProfile
 
 Var FontInstalling
 Var FontBlurb
@@ -82,22 +81,26 @@ Var ExistingProfile
 Var ExistingVersion
 Var ExistingBuildID
 Var DownloadedBytes
 Var DownloadRetryCount
 Var OpenedDownloadPage
 Var DownloadServerIP
 Var PostSigningData
 Var PreviousInstallDir
-Var PreviousInstallArch
 Var ProfileCleanupPromptType
 Var ProfileCleanupHeaderString
 Var ProfileCleanupButtonString
 Var AppLaunchWaitTickCount
 
+!define ARCH_X86 1
+!define ARCH_AMD64 2
+!define ARCH_AARCH64 3
+Var ArchToInstall
+
 ; Uncomment the following to prevent pinging the metrics server when testing
 ; the stub installer
 ;!define STUB_DEBUG
 
 !define StubURLVersion "v8"
 
 ; Successful install exit code
 !define ERR_SUCCESS 0
@@ -236,20 +239,22 @@ Var AppLaunchWaitTickCount
 ; Must be included after defines.nsi
 !include "locale-fonts.nsh"
 
 ; The OFFICIAL define is a workaround to support different urls for Release and
 ; Beta since they share the same branding when building with other branches that
 ; set the update channel to beta.
 !ifdef OFFICIAL
 !ifdef BETA_UPDATE_CHANNEL
-!undef URLStubDownload32
-!undef URLStubDownload64
-!define URLStubDownload32 "https://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-beta-latest"
-!define URLStubDownload64 "https://download.mozilla.org/?os=win64&lang=${AB_CD}&product=firefox-beta-latest"
+!undef URLStubDownloadX86
+!undef URLStubDownloadAMD64
+!undef URLStubDownloadAArch64
+!define URLStubDownloadX86 "https://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-beta-latest"
+!define URLStubDownloadAMD64 "https://download.mozilla.org/?os=win64&lang=${AB_CD}&product=firefox-beta-latest"
+!define URLStubDownloadAArch64 "https://download.mozilla.org/?os=win64-aarch64&lang=${AB_CD}&product=firefox-beta-latest"
 !undef URLManualDownload
 !define URLManualDownload "https://www.mozilla.org/${AB_CD}/firefox/installer-help/?channel=beta&installer_lang=${AB_CD}"
 !undef Channel
 !define Channel "beta"
 !endif
 !endif
 
 !undef INSTALL_BLURB_TEXT_COLOR
@@ -321,45 +326,47 @@ Function .onInit
 
   ; SSE2 CPU support
   ${If} "$R7" == "0"
     MessageBox MB_OKCANCEL|MB_ICONSTOP "$(WARN_MIN_SUPPORTED_CPU_MSG)" IDCANCEL +2
     ExecShell "open" "${URLSystemRequirements}"
     Quit
   ${EndIf}
 
-  Call ShouldInstall64Bit
-  ${If} $0 == 1
-    StrCpy $DroplistArch "$(VERSION_64BIT)"
+  Call GetArchToInstall
+  ${If} $ArchToInstall == ${ARCH_AARCH64}
+  ${OrIf} $ArchToInstall == ${ARCH_AMD64}
     StrCpy $INSTDIR "${DefaultInstDir64bit}"
   ${Else}
-    StrCpy $DroplistArch "$(VERSION_32BIT)"
     StrCpy $INSTDIR "${DefaultInstDir32bit}"
   ${EndIf}
 
   ; Require elevation if the user can elevate
   ${ElevateUAC}
 
   ; If we have any existing installation, use its location as the default
   ; path for this install, even if it's not the same architecture.
   SetRegView 32
   SetShellVarContext all ; Set SHCTX to HKLM
   ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9
 
   ${If} "$R9" == "false"
-  ${AndIf} ${RunningX64}
-    SetRegView 64
-    ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9
+    ${If} ${IsNativeAMD64}
+    ${OrIf} ${IsNativeARM64}
+      SetRegView 64
+      ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9
+    ${EndIf}
   ${EndIf}
 
   ${If} "$R9" == "false"
     SetShellVarContext current ; Set SHCTX to HKCU
     ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9
 
-    ${If} ${RunningX64}
+    ${If} ${IsNativeAMD64}
+    ${OrIf} ${IsNativeARM64}
       ; In HKCU there is no WOW64 redirection, which means we may have gotten
       ; the path to a 32-bit install even though we're 64-bit.
       ; In that case, just use the default path instead of offering an upgrade.
       ; But only do that override if the existing install is in Program Files,
       ; because that's the only place we can be sure is specific
       ; to either 32 or 64 bit applications.
       ; The WordFind syntax below searches for the first occurence of the
       ; "delimiter" (the Program Files path) in the install path and returns
@@ -368,35 +375,33 @@ Function .onInit
       ${WordFind} $R9 $PROGRAMFILES32 "+1{" $0
       ${If} $0 == ""
         StrCpy $R9 "false"
       ${EndIf}
     ${EndIf}
   ${EndIf}
 
   StrCpy $PreviousInstallDir ""
-  StrCpy $PreviousInstallArch ""
   ${If} "$R9" != "false"
     ; Don't override the default install path with an existing installation
     ; of a different architecture.
-    System::Call "*(i)p.r0"
-    StrCpy $1 "$R9\${FileMainEXE}"
-    System::Call "Kernel32::GetBinaryTypeW(w r1, p r0)i"
-    System::Call "*$0(i.r2)"
-    System::Free $0
+    StrCpy $0 $R9
+    Call GetExistingInstallArch
 
-    ${If} $2 == "6" ; 6 == SCS_64BIT_BINARY
-    ${AndIf} ${RunningX64}
+    ${If} $0 == ${ARCH_X86}
+    ${AndIf} $ArchToInstall == ${ARCH_X86}
       StrCpy $PreviousInstallDir "$R9"
-      StrCpy $PreviousInstallArch "64"
       StrCpy $INSTDIR "$PreviousInstallDir"
-    ${ElseIf} $2 == "0" ; 0 == SCS_32BIT_BINARY
-    ${AndIfNot} ${RunningX64}
+    ${ElseIf} $0 == ${ARCH_AMD64}
+    ${AndIf} $ArchToInstall == ${ARCH_AMD64}
       StrCpy $PreviousInstallDir "$R9"
-      StrCpy $PreviousInstallArch "32"
+      StrCpy $INSTDIR "$PreviousInstallDir"
+    ${ElseIf} $0 == ${ARCH_AARCH64}
+    ${AndIf} $ArchToInstall == ${ARCH_AARCH64}
+      StrCpy $PreviousInstallDir "$R9"
       StrCpy $INSTDIR "$PreviousInstallDir"
     ${EndIf}
   ${EndIf}
 
   ; Used to determine if the default installation directory was used.
   StrCpy $InitialInstallDir "$INSTDIR"
 
   ClearErrors
@@ -897,22 +902,26 @@ Function createInstall
   LockWindow off
   nsDialogs::Show
 
   ${NSD_FreeImage} $BgBitmapImage
 FunctionEnd
 
 Function StartDownload
   ${NSD_KillTimer} StartDownload
-  ${If} $DroplistArch == "$(VERSION_64BIT)"
-    InetBgDL::Get "${URLStubDownload64}${URLStubDownloadAppend}" \
+  ${If} $ArchToInstall == ${ARCH_AMD64}
+    InetBgDL::Get "${URLStubDownloadAMD64}${URLStubDownloadAppend}" \
+                  "$PLUGINSDIR\download.exe" \
+                  /CONNECTTIMEOUT 120 /RECEIVETIMEOUT 120 /END
+  ${ElseIf} $ArchToInstall == ${ARCH_AARCH64}
+    InetBgDL::Get "${URLStubDownloadAArch64}${URLStubDownloadAppend}" \
                   "$PLUGINSDIR\download.exe" \
                   /CONNECTTIMEOUT 120 /RECEIVETIMEOUT 120 /END
   ${Else}
-    InetBgDL::Get "${URLStubDownload32}${URLStubDownloadAppend}" \
+    InetBgDL::Get "${URLStubDownloadX86}${URLStubDownloadAppend}" \
                   "$PLUGINSDIR\download.exe" \
                   /CONNECTTIMEOUT 120 /RECEIVETIMEOUT 120 /END
   ${EndIf}
   StrCpy $4 ""
   ${NSD_CreateTimer} OnDownload ${DownloadIntervalMS}
   ${If} ${FileExists} "$INSTDIR\${TO_BE_DELETED}"
     RmDir /r "$INSTDIR\${TO_BE_DELETED}"
   ${EndIf}
@@ -1288,23 +1297,25 @@ Function SendPing
     ; Get the seconds elapsed from the end of the pre-installation check phase
     ; to the completion of the installation phase.
     ${GetSecondsElapsed} "$EndPreInstallPhaseTickCount" "$EndInstallPhaseTickCount" $3
 
     ; Get the seconds elapsed from the end of the installation phase to the
     ; completion of all phases.
     ${GetSecondsElapsed} "$EndInstallPhaseTickCount" "$EndFinishPhaseTickCount" $4
 
-    ${If} $DroplistArch == "$(VERSION_64BIT)"
+    ${If} $ArchToInstall == ${ARCH_AMD64}
+    ${OrIf} $ArchToInstall == ${ARCH_AARCH64}
       StrCpy $R0 "1"
     ${Else}
       StrCpy $R0 "0"
     ${EndIf}
 
-    ${If} ${RunningX64}
+    ${If} ${IsNativeAMD64}
+    ${OrIf} ${IsNativeARM64}
       StrCpy $R1 "1"
     ${Else}
       StrCpy $R1 "0"
     ${EndIf}
 
     ; Though these values are sometimes incorrect due to bug 444664 it happens
     ; so rarely it isn't worth working around it by reading the registry values.
     ${WinVerGetMajor} $5
@@ -1754,17 +1765,18 @@ Function OpenManualDownloadURL
   ExecShell "open" "${URLManualDownload}${URLManualDownloadAppend}"
 FunctionEnd
 
 Function ShouldPromptForProfileCleanup
   ; This will be our return value.
   StrCpy $ProfileCleanupPromptType 0
 
   ; Only consider installations of the same architecture we're installing.
-  ${If} $DroplistArch == "$(VERSION_64BIT)"
+  ${If} $ArchToInstall == ${ARCH_AMD64}
+  ${OrIf} $ArchToInstall == ${ARCH_AARCH64}
     SetRegView 64
   ${Else}
     SetRegView 32
   ${EndIf}
 
   ; Make sure $APPDATA is the user's AppData and not ProgramData.
   ; We'll set this back to all at the end of the function.
   SetShellVarContext current
@@ -1905,26 +1917,69 @@ Function GetLatestReleasedVersion
   ${EndSelect}
   nsJSON::Get "Output" $1 /end
   IfErrors end
   Pop $1
 
   end:
 FunctionEnd
 
-; Returns 1 in $0 if we should install the 64-bit build, or 0 if not.
-; The requirements for selecting the 64-bit build to install are:
+Function GetExistingInstallArch
+  StrCpy $0 "unknown"
+
+  ClearErrors
+  FileOpen $R1 "$0\install.log" r
+  ${If} ${Errors}
+    Return
+  ${EndIf}
+
+  ${Do}
+    ClearErrors
+    FileReadUTF16LE $R1 $R2
+    ${If} ${Errors}
+      ${Break}
+    ${EndIf}
+
+    ClearErrors
+    ${WordFind} "$R2" "Target CPU : " "E+1}" $R3
+    ${If} ${Errors}
+      ${Continue}
+    ${EndIf}
+
+    ${TrimNewLines} "$R3" $R3
+    ${If} $R3 == "x86"
+      StrCpy $0 ${ARCH_X86}
+    ${ElseIf} $R3 == "x64"
+      StrCpy $0 ${ARCH_AMD64}
+    ${ElseIf} $R3 == "AArch64"
+      StrCpy $0 ${ARCH_AARCH64}
+    ${EndIf}
+    ${Break}
+  ${Loop}
+
+  FileClose $R1
+FunctionEnd
+
+; Determine which architecture build we should download and install.
+; AArch64 is always selected if it's the native architecture of the machine.
+; Otherwise, we check a few things to determine if AMD64 is appropriate:
 ; 1) Running a 64-bit OS (we've already checked the OS version).
 ; 2) An amount of RAM strictly greater than RAM_NEEDED_FOR_64BIT
 ; 3) No third-party products installed that cause issues with the 64-bit build.
 ;    Currently this includes Lenovo OneKey Theater and Lenovo Energy Management.
-Function ShouldInstall64Bit
-  StrCpy $0 0
+; If any of those checks fail, the 32-bit x86 build is selected.
+Function GetArchToInstall
+  StrCpy $ArchToInstall ${ARCH_X86}
 
-  ${IfNot} ${RunningX64}
+  ${If} ${IsNativeARM64}
+    StrCpy $ArchToInstall ${ARCH_AARCH64}
+    Return
+  ${EndIf}
+
+  ${IfNot} ${IsNativeAMD64}
     Return
   ${EndIf}
 
   System::Call "*(i 64, i, l 0, l, l, l, l, l, l)p.r1"
   System::Call "Kernel32::GlobalMemoryStatusEx(p r1)"
   System::Call "*$1(i, i, l.r2, l, l, l, l, l, l)"
   System::Free $1
   ${If} $2 L<= ${RAM_NEEDED_FOR_64BIT}
@@ -1936,13 +1991,13 @@ Function ShouldInstall64Bit
   ${If} ${FileExists} "$PROGRAMFILES32\Lenovo\Onekey Theater\windowsapihookdll64.dll"
     Return
   ${EndIf}
 
   ${If} ${FileExists} "$PROGRAMFILES32\Lenovo\Energy Management\Energy Management.exe"
     Return
   ${EndIf}
 
-  StrCpy $0 1
+  StrCpy $ArchToInstall ${ARCH_AMD64}
 FunctionEnd
 
 Section
 SectionEnd
--- a/browser/locales/en-US/installer/nsisstrings.properties
+++ b/browser/locales/en-US/installer/nsisstrings.properties
@@ -42,11 +42,8 @@ WARN_DISK_SPACE_QUIT=You don't have suff
 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