Bug 321359 - Give embedders the ability to lock and use profiles through the XRE_InitEmbedding API, r=darin

This commit is contained in:
bsmedberg%covad.net 2006-01-12 15:29:10 +00:00
parent 08104e4050
commit 5a2ae03f16
6 changed files with 363 additions and 245 deletions

View File

@ -42,6 +42,8 @@ void xxxNeverCalledXUL()
XRE_main(0, nsnull, nsnull);
XRE_GetFileFromPath(nsnull, nsnull);
XRE_GetStaticComponents(nsnull, nsnull);
XRE_LockProfileDirectory(nsnull, nsnull);
XRE_InitEmbedding(nsnull, nsnull, nsnull, nsnull, 0);
XRE_NotifyProfile();
XRE_TermEmbedding();
}

View File

@ -54,23 +54,11 @@
#include "nscore.h"
// This directory service key is a lot like "ProfD", except that it will be
// available even when the profile hasn't been "started", or after is has been
// shut down. If we're in "no-profile" mode, such as showing the profile manager UI,
// this key will not be available.
#define NS_APP_PROFILE_DIR_STARTUP "ProfDS"
// This directory service key is a lot like NS_APP_LOCALSTORE_50_FILE,
// but it is always the "main" localstore file, even when we're in safe mode
// and we load localstore from somewhere else.
#define NS_LOCALSTORE_UNSAFE_FILE "LStoreS"
// This directory service key is a lot like NS_APP_USER_PROFILE_LOCAL_50_DIR,
// except that it will be available even when the profile hasn't been
// "started", or after it has been shut down. If we're in "no-profile" mode,
// such as showing the profile manager uI, this key will not be available.
#define NS_APP_PROFILE_LOCAL_DIR_STARTUP "ProfLDS"
class nsACString;
struct nsXREAppData;
struct nsStaticModuleInfo;

View File

