diff --git a/mozilla/modules/libpref/macbuild/libpref.xml b/mozilla/modules/libpref/macbuild/libpref.xml
index a83c873806b..c3397385a67 100644
--- a/mozilla/modules/libpref/macbuild/libpref.xml
+++ b/mozilla/modules/libpref/macbuild/libpref.xml
@@ -994,6 +994,13 @@
Text
Debug
+
+ Name
+ nsSafeSaveFile.cpp
+ MacOS
+ Text
+ Debug
+
@@ -1056,6 +1063,11 @@
prefapi.cpp
MacOS
+
+ Name
+ nsSafeSaveFile.cpp
+ MacOS
+
@@ -1999,6 +2011,13 @@
Text
+
+ Name
+ nsSafeSaveFile.cpp
+ MacOS
+ Text
+ Debug
+
@@ -2061,6 +2080,11 @@
prefapi.cpp
MacOS
+
+ Name
+ nsSafeSaveFile.cpp
+ MacOS
+
@@ -2096,6 +2120,12 @@
nsPrefsFactory.cpp
MacOS
+
+ libprefDebug.shlb
+ Name
+ nsSafeSaveFile.cpp
+ MacOS
+
libprefDebug.shlb
Name
diff --git a/mozilla/modules/libpref/src/Makefile.in b/mozilla/modules/libpref/src/Makefile.in
index 0df8b887a65..2092e3bd691 100644
--- a/mozilla/modules/libpref/src/Makefile.in
+++ b/mozilla/modules/libpref/src/Makefile.in
@@ -50,6 +50,7 @@ CPPSRCS = nsPref.cpp \
nsPrefBranch.cpp \
nsPrefService.cpp \
nsPrefsFactory.cpp \
+ nsSafeSaveFile.cpp \
prefapi.cpp \
$(NULL)
diff --git a/mozilla/modules/libpref/src/init/all.js b/mozilla/modules/libpref/src/init/all.js
index 46a57ba2d82..e8fc9e308b6 100644
--- a/mozilla/modules/libpref/src/init/all.js
+++ b/mozilla/modules/libpref/src/init/all.js
@@ -55,6 +55,8 @@ pref("general.startup.addressbook", false);
pref("general.open_location.last_url", "");
pref("general.open_location.last_window_choice", 0);
+pref("backups.number_of_prefs_copies", 1);
+
// 0 = blank, 1 = home (browser.startup.homepage), 2 = last
pref("browser.startup.page", 1);
pref("browser.startup.homepage", "chrome://navigator-region/locale/region.properties");
diff --git a/mozilla/modules/libpref/src/makefile.win b/mozilla/modules/libpref/src/makefile.win
index 2195c3edb43..4c7d93741dc 100644
--- a/mozilla/modules/libpref/src/makefile.win
+++ b/mozilla/modules/libpref/src/makefile.win
@@ -69,6 +69,7 @@ OBJS = \
.\$(OBJDIR)\nsPrefBranch.obj \
.\$(OBJDIR)\nsPrefService.obj \
.\$(OBJDIR)\nsPrefsFactory.obj \
+ .\$(OBJDIR)\nsSafeSaveFile.obj \
$(NULL)
#//------------------------------------------------------------------------
diff --git a/mozilla/modules/libpref/src/nsPrefService.cpp b/mozilla/modules/libpref/src/nsPrefService.cpp
index eefb019be86..a096b6ec459 100644
--- a/mozilla/modules/libpref/src/nsPrefService.cpp
+++ b/mozilla/modules/libpref/src/nsPrefService.cpp
@@ -37,10 +37,12 @@
* ***** END LICENSE BLOCK ***** */
#include "nsPrefService.h"
+#include "nsSafeSaveFile.h"
#include "jsapi.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsDirectoryServiceDefs.h"
#include "nsICategoryManager.h"
+#include "nsIFile.h"
#include "nsIFileStreams.h"
#include "nsIObserverService.h"
#include "nsPrefBranch.h"
@@ -51,29 +53,20 @@
#include "pldhash.h"
#include "prefapi.h"
-class nsIFileSpec; // needed for prefapi_private_data.h inclusion
#include "prefapi_private_data.h"
// supporting PREF_Init()
#include "nsIJSRuntimeService.h"
-// lose these if possible (supporting nsIFileToFileSpec)
-#include "nsIFileSpec.h"
-#include "nsFileStream.h"
-
#include "nsITimelineService.h"
// Definitions
-#define PREFS_HEADER_LINE_1 "# Mozilla User Preferences"
-#define PREFS_HEADER_LINE_2 "// This is a generated file!"
#define INITIAL_MAX_DEFAULT_PREF_FILES 10
// Prototypes
-static nsresult nsIFileToFileSpec(nsIFile* inFile, nsIFileSpec **aFileSpec);
static nsresult openPrefFile(nsIFile* aFile, PRBool aIsErrorFatal,
PRBool aIsGlobalContext, PRBool aSkipFirstLine);
-static nsresult savePrefFile(nsIFile* aFile);
// needed so we can still get the JS Runtime Service during XPCOM shutdown
@@ -184,11 +177,11 @@ NS_IMETHODIMP nsPrefService::ReadUserPrefs(nsIFile *aFile)
nsresult rv;
if (nsnull == aFile) {
- rv = useDefaultPrefFile(); // really should return a value...
+ rv = UseDefaultPrefFile(); // really should return a value...
if (NS_SUCCEEDED(rv))
- useUserPrefFile();
+ UseUserPrefFile();
- notifyObservers(NS_PREFSERVICE_READ_TOPIC_ID);
+ InformObservers(NS_PREFSERVICE_READ_TOPIC_ID);
JS_MaybeGC(gMochaContext);
} else {
@@ -208,7 +201,7 @@ NS_IMETHODIMP nsPrefService::ReadUserPrefs(nsIFile *aFile)
NS_IMETHODIMP nsPrefService::ResetPrefs()
{
- notifyObservers(NS_PREFSERVICE_RESET_TOPIC_ID);
+ InformObservers(NS_PREFSERVICE_RESET_TOPIC_ID);
PREF_CleanupPrefs();
if (!PREF_Init(nsnull))
@@ -223,14 +216,13 @@ NS_IMETHODIMP nsPrefService::ResetUserPrefs()
return NS_OK;
}
-/* void savePrefFile (in nsIFile filename); */
NS_IMETHODIMP nsPrefService::SavePrefFile(nsIFile *aFile)
{
if (nsnull == aFile) {
// It's possible that we never got a prefs file.
- return mCurrentFile ? savePrefFile(mCurrentFile) : NS_OK;
+ return mCurrentFile ? SafeSavePrefFile(mCurrentFile) : NS_OK;
} else {
- return savePrefFile(aFile);
+ return SafeSavePrefFile(aFile);
}
}
@@ -289,7 +281,7 @@ NS_IMETHODIMP nsPrefService::RemoveObserver(const char *aDomain, nsIObserver *aO
}
-nsresult nsPrefService::notifyObservers(const char *aTopic)
+nsresult nsPrefService::InformObservers(const char *aTopic)
{
nsresult rv;
nsCOMPtr observerService =
@@ -304,8 +296,75 @@ nsresult nsPrefService::notifyObservers(const char *aTopic)
return NS_OK;
}
+nsresult nsPrefService::SafeSavePrefFile(nsIFile* aFile)
+{
+ const char outHeader[] = "# Mozilla User Preferences"
+ NS_LINEBREAK
+ "// This is a generated file!"
+ NS_LINEBREAK
+ NS_LINEBREAK;
+ nsCOMPtr outStream;
+ nsCOMPtr tempFile;
+ PRUint32 writeAmount;
+ nsresult rv;
-nsresult nsPrefService::useDefaultPrefFile()
+ if (!gHashTable.ops)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ /* ?! Don't save (blank) user prefs if there was an error reading them */
+ if (gErrorOpeningUserPrefs)
+ return NS_OK;
+
+ // execute a "safe" save by saving through a tempfile
+ PRInt32 numCopies = 1;
+ mRootBranch->GetIntPref("backups.number_of_prefs_copies", &numCopies);
+
+ nsSafeSaveFile safeSave(aFile, numCopies);
+ rv = safeSave.GetSaveFile(getter_AddRefs(tempFile));
+ if (NS_FAILED(rv))
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ char** valueArray = (char**) PR_Calloc(sizeof(char*), gHashTable.entryCount);
+ if (!valueArray)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = NS_NewLocalFileOutputStream(getter_AddRefs(outStream), tempFile);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // write out the file header
+ rv = outStream->Write(outHeader, sizeof(outHeader) - 1, &writeAmount);
+
+ // get the lines that we're supposed to be writing to the file
+ PL_DHashTableEnumerate(&gHashTable, pref_savePref, valueArray);
+
+ /* Sort the preferences to make a readable file on disk */
+ NS_QuickSort(valueArray, gHashTable.entryCount, sizeof(char*), pref_CompareStrings, NULL);
+ char** walker = valueArray;
+ for (PRUint32 valueIdx = 0; valueIdx < gHashTable.entryCount; valueIdx++, walker++) {
+ if (*walker) {
+ // skip writing if an has error occurred
+ if (NS_SUCCEEDED(rv)) {
+ rv = outStream->Write(*walker, strlen(*walker), &writeAmount);
+ if (NS_SUCCEEDED(rv))
+ rv = outStream->Write(NS_LINEBREAK, NS_LINEBREAK_LEN, &writeAmount);
+ }
+ // always free though...
+ PR_Free(*walker);
+ }
+ }
+ PR_Free(valueArray);
+ outStream->Close();
+
+ // if save was successful replace the original file and perform backup(s) if desired
+ if (NS_SUCCEEDED(rv))
+ rv = safeSave.PostProcessSave();
+ else
+ safeSave.CleanupFailedSave();
+ return rv;
+}
+
+nsresult nsPrefService::UseDefaultPrefFile()
{
nsresult rv;
nsCOMPtr aFile;
@@ -333,7 +392,7 @@ nsresult nsPrefService::useDefaultPrefFile()
return rv;
}
-nsresult nsPrefService::useUserPrefFile()
+nsresult nsPrefService::UseUserPrefFile()
{
nsresult rv = NS_OK;
nsCOMPtr aFile;
@@ -402,74 +461,6 @@ static nsresult openPrefFile(nsIFile* aFile, PRBool aIsErrorFatal,
return rv;
}
-static nsresult savePrefFile(nsIFile* aFile)
-{
- nsresult rv;
- nsCOMPtr fileSpec;
-
- if (!gHashTable.ops)
- return NS_ERROR_NOT_INITIALIZED;
-
- /* ?! Don't save (blank) user prefs if there was an error reading them */
- if (gErrorOpeningUserPrefs)
- return NS_OK;
-
- // TODO: Convert the rest of this code to nsIFile and avoid this conversion to nsIFileSpec
- rv = nsIFileToFileSpec(aFile, getter_AddRefs(fileSpec));
- if (NS_FAILED(rv))
- return rv;
-
- char** valueArray = (char**) PR_Calloc(sizeof(char*), gHashTable.entryCount);
- if (!valueArray)
- return NS_ERROR_OUT_OF_MEMORY;
-
- nsOutputFileStream stream(fileSpec);
- if (!stream.is_open())
- return NS_BASE_STREAM_OSERROR;
-
- stream << PREFS_HEADER_LINE_1 << nsEndl << PREFS_HEADER_LINE_2 << nsEndl << nsEndl;
-
- // get the lines that we're supposed to be writing to the file
- PL_DHashTableEnumerate(&gHashTable, pref_savePref, valueArray);
-
- /* Sort the preferences to make a readable file on disk */
- NS_QuickSort(valueArray, gHashTable.entryCount, sizeof(char*), pref_CompareStrings, NULL);
- char** walker = valueArray;
- for (PRUint32 valueIdx = 0; valueIdx < gHashTable.entryCount; valueIdx++, walker++) {
- if (*walker) {
- stream << *walker << nsEndl;
- PR_Free(*walker);
- }
- }
- PR_Free(valueArray);
- fileSpec->CloseStream();
- return NS_OK;
-}
-
-
-//----------------------------------------------------------------------------------------
-// So discouraged is the use of nsIFileSpec, nobody wanted to have this routine be
-// public - It might lead to continued use of nsIFileSpec. Right now, this code has
-// such a need for it, here it is. Let's stop having to use it though.
-static nsresult nsIFileToFileSpec(nsIFile* inFile, nsIFileSpec **aFileSpec)
-//----------------------------------------------------------------------------------------
-{
- nsresult rv;
- nsCOMPtr newFileSpec;
- nsXPIDLCString pathBuf;
-
- rv = inFile->GetPath(getter_Copies(pathBuf));
- if (NS_FAILED(rv)) return rv;
- rv = NS_NewFileSpec(getter_AddRefs(newFileSpec));
- if (NS_FAILED(rv)) return rv;
- rv = newFileSpec->SetNativePath((const char *)pathBuf);
- if (NS_FAILED(rv)) return rv;
-
- *aFileSpec = newFileSpec;
- NS_ADDREF(*aFileSpec);
-
- return NS_OK;
-}
/*
* some stuff that gets called from Pref_Init()
diff --git a/mozilla/modules/libpref/src/nsPrefService.h b/mozilla/modules/libpref/src/nsPrefService.h
index 6870d1e67fc..1164856a2ca 100644
--- a/mozilla/modules/libpref/src/nsPrefService.h
+++ b/mozilla/modules/libpref/src/nsPrefService.h
@@ -64,9 +64,10 @@ public:
nsresult Init();
protected:
- nsresult notifyObservers(const char *aSubject);
- nsresult useDefaultPrefFile();
- nsresult useUserPrefFile();
+ nsresult InformObservers(const char *aSubject);
+ nsresult SafeSavePrefFile(nsIFile* aFile);
+ nsresult UseDefaultPrefFile();
+ nsresult UseUserPrefFile();
private:
nsCOMPtr mRootBranch;
diff --git a/mozilla/modules/libpref/src/nsSafeSaveFile.cpp b/mozilla/modules/libpref/src/nsSafeSaveFile.cpp
index d6e64be28bc..2e8fa8f4bf1 100644
--- a/mozilla/modules/libpref/src/nsSafeSaveFile.cpp
+++ b/mozilla/modules/libpref/src/nsSafeSaveFile.cpp
@@ -48,7 +48,7 @@ nsSafeSaveFile::nsSafeSaveFile(nsIFile *aTargetFile, PRInt32 aNumBackupCopies)
mBackupCount(aNumBackupCopies)
{
nsCAutoString tempFileName;
- char * temp;
+ const char * temp;
nsresult rv;
// determine the actual filename (less the extension)
@@ -56,14 +56,14 @@ nsSafeSaveFile::nsSafeSaveFile(nsIFile *aTargetFile, PRInt32 aNumBackupCopies)
if (NS_FAILED(rv)) // yikes! out of memory
return;
- temp = strrchr(mTargetFileName, '.');
+ temp = strrchr(mTargetFileName.get(), '.');
if (temp)
- mTargetNameLen = temp - mTargetFileName;
+ mTargetNameLen = temp - mTargetFileName.get();
else
- mTargetNameLen = strlen(mTargetFileName);
+ mTargetNameLen = strlen(mTargetFileName.get());
// create a new file object that points to the temp file
- tempFileName.Assign(mTargetFileName, mTargetNameLen);
+ tempFileName.Assign(mTargetFileName.get(), mTargetNameLen);
tempFileName += ".tmp";
rv = aTargetFile->Clone(getter_AddRefs(mTempFile));
if (NS_SUCCEEDED(rv))
@@ -104,14 +104,14 @@ nsresult nsSafeSaveFile::PostProcessSave(void)
if (mBackupCount > 0) {
// kill the (oldest) backup copy, if necessary
- fileName.Assign(mTargetFileName, mTargetNameLen);
+ fileName.Assign(mTargetFileName.get(), mTargetNameLen);
fileName += BACKUP_FILE_EXTENSION;
if (mBackupCount > 1)
fileName.AppendInt(mBackupCount - 1);
backupFile->SetLeafName(fileName.get());
} else {
// no backups desired, delete the previous save
- backupFile->SetLeafName(mTargetFileName);
+ backupFile->SetLeafName(mTargetFileName.get());
}
// remove the file as determined by the logic above
@@ -120,7 +120,7 @@ nsresult nsSafeSaveFile::PostProcessSave(void)
// now manage the backup copies
if (mBackupCount > 0) {
PRInt32 backupCount = mBackupCount;
- fileName.Assign(mTargetFileName, mTargetNameLen);
+ fileName.Assign(mTargetFileName.get(), mTargetNameLen);
fileName += BACKUP_FILE_EXTENSION;
while (--backupCount > 0) {
// bump all of the redundant backups up one (i.e. bak -> bak1, bak1 -> bak2, etc.)
@@ -138,14 +138,14 @@ nsresult nsSafeSaveFile::PostProcessSave(void)
};
// rename the previous save to .bak (i.e. to )
- backupFile->SetLeafName(mTargetFileName);
+ backupFile->SetLeafName(mTargetFileName.get());
rv = backupFile->MoveTo(0, fileName.get());
if (NS_FAILED(rv))
return rv;
}
// finally rename the temp file to the original name (i.e. to )
- rv = mTempFile->MoveTo(0, mTargetFileName);
+ rv = mTempFile->MoveTo(0, mTargetFileName.get());
return rv;
}
@@ -166,7 +166,7 @@ nsresult nsSafeSaveFile::PurgeOldestBackup(void)
return NS_ERROR_FILE_NOT_FOUND;
PRInt32 backupCount = mBackupCount;
- fileName.Assign(mTargetFileName, mTargetNameLen);
+ fileName.Assign(mTargetFileName.get(), mTargetNameLen);
fileName += BACKUP_FILE_EXTENSION;
while (--backupCount >= 0) {
if (backupCount)
diff --git a/mozilla/modules/libpref/src/nsSafeSaveFile.h b/mozilla/modules/libpref/src/nsSafeSaveFile.h
index 4927b238e4c..3cfb01633e4 100644
--- a/mozilla/modules/libpref/src/nsSafeSaveFile.h
+++ b/mozilla/modules/libpref/src/nsSafeSaveFile.h
@@ -55,7 +55,6 @@ class nsSafeSaveFile {
private:
nsCOMPtr mTempFile;
- nsCAutoString fileName;
nsXPIDLCString mTargetFileName;
PRInt32 mTargetNameLen;
PRInt32 mBackupCount;
diff --git a/mozilla/modules/libpref/src/prefapi.cpp b/mozilla/modules/libpref/src/prefapi.cpp
index 371f5b39e9d..865304830b1 100644
--- a/mozilla/modules/libpref/src/prefapi.cpp
+++ b/mozilla/modules/libpref/src/prefapi.cpp
@@ -36,6 +36,8 @@
* ***** END LICENSE BLOCK ***** */
#include "prefapi.h"
+#include "prefapi_private_data.h"
+#include "nsReadableUtils.h"
#include "jsapi.h"
#include "xp_core.h" /* Needed for XP_ defines */
@@ -108,7 +110,6 @@ PR_STATIC_CALLBACK(JSBool) pref_NativeUserPref(JSContext *cx, JSObject *obj, uns
PR_STATIC_CALLBACK(JSBool) pref_NativeSetConfig(JSContext *cx, JSObject *obj, unsigned int argc, jsval *argv, jsval *rval);
PR_STATIC_CALLBACK(JSBool) pref_NativeGetPref(JSContext *cx, JSObject *obj, unsigned int argc, jsval *argv, jsval *rval);
/*----------------------------------------------------------------------------------------*/
-#include "prefapi_private_data.h"
JS_STATIC_DLL_CALLBACK(JSBool)
global_enumerate(JSContext *cx, JSObject *obj)
@@ -1382,7 +1383,7 @@ pref_ErrorReporter(JSContext *cx, const char *message,
/* StandardAlert doesn't handle linefeeds. Use spaces to avoid garbage characters. */
last = PR_sprintf_append(last, " ");
#else
- last = PR_sprintf_append(last, LINEBREAK LINEBREAK);
+ last = PR_sprintf_append(last, NS_LINEBREAK NS_LINEBREAK);
#endif
if (!report)
last = PR_sprintf_append(last, "%s\n", message);
diff --git a/mozilla/modules/libpref/src/prefapi_private_data.h b/mozilla/modules/libpref/src/prefapi_private_data.h
index a7a13e1d53b..4889e2f7e22 100644
--- a/mozilla/modules/libpref/src/prefapi_private_data.h
+++ b/mozilla/modules/libpref/src/prefapi_private_data.h
@@ -44,14 +44,3 @@ PLDHashOperator PR_CALLBACK pref_savePref(PLDHashTable*, PLDHashEntryHdr *, PRUi
int PR_CALLBACK pref_CompareStrings(const void *v1, const void *v2, void* unused);
extern JSBool pref_InitInitialObjects(void);
-
-#include "nsIFileSpec.h"
-
-#ifdef XP_MAC
-# define LINEBREAK "\012"
-#elif defined(XP_WIN) || defined(XP_OS2)
-# define LINEBREAK "\015\012"
-#elif defined(XP_UNIX) || defined(XP_BEOS)
-# define LINEBREAK "\012"
-#endif /* XP_MAC */
-