Bug 396209 - "Allow applications to specify a profile directory from application.ini". r=luser, a=bsmedberg. Also fixes bugs 396486, 396199, and 386164.

This commit is contained in:
bent.mozilla@gmail.com 2007-09-26 11:35:21 -07:00
parent f1194c9bde
commit 84f84a474c
10 changed files with 269 additions and 150 deletions

View File

@ -561,17 +561,17 @@ nsresult nsProfileLock::Lock(nsILocalFile* aProfileDir,
}
#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;

View File

@ -413,9 +413,22 @@ int main(int argc, char** argv)
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;
}

View File

@ -296,7 +296,7 @@ static void TryInitGnome()
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 =
@ -495,7 +495,7 @@ bool UIGetSettingsPath(const string& vendor,
string& settingsPath)
{
char* home = getenv("HOME");
if (!home)
return false;
@ -504,14 +504,14 @@ bool UIGetSettingsPath(const string& vendor,
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)
@ -553,4 +553,3 @@ std::ofstream* UIOpenWrite(const string& filename)
{
return new std::ofstream(filename.c_str(), std::ios::out);
}

View File

@ -494,9 +494,6 @@ bool UIGetSettingsPath(const string& vendor,
settingsPath = [destPath UTF8String];
if (!UIEnsurePathExists(settingsPath))
return false;
return true;
}

View File

@ -697,9 +697,11 @@ void UIShowCrashUI(const string& dumpFile,
}
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;
@ -749,8 +751,6 @@ bool UIGetSettingsPath(const string& vendor,
}
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;
}

View File

@ -212,7 +212,7 @@ bool MinidumpCallback(const XP_CHAR* dump_path,
}
#endif
}
#if defined(XP_WIN32)
XP_CHAR cmdLine[CMDLINE_SIZE];
size = CMDLINE_SIZE;
@ -484,7 +484,7 @@ 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)
{
@ -537,7 +537,7 @@ InitUserID(nsACString& aUserID)
CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
if (!uuid)
return NS_ERROR_FAILURE;
CFUUIDBytes bytes = CFUUIDGetUUIDBytes(uuid);
memcpy(&id, &bytes, sizeof(nsID));
@ -553,7 +553,7 @@ InitUserID(nsACString& aUserID)
nsCAutoString id_str(id.ToString());
aUserID = Substring(id_str, 1, id_str.Length()-2);
return NS_OK;
}
@ -566,7 +566,7 @@ InitInstallTime(nsACString& aInstallTime)
char buf[16];
sprintf(buf, "%ld", t);
aInstallTime = buf;
return NS_OK;
}
@ -594,6 +594,28 @@ nsresult SetupExtraData(nsILocalFile* aAppDataDirectory,
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)))
@ -668,7 +690,7 @@ static void ReplaceChar(nsCString& str, const nsACString& character,
const nsACString& replacement)
{
nsCString::const_iterator start, end;
str.BeginReading(start);
str.EndReading(end);
@ -713,7 +735,7 @@ nsresult AnnotateCrashReport(const nsACString &key, const nsACString &data)
return NS_ERROR_INVALID_ARG;
nsCString escapedData(data);
// escape backslashes
ReplaceChar(escapedData, NS_LITERAL_CSTRING("\\"),
NS_LITERAL_CSTRING("\\\\"));

View File

@ -78,6 +78,7 @@ ScopedAppData::ScopedAppData(const nsXREAppData* aAppData)
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;
@ -100,6 +101,7 @@ ScopedAppData::~ScopedAppData()
SetAllocatedString(this->buildID, nsnull);
SetAllocatedString(this->ID, nsnull);
SetAllocatedString(this->copyright, nsnull);
SetAllocatedString(this->profile, nsnull);
NS_IF_RELEASE(this->directory);
@ -208,6 +210,7 @@ XRE_ParseAppData(nsILocalFile* aINIFile, nsXREAppData *aAppData)
{ "App", "BuildID", &aAppData->buildID },
{ "App", "ID", &aAppData->ID },
{ "App", "Copyright", &aAppData->copyright },
{ "App", "Profile", &aAppData->profile },
{ nsnull }
};
ReadStrings(parser, strings);

View File

