diff --git a/config/autoconf.mk.in b/config/autoconf.mk.in index 0cf396df13..f7f731d2e3 100644 --- a/config/autoconf.mk.in +++ b/config/autoconf.mk.in @@ -22,6 +22,8 @@ MOZ_APP_DISPLAYNAME = @MOZ_APP_DISPLAYNAME@ MOZ_APP_VERSION = @MOZ_APP_VERSION@ MOZ_APP_MAXVERSION = @MOZ_APP_MAXVERSION@ MOZ_MACBUNDLE_NAME= @MOZ_MACBUNDLE_NAME@ +MAR_CHANNEL_ID = @MAR_CHANNEL_ID@ +ACCEPTED_MAR_CHANNEL_IDS = @ACCEPTED_MAR_CHANNEL_IDS@ MOZ_PKG_SPECIAL = @MOZ_PKG_SPECIAL@ @@ -87,6 +89,8 @@ MOZ_UNIVERSALCHARDET = @MOZ_UNIVERSALCHARDET@ ACCESSIBILITY = @ACCESSIBILITY@ MOZ_LDAP_XPCOM = @MOZ_LDAP_XPCOM@ MOZ_BRANDING_DIRECTORY = @MOZ_BRANDING_DIRECTORY@ +MOZ_MAINTENANCE_SERVICE = @MOZ_MAINTENANCE_SERVICE@ +MOZ_VERIFY_MAR_SIGNATURE = @MOZ_VERIFY_MAR_SIGNATURE@ MOZ_UPDATER = @MOZ_UPDATER@ MOZ_UPDATE_CHANNEL = @MOZ_UPDATE_CHANNEL@ MOZ_UPDATE_PACKAGING = @MOZ_UPDATE_PACKAGING@ diff --git a/configure.in b/configure.in index c7daca3502..bbf92796ca 100644 --- a/configure.in +++ b/configure.in @@ -5335,6 +5335,40 @@ AC_CHECK_PROGS(WGET, wget, "") AC_MSG_RESULT([$WGET]) AC_SUBST(WGET) +dnl ======================================================== +dnl Maintenance Service +dnl ======================================================== + +MOZ_ARG_ENABLE_BOOL(maintenance-service, +[ --enable-maintenance-service Enable building of maintenanceservice], + MOZ_MAINTENANCE_SERVICE=1, + MOZ_MAINTENANCE_SERVICE= ) + +if test -n "$MOZ_MAINTENANCE_SERVICE"; then + if test "$OS_ARCH" = "WINNT"; then + AC_DEFINE(MOZ_MAINTENANCE_SERVICE) + else + AC_MSG_ERROR([Can only build with --enable-maintenance-service with a Windows target]) + fi +fi + +dnl ======================================================== +dnl Verify MAR signatures +dnl ======================================================== + +MOZ_ARG_ENABLE_BOOL(verify-mar, +[ --enable-verify-mar Enable verifying MAR signatures], + MOZ_VERIFY_MAR_SIGNATURE=1, + MOZ_VERIFY_MAR_SIGNATURE= ) + +if test -n "$MOZ_VERIFY_MAR_SIGNATURE"; then + if test "$OS_ARCH" = "WINNT"; then + AC_DEFINE(MOZ_VERIFY_MAR_SIGNATURE) + else + AC_MSG_ERROR([Can only build with --enable-verify-mar with a Windows target]) + fi +fi + dnl ======================================================== dnl Updater dnl ======================================================== @@ -6739,6 +6773,8 @@ AC_SUBST(ACCESSIBILITY) AC_SUBST(MOZ_SPELLCHECK) AC_SUBST(MOZ_USER_DIR) AC_SUBST(MOZ_CRASHREPORTER) +AC_SUBST(MOZ_MAINTENANCE_SERVICE) +AC_SUBST(MOZ_VERIFY_MAR_SIGNATURE) AC_SUBST(MOZ_ANGLE) AC_SUBST(MOZ_DIRECTX_SDK_PATH) AC_SUBST(MOZ_DIRECTX_SDK_CPU_SUFFIX) @@ -6808,6 +6844,8 @@ AC_SUBST(MOZ_APP_NAME) AC_SUBST(MOZ_APP_DISPLAYNAME) AC_SUBST(MOZ_APP_VERSION) AC_SUBST(MOZ_APP_MAXVERSION) +AC_SUBST(MAR_CHANNEL_ID) +AC_SUBST(ACCEPTED_MAR_CHANNEL_IDS) AC_SUBST(FIREFOX_VERSION) AC_SUBST(THUNDERBIRD_VERSION) AC_SUBST(SUNBIRD_VERSION) diff --git a/mail/Makefile.in b/mail/Makefile.in index bf3f0b5b34..6909428b0a 100644 --- a/mail/Makefile.in +++ b/mail/Makefile.in @@ -34,4 +34,7 @@ ifeq ($(OS_ARCH),WINNT) # uninstaller is included with the application for mar file generation. libs:: $(MAKE) -C installer/windows uninstaller +ifdef MOZ_MAINTENANCE_SERVICE + $(MAKE) -C installer/windows maintenanceservice_installer endif +endif \ No newline at end of file diff --git a/mail/app/profile/all-thunderbird.js b/mail/app/profile/all-thunderbird.js index 9cf4ae00dd..1307911669 100644 --- a/mail/app/profile/all-thunderbird.js +++ b/mail/app/profile/all-thunderbird.js @@ -84,6 +84,11 @@ pref("app.update.idletime", 60); // which tells users what's new in this new update. pref("app.update.showInstalledUI", false); +// Whether or not to attempt using the service for updates. +#ifdef MOZ_MAINTENANCE_SERVICE +pref("app.update.service.enabled", true); +#endif + // Release notes URL pref("app.releaseNotesURL", "http://live.mozillamessaging.com/%APP%/releasenotes?locale=%LOCALE%&version=%VERSION%&os=%OS%&buildid=%APPBUILDID%"); diff --git a/mail/base/content/aboutDialog.js b/mail/base/content/aboutDialog.js index e4be4571e4..62006a2d86 100644 --- a/mail/base/content/aboutDialog.js +++ b/mail/base/content/aboutDialog.js @@ -174,9 +174,13 @@ appUpdater.prototype = // true when there is an update already staged / ready to be applied. get isPending() { - if (this.update) - return this.update.state == "pending"; - return this.um.activeUpdate && this.um.activeUpdate.state == "pending"; + if (this.update) { + return this.update.state == "pending" || + this.update.state == "pending-service"; + } + return this.um.activeUpdate && + (this.um.activeUpdate.state == "pending" || + this.um.activeUpdate.state == "pending-service"); }, // true when there is an update download in progress. diff --git a/mail/components/preferences/advanced.js b/mail/components/preferences/advanced.js index 1eb0008bbc..362e5d71a3 100644 --- a/mail/components/preferences/advanced.js +++ b/mail/components/preferences/advanced.js @@ -231,6 +231,26 @@ var gAdvancedPane = { var disable = enabledPref.locked || !enabledPref.value || autoPref.locked || !autoPref.value || modePref.locked; warnIncompatible.disabled = disable; + +#ifdef MOZ_MAINTENANCE_SERVICE + // Check to see if the maintenance service is installed. + // If it is don't show the preference at all. + var installed; + try { + Components.utils.reportError("0"); + var wrk = Components.classes["@mozilla.org/windows-registry-key;1"] + .createInstance(Components.interfaces.nsIWindowsRegKey); + wrk.open(wrk.ROOT_KEY_LOCAL_MACHINE, + "SOFTWARE\\Mozilla\\MaintenanceService", + wrk.ACCESS_READ | wrk.WOW64_64); + installed = wrk.readIntValue("Installed"); + wrk.close(); + } catch(e) { + } + if (installed != 1) { + document.getElementById("useService").hidden = true; + } +#endif }, /** diff --git a/mail/components/preferences/advanced.xul b/mail/components/preferences/advanced.xul index 17dfd268fb..e2de08d8fb 100644 --- a/mail/components/preferences/advanced.xul +++ b/mail/components/preferences/advanced.xul @@ -96,6 +96,12 @@ + +#ifdef MOZ_MAINTENANCE_SERVICE + +#endif #endif @@ -358,6 +364,13 @@ preference="app.update.disable_button.showUpdateHistory" oncommand="gAdvancedPane.showUpdates();"/> + +#ifdef MOZ_MAINTENANCE_SERVICE + +#endif #endif diff --git a/mail/confvars.sh b/mail/confvars.sh index 1b7972d245..0d5951d82d 100755 --- a/mail/confvars.sh +++ b/mail/confvars.sh @@ -13,6 +13,13 @@ if [ "$COMM_BUILD" ]; then MOZ_LDAP_XPCOM=1 fi MOZ_COMPOSER=1 +if test "$OS_ARCH" = "WINNT"; then + if ! test "$HAVE_64BIT_OS"; then + MOZ_VERIFY_MAR_SIGNATURE=1 + MOZ_MAINTENANCE_SERVICE=1 + fi +fi + MOZ_SAFE_BROWSING=1 MOZ_MORK=1 if test -z "$MOZ_INCOMPLETE_EXTERNAL_LINKAGE"; then @@ -27,3 +34,9 @@ THUNDERBIRD_VERSION=$MOZ_APP_VERSION MOZ_BRANDING_DIRECTORY=mail/branding/nightly MOZ_OFFICIAL_BRANDING_DIRECTORY=other-licenses/branding/thunderbird +# This should usually be the same as the value MAR_CHANNEL_ID. +# If more than one ID is needed, then you should use a comma separated list +# of values. +ACCEPTED_MAR_CHANNEL_IDS=thunderbird-comm-central +# The MAR_CHANNEL_ID must not contain the following 3 characters: ",\t " +MAR_CHANNEL_ID=thunderbird-comm-central diff --git a/mail/installer/package-manifest.in b/mail/installer/package-manifest.in index 6d49951f7d..43a7fcd5ab 100644 --- a/mail/installer/package-manifest.in +++ b/mail/installer/package-manifest.in @@ -114,6 +114,7 @@ @BINPATH@/@MOZ_APP_NAME@ #endif @BINPATH@/application.ini +@BINPATH@/update-settings.ini @BINPATH@/blocklist.xml @BINPATH@/platform.ini #ifdef XP_OS2 @@ -715,6 +716,13 @@ @BINPATH@/updater@BIN_SUFFIX@ #endif +; [MaintenanceService] +; +#ifdef MOZ_MAINTENANCE_SERVICE +@BINPATH@/maintenanceservice.exe +@BINPATH@/maintenanceservice_installer.exe +#endif + ; [crash reporter] #ifdef XP_MACOSX @BINPATH@/crashreporter.app/ diff --git a/mail/installer/removed-files.in b/mail/installer/removed-files.in index 606628f632..b629182f0c 100644 --- a/mail/installer/removed-files.in +++ b/mail/installer/removed-files.in @@ -1179,3 +1179,7 @@ components/xmlextras.xpt # **************************************************************************** # * End of XPTs at the time we started linking them on Linux and Mac. * # **************************************************************************** +#ifndef MOZ_MAINTENANCE_SERVICE +maintenanceservice.exe +maintenanceservice_installer.exe +#endif \ No newline at end of file diff --git a/mail/installer/windows/Makefile.in b/mail/installer/windows/Makefile.in index 4ee7b59728..cbb28f3776 100644 --- a/mail/installer/windows/Makefile.in +++ b/mail/installer/windows/Makefile.in @@ -29,6 +29,13 @@ INSTALLER_FILES = \ nsis/shared.nsh \ $(NULL) +ifdef MOZ_MAINTENANCE_SERVICE +INSTALLER_FILES += \ + nsis/maintenanceservice_installer.nsi \ + $(NULL) +endif + + BRANDING_FILES = \ branding.nsi \ wizHeader.bmp \ @@ -61,6 +68,17 @@ uninstaller:: --preprocess-locale $(MOZILLA_SRCDIR) \ $(call EXPAND_LOCALE_SRCDIR,mail/locales)/installer $(AB_CD) $(CONFIG_DIR) +# For building the maintenanceservice installer +ifdef MOZ_MAINTENANCE_SERVICE +maintenanceservice_installer:: + $(INSTALL) $(addprefix $(srcdir)/,$(INSTALLER_FILES)) $(CONFIG_DIR) + $(PYTHON) $(MOZILLA_SRCDIR)/config/Preprocessor.py -Fsubstitution $(DEFINES) $(ACDEFINES) \ + $(srcdir)/nsis/defines.nsi.in > $(CONFIG_DIR)/defines.nsi + $(PYTHON) $(MOZILLA_SRCDIR)/toolkit/mozapps/installer/windows/nsis/preprocess-locale.py \ + --preprocess-locale $(MOZILLA_SRCDIR) \ + $(call EXPAND_LOCALE_SRCDIR,mail/locales)/installer $(AB_CD) $(CONFIG_DIR) +endif + $(CONFIG_DIR)/setup.exe:: $(RM) -r $(CONFIG_DIR) && mkdir $(CONFIG_DIR) $(INSTALL) $(addprefix $(srcdir)/,$(INSTALLER_FILES)) $(CONFIG_DIR) diff --git a/mail/installer/windows/nsis/defines.nsi.in b/mail/installer/windows/nsis/defines.nsi.in index a367917968..5c6b14cecd 100755 --- a/mail/installer/windows/nsis/defines.nsi.in +++ b/mail/installer/windows/nsis/defines.nsi.in @@ -23,6 +23,9 @@ !define PreReleaseSuffix "@PRE_RELEASE_SUFFIX@" !define BrandFullName "${BrandFullNameInternal}${PreReleaseSuffix}" +!define CERTIFICATE_NAME "Mozilla Corporation" +!define CERTIFICATE_ISSUER "Thawte Code Signing CA - G2" + # NO_INSTDIR_FROM_REG is defined for pre-releases which have a PreReleaseSuffix # (e.g. Alpha X, Beta X, etc.) to prevent finding a non-default installation # directory in the registry and using that as the default. This prevents @@ -43,6 +46,10 @@ !define MinSupportedVer "Microsoft Windows XP SP2" #endif +#ifdef MOZ_MAINTENANCE_SERVICE +!define MOZ_MAINTENANCE_SERVICE +#endif + # File details shared by both the installer and uninstaller VIProductVersion "1.0.0.0" VIAddVersionKey "ProductName" "${BrandShortName}" diff --git a/mail/installer/windows/nsis/installer.nsi b/mail/installer/windows/nsis/installer.nsi index 8184de56ce..4cba693c8f 100755 --- a/mail/installer/windows/nsis/installer.nsi +++ b/mail/installer/windows/nsis/installer.nsi @@ -3,10 +3,12 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # Required Plugins: -# AppAssocReg http://nsis.sourceforge.net/Application_Association_Registration_plug-in -# CityHash http://mxr.mozilla.org/mozilla-central/source/other-licenses/nsis/Contrib/CityHash -# ShellLink http://nsis.sourceforge.net/ShellLink_plug-in -# UAC http://nsis.sourceforge.net/UAC_plug-in +# AppAssocReg http://nsis.sourceforge.net/Application_Association_Registration_plug-in +# ApplicationID http://nsis.sourceforge.net/ApplicationID_plug-in +# CityHash http://mxr.mozilla.org/mozilla-central/source/other-licenses/nsis/Contrib/CityHash +# ShellLink http://nsis.sourceforge.net/ShellLink_plug-in +# UAC http://nsis.sourceforge.net/UAC_plug-in +# ServicesHelper Mozilla specific plugin that is located in /other-licenses/nsis ; Set verbosity to 3 (e.g. no script) to lessen the noise in the build logs !verbose 3 @@ -26,6 +28,7 @@ Var InstallType Var AddStartMenuSC Var AddQuickLaunchSC Var AddDesktopSC +Var InstallMaintenanceService Var PageName ; By defining NO_STARTMENU_DIR an installer that doesn't provide an option for @@ -75,6 +78,7 @@ VIAddVersionKey "OriginalFilename" "setup.exe" !insertmacro GetParent !insertmacro InitHashAppModelId !insertmacro IsHandlerForInstallDir +!insertmacro IsUserAdmin !insertmacro LogDesktopShortcut !insertmacro LogQuickLaunchShortcut !insertmacro LogStartMenuShortcut @@ -143,6 +147,11 @@ Page custom preOptions leaveOptions !define MUI_DIRECTORYPAGE_VERIFYONLEAVE !insertmacro MUI_PAGE_DIRECTORY +; Custom Components Page +!ifdef MOZ_MAINTENANCE_SERVICE +Page custom preComponents leaveComponents +!endif + ; Custom Shortcuts Page Page custom preShortcuts leaveShortcuts @@ -354,6 +363,37 @@ Section "-Application" APP_IDX ${EndIf} ${EndIf} +!ifdef MOZ_MAINTENANCE_SERVICE + ; If the maintenance service page was displayed then a value was already + ; explicitly selected for installing the maintenance service and + ; and so InstallMaintenanceService will already be 0 or 1. + ; If the maintenance service page was not displayed then + ; InstallMaintenanceService will be equal to "". + ${If} $InstallMaintenanceService == "" + Call IsUserAdmin + Pop $R0 + ${If} $R0 == "true" + ; Only proceed if we have HKLM write access + ${AndIf} $TmpVal == "HKLM" + ; On Windows 2000 we do not install the maintenance service. + ${AndIf} ${AtLeastWinXP} + ; The user is an admin so we should default to install service yes + StrCpy $InstallMaintenanceService "1" + ${Else} + ; The user is not admin so we should default to install service no + StrCpy $InstallMaintenanceService "0" + ${EndIf} + ${EndIf} + + ${If} $InstallMaintenanceService == "1" + ; The user wants to install the maintenance service, so execute + ; the pre-packaged maintenance service installer. + ; This option can only be turned on if the user is an admin so there + ; is no need to use ExecShell w/ verb runas to enforce elevated. + nsExec::Exec "$INSTDIR\maintenanceservice_installer.exe" + ${EndIf} +!endif + ; These need special handling on uninstall since they may be overwritten by ; an install into a different location. StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\App Paths\${FileMainEXE}" @@ -397,7 +437,7 @@ Section "-Application" APP_IDX ${Unless} ${Errors} GetFunctionAddress $0 FixShortcutAppModelIDs UAC::ExecCodeSegment $0 - ${EndIf} + ${EndUnless} ; UAC only allows elevating to an Admin account so there is no need to add ; the Start Menu or Desktop shortcuts from the original unelevated process @@ -445,6 +485,13 @@ Section "-Application" APP_IDX UAC::ExecCodeSegment $0 ${EndIf} ${EndIf} + +!ifdef MOZ_MAINTENANCE_SERVICE + ${If} $TmpVal == "HKLM" + ; Add the registry keys for allowed certificates. + ${AddMaintCertKeys} + ${EndIf} +!endif SectionEnd ; Cleanup operations to perform at the end of the installation. @@ -747,6 +794,58 @@ Function leaveShortcuts ${EndIf} FunctionEnd +!ifdef MOZ_MAINTENANCE_SERVICE +Function preComponents + ; If the service already exists, don't show this page + ServicesHelper::IsInstalled "MozillaMaintenance" + Pop $R9 + ${If} $R9 == 1 + ; The service already exists so don't show this page. + Abort + ${EndIf} + + ; On Windows 2000 we do not install the maintenance service. + ${Unless} ${AtLeastWinXP} + Abort + ${EndUnless} + + ; Don't show the custom components page if the + ; user is not an admin + Call IsUserAdmin + Pop $R9 + ${If} $R9 != "true" + Abort + ${EndIf} + + ; Only show the maintenance service page if we have write access to HKLM + ClearErrors + WriteRegStr HKLM "Software\Mozilla" \ + "${BrandShortName}InstallerTest" "Write Test" + ${If} ${Errors} + ClearErrors + Abort + ${Else} + DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" + ${EndIf} + + StrCpy $PageName "Components" + ${CheckCustomCommon} + !insertmacro MUI_HEADER_TEXT "$(COMPONENTS_PAGE_TITLE)" "$(COMPONENTS_PAGE_SUBTITLE)" + !insertmacro MUI_INSTALLOPTIONS_DISPLAY "components.ini" +FunctionEnd + +Function leaveComponents + ${MUI_INSTALLOPTIONS_READ} $0 "components.ini" "Settings" "State" + ${If} $0 != 0 + Abort + ${EndIf} + ${MUI_INSTALLOPTIONS_READ} $InstallMaintenanceService "components.ini" "Field 2" "State" + ${If} $InstallType == ${INSTALLTYPE_CUSTOM} + Call CheckExistingInstall + ${EndIf} +FunctionEnd +!endif + Function preSummary StrCpy $PageName "Summary" ; Setup the summary.ini file for the Custom Summary Page @@ -854,6 +953,7 @@ Function .onInit !insertmacro InitInstallOptionsFile "options.ini" !insertmacro InitInstallOptionsFile "shortcuts.ini" + !insertmacro InitInstallOptionsFile "components.ini" !insertmacro InitInstallOptionsFile "summary.ini" ClearErrors @@ -889,7 +989,7 @@ Function .onInit WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Type "RadioButton" WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Text "$(OPTION_STANDARD_RADIO)" - WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Left "15" + WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Left "0" WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Right "-1" WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Top "25" WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Bottom "35" @@ -898,7 +998,7 @@ Function .onInit WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Type "RadioButton" WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Text "$(OPTION_CUSTOM_RADIO)" - WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Left "15" + WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Left "0" WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Right "-1" WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Top "55" WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Bottom "65" @@ -906,14 +1006,14 @@ Function .onInit WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Type "label" WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Text "$(OPTION_STANDARD_DESC)" - WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Left "30" + WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Left "15" WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Right "-1" WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Top "37" WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Bottom "57" WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Type "label" WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Text "$(OPTION_CUSTOM_DESC)" - WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Left "30" + WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Left "15" WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Right "-1" WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Top "67" WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Bottom "87" @@ -930,7 +1030,7 @@ Function .onInit WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Type "checkbox" WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Text "$(ICONS_DESKTOP)" - WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Left "15" + WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Left "0" WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Right "-1" WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Top "20" WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Bottom "30" @@ -939,7 +1039,7 @@ Function .onInit WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Type "checkbox" WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Text "$(ICONS_STARTMENU)" - WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Left "15" + WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Left "0" WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Right "-1" WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Top "40" WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Bottom "50" @@ -947,12 +1047,31 @@ Function .onInit WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Type "checkbox" WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Text "$(ICONS_QUICKLAUNCH)" - WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Left "15" + WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Left "0" WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Right "-1" WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Top "60" WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Bottom "70" WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" State "1" + ; Setup the components.ini file for the Components Page + WriteINIStr "$PLUGINSDIR\components.ini" "Settings" NumFields "2" + + WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Type "label" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Text "$(OPTIONAL_COMPONENTS_DESC)" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Left "0" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Right "-1" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Top "5" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Bottom "15" + + WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Type "checkbox" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Text "$(MAINTENANCE_SERVICE_CHECKBOX_DESC)" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Left "0" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Right "-1" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Top "20" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Bottom "30" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" State "1" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Flags "GROUP" + ; There must always be a core directory. ${GetSize} "$EXEDIR\core\" "/S=0K" $R5 $R7 $R8 ; Add 1024 Kb to the diskspace requirement since the installer makes a copy diff --git a/mail/installer/windows/nsis/maintenanceservice_installer.nsi b/mail/installer/windows/nsis/maintenanceservice_installer.nsi new file mode 100644 index 0000000000..9b199904f3 --- /dev/null +++ b/mail/installer/windows/nsis/maintenanceservice_installer.nsi @@ -0,0 +1,255 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +; Set verbosity to 3 (e.g. no script) to lessen the noise in the build logs +!verbose 3 + +; 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 +SetCompress off +CRCCheck on + +RequestExecutionLevel admin +!addplugindir ./ + +; Variables +Var TempMaintServiceName +Var BrandFullNameDA +Var BrandFullName + +; Other included files may depend upon these includes! +; The following includes are provided by NSIS. +!include FileFunc.nsh +!include LogicLib.nsh +!include MUI.nsh +!include WinMessages.nsh +!include WinVer.nsh +!include WordFunc.nsh + +!insertmacro GetOptions +!insertmacro GetParameters +!insertmacro GetSize + +; The test slaves use this fallback key to run tests. +; And anyone that wants to run tests themselves should already have +; this installed. +!define FallbackKey \ + "SOFTWARE\Mozilla\MaintenanceService\3932ecacee736d366d6436db0f55bce4" + +!define CompanyName "Mozilla Corporation" +!define BrandFullNameInternal "" + +; The following includes are custom. +!include defines.nsi +; We keep defines.nsi defined so that we get other things like +; the version number, but we redefine BrandFullName +!define MaintFullName "Mozilla Maintenance Service" +!undef BrandFullName +!define BrandFullName "${MaintFullName}" + +!include common.nsh +!include locales.nsi + +VIAddVersionKey "FileDescription" "${MaintFullName} Installer" +VIAddVersionKey "OriginalFilename" "maintenanceservice_installer.exe" + +Name "${MaintFullName}" +OutFile "maintenanceservice_installer.exe" + +; Get installation folder from registry if available +InstallDirRegKey HKLM "Software\Mozilla\MaintenanceService" "" + +SetOverwrite on + +!define MaintUninstallKey \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\MozillaMaintenanceService" + +; The HAVE_64BIT_OS define also means that we have an x64 build, +; not just an x64 OS. +!ifdef HAVE_64BIT_OS + ; See below, we actually abort the install for x64 builds currently. + InstallDir "$PROGRAMFILES64\${MaintFullName}\" +!else + InstallDir "$PROGRAMFILES32\${MaintFullName}\" +!endif +ShowUnInstDetails nevershow + +################################################################################ +# Modern User Interface - MUI + +!define MUI_ICON setup.ico +!define MUI_UNICON setup.ico +!define MUI_WELCOMEPAGE_TITLE_3LINES +!define MUI_UNWELCOMEFINISHPAGE_BITMAP wizWatermark.bmp + +;Interface Settings +!define MUI_ABORTWARNING + +; Uninstaller Pages +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + +################################################################################ +# Language + +!insertmacro MOZ_MUI_LANGUAGE 'baseLocale' +!verbose push +!verbose 3 +!include "overrideLocale.nsh" +!include "customLocale.nsh" +!verbose pop + +; Set this after the locale files to override it if it is in the locale +; using " " for BrandingText will hide the "Nullsoft Install System..." branding +BrandingText " " + +Function .onInit + SetSilent silent +!ifdef HAVE_64BIT_OS + ; We plan to eventually enable 64bit native builds to use the maintenance + ; service, but for the initial release, to reduce testing and development, + ; 64-bit builds will not install the maintenanceservice. + Abort +!endif + + ; On Windows 2000 we do not install the maintenance service. + ; We won't run this installer from the parent installer, but just in case + ; someone tries to execute it on Windows 2000... + ${Unless} ${AtLeastWinXP} + Abort + ${EndUnless} +FunctionEnd + +Function un.onInit + StrCpy $BrandFullNameDA "${MaintFullName}" + StrCpy $BrandFullName "${MaintFullName}" +FunctionEnd + +Section "MaintenanceService" + AllowSkipFiles off + + CreateDirectory $INSTDIR + SetOutPath $INSTDIR + + ; If the service already exists, then it will be stopped when upgrading it + ; via the maintenanceservice_tmp.exe command executed below. + ; The maintenanceservice_tmp.exe command will rename the file to + ; maintenanceservice.exe if maintenanceservice_tmp.exe is newer. + ; If the service does not exist yet, we install it and drop the file on + ; disk as maintenanceservice.exe directly. + StrCpy $TempMaintServiceName "maintenanceservice.exe" + IfFileExists "$INSTDIR\maintenanceservice.exe" 0 skipAlreadyExists + StrCpy $TempMaintServiceName "maintenanceservice_tmp.exe" + skipAlreadyExists: + + ; We always write out a copy and then decide whether to install it or + ; not via calling its 'install' cmdline which works by version comparison. + CopyFiles "$EXEDIR\maintenanceservice.exe" "$INSTDIR\$TempMaintServiceName" + + ; The updater.ini file is only used when performing an install or upgrade, + ; and only if that install or upgrade is successful. If an old updater.ini + ; happened to be copied into the maintenance service installation directory + ; but the service was not newer, the updater.ini file would be unused. + ; It is used to fill the description of the service on success. + CopyFiles "$EXEDIR\updater.ini" "$INSTDIR\updater.ini" + + ; Install the application maintenance service. + ; If a service already exists, the command line parameter will stop the + ; service and only install itself if it is newer than the already installed + ; service. If successful it will remove the old maintenanceservice.exe + ; and replace it with maintenanceservice_tmp.exe. + ClearErrors + ${GetParameters} $0 + ${GetOptions} "$0" "/Upgrade" $0 + ${If} ${Errors} + nsExec::Exec '"$INSTDIR\$TempMaintServiceName" install' + ${Else} + ; The upgrade cmdline is the same as install except + ; It will fail if the service isn't already installed. + nsExec::Exec '"$INSTDIR\$TempMaintServiceName" upgrade' + ${EndIf} + + WriteUninstaller "$INSTDIR\Uninstall.exe" + WriteRegStr HKLM "${MaintUninstallKey}" "DisplayName" "${MaintFullName}" + WriteRegStr HKLM "${MaintUninstallKey}" "UninstallString" \ + '"$INSTDIR\uninstall.exe"' + WriteRegStr HKLM "${MaintUninstallKey}" "DisplayIcon" \ + "$INSTDIR\Uninstall.exe,0" + WriteRegStr HKLM "${MaintUninstallKey}" "DisplayVersion" "${AppVersion}" + WriteRegStr HKLM "${MaintUninstallKey}" "Publisher" "Mozilla" + WriteRegStr HKLM "${MaintUninstallKey}" "Comments" \ + "${BrandFullName} ${AppVersion} (${ARCH} ${AB_CD})" + WriteRegDWORD HKLM "${MaintUninstallKey}" "NoModify" 1 + ${GetSize} "$INSTDIR" "/S=0K" $R2 $R3 $R4 + WriteRegDWORD HKLM "${MaintUninstallKey}" "EstimatedSize" $R2 + + ; Write out that a maintenance service was attempted. + ; We do this because on upgrades we will check this value and we only + ; want to install once on the first upgrade to maintenance service. + ; Also write out that we are currently installed, preferences will check + ; this value to determine if we should show the service update pref. + ; Since the Maintenance service can be installed either x86 or x64, + ; always use the 64-bit registry for checking if an attempt was made. + ${If} ${RunningX64} + SetRegView 64 + ${EndIf} + WriteRegDWORD HKLM "Software\Mozilla\MaintenanceService" "Attempted" 1 + WriteRegDWORD HKLM "Software\Mozilla\MaintenanceService" "Installed" 1 + + ; Included here for debug purposes only. + ; These keys are used to bypass the installation dir is a valid installation + ; check from the service so that tests can be run. + ; WriteRegStr HKLM "${FallbackKey}\0" "name" "Mozilla Corporation" + ; WriteRegStr HKLM "${FallbackKey}\0" "issuer" "Thawte Code Signing CA - G2" + ${If} ${RunningX64} + SetRegView lastused + ${EndIf} +SectionEnd + +; By renaming before deleting we improve things slightly in case +; there is a file in use error. In this case a new install can happen. +Function un.RenameDelete + Pop $9 + ; If the .moz-delete file already exists previously, delete it + ; If it doesn't exist, the call is ignored. + ; We don't need to pass /REBOOTOK here since it was already marked that way + ; if it exists. + Delete "$9.moz-delete" + Rename "$9" "$9.moz-delete" + ${If} ${Errors} + Delete /REBOOTOK "$9" + ${Else} + Delete /REBOOTOK "$9.moz-delete" + ${EndIf} + ClearErrors +FunctionEnd + +Section "Uninstall" + ; Delete the service so that no updates will be attempted + nsExec::Exec '"$INSTDIR\maintenanceservice.exe" uninstall' + + Push "$INSTDIR\updater.ini" + Call un.RenameDelete + Push "$INSTDIR\maintenanceservice.exe" + Call un.RenameDelete + Push "$INSTDIR\maintenanceservice_tmp.exe" + Call un.RenameDelete + Push "$INSTDIR\maintenanceservice.old" + Call un.RenameDelete + Push "$INSTDIR\Uninstall.exe" + Call un.RenameDelete + RMDir /REBOOTOK "$INSTDIR" + + DeleteRegKey HKLM "${MaintUninstallKey}" + + ${If} ${RunningX64} + SetRegView 64 + ${EndIf} + DeleteRegValue HKLM "Software\Mozilla\MaintenanceService" "Installed" + DeleteRegKey HKLM "${FallbackKey}\" + ${If} ${RunningX64} + SetRegView lastused + ${EndIf} +SectionEnd diff --git a/mail/installer/windows/nsis/shared.nsh b/mail/installer/windows/nsis/shared.nsh index c6e330b1fa..168707ef41 100755 --- a/mail/installer/windows/nsis/shared.nsh +++ b/mail/installer/windows/nsis/shared.nsh @@ -83,6 +83,45 @@ ; VirtualStore directory. ${CleanVirtualStore} +!ifdef MOZ_MAINTENANCE_SERVICE + Call IsUserAdmin + Pop $R0 + ${If} $R0 == "true" + ; Only proceed if we have HKLM write access + ${AndIf} $TmpVal == "HKLM" + ; On Windows 2000 we do not install the maintenance service. + ${AndIf} ${AtLeastWinXP} + ; Add the registry keys for allowed certificates. + ${AddMaintCertKeys} + + ; We check to see if the maintenance service install was already attempted. + ; Since the Maintenance service can be installed either x86 or x64, + ; always use the 64-bit registry for checking if an attempt was made. + SetRegView 64 + ReadRegDWORD $5 HKLM "Software\Mozilla\MaintenanceService" "Attempted" + ClearErrors + SetRegView lastused + + ; If the maintenance service is already installed, do nothing. + ; The maintenance service will launch: + ; maintenanceservice_installer.exe /Upgrade to upgrade the maintenance + ; service if necessary. If the update was done from updater.exe without + ; the service (i.e. service is failing), updater.exe will do the update of + ; the service. The reasons we do not do it here is because we don't want + ; to have to prompt for limited user accounts when the service isn't used + ; and we currently call the PostUpdate twice, once for the user and once + ; for the SYSTEM account. Also, this would stop the maintenance service + ; and we need a return result back to the service when run that way. + ${If} $5 == "" + ; An install of maintenance service was never attempted. + ; We call ExecShell (which is ShellExecute) with the verb "runas" + ; to ask for elevation if the user isn't already elevated. If the user + ; is already elevated it will just launch the program. + ExecShell "runas" "$INSTDIR\maintenanceservice_installer.exe" + ${EndIf} + ${EndIf} +!endif + ; Remove talkback if it is present (remove after bug 386760 is fixed) ${If} ${FileExists} "$INSTDIR\extensions\talkback@mozilla.org\" RmDir /r "$INSTDIR\extensions\talkback@mozilla.org\" @@ -400,38 +439,52 @@ !macro SetUninstallKeys StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} ${AppVersion} (${ARCH} ${AB_CD})" + StrCpy $2 "" + ClearErrors WriteRegStr HKLM "$0" "${BrandShortName}InstallerTest" "Write Test" ${If} ${Errors} - StrCpy $1 "HKCU" - SetShellVarContext current ; Set SHCTX to the current user (e.g. HKCU) + ; If the uninstall keys already exist in HKLM don't create them in HKCU + ClearErrors + ReadRegStr $2 "HKLM" $0 "DisplayName" + ${If} $2 == "" + ; Otherwise we don't have any keys for this product in HKLM so proceeed + ; to create them in HKCU. Better handling for this will be done in: + ; Bug 711044 - Better handling for 2 uninstall icons + StrCpy $1 "HKCU" + SetShellVarContext current ; Set SHCTX to the current user (e.g. HKCU) + ${EndIf} + ClearErrors ${Else} StrCpy $1 "HKLM" SetShellVarContext all ; Set SHCTX to all users (e.g. HKLM) DeleteRegValue HKLM "$0" "${BrandShortName}InstallerTest" ${EndIf} - ${GetLongPath} "$INSTDIR" $8 + ${If} $2 == "" + ${GetLongPath} "$INSTDIR" $8 - ; Write the uninstall registry keys - ${WriteRegStr2} $1 "$0" "Comments" "${BrandFullNameInternal} ${AppVersion} (${ARCH} ${AB_CD})" 0 - ${WriteRegStr2} $1 "$0" "DisplayIcon" "$8\${FileMainEXE},0" 0 - ${WriteRegStr2} $1 "$0" "DisplayName" "${BrandFullNameInternal} ${AppVersion} (${ARCH} ${AB_CD})" 0 - ${WriteRegStr2} $1 "$0" "DisplayVersion" "${AppVersion}" 0 - ${WriteRegStr2} $1 "$0" "InstallLocation" "$8" 0 - ${WriteRegStr2} $1 "$0" "Publisher" "Mozilla" 0 - ${WriteRegStr2} $1 "$0" "UninstallString" "$8\uninstall\helper.exe" 0 - ${WriteRegStr2} $1 "$0" "URLInfoAbout" "${URLInfoAbout}" 0 - ${WriteRegStr2} $1 "$0" "URLUpdateInfo" "${URLUpdateInfo}" 0 - ${WriteRegDWORD2} $1 "$0" "NoModify" 1 0 - ${WriteRegDWORD2} $1 "$0" "NoRepair" 1 0 - ${GetSize} "$8" "/S=0K" $R2 $R3 $R4 - ${WriteRegDWORD2} $1 "$0" "EstimatedSize" $R2 0 + ; Write the uninstall registry keys + ${WriteRegStr2} $1 "$0" "Comments" "${BrandFullNameInternal} ${AppVersion} (${ARCH} ${AB_CD})" 0 + ${WriteRegStr2} $1 "$0" "DisplayIcon" "$8\${FileMainEXE},0" 0 + ${WriteRegStr2} $1 "$0" "DisplayName" "${BrandFullNameInternal} ${AppVersion} (${ARCH} ${AB_CD})" 0 + ${WriteRegStr2} $1 "$0" "DisplayVersion" "${AppVersion}" 0 + ${WriteRegStr2} $1 "$0" "InstallLocation" "$8" 0 + ${WriteRegStr2} $1 "$0" "Publisher" "Mozilla" 0 + ${WriteRegStr2} $1 "$0" "UninstallString" "$8\uninstall\helper.exe" 0 + ${WriteRegStr2} $1 "$0" "URLInfoAbout" "${URLInfoAbout}" 0 + ${WriteRegStr2} $1 "$0" "URLUpdateInfo" "${URLUpdateInfo}" 0 + ${WriteRegDWORD2} $1 "$0" "NoModify" 1 0 + ${WriteRegDWORD2} $1 "$0" "NoRepair" 1 0 - ${If} "$TmpVal" == "HKLM" - SetShellVarContext all ; Set SHCTX to all users (e.g. HKLM) - ${Else} - SetShellVarContext current ; Set SHCTX to the current user (e.g. HKCU) + ${GetSize} "$8" "/S=0K" $R2 $R3 $R4 + ${WriteRegDWORD2} $1 "$0" "EstimatedSize" $R2 0 + + ${If} "$TmpVal" == "HKLM" + SetShellVarContext all ; Set SHCTX to all users (e.g. HKLM) + ${Else} + SetShellVarContext current ; Set SHCTX to the current user (e.g. HKCU) + ${EndIf} ${EndIf} !macroend !define SetUninstallKeys "!insertmacro SetUninstallKeys" @@ -488,6 +541,35 @@ !macroend !define UpdateProtocolHandlers "!insertmacro UpdateProtocolHandlers" +!ifdef MOZ_MAINTENANCE_SERVICE +; Adds maintenance service certificate keys for the install dir. +; For the cert to work, it must also be signed by a trusted cert for the user. +!macro AddMaintCertKeys + Push $R0 + ; Allow main Mozilla cert information for updates + ; This call will push the needed key on the stack + ServicesHelper::PathToUniqueRegistryPath "$INSTDIR" + Pop $R0 + ${If} $R0 != "" + ; More than one certificate can be specified in a different subfolder + ; for example: $R0\1, but each individual binary can be signed + ; with at most one certificate. A fallback certificate can only be used + ; if the binary is replaced with a different certificate. + ; We always use the 64bit registry for certs. + ; This call is ignored on 32-bit systems. + SetRegView 64 + DeleteRegKey HKLM "$R0" + WriteRegStr HKLM "$R0\0" "name" "${CERTIFICATE_NAME}" + WriteRegStr HKLM "$R0\0" "issuer" "${CERTIFICATE_ISSUER}" + SetRegView lastused + ClearErrors + ${EndIf} + ; Restore the previously used value back + Pop $R0 +!macroend +!define AddMaintCertKeys "!insertmacro AddMaintCertKeys" +!endif + ; Removes various registry entries for reasons noted below (does not use SHCTX). !macro RemoveDeprecatedKeys StrCpy $0 "SOFTWARE\Classes" diff --git a/mail/installer/windows/nsis/uninstaller.nsi b/mail/installer/windows/nsis/uninstaller.nsi index cabfb9997d..add5c06b77 100755 --- a/mail/installer/windows/nsis/uninstaller.nsi +++ b/mail/installer/windows/nsis/uninstaller.nsi @@ -29,6 +29,7 @@ RequestExecutionLevel user !define NO_LOG Var TmpVal +Var MaintCertKey ; Other included files may depend upon these includes! ; The following includes are provided by NSIS. @@ -68,6 +69,7 @@ VIAddVersionKey "OriginalFilename" "helper.exe" !insertmacro GetPathFromString !insertmacro InitHashAppModelId !insertmacro IsHandlerForInstallDir +!insertmacro IsUserAdmin !insertmacro LogDesktopShortcut !insertmacro LogQuickLaunchShortcut !insertmacro LogStartMenuShortcut @@ -342,6 +344,21 @@ Section "Uninstall" ; removed and other ugly things will happen like recreation of the app's ; clients registry key by the OS under some conditions. System::Call "shell32::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)" + +!ifdef MOZ_MAINTENANCE_SERVICE + ; Get the path the allowed cert is at and remove it + ; Keep this block of code last since it modfies the reg view + ServicesHelper::PathToUniqueRegistryPath "$INSTDIR" + Pop $MaintCertKey + ${If} $MaintCertKey != "" + ; We always use the 64bit registry for certs + ; This call is ignored on 32-bit systems. + SetRegView 64 + DeleteRegKey HKLM "$MaintCertKey\" + SetRegView lastused + ${EndIf} +!endif + SectionEnd ################################################################################ diff --git a/mail/locales/en-US/chrome/messenger/preferences/advanced.dtd b/mail/locales/en-US/chrome/messenger/preferences/advanced.dtd index 854dc06803..488e9b9cf1 100644 --- a/mail/locales/en-US/chrome/messenger/preferences/advanced.dtd +++ b/mail/locales/en-US/chrome/messenger/preferences/advanced.dtd @@ -71,6 +71,9 @@ + + + diff --git a/mail/locales/en-US/installer/custom.properties b/mail/locales/en-US/installer/custom.properties index 1cd10fab14..da429d4f30 100755 --- a/mail/locales/en-US/installer/custom.properties +++ b/mail/locales/en-US/installer/custom.properties @@ -26,6 +26,10 @@ OPTIONS_PAGE_SUBTITLE=Choose setup options OPTIONS_MAKE_DEFAULT=&Use $BrandShortName as my default mail application SHORTCUTS_PAGE_TITLE=Set Up Shortcuts SHORTCUTS_PAGE_SUBTITLE=Create Program Icons +COMPONENTS_PAGE_TITLE=Set Up Optional Components +COMPONENTS_PAGE_SUBTITLE=Optional Recommended Components +OPTIONAL_COMPONENTS_DESC=The Maintenance Service will allow you to update $BrandShortName silently in the background. +MAINTENANCE_SERVICE_CHECKBOX_DESC=Install &Maintenance Service SUMMARY_PAGE_TITLE=Summary SUMMARY_PAGE_SUBTITLE=Ready to start installing $BrandShortName SUMMARY_INSTALLED_TO=$BrandShortName will be installed to the following location: