diff options
Diffstat (limited to 'toolkit/mozapps/update')
-rw-r--r-- | toolkit/mozapps/update/common/errors.h | 23 | ||||
-rw-r--r-- | toolkit/mozapps/update/common/moz.build | 5 | ||||
-rw-r--r-- | toolkit/mozapps/update/common/sources.mozbuild | 9 | ||||
-rw-r--r-- | toolkit/mozapps/update/nsUpdateService.js | 294 | ||||
-rw-r--r-- | toolkit/mozapps/update/tests/TestAUSHelper.cpp | 10 | ||||
-rw-r--r-- | toolkit/mozapps/update/tests/moz.build | 6 | ||||
-rw-r--r-- | toolkit/mozapps/update/updater/updater.cpp | 281 |
7 files changed, 65 insertions, 563 deletions
diff --git a/toolkit/mozapps/update/common/errors.h b/toolkit/mozapps/update/common/errors.h index aac029175..846118d55 100644 --- a/toolkit/mozapps/update/common/errors.h +++ b/toolkit/mozapps/update/common/errors.h @@ -42,18 +42,6 @@ #define MAR_CHANNEL_MISMATCH_ERROR 22 #define VERSION_DOWNGRADE_ERROR 23 -// Error codes 24-33 and 49-57 are for the Windows maintenance service. -#define SERVICE_UPDATER_COULD_NOT_BE_STARTED 24 -#define SERVICE_NOT_ENOUGH_COMMAND_LINE_ARGS 25 -#define SERVICE_UPDATER_SIGN_ERROR 26 -#define SERVICE_UPDATER_COMPARE_ERROR 27 -#define SERVICE_UPDATER_IDENTITY_ERROR 28 -#define SERVICE_STILL_APPLYING_ON_SUCCESS 29 -#define SERVICE_STILL_APPLYING_ON_FAILURE 30 -#define SERVICE_UPDATER_NOT_FIXED_DRIVE 31 -#define SERVICE_COULD_NOT_LOCK_UPDATER 32 -#define SERVICE_INSTALLDIR_ERROR 33 - #define NO_INSTALLDIR_ERROR 34 #define WRITE_ERROR_ACCESS_DENIED 35 // #define WRITE_ERROR_SHARING_VIOLATION 36 // Replaced with errors 46-48 @@ -67,17 +55,6 @@ #define DELETE_ERROR_EXPECTED_FILE 47 #define RENAME_ERROR_EXPECTED_FILE 48 -// Error codes 24-33 and 49-57 are for the Windows maintenance service. -#define SERVICE_COULD_NOT_COPY_UPDATER 49 -#define SERVICE_STILL_APPLYING_TERMINATED 50 -#define SERVICE_STILL_APPLYING_NO_EXIT_CODE 51 -#define SERVICE_INVALID_APPLYTO_DIR_STAGED_ERROR 52 -#define SERVICE_CALC_REG_PATH_ERROR 53 -#define SERVICE_INVALID_APPLYTO_DIR_ERROR 54 -#define SERVICE_INVALID_INSTALL_DIR_PATH_ERROR 55 -#define SERVICE_INVALID_WORKING_DIR_PATH_ERROR 56 -#define SERVICE_INSTALL_DIR_REG_ERROR 57 - #define WRITE_ERROR_FILE_COPY 61 #define WRITE_ERROR_DELETE_FILE 62 #define WRITE_ERROR_OPEN_PATCH_FILE 63 diff --git a/toolkit/mozapps/update/common/moz.build b/toolkit/mozapps/update/common/moz.build index cacb0bad2..ca7c4c307 100644 --- a/toolkit/mozapps/update/common/moz.build +++ b/toolkit/mozapps/update/common/moz.build @@ -17,11 +17,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': 'updatehelper.cpp', 'updatehelper.h', ] - if CONFIG['MOZ_MAINTENANCE_SERVICE']: - EXPORTS += [ - 'certificatecheck.h', - 'registrycertificates.h', - ] Library('updatecommon') diff --git a/toolkit/mozapps/update/common/sources.mozbuild b/toolkit/mozapps/update/common/sources.mozbuild index cde51e09b..339944640 100644 --- a/toolkit/mozapps/update/common/sources.mozbuild +++ b/toolkit/mozapps/update/common/sources.mozbuild @@ -10,15 +10,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': 'uachelper.cpp', 'updatehelper.cpp', ] - if CONFIG['MOZ_MAINTENANCE_SERVICE']: - sources += [ - 'certificatecheck.cpp', - 'registrycertificates.cpp', - ] - OS_LIBS += [ - 'crypt32', - 'wintrust', - ] sources += [ 'readstrings.cpp', diff --git a/toolkit/mozapps/update/nsUpdateService.js b/toolkit/mozapps/update/nsUpdateService.js index 0cf7b8938..4e2d66a5c 100644 --- a/toolkit/mozapps/update/nsUpdateService.js +++ b/toolkit/mozapps/update/nsUpdateService.js @@ -35,15 +35,13 @@ const PREF_APP_UPDATE_LOG = "app.update.log"; const PREF_APP_UPDATE_NOTIFIEDUNSUPPORTED = "app.update.notifiedUnsupported"; const PREF_APP_UPDATE_POSTUPDATE = "app.update.postupdate"; const PREF_APP_UPDATE_PROMPTWAITTIME = "app.update.promptWaitTime"; -const PREF_APP_UPDATE_SERVICE_ENABLED = "app.update.service.enabled"; -const PREF_APP_UPDATE_SERVICE_ERRORS = "app.update.service.errors"; -const PREF_APP_UPDATE_SERVICE_MAXERRORS = "app.update.service.maxErrors"; const PREF_APP_UPDATE_SILENT = "app.update.silent"; const PREF_APP_UPDATE_SOCKET_MAXERRORS = "app.update.socket.maxErrors"; const PREF_APP_UPDATE_SOCKET_RETRYTIMEOUT = "app.update.socket.retryTimeout"; const PREF_APP_UPDATE_STAGING_ENABLED = "app.update.staging.enabled"; const PREF_APP_UPDATE_URL = "app.update.url"; const PREF_APP_UPDATE_URL_DETAILS = "app.update.url.details"; +const PREF_APP_UPDATE_URL_OVERRIDE = "app.update.url.override"; const PREFBRANCH_APP_UPDATE_NEVER = "app.update.never."; @@ -72,12 +70,10 @@ const FILE_UPDATE_VERSION = "update.version"; const STATE_NONE = "null"; const STATE_DOWNLOADING = "downloading"; const STATE_PENDING = "pending"; -const STATE_PENDING_SERVICE = "pending-service"; const STATE_PENDING_ELEVATE = "pending-elevate"; const STATE_APPLYING = "applying"; const STATE_APPLIED = "applied"; const STATE_APPLIED_OS = "applied-os"; -const STATE_APPLIED_SERVICE = "applied-service"; const STATE_SUCCEEDED = "succeeded"; const STATE_DOWNLOAD_FAILED = "download-failed"; const STATE_FAILED = "failed"; @@ -85,22 +81,9 @@ const STATE_FAILED = "failed"; // The values below used by this code are from common/errors.h const WRITE_ERROR = 7; const ELEVATION_CANCELED = 9; -const SERVICE_UPDATER_COULD_NOT_BE_STARTED = 24; -const SERVICE_NOT_ENOUGH_COMMAND_LINE_ARGS = 25; -const SERVICE_UPDATER_SIGN_ERROR = 26; -const SERVICE_UPDATER_COMPARE_ERROR = 27; -const SERVICE_UPDATER_IDENTITY_ERROR = 28; -const SERVICE_STILL_APPLYING_ON_SUCCESS = 29; -const SERVICE_STILL_APPLYING_ON_FAILURE = 30; -const SERVICE_UPDATER_NOT_FIXED_DRIVE = 31; -const SERVICE_COULD_NOT_LOCK_UPDATER = 32; -const SERVICE_INSTALLDIR_ERROR = 33; const WRITE_ERROR_ACCESS_DENIED = 35; const WRITE_ERROR_CALLBACK_APP = 37; const FILESYSTEM_MOUNT_READWRITE_ERROR = 43; -const SERVICE_COULD_NOT_COPY_UPDATER = 49; -const SERVICE_STILL_APPLYING_TERMINATED = 50; -const SERVICE_STILL_APPLYING_NO_EXIT_CODE = 51; const WRITE_ERROR_FILE_COPY = 61; const WRITE_ERROR_DELETE_FILE = 62; const WRITE_ERROR_OPEN_PATCH_FILE = 63; @@ -127,21 +110,6 @@ const WRITE_ERRORS = [WRITE_ERROR, WRITE_ERROR_DELETE_BACKUP, WRITE_ERROR_EXTRACT]; -// Array of write errors to simplify checks for service errors -const SERVICE_ERRORS = [SERVICE_UPDATER_COULD_NOT_BE_STARTED, - SERVICE_NOT_ENOUGH_COMMAND_LINE_ARGS, - SERVICE_UPDATER_SIGN_ERROR, - SERVICE_UPDATER_COMPARE_ERROR, - SERVICE_UPDATER_IDENTITY_ERROR, - SERVICE_STILL_APPLYING_ON_SUCCESS, - SERVICE_STILL_APPLYING_ON_FAILURE, - SERVICE_UPDATER_NOT_FIXED_DRIVE, - SERVICE_COULD_NOT_LOCK_UPDATER, - SERVICE_INSTALLDIR_ERROR, - SERVICE_COULD_NOT_COPY_UPDATER, - SERVICE_STILL_APPLYING_TERMINATED, - SERVICE_STILL_APPLYING_NO_EXIT_CODE]; - // Error codes 80 through 99 are reserved for nsUpdateService.js and are not // defined in common/errors.h const FOTA_GENERAL_ERROR = 80; @@ -164,10 +132,6 @@ const DOWNLOAD_FOREGROUND_INTERVAL = 0; const UPDATE_WINDOW_NAME = "Update:Wizard"; -// The number of consecutive failures when updating using the service before -// setting the app.update.service.enabled preference to false. -const DEFAULT_SERVICE_MAX_ERRORS = 10; - // The number of consecutive socket errors to allow before falling back to // downloading a different MAR file or failing if already downloading the full. const DEFAULT_SOCKET_MAX_ERRORS = 10; @@ -392,15 +356,7 @@ function getElevationRequired() { * @return true if an update can be applied, false otherwise */ function getCanApplyUpdates() { - let useService = false; - if (shouldUseService()) { - // No need to perform directory write checks, the maintenance service will - // be able to write to all directories. - LOG("getCanApplyUpdates - bypass the write checks because we'll use the service"); - useService = true; - } - - if (!useService && AppConstants.platform != "macosx") { + if (AppConstants.platform != "macosx") { try { let updateTestFile = getUpdateFile([FILE_UPDATE_TEST]); LOG("getCanApplyUpdates - testing write access " + updateTestFile.path); @@ -478,7 +434,7 @@ function getCanApplyUpdates() { // No write privileges to install directory return false; } - } // if (!useService) + } LOG("getCanApplyUpdates - able to apply updates"); return true; @@ -544,13 +500,6 @@ function getCanStageUpdates() { return false; } - if (AppConstants.platform == "win" && shouldUseService()) { - // No need to perform directory write checks, the maintenance service will - // be able to write to all directories. - LOG("getCanStageUpdates - able to stage updates using the service"); - return true; - } - if (!hasUpdateMutex()) { LOG("getCanStageUpdates - unable to apply updates because another " + "instance of the application is already handling updates for this " + @@ -778,120 +727,6 @@ function writeVersionFile(dir, version) { } /** - * Determines if the service should be used to attempt an update - * or not. - * - * @return true if the service should be used for updates. - */ -function shouldUseService() { - // This function will return true if the mantenance service should be used if - // all of the following conditions are met: - // 1) This build was done with the maintenance service enabled - // 2) The maintenance service is installed - // 3) The pref for using the service is enabled - // 4) The Windows version is XP Service Pack 3 or above (for SHA-2 support) - // The maintenance service requires SHA-2 support because we sign our binaries - // with a SHA-2 certificate and the certificate is verified before the binary - // is launched. - if (!AppConstants.MOZ_MAINTENANCE_SERVICE || !isServiceInstalled() || - !getPref("getBoolPref", PREF_APP_UPDATE_SERVICE_ENABLED, false) || - !AppConstants.isPlatformAndVersionAtLeast("win", "5.1") /* WinXP */) { - return false; - } - - // If it's newer than XP, then the service pack doesn't matter. - if (Services.sysinfo.getProperty("version") != "5.1") { - return true; - } - - // If the Windows version is XP, we also need to check the service pack. - // We'll return false if only < SP3 is installed, or if we can't tell. - // Check the service pack level by calling GetVersionEx via ctypes. - const BYTE = ctypes.uint8_t; - const WORD = ctypes.uint16_t; - const DWORD = ctypes.uint32_t; - const WCHAR = ctypes.char16_t; - const BOOL = ctypes.int; - // This structure is described at: - // http://msdn.microsoft.com/en-us/library/ms724833%28v=vs.85%29.aspx - const SZCSDVERSIONLENGTH = 128; - const OSVERSIONINFOEXW = new ctypes.StructType('OSVERSIONINFOEXW', - [ - {dwOSVersionInfoSize: DWORD}, - {dwMajorVersion: DWORD}, - {dwMinorVersion: DWORD}, - {dwBuildNumber: DWORD}, - {dwPlatformId: DWORD}, - {szCSDVersion: ctypes.ArrayType(WCHAR, SZCSDVERSIONLENGTH)}, - {wServicePackMajor: WORD}, - {wServicePackMinor: WORD}, - {wSuiteMask: WORD}, - {wProductType: BYTE}, - {wReserved: BYTE} - ]); - - let kernel32 = false; - try { - kernel32 = ctypes.open("Kernel32"); - } catch (e) { - Cu.reportError("Unable to open kernel32! " + e); - return false; - } - - if (kernel32) { - try { - try { - let GetVersionEx = kernel32.declare("GetVersionExW", - ctypes.default_abi, - BOOL, - OSVERSIONINFOEXW.ptr); - let winVer = OSVERSIONINFOEXW(); - winVer.dwOSVersionInfoSize = OSVERSIONINFOEXW.size; - - if (0 !== GetVersionEx(winVer.address())) { - return winVer.wServicePackMajor >= 3; - } - Cu.reportError("Unknown failure in GetVersionEX (returned 0)"); - return false; - } catch (e) { - Cu.reportError("Error getting service pack information. Exception: " + e); - return false; - } - } finally { - kernel32.close(); - } - } - - // If the service pack check couldn't be done, assume we can't use the service. - return false; -} - -/** - * Determines if the service is is installed. - * - * @return true if the service is installed. - */ -function isServiceInstalled() { - if (AppConstants.MOZ_MAINTENANCE_SERVICE && AppConstants.platform == "win") { - let installed = 0; - try { - let wrk = Cc["@mozilla.org/windows-registry-key;1"]. - createInstance(Ci.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) { - } - installed = installed == 1; // convert to bool - LOG("isServiceInstalled = " + installed); - return installed; - } - return false; -} - -/** * Removes the contents of the updates patch directory and rotates the update * logs when present. If the update.log exists in the patch directory this will * move the last-update.log if it exists to backup-update.log in the parent @@ -1102,35 +937,6 @@ function handleUpdateFailure(update, errorCode) { Services.prefs.clearUserPref(PREF_APP_UPDATE_CANCELATIONS_OSX); } - // Replace with Array.prototype.includes when it has stabilized. - if (SERVICE_ERRORS.indexOf(update.errorCode) != -1) { - var failCount = getPref("getIntPref", - PREF_APP_UPDATE_SERVICE_ERRORS, 0); - var maxFail = getPref("getIntPref", - PREF_APP_UPDATE_SERVICE_MAXERRORS, - DEFAULT_SERVICE_MAX_ERRORS); - // Prevent the preference from setting a value greater than 10. - maxFail = Math.min(maxFail, 10); - // As a safety, when the service reaches maximum failures, it will - // disable itself and fallback to using the normal update mechanism - // without the service. - if (failCount >= maxFail) { - Services.prefs.setBoolPref(PREF_APP_UPDATE_SERVICE_ENABLED, false); - Services.prefs.clearUserPref(PREF_APP_UPDATE_SERVICE_ERRORS); - } else { - failCount++; - Services.prefs.setIntPref(PREF_APP_UPDATE_SERVICE_ERRORS, - failCount); - } - - writeStatusFile(getUpdatesDir(), update.state = STATE_PENDING); - return true; - } - - if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_SERVICE_ERRORS)) { - Services.prefs.clearUserPref(PREF_APP_UPDATE_SERVICE_ERRORS); - } - return false; } @@ -1189,9 +995,6 @@ function pingStateAndStatusCodes(aUpdate, aStartup, aStatus) { case STATE_PENDING: stateCode = 4; break; - case STATE_PENDING_SERVICE: - stateCode = 5; - break; case STATE_APPLYING: stateCode = 6; break; @@ -1201,9 +1004,6 @@ function pingStateAndStatusCodes(aUpdate, aStartup, aStatus) { case STATE_APPLIED_OS: stateCode = 8; break; - case STATE_APPLIED_SERVICE: - stateCode = 9; - break; case STATE_SUCCEEDED: stateCode = 10; break; @@ -1831,8 +1631,8 @@ UpdateService.prototype = { // version and nsUpdateDriver.cpp skipped updating due to the version being // older than the current version. if (update && update.appVersion && - (status == STATE_PENDING || status == STATE_PENDING_SERVICE || - status == STATE_APPLIED || status == STATE_APPLIED_SERVICE || + (status == STATE_PENDING || + status == STATE_APPLIED || status == STATE_PENDING_ELEVATE)) { if (Services.vc.compare(update.appVersion, Services.appinfo.version) < 0 || Services.vc.compare(update.appVersion, Services.appinfo.version) == 0 && @@ -1870,9 +1670,7 @@ UpdateService.prototype = { // that state to "applying" and we just wait and hope for the best. // If it's "applying", we know that we've already been here once, so // we really want to start from a clean state. - if (update && - (update.state == STATE_PENDING || - update.state == STATE_PENDING_SERVICE)) { + if (update && (update.state == STATE_PENDING)) { LOG("UpdateService:_postUpdateProcessing - patch found in applying " + "state for the first time"); update.state = STATE_APPLYING; @@ -2121,27 +1919,13 @@ UpdateService.prototype = { this._pingSuffix, PREF_APP_UPDATE_CANCELATIONS_OSX, 0, 0); } - if (AppConstants.MOZ_MAINTENANCE_SERVICE) { - // Histogram IDs: - // UPDATE_NOT_PREF_UPDATE_SERVICE_ENABLED_EXTERNAL - // UPDATE_NOT_PREF_UPDATE_SERVICE_ENABLED_NOTIFY - AUSTLMY.pingBoolPref("UPDATE_NOT_PREF_UPDATE_SERVICE_ENABLED_" + - this._pingSuffix, - PREF_APP_UPDATE_SERVICE_ENABLED, true); - // Histogram IDs: - // UPDATE_PREF_SERVICE_ERRORS_EXTERNAL - // UPDATE_PREF_SERVICE_ERRORS_NOTIFY - AUSTLMY.pingIntPref("UPDATE_PREF_SERVICE_ERRORS_" + this._pingSuffix, - PREF_APP_UPDATE_SERVICE_ERRORS, 0, 0); - if (AppConstants.platform == "win") { - // Histogram IDs: - // UPDATE_SERVICE_INSTALLED_EXTERNAL - // UPDATE_SERVICE_INSTALLED_NOTIFY - // UPDATE_SERVICE_MANUALLY_UNINSTALLED_EXTERNAL - // UPDATE_SERVICE_MANUALLY_UNINSTALLED_NOTIFY - AUSTLMY.pingServiceInstallStatus(this._pingSuffix, isServiceInstalled()); - } - } + let prefType = Services.prefs.getPrefType(PREF_APP_UPDATE_URL_OVERRIDE); + let overridePrefHasValue = prefType != Ci.nsIPrefBranch.PREF_INVALID; + // Histogram IDs: + // UPDATE_HAS_PREF_URL_OVERRIDE_EXTERNAL + // UPDATE_HAS_PREF_URL_OVERRIDE_NOTIFY + AUSTLMY.pingGeneric("UPDATE_HAS_PREF_URL_OVERRIDE_" + this._pingSuffix, + overridePrefHasValue, false); // If a download is in progress or the patch has been staged do nothing. if (this.isDownloading) { @@ -2151,7 +1935,7 @@ UpdateService.prototype = { if (this._downloader && this._downloader.patchIsStaged) { let readState = readStatusFile(getUpdatesDir()); - if (readState == STATE_PENDING || readState == STATE_PENDING_SERVICE || + if (readState == STATE_PENDING || readState == STATE_PENDING_ELEVATE) { AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_IS_DOWNLOADED); } else { @@ -2173,8 +1957,18 @@ UpdateService.prototype = { } else if (!UpdateUtils.ABI) { AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_NO_OS_ABI); } else if (!validUpdateURL) { - AUSTLMY.pingCheckCode(this._pingSuffix, - AUSTLMY.CHK_INVALID_DEFAULT_URL); + if (overridePrefHasValue) { + if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_URL_OVERRIDE)) { + AUSTLMY.pingCheckCode(this._pingSuffix, + AUSTLMY.CHK_INVALID_USER_OVERRIDE_URL); + } else { + AUSTLMY.pingCheckCode(this._pingSuffix, + AUSTLMY.CHK_INVALID_DEFAULT_OVERRIDE_URL); + } + } else { + AUSTLMY.pingCheckCode(this._pingSuffix, + AUSTLMY.CHK_INVALID_DEFAULT_URL); + } } else if (!getPref("getBoolPref", PREF_APP_UPDATE_ENABLED, true)) { AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_PREF_DISABLED); } else if (!hasUpdateMutex()) { @@ -2885,8 +2679,8 @@ UpdateManager.prototype = { for (let i = updates.length - 1; i >= 0; --i) { let state = updates[i].state; if (state == STATE_NONE || state == STATE_DOWNLOADING || - state == STATE_APPLIED || state == STATE_APPLIED_SERVICE || - state == STATE_PENDING || state == STATE_PENDING_SERVICE || + state == STATE_APPLIED || + state == STATE_PENDING || state == STATE_PENDING_ELEVATE) { updates.splice(i, 1); } @@ -2931,9 +2725,6 @@ UpdateManager.prototype = { update.QueryInterface(Ci.nsIWritablePropertyBag); update.setProperty("stagingFailed", "true"); } - if (update.state == STATE_APPLIED && shouldUseService()) { - writeStatusFile(getUpdatesDir(), update.state = STATE_APPLIED_SERVICE); - } // Send an observer notification which the update wizard uses in // order to update its UI. @@ -2949,9 +2740,7 @@ UpdateManager.prototype = { } if (update.state == STATE_APPLIED || - update.state == STATE_APPLIED_SERVICE || update.state == STATE_PENDING || - update.state == STATE_PENDING_SERVICE || update.state == STATE_PENDING_ELEVATE) { // Notify the user that an update has been staged and is ready for // installation (i.e. that they should restart the application). @@ -3023,11 +2812,16 @@ Checker.prototype = { getUpdateURL: function UC_getUpdateURL(force) { this._forced = force; - let url; - try { - url = Services.prefs.getDefaultBranch(null). - getCharPref(PREF_APP_UPDATE_URL); - } catch (e) { + // Use the override URL if specified. + let url = getPref("getCharPref", PREF_APP_UPDATE_URL_OVERRIDE, null); + + // Otherwise, construct the update URL from component parts. + if (!url) { + try { + url = Services.prefs.getDefaultBranch(null). + getCharPref(PREF_APP_UPDATE_URL); + } catch (e) { + } } if (!url || url == "") { @@ -3309,9 +3103,9 @@ Downloader.prototype = { // Note that if we decide to download and apply new updates after another // update has been successfully applied in the background, we need to stop // checking for the APPLIED state here. - return readState == STATE_PENDING || readState == STATE_PENDING_SERVICE || + return readState == STATE_PENDING || readState == STATE_PENDING_ELEVATE || - readState == STATE_APPLIED || readState == STATE_APPLIED_SERVICE; + readState == STATE_APPLIED; }, /** @@ -3428,7 +3222,7 @@ Downloader.prototype = { return selectedPatch; } - if (state == STATE_PENDING || state == STATE_PENDING_SERVICE || + if (state == STATE_PENDING || state == STATE_PENDING_ELEVATE) { LOG("Downloader:_selectPatch - already downloaded and staged"); return null; @@ -3721,9 +3515,7 @@ Downloader.prototype = { "max fail: " + maxFail + ", " + "retryTimeout: " + retryTimeout); if (Components.isSuccessCode(status)) { if (this._verifyDownload()) { - if (shouldUseService()) { - state = STATE_PENDING_SERVICE; - } else if (getElevationRequired()) { + if (getElevationRequired()) { state = STATE_PENDING_ELEVATE; } else { state = STATE_PENDING; @@ -3873,7 +3665,7 @@ Downloader.prototype = { return; } - if (state == STATE_PENDING || state == STATE_PENDING_SERVICE || + if (state == STATE_PENDING || state == STATE_PENDING_ELEVATE) { if (getCanStageUpdates()) { LOG("Downloader:onStopRequest - attempting to stage update: " + diff --git a/toolkit/mozapps/update/tests/TestAUSHelper.cpp b/toolkit/mozapps/update/tests/TestAUSHelper.cpp index f71103b7a..a20c4a79a 100644 --- a/toolkit/mozapps/update/tests/TestAUSHelper.cpp +++ b/toolkit/mozapps/update/tests/TestAUSHelper.cpp @@ -217,16 +217,8 @@ int NS_main(int argc, NS_tchar **argv) } if (!NS_tstrcmp(argv[1], NS_T("check-signature"))) { -#if defined(XP_WIN) && defined(MOZ_MAINTENANCE_SERVICE) - if (ERROR_SUCCESS == VerifyCertificateTrustForFile(argv[2])) { - return 0; - } else { - return 1; - } -#else - // Not implemented on non-Windows platforms + // Not implemented return 1; -#endif } if (!NS_tstrcmp(argv[1], NS_T("setup-symlink"))) { diff --git a/toolkit/mozapps/update/tests/moz.build b/toolkit/mozapps/update/tests/moz.build index 842ec7f90..94949b17f 100644 --- a/toolkit/mozapps/update/tests/moz.build +++ b/toolkit/mozapps/update/tests/moz.build @@ -15,9 +15,6 @@ XPCSHELL_TESTS_MANIFESTS += [ 'unit_base_updater/xpcshell.ini' ] -if CONFIG['MOZ_MAINTENANCE_SERVICE']: - XPCSHELL_TESTS_MANIFESTS += ['unit_service_updater/xpcshell.ini'] - SimplePrograms([ 'TestAUSHelper', 'TestAUSReadStrings', @@ -47,9 +44,6 @@ for var in ('MOZ_APP_NAME', 'MOZ_APP_BASENAME', 'MOZ_APP_DISPLAYNAME', DEFINES['NS_NO_XPCOM'] = True -if CONFIG['MOZ_MAINTENANCE_SERVICE']: - DEFINES['MOZ_MAINTENANCE_SERVICE'] = CONFIG['MOZ_MAINTENANCE_SERVICE'] - # For debugging purposes only #DEFINES['DISABLE_UPDATER_AUTHENTICODE_CHECK'] = True diff --git a/toolkit/mozapps/update/updater/updater.cpp b/toolkit/mozapps/update/updater/updater.cpp index dbf50329c..c0b01bfbc 100644 --- a/toolkit/mozapps/update/updater/updater.cpp +++ b/toolkit/mozapps/update/updater/updater.cpp @@ -119,9 +119,6 @@ struct UpdateServerThreadArgs #endif #ifdef XP_WIN -#ifdef MOZ_MAINTENANCE_SERVICE -#include "registrycertificates.h" -#endif BOOL PathAppendSafe(LPWSTR base, LPCWSTR extra); BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath, @@ -290,7 +287,6 @@ static ArchiveReader gArchiveReader; static bool gSucceeded = false; static bool sStagedUpdate = false; static bool sReplaceRequest = false; -static bool sUsingService = false; static bool sIsOSUpdate = false; #ifdef XP_WIN @@ -1954,8 +1950,7 @@ PatchIfFile::Finish(int status) /** * Launch the post update application (helper.exe). It takes in the path of the - * callback application to calculate the path of helper.exe. For service updates - * this is called from both the system account and the current user account. + * callback application to calculate the path of helper.exe. * * @param installationDir The path to the callback application binary. * @param updateInfoDir The directory where update info is stored. @@ -2024,13 +2019,6 @@ LaunchWinPostProcess(const WCHAR *installationDir, return false; } -#if !defined(TEST_UPDATER) && defined(MOZ_MAINTENANCE_SERVICE) - if (sUsingService && - !DoesBinaryMatchAllowedCertificates(installationDir, exefullpath)) { - return false; - } -#endif - WCHAR dlogFile[MAX_PATH + 1]; if (!PathGetSiblingFilePath(dlogFile, exefullpath, L"uninstall.update")) { return false; @@ -2054,12 +2042,6 @@ LaunchWinPostProcess(const WCHAR *installationDir, wcsncpy(cmdline, dummyArg, len); wcscat(cmdline, exearg); - if (sUsingService || - !_wcsnicmp(exeasync, L"false", 6) || - !_wcsnicmp(exeasync, L"0", 2)) { - async = false; - } - // We want to launch the post update helper app to update the Windows // registry even if there is a failure with removing the uninstall.update // file or copying the update.log file. @@ -2095,8 +2077,7 @@ LaunchWinPostProcess(const WCHAR *installationDir, static void LaunchCallbackApp(const NS_tchar *workingDir, int argc, - NS_tchar **argv, - bool usingService) + NS_tchar **argv) { putenv(const_cast<char*>("NO_EM_RESTART=")); putenv(const_cast<char*>("MOZ_LAUNCHED_CHILD=1")); @@ -2113,11 +2094,7 @@ LaunchCallbackApp(const NS_tchar *workingDir, #elif defined(XP_MACOSX) LaunchChild(argc, (const char**)argv); #elif defined(XP_WIN) - // Do not allow the callback to run when running an update through the - // service as session 0. The unelevated updater.exe will do the launching. - if (!usingService) { - WinLaunchChild(argv[0], argc, argv, nullptr); - } + WinLaunchChild(argv[0], argc, argv, nullptr); #else # warning "Need implementaton of LaunchCallbackApp" #endif @@ -2188,40 +2165,6 @@ WriteStatusFile(int status) WriteStatusFile(text); } -#ifdef MOZ_MAINTENANCE_SERVICE -/* - * Read the update.status file and sets isPendingService to true if - * the status is set to pending-service. - * - * @param isPendingService Out parameter for specifying if the status - * is set to pending-service or not. - * @return true if the information was retrieved and it is pending - * or pending-service. -*/ -static bool -IsUpdateStatusPendingService() -{ - NS_tchar filename[MAXPATHLEN]; - NS_tsnprintf(filename, sizeof(filename)/sizeof(filename[0]), - NS_T("%s/update.status"), gPatchDirPath); - - AutoFile file(NS_tfopen(filename, NS_T("rb"))); - if (file == nullptr) - return false; - - char buf[32] = { 0 }; - fread(buf, sizeof(buf), 1, file); - - const char kPendingService[] = "pending-service"; - const char kAppliedService[] = "applied-service"; - - return (strncmp(buf, kPendingService, - sizeof(kPendingService) - 1) == 0) || - (strncmp(buf, kAppliedService, - sizeof(kAppliedService) - 1) == 0); -} -#endif - #ifdef XP_WIN /* * Read the update.status file and sets isSuccess to true if @@ -2601,7 +2544,7 @@ UpdateThreadFunc(void *param) // updater application again in order to apply the update without // staging. if (sReplaceRequest) { - WriteStatusFile(sUsingService ? "pending-service" : "pending"); + WriteStatusFile("pending"); } else { WriteStatusFile(rv); } @@ -2668,17 +2611,6 @@ int LaunchCallbackAndPostProcessApps(int argc, NS_tchar** argv, if (!LaunchWinPostProcess(gInstallDirPath, gPatchDirPath)) { fprintf(stderr, "The post update process was not launched"); } - - // The service update will only be executed if it is already installed. - // For first time installs of the service, the install will happen from - // the PostUpdate process. We do the service update process here - // because it's possible we are updating with updater.exe without the - // service if the service failed to apply the update. We want to update - // the service to a newer version in that case. If we are not running - // through the service, then MOZ_USING_SERVICE will not exist. - if (!sUsingService) { - StartServiceUpdate(gInstallDirPath); - } } EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 0); #elif XP_MACOSX @@ -2690,8 +2622,7 @@ int LaunchCallbackAndPostProcessApps(int argc, NS_tchar** argv, LaunchCallbackApp(argv[5], argc - callbackIndex, - argv + callbackIndex, - sUsingService); + argv + callbackIndex); #ifdef XP_MACOSX } // if (!isElevated) #endif /* XP_MACOSX */ @@ -2765,8 +2696,6 @@ int NS_main(int argc, NS_tchar **argv) return 1; } - // This check is also performed in workmonitor.cpp since the maintenance - // service can be called directly. if (!IsValidFullPath(argv[1])) { // Since the status file is written to the patch directory and the patch // directory is invalid don't write the status file. @@ -2783,8 +2712,6 @@ int NS_main(int argc, NS_tchar **argv) // The directory containing the update information. NS_tstrncpy(gPatchDirPath, argv[1], MAXPATHLEN); - // This check is also performed in workmonitor.cpp since the maintenance - // service can be called directly. if (!IsValidFullPath(argv[2])) { WriteStatusFile(INVALID_INSTALL_DIR_PATH_ERROR); fprintf(stderr, "The install directory path is not valid for this " \ @@ -2809,23 +2736,7 @@ int NS_main(int argc, NS_tchar **argv) } #ifdef XP_WIN - bool useService = false; bool testOnlyFallbackKeyExists = false; - bool noServiceFallback = false; - - // We never want the service to be used unless we build with - // the maintenance service. -#ifdef MOZ_MAINTENANCE_SERVICE - useService = IsUpdateStatusPendingService(); -#ifdef TEST_UPDATER - noServiceFallback = EnvHasValue("MOZ_NO_SERVICE_FALLBACK"); - putenv(const_cast<char*>("MOZ_NO_SERVICE_FALLBACK=")); - // Our tests run with a different apply directory for each test. - // We use this registry key on our test slaves to store the - // allowed name/issuers. - testOnlyFallbackKeyExists = DoesFallbackKeyExist(); -#endif -#endif // Remove everything except close window from the context menu { @@ -2869,8 +2780,6 @@ int NS_main(int argc, NS_tchar **argv) } } - // This check is also performed in workmonitor.cpp since the maintenance - // service can be called directly. if (!IsValidFullPath(argv[3])) { WriteStatusFile(INVALID_WORKING_DIR_PATH_ERROR); fprintf(stderr, "The working directory path is not valid for this " \ @@ -2894,8 +2803,6 @@ int NS_main(int argc, NS_tchar **argv) *slash = NS_T('\0'); } - // These checks are also performed in workmonitor.cpp since the maintenance - // service can be called directly. if (argc > callbackIndex) { if (!IsValidFullPath(argv[callbackIndex])) { WriteStatusFile(INVALID_CALLBACK_PATH_ERROR); @@ -2977,8 +2884,6 @@ int NS_main(int argc, NS_tchar **argv) LOG(("WORKING DIRECTORY " LOG_S, gWorkingDirPath)); #if defined(XP_WIN) - // These checks are also performed in workmonitor.cpp since the maintenance - // service can be called directly. if (_wcsnicmp(gWorkingDirPath, gInstallDirPath, MAX_PATH) != 0) { if (!sStagedUpdate && !sReplaceRequest) { WriteStatusFile(INVALID_APPLYTO_DIR_ERROR); @@ -3030,23 +2935,11 @@ int NS_main(int argc, NS_tchar **argv) #endif #ifdef XP_WIN -#ifdef MOZ_MAINTENANCE_SERVICE - sUsingService = EnvHasValue("MOZ_USING_SERVICE"); - putenv(const_cast<char*>("MOZ_USING_SERVICE=")); -#endif - // lastFallbackError keeps track of the last error for the service not being - // used, in case of an error when fallback is not enabled we write the - // error to the update.status file. - // When fallback is disabled (MOZ_NO_SERVICE_FALLBACK does not exist) then - // we will instead fallback to not using the service and display a UAC prompt. - int lastFallbackError = FALLBACKKEY_UNKNOWN_ERROR; - // Launch a second instance of the updater with the runas verb on Windows // when write access is denied to the installation directory. HANDLE updateLockFileHandle = INVALID_HANDLE_VALUE; NS_tchar elevatedLockFilePath[MAXPATHLEN] = {NS_T('\0')}; - if (!sUsingService && - (argc > callbackIndex || sStagedUpdate || sReplaceRequest)) { + if (argc > callbackIndex || sStagedUpdate || sReplaceRequest) { NS_tchar updateLockFilePath[MAXPATHLEN]; if (sStagedUpdate) { // When staging an update, the lock file is: @@ -3104,8 +2997,7 @@ int NS_main(int argc, NS_tchar **argv) bool startedFromUnelevatedUpdater = GetFileAttributesW(elevatedLockFilePath) != INVALID_FILE_ATTRIBUTES; - // If we're running from the service, then we were started with the same - // token as the service so the permissions are already dropped. If we're + // If we're // running from an elevated updater that was started from an unelevated // updater, then we drop the permissions here. We do not drop the // permissions on the originally called updater because we use its token @@ -3116,8 +3008,7 @@ int NS_main(int argc, NS_tchar **argv) UACHelper::DisablePrivileges(nullptr); } - if (updateLockFileHandle == INVALID_HANDLE_VALUE || - (useService && testOnlyFallbackKeyExists && noServiceFallback)) { + if (updateLockFileHandle == INVALID_HANDLE_VALUE) { if (!_waccess(elevatedLockFilePath, F_OK) && NS_tremove(elevatedLockFilePath) != 0) { fprintf(stderr, "Unable to create elevated lock file! Exiting\n"); @@ -3144,105 +3035,11 @@ int NS_main(int argc, NS_tchar **argv) return 1; } - // Make sure the path to the updater to use for the update is on local. - // We do this check to make sure that file locking is available for - // race condition security checks. - if (useService) { - BOOL isLocal = FALSE; - useService = IsLocalFile(argv[0], isLocal) && isLocal; - } - - // If we have unprompted elevation we should NOT use the service - // for the update. Service updates happen with the SYSTEM account - // which has more privs than we need to update with. - // Windows 8 provides a user interface so users can configure this - // behavior and it can be configured in the registry in all Windows - // versions that support UAC. - if (useService) { - BOOL unpromptedElevation; - if (IsUnpromptedElevation(unpromptedElevation)) { - useService = !unpromptedElevation; - } - } - - // Make sure the service registry entries for the instsallation path - // are available. If not don't use the service. - if (useService) { - WCHAR maintenanceServiceKey[MAX_PATH + 1]; - if (CalculateRegistryPathFromFilePath(gInstallDirPath, - maintenanceServiceKey)) { - HKEY baseKey = nullptr; - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, - maintenanceServiceKey, 0, - KEY_READ | KEY_WOW64_64KEY, - &baseKey) == ERROR_SUCCESS) { - RegCloseKey(baseKey); - } else { -#ifdef TEST_UPDATER - useService = testOnlyFallbackKeyExists; -#endif - if (!useService) { - lastFallbackError = FALLBACKKEY_NOKEY_ERROR; - } - } - } else { - useService = false; - lastFallbackError = FALLBACKKEY_REGPATH_ERROR; - } - } - - // Originally we used to write "pending" to update.status before - // launching the service command. This is no longer needed now - // since the service command is launched from updater.exe. If anything - // fails in between, we can fall back to using the normal update process - // on our own. - - // If we still want to use the service try to launch the service - // comamnd for the update. - if (useService) { - // If the update couldn't be started, then set useService to false so - // we do the update the old way. - DWORD ret = LaunchServiceSoftwareUpdateCommand(argc, (LPCWSTR *)argv); - useService = (ret == ERROR_SUCCESS); - // If the command was launched then wait for the service to be done. - if (useService) { - bool showProgressUI = false; - // Never show the progress UI when staging updates. - if (!sStagedUpdate) { - // We need to call this separately instead of allowing ShowProgressUI - // to initialize the strings because the service will move the - // ini file out of the way when running updater. - showProgressUI = !InitProgressUIStrings(); - } - // Wait for the service to stop for 5 seconds. If the service - // has still not stopped then show an indeterminate progress bar. - DWORD lastState = WaitForServiceStop(SVC_NAME, 5); - if (lastState != SERVICE_STOPPED) { - Thread t1; - if (t1.Run(WaitForServiceFinishThread, nullptr) == 0 && - showProgressUI) { - ShowProgressUI(true, false); - } - t1.Join(); - } - - lastState = WaitForServiceStop(SVC_NAME, 1); - if (lastState != SERVICE_STOPPED) { - // If the service doesn't stop after 10 minutes there is - // something seriously wrong. - lastFallbackError = FALLBACKKEY_SERVICE_NO_STOP_ERROR; - useService = false; - } - } else { - lastFallbackError = FALLBACKKEY_LAUNCH_ERROR; - } - } - - // If the service can't be used when staging an update, make sure that + // When staging an update, make sure that // the UAC prompt is not shown! In this case, just set the status to // pending and the update will be applied during the next startup. - if (!useService && sStagedUpdate) { + if (sStagedUpdate) { if (updateLockFileHandle != INVALID_HANDLE_VALUE) { CloseHandle(updateLockFileHandle); } @@ -3250,32 +3047,10 @@ int NS_main(int argc, NS_tchar **argv) return 0; } - // If we started the service command, and it finished, check the - // update.status file to make sure it succeeded, and if it did - // we need to manually start the PostUpdate process from the - // current user's session of this unelevated updater.exe the - // current process is running as. - // Note that we don't need to do this if we're just staging the update, - // as the PostUpdate step runs when performing the replacing in that case. - if (useService && !sStagedUpdate) { - bool updateStatusSucceeded = false; - if (IsUpdateStatusSucceeded(updateStatusSucceeded) && - updateStatusSucceeded) { - if (!LaunchWinPostProcess(gInstallDirPath, gPatchDirPath)) { - fprintf(stderr, "The post update process which runs as the user" - " for service update could not be launched."); - } - } - } - - // If we didn't want to use the service at all, or if an update was - // already happening, or launching the service command failed, then - // launch the elevated updater.exe as we do without the service. + // If an update was already happening, launch the elevated updater.exe. // We don't launch the elevated updater in the case that we did have - // write access all along because in that case the only reason we're - // using the service is because we are testing. - if (!useService && !noServiceFallback && - updateLockFileHandle == INVALID_HANDLE_VALUE) { + // write access all along because in that case we are testing. + if (updateLockFileHandle == INVALID_HANDLE_VALUE) { SHELLEXECUTEINFO sinfo; memset(&sinfo, 0, sizeof(SHELLEXECUTEINFO)); sinfo.cbSize = sizeof(SHELLEXECUTEINFO); @@ -3301,32 +3076,21 @@ int NS_main(int argc, NS_tchar **argv) if (argc > callbackIndex) { LaunchCallbackApp(argv[5], argc - callbackIndex, - argv + callbackIndex, sUsingService); + argv + callbackIndex); } CloseHandle(elevatedFileHandle); - if (!useService && !noServiceFallback && - INVALID_HANDLE_VALUE == updateLockFileHandle) { - // We didn't use the service and we did run the elevated updater.exe. + if (INVALID_HANDLE_VALUE == updateLockFileHandle) { + // We ran the elevated updater.exe. // The elevated updater.exe is responsible for writing out the // update.status file. return 0; - } else if (useService) { - // The service command was launched. The service is responsible for - // writing out the update.status file. - if (updateLockFileHandle != INVALID_HANDLE_VALUE) { - CloseHandle(updateLockFileHandle); - } - return 0; } else { - // Otherwise the service command was not launched at all. // We are only reaching this code path because we had write access // all along to the directory and a fallback key existed, and we - // have fallback disabled (MOZ_NO_SERVICE_FALLBACK env var exists). - // We only currently use this env var from XPCShell tests. + // have fallback disabled. CloseHandle(updateLockFileHandle); - WriteStatusFile(lastFallbackError); return 0; } } @@ -3386,7 +3150,7 @@ int NS_main(int argc, NS_tchar **argv) EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1); if (argc > callbackIndex) { LaunchCallbackApp(argv[5], argc - callbackIndex, - argv + callbackIndex, sUsingService); + argv + callbackIndex); } return 1; } @@ -3440,8 +3204,7 @@ int NS_main(int argc, NS_tchar **argv) if (argc > callbackIndex) { LaunchCallbackApp(argv[5], argc - callbackIndex, - argv + callbackIndex, - sUsingService); + argv + callbackIndex); } return 1; } @@ -3504,8 +3267,7 @@ int NS_main(int argc, NS_tchar **argv) EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1); LaunchCallbackApp(argv[callbackIndex], argc - callbackIndex, - argv + callbackIndex, - sUsingService); + argv + callbackIndex); return 1; } @@ -3553,8 +3315,7 @@ int NS_main(int argc, NS_tchar **argv) EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1); LaunchCallbackApp(argv[5], argc - callbackIndex, - argv + callbackIndex, - sUsingService); + argv + callbackIndex); return 1; } LOG(("NS_main: callback app file in use, continuing without " \ |