@ -62,13 +62,14 @@
#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
@ -132,7 +133,7 @@ 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;
@ -507,7 +508,7 @@ nsXREDirProvider::GetFiles(const char* aProperty, nsISimpleEnumerator** aResult)
static void
LoadExtensionDirectories(nsINIParser &parser,
const char *aSection,
const char *aSection,
nsCOMArray<nsIFile> &aDirectories)
{
nsresult rv;
@ -583,7 +584,7 @@ nsXREDirProvider::LoadAppBundleDirs()
nsresult rv = mXULAppDir->Clone(getter_AddRefs(dir));
if (NS_FAILED(rv))
return;
dir->AppendNative(NS_LITERAL_CSTRING("distribution"));
dir->AppendNative(NS_LITERAL_CSTRING("bundles"));
@ -633,7 +634,7 @@ nsXREDirProvider::GetFilesInternal(const char* aProperty,
if (!strcmp(aProperty, XRE_EXTENSIONS_DIR_LIST)) {
nsCOMArray<nsIFile> directories;
static const char *const kAppendNothing[] = { nsnull };
LoadBundleDirectories();
@ -712,7 +713,7 @@ nsXREDirProvider::GetFilesInternal(const char* aProperty,
manifests);
rv = NS_NewArrayEnumerator(aResult, manifests);
}
}
else if (!strcmp(aProperty, NS_SKIN_MANIFESTS_FILE_LIST)) {
nsCOMArray<nsIFile> manifests;
@ -850,29 +851,26 @@ nsXREDirProvider::DoShutdown()
}
}
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;
}
@ -885,18 +883,23 @@ 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);
@ -904,25 +907,24 @@ nsXREDirProvider::GetUpdateRootDir(nsIFile* *aResult)
// 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);
@ -988,11 +990,11 @@ nsXREDirProvider::GetUserDataDirectory(nsILocalFile** aFile, PRBool aLocal)
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);
@ -1006,39 +1008,16 @@ nsXREDirProvider::GetUserDataDirectory(nsILocalFile** aFile, PRBool aLocal)
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
@ -1061,15 +1040,6 @@ nsXREDirProvider::GetUserDataDirectory(nsILocalFile** aFile, PRBool aLocal)
*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))
@ -1081,15 +1051,6 @@ nsXREDirProvider::GetUserDataDirectory(nsILocalFile** aFile, PRBool aLocal)
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)
@ -1097,32 +1058,13 @@ nsXREDirProvider::GetUserDataDirectory(nsILocalFile** aFile, PRBool aLocal)
rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), PR_TRUE,
getter_AddRefs(localDir));
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));
NS_ENSURE_SUCCESS(rv, rv);
#else
#error dont_know_how_to_get_product_dir_on_your_platform
#error "Don't know how to get product dir on your platform"
#endif
NS_ENSURE_SUCCESS(rv, rv);
rv = AppendProfilePath(localDir);
NS_ENSURE_SUCCESS(rv, rv);
#ifdef DEBUG_jungshik
nsCAutoString cwd;
@ -1132,8 +1074,7 @@ nsXREDirProvider::GetUserDataDirectory(nsILocalFile** aFile, PRBool aLocal)
rv = EnsureDirectoryExists(localDir);
NS_ENSURE_SUCCESS(rv, rv);
*aFile = localDir;
NS_ADDREF(*aFile);
NS_ADDREF(*aFile = localDir);
return NS_OK;
}
@ -1165,10 +1106,10 @@ 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;
@ -1179,7 +1120,7 @@ nsXREDirProvider::EnsureProfileFileExists(nsIFile *aFile)
rv = defaultsFile->AppendNative(leafName);
if (NS_FAILED(rv)) return;
defaultsFile->CopyToNative(mProfileDir, EmptyCString());
}
@ -1196,10 +1137,107 @@ nsXREDirProvider::GetProfileDefaultsDir(nsIFile* *aResult)
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;
}

View File

@ -86,7 +86,7 @@ public:
/* 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;
@ -119,6 +119,14 @@ protected:
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();

View File

@ -94,7 +94,7 @@ struct nsXREAppData
*/
const char *version;
/**
/**
* The application's build identifier, e.g. "2004051604"
*/
const char *buildID;
@ -138,6 +138,23 @@ struct nsXREAppData
* 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;
};
/**
@ -164,11 +181,33 @@ struct nsXREAppData
"@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"
@ -222,7 +261,7 @@ struct nsXREAppData
*
* @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