--- a/profile/dirserviceprovider/src/nsProfileLock.cpp
+++ b/profile/dirserviceprovider/src/nsProfileLock.cpp
@@ -556,27 +556,27 @@ nsresult nsProfileLock::Lock(nsILocalFil
{
// If that failed for any reason other than NS_ERROR_FILE_ACCESS_DENIED,
// assume we tried an NFS that does not support it. Now, try with symlink
// using the old symlink path
rv = LockWithSymlink(oldFilePath, PR_FALSE);
}
#elif defined(XP_WIN)
- nsCAutoString filePath;
- rv = lockFile->GetNativePath(filePath);
+ nsAutoString filePath;
+ rv = lockFile->GetPath(filePath);
if (NS_FAILED(rv))
return rv;
- mLockFileHandle = CreateFile(filePath.get(),
- GENERIC_READ | GENERIC_WRITE,
- 0, // no sharing - of course
- nsnull,
- OPEN_ALWAYS,
- FILE_FLAG_DELETE_ON_CLOSE,
- nsnull);
+ mLockFileHandle = CreateFileW(filePath.get(),
+ GENERIC_READ | GENERIC_WRITE,
+ 0, // no sharing - of course
+ nsnull,
+ OPEN_ALWAYS,
+ FILE_FLAG_DELETE_ON_CLOSE,
+ nsnull);
if (mLockFileHandle == INVALID_HANDLE_VALUE) {
// XXXbsmedberg: provide a profile-unlocker here!
return NS_ERROR_FILE_ACCESS_DENIED;
}
#elif defined(XP_OS2)
nsCAutoString filePath;
rv = lockFile->GetNativePath(filePath);
if (NS_FAILED(rv))
--- a/toolkit/crashreporter/client/crashreporter.cpp
+++ b/toolkit/crashreporter/client/crashreporter.cpp
@@ -408,19 +408,32 @@ int main(int argc, char** argv)
// to be product specific
RewriteStrings(queryParameters);
if (queryParameters.find("ServerURL") == queryParameters.end()) {
UIError(gStrings[ST_ERROR_NOSERVERURL]);
return 0;
}
- string product = queryParameters["ProductName"];
- string vendor = queryParameters["Vendor"];
- if (!UIGetSettingsPath(vendor, product, gSettingsPath)) {
+ // Hopefully the settings path exists in the environment. Try that before
+ // asking the platform-specific code to guess.
+ static const char kDataDirKey[] = "MOZ_CRASHREPORTER_DATA_DIRECTORY";
+ const char *settingsPath = getenv(kDataDirKey);
+ if (settingsPath && *settingsPath) {
+ gSettingsPath = settingsPath;
+ }
+ else {
+ string product = queryParameters["ProductName"];
+ string vendor = queryParameters["Vendor"];
+ if (!UIGetSettingsPath(vendor, product, gSettingsPath)) {
+ gSettingsPath.clear();
+ }
+ }
+
+ if (gSettingsPath.empty() || !UIEnsurePathExists(gSettingsPath)) {
UIError(gStrings[ST_ERROR_NOSETTINGSPATH]);
return 0;
}
if (!UIFileExists(gDumpFile)) {
UIError(gStrings[ST_ERROR_DUMPFILEEXISTS]);
return 0;
}
--- a/toolkit/crashreporter/client/crashreporter_linux.cpp
+++ b/toolkit/crashreporter/client/crashreporter_linux.cpp
@@ -291,17 +291,17 @@ static void TryInitGnome()
{
gnomeLib = dlopen("libgnome-2.so.0", RTLD_LAZY);
if (!gnomeLib)
return;
gnomeuiLib = dlopen("libgnomeui-2.so.0", RTLD_LAZY);
if (!gnomeuiLib)
return;
-
+
_gnome_program_init_fn gnome_program_init =
(_gnome_program_init_fn)(dlsym(gnomeLib, "gnome_program_init"));
_libgnomeui_module_info_get_fn libgnomeui_module_info_get =
(_libgnomeui_module_info_get_fn)(dlsym(gnomeuiLib, "libgnomeui_module_info_get"));
if (gnome_program_init && libgnomeui_module_info_get) {
gnome_program_init("crashreporter", "1.0", libgnomeui_module_info_get(),
gArgc, gArgv, NULL);
@@ -490,33 +490,33 @@ bool UIGetIniPath(string& path)
* Settings are stored in ~/.vendor/product, or
* ~/.product if vendor is empty.
*/
bool UIGetSettingsPath(const string& vendor,
const string& product,
string& settingsPath)
{
char* home = getenv("HOME");
-
+
if (!home)
return false;
settingsPath = home;
settingsPath += "/.";
if (!vendor.empty()) {
string lc_vendor;
std::transform(vendor.begin(), vendor.end(), back_inserter(lc_vendor),
- (int(*)(int)) std::tolower);
+ (int(*)(int)) std::tolower);
settingsPath += lc_vendor + "/";
}
string lc_product;
std::transform(product.begin(), product.end(), back_inserter(lc_product),
- (int(*)(int)) std::tolower);
+ (int(*)(int)) std::tolower);
settingsPath += lc_product + "/Crash Reports";
- return UIEnsurePathExists(settingsPath);
+ return true;
}
bool UIEnsurePathExists(const string& path)
{
int ret = mkdir(path.c_str(), S_IRWXU);
int e = errno;
if (ret == -1 && e != EEXIST)
return false;
@@ -548,9 +548,8 @@ std::ifstream* UIOpenRead(const string&
{
return new std::ifstream(filename.c_str(), std::ios::in);
}
std::ofstream* UIOpenWrite(const string& filename)
{
return new std::ofstream(filename.c_str(), std::ios::out);
}
-
--- a/toolkit/crashreporter/client/crashreporter_osx.mm
+++ b/toolkit/crashreporter/client/crashreporter_osx.mm
@@ -489,19 +489,16 @@ bool UIGetSettingsPath(const string& ven
string tempPath = [destPath UTF8String];
if (!UIEnsurePathExists(tempPath))
return false;
destPath = [destPath stringByAppendingPathComponent: @"Crash Reports"];
settingsPath = [destPath UTF8String];
- if (!UIEnsurePathExists(settingsPath))
- return false;
-
return true;
}
bool UIEnsurePathExists(const string& path)
{
int ret = mkdir(path.c_str(), S_IRWXU);
int e = errno;
if (ret == -1 && e != EEXIST)
--- a/toolkit/crashreporter/client/crashreporter_win.cpp
+++ b/toolkit/crashreporter/client/crashreporter_win.cpp
@@ -692,19 +692,21 @@ void UIShowCrashUI(const string& dumpFil
for (StringTable::const_iterator i = queryParameters.begin();
i != queryParameters.end();
i++) {
gQueryParameters[UTF8ToWide(i->first)] = UTF8ToWide(i->second);
}
if (gQueryParameters.find(L"Vendor") != gQueryParameters.end()) {
- gCrashReporterKey = L"Software\\" +
- gQueryParameters[L"Vendor"] +
- L"\\Crash Reporter";
+ gCrashReporterKey = L"Software\\";
+ if (!gQueryParameters[L"Vendor"].empty()) {
+ gCrashReporterKey += gQueryParameters[L"Vendor"] + L"\\";
+ }
+ gCrashReporterKey += gQueryParameters[L"Name"] + L"\\Crash Reporter";
}
gRestartArgs = restartArgs;
DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_SENDDIALOG), NULL,
(DLGPROC)CrashReporterDialogProc, 0);
}
@@ -744,18 +746,16 @@ bool UIGetSettingsPath(const string& ven
NULL,
0,
path))) {
if (!vendor.empty()) {
PathAppend(path, UTF8ToWide(vendor).c_str());
}
PathAppend(path, UTF8ToWide(product).c_str());
PathAppend(path, L"Crash Reports");
- // in case it doesn't exist
- CreateDirectory(path, NULL);
settings_path = WideToUTF8(path);
return true;
}
return false;
}
bool UIEnsurePathExists(const string& path)
{
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -207,17 +207,17 @@ bool MinidumpCallback(const XP_CHAR* dum
O_WRONLY | O_CREAT | O_TRUNC,
0600);
if (fd != -1) {
write(fd, crashTimeString, crashTimeStringLen);
close(fd);
}
#endif
}
-
+
#if defined(XP_WIN32)
XP_CHAR cmdLine[CMDLINE_SIZE];
size = CMDLINE_SIZE;
p = Concat(cmdLine, L"\"", &size);
p = Concat(p, crashReporterPath, &size);
p = Concat(p, L"\" \"", &size);
p = Concat(p, minidumpPath, &size);
Concat(p, L"\"", &size);
@@ -479,17 +479,17 @@ GetFileContents(nsIFile* aFile, nsACStri
// Function typedef for initializing a piece of data that we
// don't already have.
typedef nsresult (*InitDataFunc)(nsACString&);
// Attempt to read aFile's contents into aContents, if aFile
// does not exist, create it and initialize its contents
// by calling aInitFunc for the data.
-static nsresult
+static nsresult
GetOrInit(nsIFile* aDir, const nsACString& filename,
nsACString& aContents, InitDataFunc aInitFunc)
{
PRBool exists;
nsCOMPtr<nsIFile> dataFile;
nsresult rv = aDir->Clone(getter_AddRefs(dataFile));
NS_ENSURE_SUCCESS(rv, rv);
@@ -532,46 +532,46 @@ InitUserID(nsACString& aUserID)
#if defined(XP_WIN)
HRESULT hr = CoCreateGuid((GUID*)&id);
if (NS_FAILED(hr))
return NS_ERROR_FAILURE;
#elif defined(XP_MACOSX)
CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
if (!uuid)
return NS_ERROR_FAILURE;
-
+
CFUUIDBytes bytes = CFUUIDGetUUIDBytes(uuid);
memcpy(&id, &bytes, sizeof(nsID));
CFRelease(uuid);
#else
// UNIX or some such thing
id.m0 = random();
id.m1 = random();
id.m2 = random();
*reinterpret_cast<PRUint32*>(&id.m3[0]) = random();
*reinterpret_cast<PRUint32*>(&id.m3[4]) = random();
#endif
nsCAutoString id_str(id.ToString());
aUserID = Substring(id_str, 1, id_str.Length()-2);
-
+
return NS_OK;
}
// Init the "install time" data. We're taking an easy way out here
// and just setting this to "the time when this version was first run".
static nsresult
InitInstallTime(nsACString& aInstallTime)
{
time_t t = time(NULL);
char buf[16];
sprintf(buf, "%ld", t);
aInstallTime = buf;
-
+
return NS_OK;
}
// Annotate the crash report with a Unique User ID and time
// since install. Also do some prep work for recording
// time since last crash, which must be calculated at
// crash time.
// If any piece of data doesn't exist, initialize it first.
@@ -589,16 +589,38 @@ nsresult SetupExtraData(nsILocalFile* aA
rv = dataDirectory->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
if (!exists) {
rv = dataDirectory->Create(nsIFile::DIRECTORY_TYPE, 0700);
NS_ENSURE_SUCCESS(rv, rv);
}
+ // Save this path in the environment for the crash reporter application.
+ nsCAutoString dataDirEnv("MOZ_CRASHREPORTER_DATA_DIRECTORY=");
+
+#if defined(XP_WIN32)
+ nsAutoString dataDirectoryPath;
+ rv = dataDirectory->GetPath(dataDirectoryPath);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ AppendUTF16toUTF8(dataDirectoryPath, dataDirEnv);
+#else
+ nsCAutoString dataDirectoryPath;
+ rv = dataDirectory->GetNativePath(dataDirectoryPath);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ dataDirEnv.Append(dataDirectoryPath);
+#endif
+
+ char* env = ToNewCString(dataDirEnv);
+ NS_ENSURE_TRUE(env, NS_ERROR_OUT_OF_MEMORY);
+
+ PR_SetEnv(env);
+
nsCAutoString data;
if(NS_SUCCEEDED(GetOrInit(dataDirectory, NS_LITERAL_CSTRING("UserID"),
data, InitUserID)))
AnnotateCrashReport(NS_LITERAL_CSTRING("UserID"), data);
if(NS_SUCCEEDED(GetOrInit(dataDirectory,
NS_LITERAL_CSTRING("InstallTime") + aBuildID,
data, InitInstallTime)))
@@ -663,17 +685,17 @@ nsresult UnsetExceptionHandler()
return NS_OK;
}
static void ReplaceChar(nsCString& str, const nsACString& character,
const nsACString& replacement)
{
nsCString::const_iterator start, end;
-
+
str.BeginReading(start);
str.EndReading(end);
while (FindInReadable(character, start, end)) {
PRInt32 pos = end.size_backward();
str.Replace(pos - 1, 1, replacement);
str.BeginReading(start);
@@ -708,17 +730,17 @@ nsresult AnnotateCrashReport(const nsACS
if (DoFindInReadable(key, NS_LITERAL_CSTRING("=")) ||
DoFindInReadable(key, NS_LITERAL_CSTRING("\n")))
return NS_ERROR_INVALID_ARG;
if (DoFindInReadable(data, NS_LITERAL_CSTRING("\0")))
return NS_ERROR_INVALID_ARG;
nsCString escapedData(data);
-
+
// escape backslashes
ReplaceChar(escapedData, NS_LITERAL_CSTRING("\\"),
NS_LITERAL_CSTRING("\\\\"));
// escape newlines
ReplaceChar(escapedData, NS_LITERAL_CSTRING("\n"),
NS_LITERAL_CSTRING("\\n"));
nsresult rv = crashReporterAPIData_Hash->Put(key, escapedData);
--- a/toolkit/xre/nsAppData.cpp
+++ b/toolkit/xre/nsAppData.cpp
@@ -73,16 +73,17 @@ ScopedAppData::ScopedAppData(const nsXRE
this->size = aAppData->size;
SetAllocatedString(this->vendor, aAppData->vendor);
SetAllocatedString(this->name, aAppData->name);
SetAllocatedString(this->version, aAppData->version);
SetAllocatedString(this->buildID, aAppData->buildID);
SetAllocatedString(this->ID, aAppData->ID);
SetAllocatedString(this->copyright, aAppData->copyright);
+ SetAllocatedString(this->profile, aAppData->profile);
SetStrongPtr(this->directory, aAppData->directory);
this->flags = aAppData->flags;
if (aAppData->size > offsetof(nsXREAppData, xreDirectory)) {
SetStrongPtr(this->xreDirectory, aAppData->xreDirectory);
SetAllocatedString(this->minVersion, aAppData->minVersion);
SetAllocatedString(this->maxVersion, aAppData->maxVersion);
}
@@ -95,16 +96,17 @@ ScopedAppData::ScopedAppData(const nsXRE
ScopedAppData::~ScopedAppData()
{
SetAllocatedString(this->vendor, nsnull);
SetAllocatedString(this->name, nsnull);
SetAllocatedString(this->version, nsnull);
SetAllocatedString(this->buildID, nsnull);
SetAllocatedString(this->ID, nsnull);
SetAllocatedString(this->copyright, nsnull);
+ SetAllocatedString(this->profile, nsnull);
NS_IF_RELEASE(this->directory);
SetStrongPtr(this->xreDirectory, (nsILocalFile*) nsnull);
SetAllocatedString(this->minVersion, nsnull);
SetAllocatedString(this->maxVersion, nsnull);
SetAllocatedString(this->crashReporterURL, nsnull);
@@ -203,16 +205,17 @@ XRE_ParseAppData(nsILocalFile* aINIFile,
ReadString strings[] = {
{ "App", "Vendor", &aAppData->vendor },
{ "App", "Name", &aAppData->name },
{ "App", "Version", &aAppData->version },
{ "App", "BuildID", &aAppData->buildID },
{ "App", "ID", &aAppData->ID },
{ "App", "Copyright", &aAppData->copyright },
+ { "App", "Profile", &aAppData->profile },
{ nsnull }
};
ReadStrings(parser, strings);
ReadFlag flags[] = {
{ "XRE", "EnableProfileMigrator", NS_XRE_ENABLE_PROFILE_MIGRATOR },
{ "XRE", "EnableExtensionManager", NS_XRE_ENABLE_EXTENSION_MANAGER },
{ nsnull }
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -57,23 +57,24 @@
#include "nsDirectoryServiceUtils.h"
#include "nsXULAppAPI.h"
#include "nsINIParser.h"
#include "nsDependentString.h"
#include "nsCOMArray.h"
#include "nsArrayEnumerator.h"
#include "nsEnumeratorUtils.h"
+#include "nsReadableUtils.h"
#include <stdlib.h>
#ifdef XP_WIN
#include <windows.h>
#include <shlobj.h>
-// This is not defined by VC6.
+// This is not defined by VC6.
#ifndef CSIDL_LOCAL_APPDATA
#define CSIDL_LOCAL_APPDATA 0x001C
#endif
#endif
#ifdef XP_MACOSX
#include "nsILocalFileMac.h"
#endif
#ifdef XP_BEOS
@@ -127,17 +128,17 @@ nsXREDirProvider::Initialize(nsIFile *aX
}
nsresult
nsXREDirProvider::SetProfile(nsIFile* aDir, nsIFile* aLocalDir)
{
NS_ASSERTION(aDir && aLocalDir, "We don't support no-profile apps yet!");
nsresult rv;
-
+
rv = EnsureDirectoryExists(aDir);
if (NS_FAILED(rv))
return rv;
rv = EnsureDirectoryExists(aLocalDir);
if (NS_FAILED(rv))
return rv;
@@ -502,17 +503,17 @@ nsXREDirProvider::GetFiles(const char* a
if (NS_FAILED(rv))
return rv;
return NS_SUCCESS_AGGREGATE_RESULT;
}
static void
LoadExtensionDirectories(nsINIParser &parser,
- const char *aSection,
+ const char *aSection,
nsCOMArray<nsIFile> &aDirectories)
{
nsresult rv;
PRInt32 i = 0;
do {
nsCAutoString buf("Extension");
buf.AppendInt(i++);
@@ -578,17 +579,17 @@ nsXREDirProvider::LoadAppBundleDirs()
{
if (!mXULAppDir)
return;
nsCOMPtr<nsIFile> dir;
nsresult rv = mXULAppDir->Clone(getter_AddRefs(dir));
if (NS_FAILED(rv))
return;
-
+
dir->AppendNative(NS_LITERAL_CSTRING("distribution"));
dir->AppendNative(NS_LITERAL_CSTRING("bundles"));
PRBool exists;
if (NS_FAILED(dir->Exists(&exists)) || !exists)
return;
nsCOMPtr<nsISimpleEnumerator> e;
@@ -628,17 +629,17 @@ nsresult
nsXREDirProvider::GetFilesInternal(const char* aProperty,
nsISimpleEnumerator** aResult)
{
nsresult rv = NS_OK;
*aResult = nsnull;
if (!strcmp(aProperty, XRE_EXTENSIONS_DIR_LIST)) {
nsCOMArray<nsIFile> directories;
-
+
static const char *const kAppendNothing[] = { nsnull };
LoadBundleDirectories();
LoadDirsIntoArray(mAppBundleDirectories,
kAppendNothing, directories);
LoadDirsIntoArray(mExtensionDirectories,
kAppendNothing, directories);
@@ -707,17 +708,17 @@ nsXREDirProvider::GetFilesInternal(const
LoadDirsIntoArray(mAppBundleDirectories,
kAppendChromeManifests,
manifests);
LoadDirsIntoArray(mExtensionDirectories,
kAppendChromeManifests,
manifests);
rv = NS_NewArrayEnumerator(aResult, manifests);
- }
+ }
else if (!strcmp(aProperty, NS_SKIN_MANIFESTS_FILE_LIST)) {
nsCOMArray<nsIFile> manifests;
LoadBundleDirectories();
LoadDirsIntoArray(mThemeDirectories,
kAppendChromeManifests, manifests);
rv = NS_NewArrayEnumerator(aResult, manifests);
@@ -845,89 +846,90 @@ nsXREDirProvider::DoShutdown()
// Phase 3: Notify observers of a profile change
obssvc->NotifyObservers(cs, "profile-before-change", kShutdownPersist);
}
mProfileNotified = PR_FALSE;
}
}
-static void
-GetProfileFolderName(char* aProfileFolderName, const char* aSource)
-{
- const char* reading = aSource;
-
- while (*reading) {
- *aProfileFolderName = tolower(*reading);
- ++aProfileFolderName; ++reading;
- }
- *aProfileFolderName = '\0';
-}
-
#ifdef XP_WIN
static nsresult
-GetShellFolderPath(int folder, char result[MAXPATHLEN])
+GetShellFolderPath(int folder, nsAString& _retval)
{
LPITEMIDLIST pItemIDList = NULL;
+ PRUnichar* buf;
+ PRUint32 bufLength = _retval.GetMutableData(&buf, MAXPATHLEN);
+ NS_ENSURE_TRUE(bufLength >= MAXPATHLEN, NS_ERROR_OUT_OF_MEMORY);
+
nsresult rv;
if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, folder, &pItemIDList)) &&
- SUCCEEDED(SHGetPathFromIDList(pItemIDList, result))) {
+ SHGetPathFromIDListW(pItemIDList, buf)) {
+ // We're going to use wcslen (wcsnlen not available in msvc7.1) so make
+ // sure to null terminate.
+ buf[bufLength - 1] = L'\0';
+ _retval.SetLength(wcslen(buf));
rv = NS_OK;
} else {
+ _retval.SetLength(0);
rv = NS_ERROR_NOT_AVAILABLE;
}
CoTaskMemFree(pItemIDList);
return rv;
}
nsresult
nsXREDirProvider::GetUpdateRootDir(nsIFile* *aResult)
{
nsCOMPtr<nsIFile> appDir = GetAppDir();
- nsCAutoString appPath;
- nsresult rv = appDir->GetNativePath(appPath);
+
+ nsAutoString appPath;
+ nsresult rv = appDir->GetPath(appPath);
NS_ENSURE_SUCCESS(rv, rv);
// AppDir may be a short path. Convert to long path to make sure
// the consistency of the update folder location
- nsCString longPath;
- char *buf;
- longPath.GetMutableData(&buf, MAXPATHLEN);
- DWORD len = GetLongPathName(appPath.get(), buf, MAXPATHLEN);
+ nsString longPath;
+ PRUnichar* buf;
+
+ PRUint32 bufLength = longPath.GetMutableData(&buf, MAXPATHLEN);
+ NS_ENSURE_TRUE(bufLength >= MAXPATHLEN, NS_ERROR_OUT_OF_MEMORY);
+
+ DWORD len = GetLongPathNameW(appPath.get(), buf, bufLength);
+
// Failing GetLongPathName() is not fatal.
- if (len <= 0 || len >= MAXPATHLEN)
+ if (len <= 0 || len >= bufLength)
longPath.Assign(appPath);
else
longPath.SetLength(len);
// Use <UserLocalDataDir>\updates\<relative path to app dir from
// Program Files> if app dir is under Program Files to avoid the
// folder virtualization mess on Windows Vista
- char programFiles[MAXPATHLEN];
+ nsAutoString programFiles;
rv = GetShellFolderPath(CSIDL_PROGRAM_FILES, programFiles);
NS_ENSURE_SUCCESS(rv, rv);
- PRUint32 programFilesLen = strlen(programFiles);
- programFiles[programFilesLen++] = '\\';
- programFiles[programFilesLen] = '\0';
+ programFiles.AppendLiteral("\\");
+ PRUint32 programFilesLen = programFiles.Length();
if (longPath.Length() < programFilesLen)
return NS_ERROR_FAILURE;
- if (_strnicmp(programFiles, longPath.get(), programFilesLen) != 0)
+ if (_wcsnicmp(programFiles.get(), longPath.get(), programFilesLen) != 0)
return NS_ERROR_FAILURE;
nsCOMPtr<nsILocalFile> updRoot;
rv = GetUserLocalDataDirectory(getter_AddRefs(updRoot));
NS_ENSURE_SUCCESS(rv, rv);
- rv = updRoot->AppendRelativeNativePath(Substring(longPath, programFilesLen));
+ rv = updRoot->AppendRelativePath(Substring(longPath, programFilesLen));
NS_ENSURE_SUCCESS(rv, rv);
NS_ADDREF(*aResult = updRoot);
return NS_OK;
}
#endif
nsresult
@@ -983,67 +985,44 @@ nsXREDirProvider::GetUserDataDirectory(n
nsCOMPtr<nsILocalFile> localDir;
#if defined(XP_MACOSX)
FSRef fsRef;
OSType folderType;
if (aLocal) {
folderType = kCachedDataFolderType;
} else {
-#ifdef MOZ_THUNDERBIRD
+#ifdef MOZ_THUNDERBIRD
folderType = kDomainLibraryFolderType;
#else
folderType = kApplicationSupportFolderType;
-#endif
+#endif
}
OSErr err = ::FSFindFolder(kUserDomain, folderType, kCreateFolder, &fsRef);
NS_ENSURE_FALSE(err, NS_ERROR_FAILURE);
rv = NS_NewNativeLocalFile(EmptyCString(), PR_TRUE, getter_AddRefs(localDir));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsILocalFileMac> dirFileMac = do_QueryInterface(localDir);
NS_ENSURE_TRUE(dirFileMac, NS_ERROR_UNEXPECTED);
rv = dirFileMac->InitWithFSRef(&fsRef);
NS_ENSURE_SUCCESS(rv, rv);
- // Note that MacOS ignores the vendor when creating the profile hierarchy - all
- // application preferences directories live alongside one another in
- // ~/Library/Application Support/
- rv = dirFileMac->AppendNative(nsDependentCString(gAppData->name));
- NS_ENSURE_SUCCESS(rv, rv);
+ localDir = do_QueryInterface(dirFileMac, &rv);
#elif defined(XP_WIN)
- char path[MAXPATHLEN];
-
- // CSIDL_LOCAL_APPDATA is only defined on newer versions of Windows. If the
- // OS does not understand it, then we'll fallback to the regular APPDATA
- // location. If neither is defined, then we fallback to the Windows folder.
-
+ nsString path;
if (aLocal)
rv = GetShellFolderPath(CSIDL_LOCAL_APPDATA, path);
if (!aLocal || NS_FAILED(rv))
rv = GetShellFolderPath(CSIDL_APPDATA, path);
-
- if (NS_FAILED(rv) && !GetWindowsDirectory(path, sizeof(path))) {
- NS_WARNING("Aaah, no windows directory!");
- return NS_ERROR_FAILURE;
- }
-
- rv = NS_NewNativeLocalFile(nsDependentCString(path),
- PR_TRUE, getter_AddRefs(localDir));
NS_ENSURE_SUCCESS(rv, rv);
- if (gAppData->vendor) {
- rv = localDir->AppendNative(nsDependentCString(gAppData->vendor));
- NS_ENSURE_SUCCESS(rv, rv);
- }
- rv = localDir->AppendNative(nsDependentCString(gAppData->name));
- NS_ENSURE_SUCCESS(rv, rv);
-
+ rv = NS_NewLocalFile(path, PR_TRUE, getter_AddRefs(localDir));
#elif defined(XP_OS2)
#if 0 /* For OS/2 we want to always use MOZILLA_HOME */
// we want an environment variable of the form
// FIREFOX_HOME, etc
nsDependentCString envVar(nsDependentCString(gAppData->name));
envVar.Append("_HOME");
char *pHome = getenv(envVar.get());
#endif
@@ -1056,89 +1035,51 @@ nsXREDirProvider::GetUserDataDirectory(n
PTIB ptib;
char appDir[CCHMAXPATH];
DosGetInfoBlocks(&ptib, &ppib);
DosQueryModuleName(ppib->pib_hmte, CCHMAXPATH, appDir);
*strrchr(appDir, '\\') = '\0';
rv = NS_NewNativeLocalFile(nsDependentCString(appDir), PR_TRUE, getter_AddRefs(localDir));
}
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (gAppData->vendor) {
- rv = localDir->AppendNative(nsDependentCString(gAppData->vendor));
- NS_ENSURE_SUCCESS(rv, rv);
- }
- rv = localDir->AppendNative(nsDependentCString(gAppData->name));
- NS_ENSURE_SUCCESS(rv, rv);
-
#elif defined(XP_BEOS)
char appDir[MAXPATHLEN];
if (find_directory(B_USER_SETTINGS_DIRECTORY, NULL, true, appDir, MAXPATHLEN))
return NS_ERROR_FAILURE;
int len = strlen(appDir);
appDir[len] = '/';
appDir[len+1] = '\0';
rv = NS_NewNativeLocalFile(nsDependentCString(appDir), PR_TRUE,
getter_AddRefs(localDir));
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (gAppData->vendor) {
- rv = localDir->AppendNative(nsDependentCString(gAppData->vendor));
- NS_ENSURE_SUCCESS(rv, rv);
- }
- rv = localDir->AppendNative(nsDependentCString(gAppData->name));
- NS_ENSURE_SUCCESS(rv, rv);
-
#elif defined(XP_UNIX)
const char* homeDir = getenv("HOME");
if (!homeDir || !*homeDir)
return NS_ERROR_FAILURE;
rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), PR_TRUE,
getter_AddRefs(localDir));
+#else
+#error "Don't know how to get product dir on your platform"
+#endif
NS_ENSURE_SUCCESS(rv, rv);
-
- char* appNameFolder = nsnull;
- char profileFolderName[MAXPATHLEN] = ".";
-
- // Offset 1 for the outermost folder to make it hidden (i.e. using the ".")
- char* writing = profileFolderName + 1;
- if (gAppData->vendor) {
- GetProfileFolderName(writing, gAppData->vendor);
-
- rv = localDir->AppendNative(nsDependentCString(profileFolderName));
- NS_ENSURE_SUCCESS(rv, rv);
-
- char temp[MAXPATHLEN];
- GetProfileFolderName(temp, gAppData->name);
- appNameFolder = temp;
- }
- else {
- GetProfileFolderName(writing, gAppData->name);
- appNameFolder = profileFolderName;
- }
- rv = localDir->AppendNative(nsDependentCString(appNameFolder));
+
+ rv = AppendProfilePath(localDir);
NS_ENSURE_SUCCESS(rv, rv);
-#else
-#error dont_know_how_to_get_product_dir_on_your_platform
-#endif
#ifdef DEBUG_jungshik
nsCAutoString cwd;
localDir->GetNativePath(cwd);
printf("nsXREDirProvider::GetUserDataDirectory: %s\n", cwd.get());
#endif
rv = EnsureDirectoryExists(localDir);
NS_ENSURE_SUCCESS(rv, rv);
- *aFile = localDir;
- NS_ADDREF(*aFile);
+ NS_ADDREF(*aFile = localDir);
return NS_OK;
}
nsresult
nsXREDirProvider::EnsureDirectoryExists(nsIFile* aDirectory)
{
PRBool exists;
nsresult rv = aDirectory->Exists(&exists);
@@ -1160,46 +1101,143 @@ nsXREDirProvider::EnsureDirectoryExists(
return rv;
}
void
nsXREDirProvider::EnsureProfileFileExists(nsIFile *aFile)
{
nsresult rv;
PRBool exists;
-
+
rv = aFile->Exists(&exists);
if (NS_FAILED(rv) || exists) return;
-
+
nsCAutoString leafName;
rv = aFile->GetNativeLeafName(leafName);
if (NS_FAILED(rv)) return;
nsCOMPtr<nsIFile> defaultsFile;
rv = GetProfileDefaultsDir(getter_AddRefs(defaultsFile));
if (NS_FAILED(rv)) return;
rv = defaultsFile->AppendNative(leafName);
if (NS_FAILED(rv)) return;
-
+
defaultsFile->CopyToNative(mProfileDir, EmptyCString());
}
nsresult
nsXREDirProvider::GetProfileDefaultsDir(nsIFile* *aResult)
{
NS_ASSERTION(mGREDir, "nsXREDirProvider not initialized.");
NS_PRECONDITION(aResult, "Null out-param");
nsresult rv;
nsCOMPtr<nsIFile> defaultsDir;
rv = GetAppDir()->Clone(getter_AddRefs(defaultsDir));
NS_ENSURE_SUCCESS(rv, rv);
rv = defaultsDir->AppendNative(NS_LITERAL_CSTRING("defaults"));
- rv |= defaultsDir->AppendNative(NS_LITERAL_CSTRING("profile"));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = defaultsDir->AppendNative(NS_LITERAL_CSTRING("profile"));
NS_ENSURE_SUCCESS(rv, rv);
NS_ADDREF(*aResult = defaultsDir);
return NS_OK;
}
+nsresult
+nsXREDirProvider::AppendProfilePath(nsIFile* aFile)
+{
+ NS_ASSERTION(aFile, "Null pointer!");
+
+ nsresult rv;
+
+#if defined (XP_MACOSX)
+ if (gAppData->profile) {
+ rv = AppendProfileString(aFile, gAppData->profile);
+ }
+ else {
+ // Note that MacOS ignores the vendor when creating the profile hierarchy -
+ // all application preferences directories live alongside one another in
+ // ~/Library/Application Support/
+ rv = aFile->AppendNative(nsDependentCString(gAppData->name));
+ }
+ NS_ENSURE_SUCCESS(rv, rv);
+
+#elif defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS)
+ if (gAppData->profile) {
+ rv = AppendProfileString(aFile, gAppData->profile);
+ }
+ else {
+ if (gAppData->vendor) {
+ rv = aFile->AppendNative(nsDependentCString(gAppData->vendor));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ rv = aFile->AppendNative(nsDependentCString(gAppData->name));
+ }
+ NS_ENSURE_SUCCESS(rv, rv);
+
+#elif defined(XP_UNIX)
+ // Make it hidden (i.e. using the ".")
+ nsCAutoString folder(".");
+
+ if (gAppData->profile) {
+ // Skip any leading path characters
+ const char* profileStart = gAppData->profile;
+ while (*profileStart == '/' || *profileStart == '\\')
+ profileStart++;
+
+ // On the off chance that someone wanted their folder to be hidden don't
+ // let it become ".."
+ if (*profileStart == '.')
+ profileStart++;
+
+ folder.Append(profileStart);
+ ToLowerCase(folder);
+
+ rv = AppendProfileString(aFile, folder.BeginReading());
+ }
+ else {
+ if (gAppData->vendor) {
+ folder.Append(gAppData->vendor);
+ ToLowerCase(folder);
+
+ rv = aFile->AppendNative(folder);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ folder.Truncate();
+ }
+
+ folder.Append(gAppData->name);
+ ToLowerCase(folder);
+
+ rv = aFile->AppendNative(folder);
+ }
+ NS_ENSURE_SUCCESS(rv, rv);
+
+#else
+#error "Don't know how to get profile path on your platform"
+#endif
+ return NS_OK;
+}
+
+nsresult
+nsXREDirProvider::AppendProfileString(nsIFile* aFile, const char* aPath)
+{
+ NS_ASSERTION(aFile, "Null file!");
+ NS_ASSERTION(aPath, "Null path!");
+
+ nsCAutoString pathDup(aPath);
+
+ char* path = pathDup.BeginWriting();
+
+ nsresult rv;
+ char* subdir;
+ while ((subdir = NS_strtok("/\\", &path))) {
+ rv = aFile->AppendNative(nsDependentCString(subdir));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ return NS_OK;
+}
--- a/toolkit/xre/nsXREDirProvider.h
+++ b/toolkit/xre/nsXREDirProvider.h
@@ -81,17 +81,17 @@ public:
return GetUserDataDirectory(aFile, PR_FALSE);
}
static nsresult GetUserLocalDataDirectory(nsILocalFile* *aFile) {
return GetUserDataDirectory(aFile, PR_TRUE);
}
/* make sure you clone it, if you need to do stuff to it */
nsIFile* GetGREDir() { return mGREDir; }
- nsIFile* GetAppDir() {
+ nsIFile* GetAppDir() {
if (mXULAppDir)
return mXULAppDir;
return mGREDir;
}
/**
* Get the directory under which update directory is created.
* This method may be called before XPCOM is started. aResult
@@ -114,16 +114,24 @@ public:
nsresult GetProfileDir(nsIFile* *aResult);
protected:
nsresult GetFilesInternal(const char* aProperty, nsISimpleEnumerator** aResult);
static nsresult GetUserDataDirectory(nsILocalFile* *aFile, PRBool aLocal);
static nsresult EnsureDirectoryExists(nsIFile* aDirectory);
void EnsureProfileFileExists(nsIFile* aFile);
+ // Determine the profile path within the UAppData directory. This is different
+ // on every major platform.
+ static nsresult AppendProfilePath(nsIFile* aFile);
+
+ // Internal helper that splits a path into components using the '/' and '\\'
+ // delimiters.
+ static inline nsresult AppendProfileString(nsIFile* aFile, const char* aPath);
+
// Calculate all bundle directories, including distribution bundles,
// extensions, and themes
void LoadBundleDirectories();
void LoadAppBundleDirs();
void Append(nsIFile* aDirectory);
nsCOMPtr<nsIDirectoryServiceProvider> mAppProvider;
--- a/toolkit/xre/nsXULAppAPI.h
+++ b/toolkit/xre/nsXULAppAPI.h
@@ -89,17 +89,17 @@ struct nsXREAppData
/**
* The major version, e.g. "0.8.0+". Optional (may be null), but
* required for advanced application features such as the extension
* manager and update service. Must not be the empty string.
*/
const char *version;
- /**
+ /**
* The application's build identifier, e.g. "2004051604"
*/
const char *buildID;
/**
* The application's UUID. Used by the extension manager to determine
* compatible extensions. Optional, but required for advanced application
* features such as the extension manager and update service.
@@ -133,16 +133,33 @@ struct nsXREAppData
*/
const char *minVersion;
const char *maxVersion;
/**
* The server URL to send crash reports to.
*/
const char *crashReporterURL;
+
+ /**
+ * The profile directory that will be used. Optional (may be null). Must not
+ * be the empty string, must be ASCII. The path is split into components
+ * along the path separator characters '/' and '\'.
+ *
+ * The application data directory ("UAppData", see below) is normally
+ * composed as follows, where $HOME is platform-specific:
+ *
+ * UAppData = $HOME[/$vendor]/$name
+ *
+ * If present, the 'profile' string will be used instead of the combination of
+ * vendor and name as follows:
+ *
+ * UAppData = $HOME/$profile
+ */
+ const char *profile;
};
/**
* Indicates whether or not the profile migrator service may be
* invoked at startup when creating a profile.
*/
#define NS_XRE_ENABLE_PROFILE_MIGRATOR (1 << 1)
@@ -159,21 +176,43 @@ struct nsXREAppData
/**
* The contract id for the nsIXULAppInfo service.
*/
#define XULAPPINFO_SERVICE_CONTRACTID \
"@mozilla.org/xre/app-info;1"
/**
- * A directory service key which provides the platform-correct
- * "application data" directory.
- * Windows: Documents and Settings\<User>\Application Data\<Vendor>\<Application>
- * Unix: ~/.<vendor>/<application>
- * Mac: ~/Library/Application Supports/<Application>
+ * A directory service key which provides the platform-correct "application
+ * data" directory as follows, where $name and $vendor are as defined above and
+ * $vendor is optional:
+ *
+ * Windows:
+ * HOME = Documents and Settings\$USER\Application Data
+ * UAppData = $HOME[\$vendor]\$name
+ *
+ * Unix:
+ * HOME = ~
+ * UAppData = $HOME/.[$vendor/]$name
+ *
+ * Mac:
+ * HOME = ~
+ * UAppData = $HOME/Library/Application Support/$name
+ *
+ * Note that the "profile" member above will change the value of UAppData as
+ * follows:
+ *
+ * Windows:
+ * UAppData = $HOME\$profile
+ *
+ * Unix:
+ * UAppData = $HOME/.$profile
+ *
+ * Mac:
+ * UAppData = $HOME/Library/Application Support/$profile
*/
#define XRE_USER_APP_DATA_DIR "UAppData"
/**
* A directory service key which provides a list of all enabled extension
* directories. The list includes compatible platform-specific extension
* subdirectories.
*
@@ -217,17 +256,17 @@ struct nsXREAppData
*
* @param argc/argv Command-line parameters to pass to the application. These
* are in the "native" character set.
*
* @param aAppData Information about the application to be run.
*
* @return A native result code suitable for returning from main().
*
- * @note If the binary is linked against the standalone XPCOM glue,
+ * @note If the binary is linked against the standalone XPCOM glue,
* XPCOMGlueStartup() should be called before this method.
*
* @note XXXbsmedberg Nobody uses the glue yet, but there is a
* potential problem: on windows, the standalone glue calls
* SetCurrentDirectory, and relative paths on the command line
* won't be correct.
*/
XRE_API(int,