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:
Родитель
ddfe3a1457
Коммит
a342419c38
|
@ -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__
|
||||
|
|
Загрузка…
Ссылка в новой задаче