@ -46,130 +46,12 @@
#include "nsIToolkitChromeRegistry.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsArrayEnumerator.h"
#include "nsCOMArray.h"
#include "nsAppRunner.h"
#include "nsDirectoryServiceDefs.h"
#include "nsEnumeratorUtils.h"
#include "nsStaticComponents.h"
#include "nsString.h"
class nsEmbeddingDirProvider : public nsIDirectoryServiceProvider2
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDIRECTORYSERVICEPROVIDER
NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
nsEmbeddingDirProvider(nsILocalFile* aGREDir,
nsILocalFile* aAppDir,
nsIDirectoryServiceProvider* aAppProvider) :
mGREDir(aGREDir),
mAppDir(aAppDir),
mAppProvider(aAppProvider) { }
private:
nsCOMPtr<nsILocalFile> mGREDir;
nsCOMPtr<nsILocalFile> mAppDir;
nsCOMPtr<nsIDirectoryServiceProvider> mAppProvider;
};
NS_IMPL_ISUPPORTS2(nsEmbeddingDirProvider,
nsIDirectoryServiceProvider,
nsIDirectoryServiceProvider2)
NS_IMETHODIMP
nsEmbeddingDirProvider::GetFile(const char *aProperty, PRBool *aPersistent,
nsIFile* *aFile)
{
nsresult rv;
if (mAppProvider) {
rv = mAppProvider->GetFile(aProperty, aPersistent, aFile);
if (NS_SUCCEEDED(rv) && *aFile)
return rv;
}
if (!strcmp(aProperty, NS_OS_CURRENT_PROCESS_DIR) ||
!strcmp(aProperty, NS_APP_INSTALL_CLEANUP_DIR)) {
// NOTE: this is *different* than NS_XPCOM_CURRENT_PROCESS_DIR. This points
// to the application dir. NS_XPCOM_CURRENT_PROCESS_DIR points to the toolkit.
return mAppDir->Clone(aFile);
}
if (!strcmp(aProperty, NS_GRE_DIR)) {
return mGREDir->Clone(aFile);
}
if (!strcmp(aProperty, NS_APP_PREF_DEFAULTS_50_DIR))
{
nsCOMPtr<nsIFile> file;
rv = mAppDir->Clone(getter_AddRefs(file));
NS_ENSURE_SUCCESS(rv, rv);
rv = file->AppendNative(NS_LITERAL_CSTRING("defaults"));
NS_ENSURE_SUCCESS(rv, rv);
rv = file->AppendNative(NS_LITERAL_CSTRING("pref"));
NS_ENSURE_SUCCESS(rv, rv);
NS_ADDREF(*aFile = file);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsEmbeddingDirProvider::GetFiles(const char* aProperty,
nsISimpleEnumerator** aResult)
{
nsresult rv;
nsCOMPtr<nsISimpleEnumerator> appEnum;
nsCOMPtr<nsIDirectoryServiceProvider2> appP2
(do_QueryInterface(mAppProvider));
if (appP2) {
rv = appP2->GetFiles(aProperty, getter_AddRefs(appEnum));
if (NS_SUCCEEDED(rv) && rv != NS_SUCCESS_AGGREGATE_RESULT) {
NS_ADDREF(*aResult = appEnum);
return NS_OK;
}
}
nsCOMArray<nsIFile> dirs;
if (!strcmp(aProperty, NS_CHROME_MANIFESTS_FILE_LIST) ||
!strcmp(aProperty, NS_APP_CHROME_DIR_LIST)) {
nsCOMPtr<nsIFile> manifest;
mGREDir->Clone(getter_AddRefs(manifest));
manifest->AppendNative(NS_LITERAL_CSTRING("chrome"));
dirs.AppendObject(manifest);
mAppDir->Clone(getter_AddRefs(manifest));
manifest->AppendNative(NS_LITERAL_CSTRING("chrome"));
dirs.AppendObject(manifest);
}
if (dirs.Count()) {
nsCOMPtr<nsISimpleEnumerator> thisEnum;
rv = NS_NewArrayEnumerator(getter_AddRefs(thisEnum), dirs);
NS_ENSURE_SUCCESS(rv, rv);
if (appEnum) {
return NS_NewUnionEnumerator(aResult, appEnum, thisEnum);
}
NS_ADDREF(*aResult = thisEnum);
return NS_OK;
}
if (appEnum) {
NS_ADDREF(*aResult = appEnum);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
#include "nsXREDirProvider.h"
#include "nsIToolkitProfile.h"
void
XRE_GetStaticComponents(nsStaticModuleInfo const **aStaticComponents,
@ -179,6 +61,20 @@ XRE_GetStaticComponents(nsStaticModuleInfo const **aStaticComponents,
*aComponentCount = kStaticModuleCount;
}
nsresult
XRE_LockProfileDirectory(nsILocalFile* aDirectory,
nsISupports* *aLockObject)
{
nsCOMPtr<nsIProfileLock> lock;
nsresult rv = NS_LockProfilePath(aDirectory, nsnull, nsnull,
getter_AddRefs(lock));
if (NS_SUCCEEDED(rv))
NS_ADDREF(*aLockObject = lock);
return rv;
}
static nsStaticModuleInfo *sCombined;
static PRInt32 sInitCounter;
@ -189,23 +85,30 @@ XRE_InitEmbedding(nsILocalFile *aLibXULDirectory,
nsStaticModuleInfo const *aStaticComponents,
PRUint32 aStaticComponentCount)
{
if (++sInitCounter > 1)
return NS_OK;
// Initialize some globals to make nsXREDirProvider happy
static char* kNullCommandLine[] = { nsnull };
gArgv = kNullCommandLine;
gArgc = 0;
NS_ENSURE_ARG(aLibXULDirectory);
if (++sInitCounter > 1) // XXXbsmedberg is this really the right solution?
return NS_OK;
if (!aAppDirectory)
aAppDirectory = aLibXULDirectory;
nsresult rv;
nsCOMPtr<nsIDirectoryServiceProvider> dirSvc
(new nsEmbeddingDirProvider(aLibXULDirectory,
aAppDirectory,
aAppDirProvider));
if (!dirSvc)
new nsXREDirProvider; // This sets gDirServiceProvider
if (!gDirServiceProvider)
return NS_ERROR_OUT_OF_MEMORY;
rv = gDirServiceProvider->Initialize(aAppDirectory, aLibXULDirectory,
aAppDirProvider);
if (NS_FAILED(rv))
return rv;
// Combine the toolkit static components and the app components.
PRUint32 combinedCount = kStaticModuleCount + aStaticComponentCount;
@ -218,7 +121,7 @@ XRE_InitEmbedding(nsILocalFile *aLibXULDirectory,
memcpy(sCombined + kStaticModuleCount, aStaticComponents,
sizeof(nsStaticModuleInfo) * aStaticComponentCount);
rv = NS_InitXPCOM3(nsnull, aAppDirectory, dirSvc,
rv = NS_InitXPCOM3(nsnull, aAppDirectory, gDirServiceProvider,
sCombined, combinedCount);
if (NS_FAILED(rv))
return rv;
@ -247,12 +150,24 @@ XRE_InitEmbedding(nsILocalFile *aLibXULDirectory,
return NS_OK;
}
void
XRE_NotifyProfile()
{
NS_ASSERTION(gDirServiceProvider, "XRE_InitEmbedding was not called!");
gDirServiceProvider->DoStartup();
}
void
XRE_TermEmbedding()
{
if (--sInitCounter != 0)
return;
NS_ASSERTION(gDirServiceProvider,
"XRE_TermEmbedding without XRE_InitEmbedding");
gDirServiceProvider->DoShutdown();
NS_ShutdownXPCOM(nsnull);
delete [] sCombined;
delete gDirServiceProvider;
}

View File

@ -52,12 +52,14 @@
#include "nsAppDirectoryServiceDefs.h"
#include "nsDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#include "nsXULAppAPI.h"
#include "nsINIParser.h"
#include "nsDependentString.h"
#include "nsCOMArray.h"
#include "nsArrayEnumerator.h"
#include "nsEnumeratorUtils.h"
#include <stdlib.h>
@ -106,23 +108,31 @@ nsXREDirProvider::~nsXREDirProvider()
}
nsresult
nsXREDirProvider::Initialize(nsIFile *aXULAppDir)
nsXREDirProvider::Initialize(nsIFile *aXULAppDir,
nsILocalFile *aGREDir,
nsIDirectoryServiceProvider* aAppProvider)
{
mAppProvider = aAppProvider;
mXULAppDir = aXULAppDir;
nsCOMPtr<nsILocalFile> lf;
nsresult rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
if (NS_FAILED(rv))
return rv;
if (aGREDir) {
mGREDir = aGREDir;
}
else {
nsCOMPtr<nsILocalFile> lf;
nsresult rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIFile> greDir;
rv = lf->GetParent(getter_AddRefs(greDir));
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIFile> greDir;
rv = lf->GetParent(getter_AddRefs(greDir));
if (NS_FAILED(rv))
return rv;
mGREDir = do_QueryInterface(greDir);
if (!mGREDir)
return NS_ERROR_FAILURE;
mGREDir = do_QueryInterface(greDir);
if (!mGREDir)
return NS_ERROR_FAILURE;
}
return NS_OK;
}
@ -175,18 +185,57 @@ NS_IMETHODIMP
nsXREDirProvider::GetFile(const char* aProperty, PRBool* aPersistent,
nsIFile** aFile)
{
nsresult rv;
PRBool gettingProfile = PR_FALSE;
if (!strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR)) {
// If XRE_NotifyProfile hasn't been called, don't fall through to
// mAppProvider on the profile keys.
if (!mProfileNotified)
return NS_ERROR_FAILURE;
if (mProfileLocalDir)
return mProfileLocalDir->Clone(aFile);
if (mAppProvider)
return mAppProvider->GetFile(aProperty, aPersistent, aFile);
// This falls through to the case below
gettingProfile = PR_TRUE;
}
if (!strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) || gettingProfile) {
if (!mProfileNotified)
return NS_ERROR_FAILURE;
if (mProfileDir)
return mProfileDir->Clone(aFile);
if (mAppProvider)
return mAppProvider->GetFile(aProperty, aPersistent, aFile);
// If we don't succeed here, bail early so that we aren't reentrant
// through the "GetProfileDir" call below.
return NS_ERROR_FAILURE;
}
if (mAppProvider) {
rv = mAppProvider->GetFile(aProperty, aPersistent, aFile);
if (NS_SUCCEEDED(rv) && *aFile)
return rv;
}
*aPersistent = PR_TRUE;
if (!strcmp(aProperty, NS_GRE_DIR)) {
return mGREDir->Clone(aFile);
}
if (!strcmp(aProperty, NS_OS_CURRENT_PROCESS_DIR) ||
else if (!strcmp(aProperty, NS_OS_CURRENT_PROCESS_DIR) ||
!strcmp(aProperty, NS_APP_INSTALL_CLEANUP_DIR)) {
return GetAppDir()->Clone(aFile);
}
nsresult rv = NS_ERROR_FAILURE;
rv = NS_ERROR_FAILURE;
nsCOMPtr<nsIFile> file;
if (!strcmp(aProperty, NS_APP_PROFILE_DEFAULTS_50_DIR) ||
@ -210,29 +259,34 @@ nsXREDirProvider::GetFile(const char* aProperty, PRBool* aPersistent,
}
else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_FILE)) {
rv = GetUserAppDataDirectory((nsILocalFile**)(nsIFile**) getter_AddRefs(file));
rv |= file->AppendNative(NS_LITERAL_CSTRING(APP_REGISTRY_NAME));
if (NS_SUCCEEDED(rv))
rv = file->AppendNative(NS_LITERAL_CSTRING(APP_REGISTRY_NAME));
}
else if (!strcmp(aProperty, NS_APP_USER_PROFILES_ROOT_DIR)) {
rv = GetUserAppDataDirectory((nsILocalFile**)(nsIFile**) getter_AddRefs(file));
if (NS_SUCCEEDED(rv)) {
#if !defined(XP_UNIX) || defined(XP_MACOSX)
rv |= file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
#endif
// We must create the profile directory here if it does not exist.
rv |= EnsureDirectoryExists(file);
// We must create the profile directory here if it does not exist.
rv |= EnsureDirectoryExists(file);
}
}
else if (!strcmp(aProperty, NS_APP_USER_PROFILES_LOCAL_ROOT_DIR)) {
rv = GetUserLocalDataDirectory((nsILocalFile**)(nsIFile**) getter_AddRefs(file));
if (NS_SUCCEEDED(rv)) {
#if !defined(XP_UNIX) || defined(XP_MACOSX)
rv |= file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
#endif
// We must create the profile directory here if it does not exist.
rv |= EnsureDirectoryExists(file);
// We must create the profile directory here if it does not exist.
rv |= EnsureDirectoryExists(file);
}
}
else if (!strcmp(aProperty, XRE_EXECUTABLE_FILE)) {
else if (!strcmp(aProperty, XRE_EXECUTABLE_FILE) && gArgv[0]) {
nsCOMPtr<nsILocalFile> lf;
rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
if (NS_SUCCEEDED(rv))
@ -241,93 +295,84 @@ nsXREDirProvider::GetFile(const char* aProperty, PRBool* aPersistent,
else if (!strcmp(aProperty, "resource:app")) {
rv = GetAppDir()->Clone(getter_AddRefs(file));
}
else if (mProfileDir) {
else if (!strcmp(aProperty, NS_APP_PROFILE_DIR_STARTUP) && mProfileDir) {
return mProfileDir->Clone(aFile);
}
else if (!strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
if (mProfileLocalDir)
return mProfileLocalDir->Clone(aFile);
if (mProfileDir)
return mProfileDir->Clone(aFile);
if (mAppProvider)
return mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP, aPersistent,
aFile);
}
else if (NS_SUCCEEDED(GetProfileStartupDir(getter_AddRefs(file)))) {
// We need to allow component, xpt, and chrome registration to
// occur prior to the profile-after-change notification.
if (!strcmp(aProperty, NS_XPCOM_COMPONENT_REGISTRY_FILE)) {
rv = mProfileDir->Clone(getter_AddRefs(file));
rv |= file->AppendNative(NS_LITERAL_CSTRING("compreg.dat"));
rv = file->AppendNative(NS_LITERAL_CSTRING("compreg.dat"));
}
else if (!strcmp(aProperty, NS_XPCOM_XPTI_REGISTRY_FILE)) {
rv = mProfileDir->Clone(getter_AddRefs(file));
rv |= file->AppendNative(NS_LITERAL_CSTRING("xpti.dat"));
rv = file->AppendNative(NS_LITERAL_CSTRING("xpti.dat"));
}
else if (!strcmp(aProperty, NS_APP_USER_CHROME_DIR)) {
rv = mProfileDir->Clone(getter_AddRefs(file));
rv |= file->AppendNative(NS_LITERAL_CSTRING("chrome"));
}
else if (!strcmp(aProperty, NS_APP_PROFILE_DIR_STARTUP) && mProfileDir) {
return mProfileDir->Clone(aFile);
}
else if (!strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP) &&
mProfileLocalDir) {
return mProfileLocalDir->Clone(aFile);
}
else if (mProfileNotified) {
if (!strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) ||
!strcmp(aProperty, NS_APP_PREFS_50_DIR)) {
return mProfileDir->Clone(aFile);
}
else if (!strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR)) {
return mProfileLocalDir->Clone(aFile);
}
else if (!strcmp(aProperty, NS_APP_PREFS_50_FILE)) {
rv = mProfileDir->Clone(getter_AddRefs(file));
rv |= file->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
}
else if (!strcmp(aProperty, NS_LOCALSTORE_UNSAFE_FILE)) {
rv = mProfileDir->Clone(getter_AddRefs(file));
rv |= file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
}
else if (!strcmp(aProperty, NS_APP_LOCALSTORE_50_FILE)) {
rv = mProfileDir->Clone(getter_AddRefs(file));
if (gSafeMode) {
rv |= file->AppendNative(NS_LITERAL_CSTRING("localstore-safe.rdf"));
file->Remove(PR_FALSE);
}
else {
rv |= file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
EnsureProfileFileExists(file);
}
}
else if (!strcmp(aProperty, NS_APP_HISTORY_50_FILE)) {
rv = mProfileDir->Clone(getter_AddRefs(file));
rv |= file->AppendNative(NS_LITERAL_CSTRING("history.dat"));
}
else if (!strcmp(aProperty, NS_APP_USER_MIMETYPES_50_FILE)) {
rv = mProfileDir->Clone(getter_AddRefs(file));
rv |= file->AppendNative(NS_LITERAL_CSTRING("mimeTypes.rdf"));
EnsureProfileFileExists(file);
}
else if (!strcmp(aProperty, NS_APP_STORAGE_50_FILE)) {
rv = mProfileDir->Clone(getter_AddRefs(file));
rv |= file->AppendNative(NS_LITERAL_CSTRING("storage.sdb"));
}
else if (!strcmp(aProperty, NS_APP_DOWNLOADS_50_FILE)) {
rv = mProfileDir->Clone(getter_AddRefs(file));
rv |= file->AppendNative(NS_LITERAL_CSTRING("downloads.rdf"));
}
// XXXbsmedberg move these defines into application-specific providers.
else if (!strcmp(aProperty, NS_APP_MAIL_50_DIR)) {
rv = mProfileDir->Clone(getter_AddRefs(file));
rv |= file->AppendNative(NS_LITERAL_CSTRING("Mail"));
}
else if (!strcmp(aProperty, NS_APP_IMAP_MAIL_50_DIR)) {
rv = mProfileDir->Clone(getter_AddRefs(file));
rv |= file->AppendNative(NS_LITERAL_CSTRING("ImapMail"));
}
else if (!strcmp(aProperty, NS_APP_NEWS_50_DIR)) {
rv = mProfileDir->Clone(getter_AddRefs(file));
rv |= file->AppendNative(NS_LITERAL_CSTRING("News"));
}
else if (!strcmp(aProperty, NS_APP_MESSENGER_FOLDER_CACHE_50_DIR)) {
rv = mProfileDir->Clone(getter_AddRefs(file));
rv |= file->AppendNative(NS_LITERAL_CSTRING("panacea.dat"));
}
rv = file->AppendNative(NS_LITERAL_CSTRING("chrome"));
}
}
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
if (!file) return NS_ERROR_FAILURE;
if (NS_SUCCEEDED(GetProfileDir(getter_AddRefs(file)))) {
if (!strcmp(aProperty, NS_APP_PREFS_50_DIR)) {
rv = NS_OK;
}
else if (!strcmp(aProperty, NS_APP_PREFS_50_FILE)) {
rv = file->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
}
else if (!strcmp(aProperty, NS_LOCALSTORE_UNSAFE_FILE)) {
rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
}
else if (!strcmp(aProperty, NS_APP_LOCALSTORE_50_FILE)) {
if (gSafeMode) {
rv = file->AppendNative(NS_LITERAL_CSTRING("localstore-safe.rdf"));
file->Remove(PR_FALSE);
}
else {
rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
EnsureProfileFileExists(file);
}
}
else if (!strcmp(aProperty, NS_APP_HISTORY_50_FILE)) {
rv = file->AppendNative(NS_LITERAL_CSTRING("history.dat"));
}
else if (!strcmp(aProperty, NS_APP_USER_MIMETYPES_50_FILE)) {
rv = file->AppendNative(NS_LITERAL_CSTRING("mimeTypes.rdf"));
EnsureProfileFileExists(file);
}
else if (!strcmp(aProperty, NS_APP_STORAGE_50_FILE)) {
rv = file->AppendNative(NS_LITERAL_CSTRING("storage.sdb"));
}
else if (!strcmp(aProperty, NS_APP_DOWNLOADS_50_FILE)) {
rv = file->AppendNative(NS_LITERAL_CSTRING("downloads.rdf"));
}
// XXXbsmedberg move these defines into application-specific providers.
else if (!strcmp(aProperty, NS_APP_MAIL_50_DIR)) {
rv = file->AppendNative(NS_LITERAL_CSTRING("Mail"));
}
else if (!strcmp(aProperty, NS_APP_IMAP_MAIL_50_DIR)) {
rv = file->AppendNative(NS_LITERAL_CSTRING("ImapMail"));
}
else if (!strcmp(aProperty, NS_APP_NEWS_50_DIR)) {
rv = file->AppendNative(NS_LITERAL_CSTRING("News"));
}
else if (!strcmp(aProperty, NS_APP_MESSENGER_FOLDER_CACHE_50_DIR)) {
rv = file->AppendNative(NS_LITERAL_CSTRING("panacea.dat"));
}
}
if (NS_FAILED(rv) || !file)
return NS_ERROR_FAILURE;
NS_ADDREF(*aFile = file);
return NS_OK;
@ -422,6 +467,44 @@ static const char *const kAppendChromeManifests[] =
NS_IMETHODIMP
nsXREDirProvider::GetFiles(const char* aProperty, nsISimpleEnumerator** aResult)
{
nsresult rv;
nsCOMPtr<nsISimpleEnumerator> appEnum;
nsCOMPtr<nsIDirectoryServiceProvider2>
appP2(do_QueryInterface(mAppProvider));
if (appP2) {
rv = appP2->GetFiles(aProperty, getter_AddRefs(appEnum));
if (NS_FAILED(rv)) {
appEnum = nsnull;
}
else if (rv != NS_SUCCESS_AGGREGATE_RESULT) {
NS_ADDREF(*aResult = appEnum);
return NS_OK;
}
}
nsCOMPtr<nsISimpleEnumerator> xreEnum;
rv = GetFilesInternal(aProperty, getter_AddRefs(xreEnum));
if (NS_FAILED(rv)) {
if (appEnum) {
NS_ADDREF(*aResult = appEnum);
return NS_SUCCESS_AGGREGATE_RESULT;
}
return rv;
}
rv = NS_NewUnionEnumerator(aResult, appEnum, xreEnum);
if (NS_FAILED(rv))
return rv;
return NS_SUCCESS_AGGREGATE_RESULT;
}
nsresult
nsXREDirProvider::GetFilesInternal(const char* aProperty,
nsISimpleEnumerator** aResult)
{
nsresult rv = NS_OK;
*aResult = nsnull;
@ -697,10 +780,53 @@ GetShellFolderPath(int folder, char result[MAXPATHLEN])
}
#endif
nsresult
nsXREDirProvider::GetProfileStartupDir(nsIFile* *aResult)
{
if (mProfileDir)
return mProfileDir->Clone(aResult);
if (mAppProvider) {
nsCOMPtr<nsIFile> needsclone;
PRBool dummy;
nsresult rv = mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP,
&dummy,
getter_AddRefs(needsclone));
if (NS_SUCCEEDED(rv))
return needsclone->Clone(aResult);
}
return NS_ERROR_FAILURE;
}
nsresult
nsXREDirProvider::GetProfileDir(nsIFile* *aResult)
{
if (mProfileDir) {
if (!mProfileNotified)
return NS_ERROR_FAILURE;
return mProfileDir->Clone(aResult);
}
if (mAppProvider) {
nsCOMPtr<nsIFile> needsclone;
PRBool dummy;
nsresult rv = mAppProvider->GetFile(NS_APP_USER_PROFILE_50_DIR,
&dummy,
getter_AddRefs(needsclone));
if (NS_SUCCEEDED(rv))
return needsclone->Clone(aResult);
}
return NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, aResult);
}
nsresult
nsXREDirProvider::GetUserDataDirectory(nsILocalFile** aFile, PRBool aLocal)
{
NS_ASSERTION(gAppData, "gAppData not initialized!");
if (!gAppData)
return NS_ERROR_FAILURE;
// Copied from nsAppFileLocationProvider (more or less)
nsresult rv;

View File

@ -57,7 +57,11 @@ public:
NS_DECL_NSIPROFILESTARTUP
nsXREDirProvider();
nsresult Initialize(nsIFile *aXULAppDir);
// if aXULAppDir is null, use gArgv[0]
nsresult Initialize(nsIFile *aXULAppDir,
nsILocalFile *aGREDir = nsnull,
nsIDirectoryServiceProvider* aAppProvider = nsnull);
~nsXREDirProvider();
// We only set the profile dir, we don't ensure that it exists;
@ -85,11 +89,27 @@ public:
return mGREDir;
}
/**
* Get the profile startup directory as determined by this class or by
* mAppProvider. This method may be called before XPCOM is started. aResult
* is a clone, it may be modified.
*/
nsresult GetProfileStartupDir(nsIFile* *aResult);
/**
* Get the profile directory as determined by this class or by an
* embedder-provided XPCOM directory provider. Only call this method
* when XPCOM is initialized! aResult is a clone, it may be modified.
*/
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);
nsCOMPtr<nsIDirectoryServiceProvider> mAppProvider;
nsCOMPtr<nsILocalFile> mGREDir;
nsCOMPtr<nsIFile> mXULAppDir;
nsCOMPtr<nsIFile> mProfileDir;

View File

@ -44,6 +44,7 @@
#include "nsID.h"
#include "xrecore.h"
#include "nsXPCOM.h"
#include "nsISupports.h"
/**
* Application-specific data needed to start the apprunner.
@ -160,6 +161,28 @@ struct nsXREAppData
*/
#define XRE_EXECUTABLE_FILE "XREExeF"
/**
* A directory service key which specifies the profile
* directory. Unlike the NS_APP_USER_PROFILE_50_DIR key, this key may
* be available when the profile hasn't been "started", or after is
* has been shut down. If the application is running without a
* profile, such as when showing the profile manager UI, this key will
* not be available. This key is provided by the XUL apprunner or by
* the aAppDirProvider object passed to XRE_InitEmbedding.
*/
#define NS_APP_PROFILE_DIR_STARTUP "ProfDS"
/**
* A directory service key which specifies the profile
* directory. Unlike the NS_APP_USER_PROFILE_LOCAL_50_DIR key, this key may
* be available when the profile hasn't been "started", or after is
* has been shut down. If the application is running without a
* profile, such as when showing the profile manager UI, this key will
* not be available. This key is provided by the XUL apprunner or by
* the aAppDirProvider object passed to XRE_InitEmbedding.
*/
#define NS_APP_PROFILE_LOCAL_DIR_STARTUP "ProfLDS"
/**
* Begin an XUL application. Does not return until the user exits the
* application.
@ -205,6 +228,17 @@ XRE_API(void,
XRE_GetStaticComponents, (nsStaticModuleInfo const **aStaticComponents,
PRUint32 *aComponentCount))
/**
* Lock a profile directory using platform-specific semantics.
*
* @param aDirectory The profile directory to lock.
* @param aLockObject An opaque lock object. The directory will remain locked
* as long as the XPCOM reference is held.
*/
XRE_API(nsresult,
XRE_LockProfileDirectory, (nsILocalFile* aDirectory,
nsISupports* *aLockObject))
/**
* Initialize libXUL for embedding purposes.
*
@ -212,7 +246,8 @@ XRE_API(void,
* was found.
* @param aAppDirectory The directory in which the application components
* and resources can be found. This will map to
* the "resource:app" directory service key.
* the NS_OS_CURRENT_PROCESS_DIR directory service
* key.
* @param aAppDirProvider A directory provider for the application. This
* provider will be aggregated by a libxul provider
* which will provide the base required GRE keys.
@ -237,6 +272,38 @@ XRE_API(nsresult,
nsStaticModuleInfo const *aStaticComponents,
PRUint32 aStaticComponentCount))
/**
* Fire notifications to inform the toolkit about a new profile. This
* method should be called after XRE_InitEmbedding if the embedder
* wishes to run with a profile. Normally the embedder should call
* XRE_LockProfileDirectory to lock the directory before calling this
* method.
*
* @note There are two possibilities for selecting a profile:
*
* 1) Select the profile before calling XRE_InitEmbedding. The aAppDirProvider
* object passed to XRE_InitEmbedding should provide the
* NS_APP_USER_PROFILE_50_DIR key, and may also provide the following keys:
* - NS_APP_USER_PROFILE_LOCAL_50_DIR
* - NS_APP_PROFILE_DIR_STARTUP
* - NS_APP_PROFILE_LOCAL_DIR_STARTUP
* In this scenario XRE_NotifyProfile should be called immediately after
* XRE_InitEmbedding. Component registration information will be stored in
* the profile and JS components may be stored in the fastload cache.
*
* 2) Select a profile some time after calling XRE_InitEmbedding. In this case
* the embedder must install a directory service provider which provides
* NS_APP_USER_PROFILE_50_DIR and optionally
* NS_APP_USER_PROFILE_LOCAL_50_DIR. Component registration information
* will be stored in the application directory and JS components will not
* fastload.
*/
XRE_API(void,
XRE_NotifyProfile, ())
/**
* Terminate embedding started with XRE_InitEmbedding or XRE_InitEmbedding2
*/
XRE_API(void,
XRE_TermEmbedding, ())