Bug 1168743 - client changes - Only use env vars in the test updater and general app update cleanup. r=mhowell

This commit is contained in:
Robert Strong 2016-06-11 08:31:10 -07:00
parent 561d8d2f2d
commit 61a8d4f0c1
6 changed files with 185 additions and 179 deletions

View File

@ -7,6 +7,7 @@ DWORD LaunchServiceSoftwareUpdateCommand(int argc, LPCWSTR *argv);
BOOL WriteStatusFailure(LPCWSTR updateDirPath, int errorCode);
DWORD WaitForServiceStop(LPCWSTR serviceName, DWORD maxWaitSeconds);
DWORD WaitForProcessExit(LPCWSTR filename, DWORD maxSeconds);
DWORD IsProcessRunning(LPCWSTR filename);
BOOL DoesFallbackKeyExist();
BOOL IsLocalFile(LPCWSTR file, BOOL &isLocal);
DWORD StartServiceCommand(int argc, LPCWSTR* argv);

View File

@ -19,59 +19,82 @@ UpdateLog::UpdateLog() : logFP(nullptr)
}
void UpdateLog::Init(NS_tchar* sourcePath,
const NS_tchar* fileName,
const NS_tchar* alternateFileName,
bool append)
const NS_tchar* fileName)
{
if (logFP)
if (logFP) {
return;
}
#ifdef XP_WIN
GetTempFileNameW(sourcePath, L"log", 0, mTmpFilePath);
int dstFilePathLen = NS_tsnprintf(mDstFilePath,
sizeof(mDstFilePath)/sizeof(mDstFilePath[0]),
NS_T("%s/%s"), sourcePath, append ? alternateFileName : fileName);
NS_T("%s/%s"), sourcePath, fileName);
// If the destination path was over the length limit,
// disable logging by skipping opening the file and setting logFP.
if ((dstFilePathLen > 0) &&
(dstFilePathLen <
static_cast<int>(sizeof(mDstFilePath)/sizeof(mDstFilePath[0])))) {
if (append) {
MoveFileExW(mDstFilePath, mTmpFilePath, MOVEFILE_REPLACE_EXISTING);
}
logFP = NS_tfopen(mTmpFilePath, append ? NS_T("a") : NS_T("w"));
#ifdef XP_WIN
GetTempFileNameW(sourcePath, L"log", 0, mTmpFilePath);
logFP = NS_tfopen(mTmpFilePath, NS_T("w"));
// Delete this file now so it is possible to tell from the unelevated
// updater process if the elevated updater process has written the log.
DeleteFileW(mDstFilePath);
}
#elif XP_MACOSX
logFP = NS_tfopen(mDstFilePath, NS_T("w"));
#else
int dstFilePathLen = 0;
if (alternateFileName && NS_taccess(mDstFilePath, F_OK)) {
dstFilePathLen = NS_tsnprintf(mDstFilePath,
sizeof(mDstFilePath)/sizeof(mDstFilePath[0]),
NS_T("%s/%s"), sourcePath, alternateFileName);
} else {
dstFilePathLen = NS_tsnprintf(mDstFilePath,
sizeof(mDstFilePath)/sizeof(mDstFilePath[0]),
NS_T("%s/%s"), sourcePath, fileName);
}
// If the destination path was over the length limit,
// disable logging by skipping opening the file and setting logFP.
if ((dstFilePathLen > 0) &&
(dstFilePathLen <
static_cast<int>(sizeof(mDstFilePath)/sizeof(mDstFilePath[0])))) {
logFP = NS_tfopen(mDstFilePath, append ? NS_T("a") : NS_T("w"));
}
// On platforms that have an updates directory in the installation directory
// (e.g. platforms other than Windows and Mac) the update log is written to
// a temporary file and then to the update log file. This is needed since
// the installation directory is moved during a replace request. This can be
// removed when the platform's updates directory is located outside of the
// installation directory.
logFP = tmpfile();
#endif
}
}
void UpdateLog::Finish()
{
if (!logFP)
if (!logFP) {
return;
}
#if !defined(XP_WIN) && !defined(XP_MACOSX)
const int blockSize = 1024;
char buffer[blockSize];
fflush(logFP);
rewind(logFP);
FILE *updateLogFP = NS_tfopen(mDstFilePath, NS_T("wb+"));
while (!feof(logFP)) {
size_t read = fread(buffer, 1, blockSize, logFP);
if (ferror(logFP)) {
fclose(logFP);
logFP = nullptr;
fclose(updateLogFP);
updateLogFP = nullptr;
return;
}
size_t written = 0;
while (written < read) {
size_t chunkWritten = fwrite(buffer, 1, read - written, updateLogFP);
if (chunkWritten <= 0) {
fclose(logFP);
logFP = nullptr;
fclose(updateLogFP);
updateLogFP = nullptr;
return;
}
written += chunkWritten;
}
}
fclose(updateLogFP);
updateLogFP = nullptr;
#endif
fclose(logFP);
logFP = nullptr;
@ -89,16 +112,18 @@ void UpdateLog::Finish()
void UpdateLog::Flush()
{
if (!logFP)
if (!logFP) {
return;
}
fflush(logFP);
}
void UpdateLog::Printf(const char *fmt, ... )
{
if (!logFP)
if (!logFP) {
return;
}
va_list ap;
va_start(ap, fmt);
@ -109,8 +134,9 @@ void UpdateLog::Printf(const char *fmt, ... )
void UpdateLog::WarnPrintf(const char *fmt, ... )
{
if (!logFP)
if (!logFP) {
return;
}
va_list ap;
va_start(ap, fmt);

View File

@ -17,8 +17,7 @@ public:
return primaryLog;
}
void Init(NS_tchar* sourcePath, const NS_tchar* fileName,
const NS_tchar* alternateFileName, bool append);
void Init(NS_tchar* sourcePath, const NS_tchar* fileName);
void Finish();
void Flush();
void Printf(const char *fmt, ... );
@ -39,9 +38,7 @@ protected:
#define LOG_WARN(args) UpdateLog::GetPrimaryLog().WarnPrintf args
#define LOG(args) UpdateLog::GetPrimaryLog().Printf args
#define LogInit(PATHNAME_, FILENAME_) \
UpdateLog::GetPrimaryLog().Init(PATHNAME_, FILENAME_, 0, false)
#define LogInitAppend(PATHNAME_, FILENAME_, ALTERNATE_) \
UpdateLog::GetPrimaryLog().Init(PATHNAME_, FILENAME_, ALTERNATE_, true)
UpdateLog::GetPrimaryLog().Init(PATHNAME_, FILENAME_)
#define LogFinish() UpdateLog::GetPrimaryLog().Finish()
#define LogFlush() UpdateLog::GetPrimaryLog().Flush()

View File

@ -20,13 +20,13 @@ const UPDATESERVICE_CONTRACTID = "@mozilla.org/updates/update-service;1";
const PREF_APP_UPDATE_ALTWINDOWTYPE = "app.update.altwindowtype";
const PREF_APP_UPDATE_AUTO = "app.update.auto";
const PREF_APP_UPDATE_BACKGROUND_INTERVAL = "app.update.download.backgroundInterval";
const PREF_APP_UPDATE_BACKGROUNDINTERVAL = "app.update.download.backgroundInterval";
const PREF_APP_UPDATE_BACKGROUNDERRORS = "app.update.backgroundErrors";
const PREF_APP_UPDATE_BACKGROUNDMAXERRORS = "app.update.backgroundMaxErrors";
const PREF_APP_UPDATE_CANCELATIONS = "app.update.cancelations";
const PREF_APP_UPDATE_CANCELATIONS_OSX = "app.update.cancelations.osx";
const PREF_APP_UPDATE_CERTS_BRANCH = "app.update.certs.";
const PREF_APP_UPDATE_CERT_CHECKATTRS = "app.update.cert.checkAttributes";
const PREF_APP_UPDATE_CANCELATIONS_OSX_MAX = "app.update.cancelations.osx.max";
const PREF_APP_UPDATE_CERT_CHECKATTRIBUTES = "app.update.cert.checkAttributes";
const PREF_APP_UPDATE_CERT_ERRORS = "app.update.cert.errors";
const PREF_APP_UPDATE_CERT_MAXERRORS = "app.update.cert.maxErrors";
const PREF_APP_UPDATE_CERT_REQUIREBUILTIN = "app.update.cert.requireBuiltIn";
@ -36,27 +36,28 @@ const PREF_APP_UPDATE_ENABLED = "app.update.enabled";
const PREF_APP_UPDATE_IDLETIME = "app.update.idletime";
const PREF_APP_UPDATE_INTERVAL = "app.update.interval";
const PREF_APP_UPDATE_LOG = "app.update.log";
const PREF_APP_UPDATE_MAX_OSX_CANCELATIONS = "app.update.cancelations.osx.max";
const PREF_APP_UPDATE_NEVER_BRANCH = "app.update.never.";
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 PREF_APP_UPDATE_SERVICE_ENABLED = "app.update.service.enabled";
const PREF_APP_UPDATE_SERVICE_ERRORS = "app.update.service.errors";
const PREF_APP_UPDATE_SERVICE_MAX_ERRORS = "app.update.service.maxErrors";
const PREF_APP_UPDATE_SOCKET_ERRORS = "app.update.socket.maxErrors";
const PREF_APP_UPDATE_RETRY_TIMEOUT = "app.update.socket.retryTimeout";
const URI_UPDATE_PROMPT_DIALOG = "chrome://mozapps/content/update/updates.xul";
const URI_UPDATE_HISTORY_DIALOG = "chrome://mozapps/content/update/history.xul";
const PREFBRANCH_APP_UPDATE_CERTS = "app.update.certs.";
const PREFBRANCH_APP_UPDATE_NEVER = "app.update.never.";
const URI_BRAND_PROPERTIES = "chrome://branding/locale/brand.properties";
const URI_UPDATES_PROPERTIES = "chrome://mozapps/locale/update/updates.properties";
const URI_UPDATE_HISTORY_DIALOG = "chrome://mozapps/content/update/history.xul";
const URI_UPDATE_NS = "http://www.mozilla.org/2005/app-update";
const URI_UPDATE_PROMPT_DIALOG = "chrome://mozapps/content/update/updates.xul";
const URI_UPDATES_PROPERTIES = "chrome://mozapps/locale/update/updates.properties";
const KEY_GRED = "GreD";
const KEY_UPDROOT = "UpdRootD";
@ -68,16 +69,16 @@ const DIR_UPDATED = "updated";
const DIR_UPDATED_APP = "Updated.app";
const DIR_UPDATES = "updates";
const FILE_UPDATE_STATUS = "update.status";
const FILE_UPDATE_VERSION = "update.version";
const FILE_UPDATE_ARCHIVE = "update.mar";
const FILE_UPDATE_LINK = "update.link";
const FILE_UPDATE_LOG = "update.log";
const FILE_UPDATES_DB = "updates.xml";
const FILE_UPDATE_ACTIVE = "active-update.xml";
const FILE_PERMS_TEST = "update.test";
const FILE_LAST_LOG = "last-update.log";
const FILE_BACKUP_LOG = "backup-update.log";
const FILE_ACTIVE_UPDATE_XML = "active-update.xml";
const FILE_BACKUP_UPDATE_LOG = "backup-update.log";
const FILE_LAST_UPDATE_LOG = "last-update.log";
const FILE_UPDATES_XML = "updates.xml";
const FILE_UPDATE_LINK = "update.link";
const FILE_UPDATE_LOG = "update.log";
const FILE_UPDATE_MAR = "update.mar";
const FILE_UPDATE_STATUS = "update.status";
const FILE_UPDATE_TEST = "update.test";
const FILE_UPDATE_VERSION = "update.version";
const STATE_NONE = "null";
const STATE_DOWNLOADING = "downloading";
@ -185,11 +186,11 @@ const DEFAULT_SERVICE_MAX_ERRORS = 10;
const DEFAULT_SOCKET_MAX_ERRORS = 10;
// The number of milliseconds to wait before retrying a connection error.
const DEFAULT_UPDATE_RETRY_TIMEOUT = 2000;
const DEFAULT_SOCKET_RETRYTIMEOUT = 2000;
// Default maximum number of elevation cancelations per update version before
// giving up.
const DEFAULT_MAX_OSX_CANCELATIONS = 3;
const DEFAULT_CANCELATIONS_OSX_MAX = 3;
// This maps app IDs to their respective notification topic which signals when
// the application's user interface has been displayed.
@ -426,7 +427,7 @@ function getCanApplyUpdates() {
if (!useService && AppConstants.platform != "macosx") {
try {
let updateTestFile = getUpdateFile([FILE_PERMS_TEST]);
let updateTestFile = getUpdateFile([FILE_UPDATE_TEST]);
LOG("getCanApplyUpdates - testing write access " + updateTestFile.path);
testWriteAccess(updateTestFile, false);
if (AppConstants.platform == "win") {
@ -488,7 +489,7 @@ function getCanApplyUpdates() {
if (!userCanElevate) {
// if we're unable to create the test file this will throw an exception.
let appDirTestFile = getAppBaseDir();
appDirTestFile.append(FILE_PERMS_TEST);
appDirTestFile.append(FILE_UPDATE_TEST);
LOG("getCanApplyUpdates - testing write access " + appDirTestFile.path);
if (appDirTestFile.exists()) {
appDirTestFile.remove(false);
@ -525,10 +526,10 @@ XPCOMUtils.defineLazyGetter(this, "gCanStageUpdatesSession",
try {
let updateTestFile;
if (AppConstants.platform == "macosx") {
updateTestFile = getUpdateFile([FILE_PERMS_TEST]);
updateTestFile = getUpdateFile([FILE_UPDATE_TEST]);
} else {
updateTestFile = getInstallDirRoot();
updateTestFile.append(FILE_PERMS_TEST);
updateTestFile.append(FILE_UPDATE_TEST);
}
LOG("gCanStageUpdatesSession - testing write access " +
updateTestFile.path);
@ -538,7 +539,7 @@ XPCOMUtils.defineLazyGetter(this, "gCanStageUpdatesSession",
// well, as we need to be able to move files in that directory during the
// replacing step.
updateTestFile = getInstallDirRoot().parent;
updateTestFile.append(FILE_PERMS_TEST);
updateTestFile.append(FILE_UPDATE_TEST);
LOG("gCanStageUpdatesSession - testing write access " +
updateTestFile.path);
updateTestFile.createUnique(Ci.nsILocalFile.DIRECTORY_TYPE,
@ -769,29 +770,6 @@ function getUpdatesDir() {
return getUpdateDirCreate([DIR_UPDATES, "0"]);
}
/**
* Get the Active Updates directory inside the directory where we apply the
* staged update.
* @return The active updates directory inside the updated directory, as a
* nsIFile object.
*/
function getUpdatesDirInApplyToDir() {
let dir = getAppBaseDir();
if (AppConstants.platform == "macosx") {
dir = dir.parent.parent; // the bundle directory
dir.append(DIR_UPDATED_APP);
dir.append("Contents");
dir.append("MacOS");
} else {
dir.append(DIR_UPDATED);
}
dir.append(DIR_UPDATES);
if (!dir.exists()) {
dir.create(Ci.nsILocalFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
}
return dir;
}
/**
* Reads the update state from the update.status file in the specified
* directory.
@ -1129,28 +1107,23 @@ function cleanUpUpdatesDir(aBackgroundUpdate) {
let file = updateDir.clone();
file.append(FILE_UPDATE_LOG);
if (file.exists()) {
let dir;
if (aBackgroundUpdate && getUpdateDirNoCreate([]).equals(getAppBaseDir())) {
dir = getUpdatesDirInApplyToDir();
} else {
dir = updateDir.parent;
}
let dir = updateDir.parent;
let logFile = dir.clone();
logFile.append(FILE_LAST_LOG);
logFile.append(FILE_LAST_UPDATE_LOG);
if (logFile.exists()) {
try {
logFile.moveTo(dir, FILE_BACKUP_LOG);
logFile.moveTo(dir, FILE_BACKUP_UPDATE_LOG);
} catch (e) {
LOG("cleanUpUpdatesDir - failed to rename file " + logFile.path +
" to " + FILE_BACKUP_LOG);
" to " + FILE_BACKUP_UPDATE_LOG);
}
}
try {
file.moveTo(dir, FILE_LAST_LOG);
file.moveTo(dir, FILE_LAST_UPDATE_LOG);
} catch (e) {
LOG("cleanUpUpdatesDir - failed to rename file " + file.path +
" to " + FILE_LAST_LOG);
" to " + FILE_LAST_UPDATE_LOG);
}
}
@ -1302,9 +1275,9 @@ function handleUpdateFailure(update, errorCode) {
Services.prefs.setIntPref(PREF_APP_UPDATE_CANCELATIONS_OSX,
osxCancelations);
let maxCancels = getPref("getIntPref",
PREF_APP_UPDATE_MAX_OSX_CANCELATIONS,
DEFAULT_MAX_OSX_CANCELATIONS);
if (osxCancelations >= DEFAULT_MAX_OSX_CANCELATIONS) {
PREF_APP_UPDATE_CANCELATIONS_OSX_MAX,
DEFAULT_CANCELATIONS_OSX_MAX);
if (osxCancelations >= DEFAULT_CANCELATIONS_OSX_MAX) {
cleanupActiveUpdate();
} else {
writeStatusFile(getUpdatesDir(),
@ -1336,7 +1309,7 @@ function handleUpdateFailure(update, errorCode) {
var failCount = getPref("getIntPref",
PREF_APP_UPDATE_SERVICE_ERRORS, 0);
var maxFail = getPref("getIntPref",
PREF_APP_UPDATE_SERVICE_MAX_ERRORS,
PREF_APP_UPDATE_SERVICE_MAXERRORS,
DEFAULT_SERVICE_MAX_ERRORS);
// As a safety, when the service reaches maximum failures, it will
@ -2168,10 +2141,6 @@ UpdateService.prototype = {
}
update = new Update(null);
}
let prompter = Cc["@mozilla.org/updates/update-prompt;1"].
createInstance(Ci.nsIUpdatePrompt);
update.state = status;
if (status == STATE_SUCCEEDED) {
@ -2184,6 +2153,8 @@ UpdateService.prototype = {
// Done with this update. Clean it up.
cleanupActiveUpdate();
} else if (status == STATE_PENDING_ELEVATE) {
let prompter = Cc["@mozilla.org/updates/update-prompt;1"].
createInstance(Ci.nsIUpdatePrompt);
prompter.showUpdateElevationRequired();
return;
} else {
@ -2199,13 +2170,15 @@ UpdateService.prototype = {
update.state = ary[0];
if (update.state == STATE_FAILED && ary[1]) {
if (handleUpdateFailure(update, ary[1])) {
cleanUpUpdatesDir(true);
return;
}
}
// Something went wrong with the patch application process.
handleFallbackToCompleteUpdate(update, false);
let prompter = Cc["@mozilla.org/updates/update-prompt;1"].
createInstance(Ci.nsIUpdatePrompt);
prompter.showUpdateError(update);
}
@ -2550,7 +2523,7 @@ UpdateService.prototype = {
// Skip the update if the user responded with "never" to this update's
// application version and the update specifies showNeverForVersion
// (see bug 350636).
let neverPrefName = PREF_APP_UPDATE_NEVER_BRANCH + aUpdate.appVersion;
let neverPrefName = PREFBRANCH_APP_UPDATE_NEVER + aUpdate.appVersion;
if (aUpdate.showNeverForVersion &&
getPref("getBoolPref", neverPrefName, false)) {
LOG("UpdateService:selectUpdate - skipping update because the " +
@ -2603,8 +2576,8 @@ UpdateService.prototype = {
let rejectedVersion = getPref("getCharPref",
PREF_APP_UPDATE_ELEVATE_NEVER, "");
let maxCancels = getPref("getIntPref",
PREF_APP_UPDATE_MAX_OSX_CANCELATIONS,
DEFAULT_MAX_OSX_CANCELATIONS);
PREF_APP_UPDATE_CANCELATIONS_OSX_MAX,
DEFAULT_CANCELATIONS_OSX_MAX);
if (numCancels >= maxCancels) {
LOG("UpdateService:selectUpdate - the user requires elevation to " +
"install this update, but the user has exceeded the max " +
@ -2972,7 +2945,7 @@ UpdateService.prototype = {
function UpdateManager() {
// Ensure the Active Update file is loaded
var updates = this._loadXMLFileIntoArray(getUpdateFile(
[FILE_UPDATE_ACTIVE]));
[FILE_ACTIVE_UPDATE_XML]));
if (updates.length > 0) {
// Under some edgecases such as Windows system restore the active-update.xml
// will contain a pending update without the status file which will return
@ -2980,7 +2953,7 @@ function UpdateManager() {
// rewrite the active-update.xml file without the broken update.
if (readStatusFile(getUpdatesDir()) == STATE_NONE) {
cleanUpUpdatesDir();
this._writeUpdatesToXMLFile([], getUpdateFile([FILE_UPDATE_ACTIVE]));
this._writeUpdatesToXMLFile([], getUpdateFile([FILE_ACTIVE_UPDATE_XML]));
}
else
this._activeUpdate = updates[0];
@ -3011,10 +2984,10 @@ UpdateManager.prototype = {
// Hack to be able to run and cleanup tests by reloading the update data.
if (topic == "um-reload-update-data") {
this._updates = this._loadXMLFileIntoArray(getUpdateFile(
[FILE_UPDATES_DB]));
[FILE_UPDATES_XML]));
this._activeUpdate = null;
var updates = this._loadXMLFileIntoArray(getUpdateFile(
[FILE_UPDATE_ACTIVE]));
[FILE_ACTIVE_UPDATE_XML]));
if (updates.length > 0)
this._activeUpdate = updates[0];
}
@ -3075,9 +3048,9 @@ UpdateManager.prototype = {
_ensureUpdates: function UM__ensureUpdates() {
if (!this._updates) {
this._updates = this._loadXMLFileIntoArray(getUpdateFile(
[FILE_UPDATES_DB]));
[FILE_UPDATES_XML]));
var activeUpdates = this._loadXMLFileIntoArray(getUpdateFile(
[FILE_UPDATE_ACTIVE]));
[FILE_ACTIVE_UPDATE_XML]));
if (activeUpdates.length > 0)
this._activeUpdate = activeUpdates[0];
}
@ -3133,7 +3106,7 @@ UpdateManager.prototype = {
}
else
this._writeUpdatesToXMLFile([this._activeUpdate],
getUpdateFile([FILE_UPDATE_ACTIVE]));
getUpdateFile([FILE_ACTIVE_UPDATE_XML]));
return activeUpdate;
},
@ -3208,7 +3181,7 @@ UpdateManager.prototype = {
*/
saveUpdates: function UM_saveUpdates() {
this._writeUpdatesToXMLFile([this._activeUpdate],
getUpdateFile([FILE_UPDATE_ACTIVE]));
getUpdateFile([FILE_ACTIVE_UPDATE_XML]));
if (this._activeUpdate)
this._addUpdate(this._activeUpdate);
@ -3227,7 +3200,7 @@ UpdateManager.prototype = {
}
this._writeUpdatesToXMLFile(updates.slice(0, 10),
getUpdateFile([FILE_UPDATES_DB]));
getUpdateFile([FILE_UPDATES_XML]));
}
},
@ -3245,6 +3218,10 @@ UpdateManager.prototype = {
var parts = status.split(":");
update.state = parts[0];
// Move the update log to the last update log so it isn't removed when
// falling back to a complete update.
cleanUpUpdatesDir(true);
if (update.state == STATE_FAILED && parts[1]) {
updateSucceeded = false;
if (!handleUpdateFailure(update, parts[1])) {
@ -3261,9 +3238,8 @@ UpdateManager.prototype = {
if (update.state != STATE_PENDING &&
update.state != STATE_PENDING_SERVICE &&
update.state != STATE_PENDING_ELEVATE) {
// Destroy the updates directory, since we're done with it.
// Make sure to not do this when the updater has fallen back to
// non-staged updates.
// If the update has not fallen back to a non staged update destroy the
// updates directory since a new update will be downloaded.
cleanUpUpdatesDir(updateSucceeded);
}
@ -3273,9 +3249,9 @@ UpdateManager.prototype = {
"the update was staged. state: " + update.state + ", status: " + status);
Services.obs.notifyObservers(null, "update-staged", update.state);
// Do this after *everything* else, since it will likely cause the app
// to shut down.
if (AppConstants.platform == "gonk") {
// Do this after everything else, since it will likely cause the app to
// shut down.
if (update.state == STATE_APPLIED) {
// Notify the user that an update has been staged and is ready for
// installation (i.e. that they should restart the application). We do
@ -3517,8 +3493,8 @@ Checker.prototype = {
var prefs = Services.prefs;
var certs = null;
if (!getPref("getCharPref", PREF_APP_UPDATE_URL_OVERRIDE, null) &&
getPref("getBoolPref", PREF_APP_UPDATE_CERT_CHECKATTRS, true)) {
certs = gCertUtils.readCertPrefs(PREF_APP_UPDATE_CERTS_BRANCH);
getPref("getBoolPref", PREF_APP_UPDATE_CERT_CHECKATTRIBUTES, true)) {
certs = gCertUtils.readCertPrefs(PREFBRANCH_APP_UPDATE_CERTS);
}
try {
@ -3887,7 +3863,7 @@ Downloader.prototype = {
updateArchive = getUpdatesDir().clone();
}
updateArchive.append(FILE_UPDATE_ARCHIVE);
updateArchive.append(FILE_UPDATE_MAR);
return updateArchive;
},
@ -3933,7 +3909,7 @@ Downloader.prototype = {
// No link file. We'll just assume that the update.mar is in the
// update directory.
patchFile = updateDir.clone();
patchFile.append(FILE_UPDATE_ARCHIVE);
patchFile.append(FILE_UPDATE_MAR);
}
if (patchFile.exists()) {
LOG("Downloader:downloadUpdate - resuming with patchFile " + patchFile.path);
@ -4015,7 +3991,7 @@ Downloader.prototype = {
LOG("Downloader:downloadUpdate - downloading from " + uri.spec + " to " +
patchFile.path);
var interval = this.background ? getPref("getIntPref",
PREF_APP_UPDATE_BACKGROUND_INTERVAL,
PREF_APP_UPDATE_BACKGROUNDINTERVAL,
DOWNLOAD_BACKGROUND_INTERVAL)
: DOWNLOAD_FOREGROUND_INTERVAL;
this._request.init(uri, patchFile, DOWNLOAD_CHUNK_SIZE, interval);
@ -4181,9 +4157,9 @@ Downloader.prototype = {
var shouldRegisterOnlineObserver = false;
var shouldRetrySoon = false;
var deleteActiveUpdate = false;
var retryTimeout = getPref("getIntPref", PREF_APP_UPDATE_RETRY_TIMEOUT,
DEFAULT_UPDATE_RETRY_TIMEOUT);
var maxFail = getPref("getIntPref", PREF_APP_UPDATE_SOCKET_ERRORS,
var retryTimeout = getPref("getIntPref", PREF_APP_UPDATE_SOCKET_RETRYTIMEOUT,
DEFAULT_SOCKET_RETRYTIMEOUT);
var maxFail = getPref("getIntPref", PREF_APP_UPDATE_SOCKET_MAXERRORS,
DEFAULT_SOCKET_MAX_ERRORS);
LOG("Downloader:onStopRequest - status: " + status + ", " +
"current fail: " + this.updateService._consecutiveSocketErrors + ", " +

View File

@ -2281,6 +2281,22 @@ ProcessReplaceRequest()
return rv;
}
#if !defined(XP_WIN) && !defined(XP_MACOSX)
// Platforms that have their updates directory in the installation directory
// need to have the last-update.log and backup-update.log files moved from the
// old installation directory to the new installation directory.
NS_tchar tmpLog[MAXPATHLEN];
NS_tsnprintf(tmpLog, sizeof(tmpLog)/sizeof(tmpLog[0]),
NS_T("%s/updates/last-update.log"), tmpDir);
if (!NS_taccess(tmpLog, F_OK)) {
NS_tchar destLog[MAXPATHLEN];
NS_tsnprintf(destLog, sizeof(destLog)/sizeof(destLog[0]),
NS_T("%s/updates/last-update.log"), destDir);
NS_tremove(destLog);
NS_trename(tmpLog, destLog);
}
#endif
LOG(("Now, remove the tmpDir"));
rv = ensure_remove_recursive(tmpDir, true);
if (rv) {
@ -2496,7 +2512,19 @@ UpdateThreadFunc(void *param)
}
}
if (sReplaceRequest && rv) {
if (rv && (sReplaceRequest || sStagedUpdate)) {
#ifdef XP_WIN
// On Windows, the current working directory of the process should be changed
// so that it's not locked. The working directory for staging an update was
// already changed earlier.
if (sStagedUpdate) {
NS_tchar sysDir[MAX_PATH + 1] = { L'\0' };
if (GetSystemDirectoryW(sysDir, MAX_PATH + 1)) {
NS_tchdir(sysDir);
}
}
#endif
ensure_remove_recursive(gWorkingDirPath);
// When attempting to replace the application, we should fall back
// to non-staged updates in case of a failure. We do this by
// setting the status to pending, exiting the updater, and
@ -2504,8 +2532,9 @@ UpdateThreadFunc(void *param)
// startup path will see the pending status, and will start the
// updater application again in order to apply the update without
// staging.
ensure_remove_recursive(gWorkingDirPath);
WriteStatusFile(sUsingService ? "pending-service" : "pending");
if (sReplaceRequest) {
WriteStatusFile(sUsingService ? "pending-service" : "pending");
}
#ifdef TEST_UPDATER
// Some tests need to use --test-process-updates again.
putenv(const_cast<char*>("MOZ_TEST_PROCESS_UPDATES="));
@ -2701,17 +2730,20 @@ int NS_main(int argc, NS_tchar **argv)
#ifdef XP_WIN
bool useService = false;
bool testOnlyFallbackKeyExists = false;
bool noServiceFallback = EnvHasValue("MOZ_NO_SERVICE_FALLBACK");
putenv(const_cast<char*>("MOZ_NO_SERVICE_FALLBACK="));
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
@ -2793,26 +2825,7 @@ int NS_main(int argc, NS_tchar **argv)
putenv(const_cast<char*>("MOZ_OS_UPDATE="));
}
if (sReplaceRequest) {
// If we're attempting to replace the application, try to append to the
// log generated when staging the staged update.
#ifdef XP_WIN
NS_tchar* logDir = gPatchDirPath;
#else
#ifdef XP_MACOSX
NS_tchar* logDir = gPatchDirPath;
#else
NS_tchar logDir[MAXPATHLEN];
NS_tsnprintf(logDir, sizeof(logDir)/sizeof(logDir[0]),
NS_T("%s/updated/updates"),
gInstallDirPath);
#endif
#endif
LogInitAppend(logDir, NS_T("last-update.log"), NS_T("update.log"));
} else {
LogInit(gPatchDirPath, NS_T("update.log"));
}
LogInit(gPatchDirPath, NS_T("update.log"));
if (!WriteStatusFile("applying")) {
LOG(("failed setting status to 'applying'"));
@ -2897,8 +2910,9 @@ int NS_main(int argc, NS_tchar **argv)
DWORD waitTime = PARENT_WAIT;
DWORD result = WaitForSingleObject(parent, waitTime);
CloseHandle(parent);
if (result != WAIT_OBJECT_0)
if (result != WAIT_OBJECT_0) {
return 1;
}
}
}
#else
@ -2906,18 +2920,16 @@ int NS_main(int argc, NS_tchar **argv)
waitpid(pid, nullptr, 0);
#endif
if (sReplaceRequest) {
#ifdef XP_WIN
if (sReplaceRequest) {
// On Windows, the current working directory of the process should be changed
// so that it's not locked.
NS_tchar sysDir[MAX_PATH + 1] = { L'\0' };
if (GetSystemDirectoryW(sysDir, MAX_PATH + 1)) {
NS_tchdir(sysDir);
}
#endif
}
#if defined(XP_WIN)
#ifdef MOZ_MAINTENANCE_SERVICE
sUsingService = EnvHasValue("MOZ_USING_SERVICE");
putenv(const_cast<char*>("MOZ_USING_SERVICE="));
@ -3066,7 +3078,9 @@ int NS_main(int argc, NS_tchar **argv)
&baseKey) == ERROR_SUCCESS) {
RegCloseKey(baseKey);
} else {
#ifdef TEST_UPDATER
useService = testOnlyFallbackKeyExists;
#endif
if (!useService) {
lastFallbackError = FALLBACKKEY_NOKEY_ERROR;
}
@ -3231,11 +3245,13 @@ int NS_main(int argc, NS_tchar **argv)
// calling LogFinish() before the GonkAutoMounter destructor has a chance
// to be called
{
#if !defined(TEST_UPDATER)
GonkAutoMounter mounter;
if (mounter.GetAccess() != MountAccess::ReadWrite) {
WriteStatusFile(FILESYSTEM_MOUNT_READWRITE_ERROR);
return 1;
}
#endif
#endif
if (sStagedUpdate) {
@ -3280,8 +3296,9 @@ int NS_main(int argc, NS_tchar **argv)
// Allocate enough space for the length of the path an optional additional
// trailing slash and null termination.
NS_tchar *destpath = (NS_tchar *) malloc((NS_tstrlen(gWorkingDirPath) + 2) * sizeof(NS_tchar));
if (!destpath)
if (!destpath) {
return 1;
}
NS_tchar *c = destpath;
NS_tstrcpy(c, gWorkingDirPath);

View File

@ -1025,17 +1025,6 @@ ProcessUpdates(nsIFile *greDir, nsIFile *appDir, nsIFile *updRootDir,
if (NS_FAILED(rv))
return rv;
ProcessType dummyPID; // this will only be used for MOZ_UPDATE_STAGING
const char *processingUpdates = PR_GetEnv("MOZ_TEST_PROCESS_UPDATES");
if (processingUpdates && *processingUpdates) {
// Enable the tests to request an update to be staged.
const char *stagingUpdate = PR_GetEnv("MOZ_UPDATE_STAGING");
if (stagingUpdate && *stagingUpdate) {
restart = false;
pid = &dummyPID;
}
}
nsCOMPtr<nsIFile> statusFile;
UpdateStatus status = GetUpdateStatus(updatesDir, statusFile);
switch (status) {