Bug 313057: Automatic updater downgrades/overwrites browser version when an older/identical version is in the queue. r=bsmedberg, a1.9.1b2=beltzner

This commit is contained in:
Robert Strong 2008-11-14 12:11:08 +00:00
Родитель ddfe3a1457
Коммит a342419c38
4 изменённых файлов: 88 добавлений и 7 удалений

Просмотреть файл

@ -84,6 +84,7 @@ const KEY_UAPPDATA = "UAppData";
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_LOG = "update.log"
const FILE_UPDATES_DB = "updates.xml";
@ -398,6 +399,28 @@ function writeStatusFile(dir, state) {
writeStringToFile(statusFile, state);
}
/**
# Writes the update's application version to a file in the patch directory. If
# the update doesn't provide application version information via the
# extensionVersion attribute the string "null" will be written to the file.
# This value is compared during startup (in nsUpdateDriver.cpp) to determine if
# the update should be applied. Note that this won't provide protection from
# downgrade of the application for the nightly user case where the application
# version doesn't change.
# @param dir
# The patch directory where the update.version file should be
# written.
# @param version
# The version value to write. Will be the string "null" when the
# update doesn't provide the extensionVersion attribute in the update
# xml.
*/
function writeVersionFile(dir, version) {
var versionFile = dir.clone();
versionFile.append(FILE_UPDATE_VERSION);
writeStringToFile(versionFile, version);
}
/**
* Removes the Updates Directory
* @param key
@ -1228,6 +1251,7 @@ UpdateService.prototype = {
if (update.errorCode == WRITE_ERROR) {
prompter.showUpdateError(update);
writeStatusFile(getUpdatesDir(), update.state = STATE_PENDING);
writeVersionFile(getUpdatesDir(), update.extensionVersion);
return;
}
}
@ -2410,6 +2434,7 @@ Downloader.prototype = {
// This is a pretty fatal error. Just bail.
LOG("Downloader", "_selectPatch - failed to apply complete patch!");
writeStatusFile(updateDir, STATE_NONE);
writeVersionFile(getUpdatesDir(), null);
return null;
}
}
@ -2635,6 +2660,7 @@ Downloader.prototype = {
// Tell the updater.exe we're ready to apply.
writeStatusFile(getUpdatesDir(), state);
writeVersionFile(getUpdatesDir(), this._update.extensionVersion);
this._update.installDate = (new Date()).getTime();
this._update.statusText = updateStrings.GetStringFromName("installPending");
}

Просмотреть файл

@ -2976,7 +2976,8 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
dirProvider.GetAppDir(),
updRoot,
gRestartArgc,
gRestartArgv);
gRestartArgv,
appData.version);
#endif
nsCOMPtr<nsIProfileLock> profileLock;

Просмотреть файл

@ -22,6 +22,7 @@
* Contributor(s):
* Darin Fisher <darin@meer.net>
* Ben Turner <mozilla@songbirdnest.com>
* Robert Strong <robert.bugzilla@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -51,6 +52,7 @@
#include "nsPrintfCString.h"
#include "prproces.h"
#include "prlog.h"
#include "nsVersionComparator.h"
#ifdef XP_MACOSX
#include "nsILocalFileMac.h"
@ -222,16 +224,16 @@ GetFile(nsIFile *dir, const nsCSubstring &name, nsCOMPtr<nsILocalFile> &result)
{
nsresult rv;
nsCOMPtr<nsIFile> statusFile;
rv = dir->Clone(getter_AddRefs(statusFile));
nsCOMPtr<nsIFile> file;
rv = dir->Clone(getter_AddRefs(file));
if (NS_FAILED(rv))
return PR_FALSE;
rv = statusFile->AppendNative(name);
rv = file->AppendNative(name);
if (NS_FAILED(rv))
return PR_FALSE;
result = do_QueryInterface(statusFile, &rv);
result = do_QueryInterface(file, &rv);
return NS_SUCCEEDED(rv);
}
@ -274,6 +276,42 @@ SetStatus(nsILocalFile *statusFile, const char *status)
return PR_TRUE;
}
static PRBool
GetVersionFile(nsIFile *dir, nsCOMPtr<nsILocalFile> &result)
{
return GetFile(dir, NS_LITERAL_CSTRING("update.version"), result);
}
// Compares the current application version with the update's application
// version.
static PRBool
IsOlderVersion(nsILocalFile *versionFile, const char *&appVersion)
{
nsresult rv;
FILE *fp;
rv = versionFile->OpenANSIFileDesc("r", &fp);
if (NS_FAILED(rv))
return PR_TRUE;
char buf[32];
char *result = fgets(buf, sizeof(buf), fp);
fclose(fp);
if (!result)
return PR_TRUE;
// If the update xml doesn't provide the application version the file will
// contain the string "null" and it is assumed that the update is not older.
const char kNull[] = "null";
if (strncmp(buf, kNull, sizeof(kNull) - 1) == 0)
return PR_FALSE;
if (NS_CompareVersions(appVersion, result) > 0)
return PR_TRUE;
return PR_FALSE;
}
static PRBool
CopyFileIntoUpdateDir(nsIFile *parentDir, const char *leafName, nsIFile *updateDir)
{
@ -505,7 +543,7 @@ end:
nsresult
ProcessUpdates(nsIFile *greDir, nsIFile *appDir, nsIFile *updRootDir,
int argc, char **argv)
int argc, char **argv, const char *&appVersion)
{
nsresult rv;
@ -533,6 +571,16 @@ ProcessUpdates(nsIFile *greDir, nsIFile *appDir, nsIFile *updRootDir,
for (int i = 0; i < dirEntries.Count(); ++i) {
nsCOMPtr<nsILocalFile> statusFile;
if (GetStatusFile(dirEntries[i], statusFile) && IsPending(statusFile)) {
nsCOMPtr<nsILocalFile> versionFile;
// Remove the update if the update application version file doesn't exist
// or if the update's application version is less than the current
// application version.
if (!GetVersionFile(dirEntries[i], versionFile) ||
IsOlderVersion(versionFile, appVersion)) {
dirEntries[i]->Remove(PR_TRUE);
continue;
}
ApplyUpdate(greDir, dirEntries[i], statusFile, appDir, argc, argv);
break;
}

Просмотреть файл

@ -22,6 +22,7 @@
* Contributor(s):
* Darin Fisher <darin@meer.net>
* Ben Turner <mozilla@songbirdnest.com>
* Robert Strong <robert.bugzilla@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -55,10 +56,15 @@ class nsIFile;
* The argc and argv passed to this function should be what is needed to
* relaunch the current process.
*
* The appVersion param passed to this function is the current application's
* version and is used to determine if an update's version is older than the
* current application version.
*
* This function does not modify appDir.
*/
NS_HIDDEN_(nsresult) ProcessUpdates(nsIFile *greDir, nsIFile *appDir,
nsIFile *updRootDir,
int argc, char **argv);
int argc, char **argv,
const char *&appVersion);
#endif // nsUpdateDriver_h__