mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-10 17:24:29 +00:00
Bug 1168743 - client changes - Only use env vars in the test updater and general app update cleanup. r=mhowell
This commit is contained in:
parent
561d8d2f2d
commit
61a8d4f0c1
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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 + ", " +
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user