fixes bug 291033 "Enable support for profile temp directory on local filesystem" aka "delete my cache please" r=bsmedberg a=chofmann

This commit is contained in:
darin%meer.net 2005-04-26 00:37:23 +00:00
Родитель 1571314243
Коммит 035f8ed08d
18 изменённых файлов: 603 добавлений и 328 удалений

Просмотреть файл

@ -385,7 +385,8 @@ nsProfileMigrator::ImportRegistryProfiles(const nsACString& aAppName)
if (NS_FAILED(rv)) continue;
nsCOMPtr<nsIToolkitProfile> tprofile;
profileSvc->CreateProfile(profileFile, nsDependentCString(profileName),
profileSvc->CreateProfile(profileFile, nsnull,
nsDependentCString(profileName),
getter_AddRefs(tprofile));
migrated = PR_TRUE;
}

Просмотреть файл

@ -253,7 +253,8 @@ nsProfileMigrator::ImportRegistryProfiles(const nsACString& aAppName)
if (NS_FAILED(rv)) continue;
nsCOMPtr<nsIToolkitProfile> tprofile;
profileSvc->CreateProfile(profileFile, nsDependentCString(profileName),
profileSvc->CreateProfile(profileFile, nsnull,
nsDependentCString(profileName),
getter_AddRefs(tprofile));
migrated = PR_TRUE;
}

1
netwerk/cache/src/Makefile.in поставляемый
Просмотреть файл

@ -83,6 +83,7 @@ CPPSRCS += \
nsDiskCacheEntry.cpp \
nsDiskCacheMap.cpp \
nsDiskCacheStreams.cpp \
nsDeleteDir.cpp \
$(NULL)
endif
endif

35
netwerk/cache/src/nsCacheService.cpp поставляемый
Просмотреть файл

@ -66,6 +66,7 @@
#include "nsDirectoryServiceDefs.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsVoidArray.h"
#include "nsDeleteDir.h"
@ -342,16 +343,34 @@ nsCacheProfilePrefObserver::ReadPrefs(nsIPrefBranch* branch)
getter_AddRefs(directory));
if (NS_FAILED(rv)) {
// try to get the profile directory (there may not be a profile yet)
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
getter_AddRefs(directory));
#if DEBUG
if (NS_FAILED(rv)) {
// use current process directory during development
rv = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR,
getter_AddRefs(directory));
nsCOMPtr<nsIFile> profDir;
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
getter_AddRefs(profDir));
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_LOCAL_50_DIR,
getter_AddRefs(directory));
if (!directory)
directory = profDir;
else if (profDir) {
PRBool same;
if (NS_SUCCEEDED(profDir->Equals(directory, &same)) && !same) {
// We no longer store the cache directory in the main
// profile directory, so we should cleanup the old one.
rv = profDir->AppendNative(NS_LITERAL_CSTRING("Cache"));
if (NS_SUCCEEDED(rv)) {
PRBool exists;
if (NS_SUCCEEDED(profDir->Exists(&exists)) && exists)
DeleteDir(profDir, PR_FALSE);
}
}
}
#endif
}
#if DEBUG
if (!directory) {
// use current process directory during development
rv = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR,
getter_AddRefs(directory));
}
#endif
if (directory)
mDiskCacheParentDirectory = do_QueryInterface(directory, &rv);
}

122
netwerk/cache/src/nsDeleteDir.cpp поставляемый Normal file
Просмотреть файл

@ -0,0 +1,122 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Darin Fisher <darin@meer.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsDeleteDir.h"
#include "nsIFile.h"
#include "nsString.h"
#include "prthread.h"
PR_STATIC_CALLBACK(void) DeleteDirThreadFunc(void *arg)
{
nsIFile *dir = NS_STATIC_CAST(nsIFile *, arg);
dir->Remove(PR_TRUE);
NS_RELEASE(dir);
}
nsresult DeleteDir(nsIFile *dirIn, PRBool moveToTrash)
{
nsresult rv;
nsCOMPtr<nsIFile> trash, dir;
// Need to make a clone of this since we don't want to modify the input
// file object.
rv = dirIn->Clone(getter_AddRefs(dir));
if (NS_FAILED(rv))
return rv;
if (moveToTrash)
{
rv = GetTrashDir(dir, &trash);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIFile> subDir;
rv = trash->Clone(getter_AddRefs(subDir));
if (NS_FAILED(rv))
return rv;
rv = subDir->AppendNative(NS_LITERAL_CSTRING("Trash"));
if (NS_FAILED(rv))
return rv;
rv = subDir->CreateUnique(nsIFile::DIRECTORY_TYPE, 0700);
if (NS_FAILED(rv))
return rv;
rv = dir->MoveToNative(subDir, EmptyCString());
if (NS_FAILED(rv))
return rv;
}
else
{
// we want to pass a clone of the original off to the worker thread.
trash.swap(dir);
}
// Steal ownership of trash directory; let the thread release it.
nsIFile *trashRef = nsnull;
trash.swap(trashRef);
// now, invoke the worker thread
PRThread *thread = PR_CreateThread(PR_USER_THREAD,
DeleteDirThreadFunc,
trashRef,
PR_PRIORITY_LOW,
PR_GLOBAL_THREAD,
PR_UNJOINABLE_THREAD,
0);
if (!thread)
return NS_ERROR_UNEXPECTED;
return NS_OK;
}
nsresult GetTrashDir(nsIFile *target, nsCOMPtr<nsIFile> *result)
{
nsresult rv = target->Clone(getter_AddRefs(*result));
if (NS_FAILED(rv))
return rv;
nsCAutoString leaf;
rv = (*result)->GetNativeLeafName(leaf);
if (NS_FAILED(rv))
return rv;
leaf.AppendLiteral(".Trash");
return (*result)->SetNativeLeafName(leaf);
}

68
netwerk/cache/src/nsDeleteDir.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,68 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Darin Fisher <darin@meer.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsDeleteDir_h__
#define nsDeleteDir_h__
#include "nsCOMPtr.h"
class nsIFile;
/**
* This routine attempts to delete a directory that may contain some files that
* are still in use. This later point is only an issue on Windows and a few
* other systems.
*
* If the moveToTrash parameter is true, then the process for deleting the
* directory creates a sibling directory of the same name with the ".Trash"
* suffix. It then attempts to move the given directory into the corresponding
* trash folder (moving individual files if necessary). Next, it proceeds to
* delete each file in the trash folder on a low-priority background thread.
*
* If the moveToTrash parameter is false, then the given directory is deleted
* directly.
*/
NS_HIDDEN_(nsresult) DeleteDir(nsIFile *dir, PRBool moveToTrash);
/**
* This routine returns the trash directory corresponding to the given
* directory.
*/
NS_HIDDEN_(nsresult) GetTrashDir(nsIFile *dir, nsCOMPtr<nsIFile> *result);
#endif // nsDeleteDir_h__

271
netwerk/cache/src/nsDiskCacheDevice.cpp поставляемый
Просмотреть файл

@ -64,8 +64,6 @@
#include "private/pprio.h"
#endif
#include "nsDiskCacheDevice.h"
#include "nsDiskCacheEntry.h"
#include "nsDiskCacheMap.h"
@ -76,6 +74,8 @@
#include "nsCacheService.h"
#include "nsCache.h"
#include "nsDeleteDir.h"
#include "nsICacheVisitor.h"
#include "nsReadableUtils.h"
#include "nsIInputStream.h"
@ -335,7 +335,6 @@ nsDiskCacheDevice::nsDiskCacheDevice()
: mCacheCapacity(0)
, mCacheMap(nsnull)
, mInitialized(PR_FALSE)
, mFirstInit(PR_TRUE)
{
}
@ -367,7 +366,6 @@ nsDiskCacheDevice::Init()
}
mInitialized = PR_TRUE;
mFirstInit = PR_FALSE;
return NS_OK;
error_exit:
@ -814,22 +812,6 @@ nsDiskCacheDevice::EvictEntries(const char * clientID)
#endif
// "Cache.Trash" directory is a sibling of the "Cache" directory
nsresult
nsDiskCacheDevice::GetCacheTrashDirectory(nsIFile ** result)
{
nsCOMPtr<nsIFile> cacheTrashDir;
nsresult rv = mCacheDirectory->Clone(getter_AddRefs(cacheTrashDir));
if (NS_FAILED(rv)) return rv;
rv = cacheTrashDir->SetNativeLeafName(NS_LITERAL_CSTRING("Cache.Trash"));
if (NS_FAILED(rv)) return rv;
*result = cacheTrashDir.get();
NS_ADDREF(*result);
return rv;
}
nsresult
nsDiskCacheDevice::OpenDiskCache()
{
@ -838,48 +820,46 @@ nsDiskCacheDevice::OpenDiskCache()
// Try opening cache map file.
NS_ASSERTION(mCacheMap == nsnull, "leaking mCacheMap");
mCacheMap = new nsDiskCacheMap;
if (!mCacheMap) {
if (!mCacheMap)
return NS_ERROR_OUT_OF_MEMORY;
}
// if we don't have a cache directory, create one and open it
PRBool cacheDirExists;
rv = mCacheDirectory->Exists(&cacheDirExists);
if (NS_FAILED(rv)) return rv;
PRBool exists;
rv = mCacheDirectory->Exists(&exists);
if (NS_FAILED(rv))
return rv;
if (cacheDirExists) {
PRBool trashing = PR_FALSE;
if (exists) {
rv = mCacheMap->Open(mCacheDirectory);
// move "corrupt" caches to trash
if (rv == NS_ERROR_FILE_CORRUPTED) {
rv = MoveCacheToTrash(nsnull); // ignore returned dir name
if (NS_FAILED(rv)) return rv;
cacheDirExists = PR_FALSE;
} else if (NS_FAILED(rv)) return rv;
rv = DeleteDir(mCacheDirectory, PR_TRUE);
if (NS_FAILED(rv))
return rv;
exists = PR_FALSE;
trashing = PR_TRUE;
}
else if (NS_FAILED(rv))
return rv;
}
// if we don't have a cache directory, create one and open it
if (!cacheDirExists) {
if (!exists) {
rv = InitializeCacheDirectory();
if (NS_FAILED(rv)) return rv;
if (NS_FAILED(rv))
return rv;
}
if (! mFirstInit) return NS_OK; // we're done
// Empty Cache Trash
PRBool trashDirExists;
nsCOMPtr<nsIFile> trashDir;
rv = GetCacheTrashDirectory(getter_AddRefs(trashDir));
if (NS_FAILED(rv)) return rv;
rv = trashDir->Exists(&trashDirExists);
if (NS_FAILED(rv)) return rv;
if (trashDirExists) {
nsCOMArray<nsIFile> * trashList;
rv = ListTrashContents(&trashList);
if (NS_FAILED(rv)) return rv;
rv = DeleteFiles(trashList); // spin up thread to delete contents
if (NS_FAILED(rv)) return rv;
if (!trashing) {
// delete any trash files leftover from a previous run
nsCOMPtr<nsIFile> trashDir;
GetTrashDir(mCacheDirectory, &trashDir);
if (trashDir) {
PRBool exists;
if (NS_SUCCEEDED(trashDir->Exists(&exists)) && exists)
DeleteDir(trashDir, PR_FALSE);
}
}
return NS_OK;
@ -889,193 +869,18 @@ nsDiskCacheDevice::OpenDiskCache()
nsresult
nsDiskCacheDevice::ClearDiskCache()
{
if (mBindery.ActiveBindings()) return NS_ERROR_CACHE_IN_USE;
if (mBindery.ActiveBindings())
return NS_ERROR_CACHE_IN_USE;
nsresult rv;
nsCOMPtr<nsIFile> trashDir;
nsCOMArray<nsIFile> * deleteList = new nsCOMArray<nsIFile>;
if (!deleteList) return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = Shutdown_Private(PR_FALSE); // false: don't bother flushing
if (NS_FAILED(rv))
return rv;
rv = Shutdown_Private(PR_FALSE); // false = don't bother flushing
if (NS_FAILED(rv)) goto error_exit;
rv = DeleteDir(mCacheDirectory, PR_TRUE);
if (NS_FAILED(rv))
return rv;
rv = MoveCacheToTrash(getter_AddRefs(trashDir));
if (NS_FAILED(rv)) goto error_exit;
rv = deleteList->AppendObject(trashDir);
if (NS_FAILED(rv)) goto error_exit;
rv = DeleteFiles(deleteList);
if (NS_FAILED(rv)) goto error_exit;
rv = Init();
return rv;
error_exit:
delete deleteList;
return rv;
}
// function passed to PR_CreateThread
static void PR_CALLBACK
DoDeleteFileList(void *arg)
{
nsCOMArray<nsIFile> * fileList = NS_STATIC_CAST(nsCOMArray<nsIFile> *, arg);
nsresult rv;
// iterate over items in fileList, recursively deleting each
PRInt32 count = fileList->Count();
for (PRInt32 i=0; i<count; i++) {
nsIFile * item = fileList->ObjectAt(i);
CACHE_LOG_PATH(PR_LOG_ALWAYS, "deleting: %s\n", item);
rv = item->Remove(PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(rv),"failure cleaning up cache");
}
delete fileList; // destroy nsCOMArray
}
#define DEFAULT_STACK_SIZE 0
nsresult
nsDiskCacheDevice::DeleteFiles(nsCOMArray<nsIFile> * fileList)
{
// start up another thread to delete deleteDir
PRThread * thread;
thread = PR_CreateThread(PR_USER_THREAD,
DoDeleteFileList,
fileList,
PR_PRIORITY_NORMAL,
PR_GLOBAL_THREAD,
PR_UNJOINABLE_THREAD,
DEFAULT_STACK_SIZE);
if (!thread) return NS_ERROR_UNEXPECTED;
return NS_OK;
}
/**
* ListTrashContents - return pointer to array of nsIFile to delete
*/
nsresult
nsDiskCacheDevice::ListTrashContents(nsCOMArray<nsIFile> ** result)
{
nsresult rv;
nsCOMPtr<nsIFile> trashDir;
*result = nsnull;
// does "Cache.Trash" directory exist?
rv = GetCacheTrashDirectory(getter_AddRefs(trashDir));
if (NS_FAILED(rv)) return rv;
PRBool exists;
rv = trashDir->Exists(&exists);
if (NS_FAILED(rv)) return rv;
if (!exists) {
return NS_OK;
}
nsCOMArray<nsIFile> * array = new nsCOMArray<nsIFile>;
if (!array) return NS_ERROR_OUT_OF_MEMORY;
// iterate over trash directory building array of directory objects
nsCOMPtr<nsISimpleEnumerator> dirEntries;
nsCOMPtr<nsIFile> item;
PRBool more, success;
rv = trashDir->GetDirectoryEntries(getter_AddRefs(dirEntries));
if (NS_FAILED(rv) || !dirEntries) goto error_exit; // !dirEntries returns NS_OK
rv = dirEntries->HasMoreElements(&more);
if (NS_FAILED(rv)) goto error_exit;
while (more) {
rv = dirEntries->GetNext(getter_AddRefs(item));
if (NS_FAILED(rv)) goto error_exit;
success = array->AppendObject(item);
if (!success) {
rv = NS_ERROR_OUT_OF_MEMORY;
goto error_exit;
}
rv = dirEntries->HasMoreElements(&more);
if (NS_FAILED(rv)) goto error_exit;
}
// return resulting array
*result = array;
return NS_OK;
error_exit:
delete array;
return rv;
}
// Move 'Cache' dir into unique directory inside 'Cache.Trash', return name of unique directory
nsresult
nsDiskCacheDevice::MoveCacheToTrash(nsIFile ** result)
{
nsresult rv;
nsCOMPtr<nsIFile> trashDir;
if (result) *result = nsnull;
rv = GetCacheTrashDirectory(getter_AddRefs(trashDir));
if (NS_FAILED(rv)) return rv;
// verify cache.trash exists and is a directory
PRBool exists;
rv = trashDir->Exists(&exists);
if (NS_FAILED(rv)) return rv;
if (exists) {
PRBool isDirectory;
rv = trashDir->IsDirectory(&isDirectory);
if (NS_FAILED(rv)) return rv;
if (!isDirectory) {
// delete file or fail
rv = trashDir->Remove(PR_FALSE);
if (NS_FAILED(rv)) return rv;
exists = PR_FALSE;
}
}
if (!exists) {
// cache.trash doesn't exists, so create it
rv = trashDir->Create(nsIFile::DIRECTORY_TYPE, 0777);
if (NS_FAILED(rv)) return rv;
}
// create unique directory
nsCOMPtr<nsIFile> uniqueDir;
rv = trashDir->Clone(getter_AddRefs(uniqueDir));
if (NS_FAILED(rv)) return rv;
rv = uniqueDir->AppendNative(NS_LITERAL_CSTRING("Trash"));
if (NS_FAILED(rv)) return rv;
rv = uniqueDir->CreateUnique(nsIFile::DIRECTORY_TYPE, 0777);
if (NS_FAILED(rv)) return rv;
// move cache directory into unique trash directory
nsCOMPtr<nsIFile> parentDir;
rv = mCacheDirectory->GetParent(getter_AddRefs(parentDir));
if (NS_FAILED(rv)) return rv;
rv = mCacheDirectory->MoveToNative(uniqueDir, EmptyCString());
if (NS_FAILED(rv)) return rv;
// set mCacheDirectory to point to parentDir/Cache/ again
rv = parentDir->AppendNative(NS_LITERAL_CSTRING("Cache"));
if (NS_FAILED(rv)) return rv;
mCacheDirectory = do_QueryInterface(parentDir);
// return unique directory, in case caller wants specifically delete it
if (result)
NS_ADDREF(*result = uniqueDir);
return NS_OK;
return Init();
}

5
netwerk/cache/src/nsDiskCacheDevice.h поставляемый
Просмотреть файл

@ -110,12 +110,8 @@ private:
* Private methods
*/
nsresult GetCacheTrashDirectory(nsIFile ** result);
nsresult OpenDiskCache();
nsresult ClearDiskCache();
nsresult DeleteFiles(nsCOMArray<nsIFile> * fileList);
nsresult ListTrashContents(nsCOMArray<nsIFile> ** result);
nsresult MoveCacheToTrash(nsIFile ** result);
nsresult InitializeCacheDirectory();
@ -129,7 +125,6 @@ private:
PRUint32 mCacheCapacity; // XXX need soft/hard limits, currentTotal
nsDiskCacheMap * mCacheMap;
PRPackedBool mInitialized;
PRPackedBool mFirstInit;
};
#endif // _nsDiskCacheDevice_h_

Просмотреть файл

@ -224,7 +224,7 @@ function onFinish()
// Create profile named profileName in profileRoot.
try {
profile = gProfileService.createProfile(gProfileRoot, profileName);
profile = gProfileService.createProfile(gProfileRoot, null, profileName);
}
catch (e) {
var profileCreationFailed =

Просмотреть файл

@ -45,11 +45,27 @@ interface nsIProfileUnlocker;
* Hold on to a profile lock. Once you release the last reference to this
* interface, the profile lock is released.
*/
[scriptable, uuid(6f987826-e4dd-453d-bb66-a1e46088fced)]
[scriptable, uuid(50e07b0a-f338-4da3-bcdb-f4bb0db94dbe)]
interface nsIProfileLock : nsISupports
{
/**
* The main profile directory.
*/
readonly attribute nsILocalFile directory;
/**
* A directory corresponding to the main profile directory that exists for
* the purpose of storing data on the local filesystem, including cache
* files or other data files that may not represent critical user data.
* (e.g., this directory may not be included as part of a backup scheme.)
*
* In some cases, this directory may just be the main profile directory.
*/
readonly attribute nsILocalFile localDirectory;
/**
* Unlock the profile.
*/
void unlock();
};
@ -58,12 +74,32 @@ interface nsIProfileLock : nsISupports
* @note THIS INTERFACE SHOULD BE IMPLEMENTED BY THE TOOLKIT CODE ONLY! DON'T
* EVEN THINK ABOUT IMPLEMENTING THIS IN JAVASCRIPT!
*/
[scriptable, uuid(0008686a-ee99-4a27-8f1b-190596f535b1)]
[scriptable, uuid(7422b090-4a86-4407-972e-75468a625388)]
interface nsIToolkitProfile : nsISupports
{
/**
* The location of the profile directory.
*/
readonly attribute nsILocalFile rootDir;
/**
* The location of the profile local directory, which may be the same as
* the root directory. See nsIProfileLock::localDirectory.
*/
readonly attribute nsILocalFile localDir;
/**
* The name of the profile.
*/
attribute AUTF8String name;
/**
* Removes the profile from the registry of profiles.
*
* @param removeFiles
* Indicates whether or not the profile directory should be
* removed in addition.
*/
void remove(in boolean removeFiles);
/**

Просмотреть файл

@ -64,17 +64,25 @@ interface nsIToolkitProfileService : nsISupports
* Lock an arbitrary path as a profile. If the path does not exist, it
* will be created and the defaults copied from the application directory.
*/
nsIProfileLock lockProfilePath(in nsILocalFile aDirectory);
nsIProfileLock lockProfilePath(in nsILocalFile aDirectory,
in nsILocalFile aTempDirectory);
/**
* Create a new profile.
*
* @param rootDir The profile directory. May be null, in which case a suitable
* default will be chosen based on the profile name.
* @param name The profile name.
* @param aRootDir
* The profile directory. May be null, in which case a suitable
* default will be chosen based on the profile name.
* @param aTempDir
* The profile temporary directory. May be null, in which case a
* suitable default will be chosen based either on the profile name
* if aRootDir is null or aRootDir itself.
* @param aName
* The profile name.
*/
nsIToolkitProfile createProfile(in nsILocalFile rootDir,
in AUTF8String name);
nsIToolkitProfile createProfile(in nsILocalFile aRootDir,
in nsILocalFile aTempDir,
in AUTF8String aName);
/**
* Returns the number of profiles.

Просмотреть файл

@ -84,13 +84,16 @@ public:
~nsToolkitProfile() { }
private:
nsToolkitProfile(const nsACString& aName, nsILocalFile* aFile,
nsToolkitProfile(const nsACString& aName,
nsILocalFile* aRootDir,
nsILocalFile* aLocalDir,
nsToolkitProfile* aPrev);
friend class nsToolkitProfileLock;
nsCString mName;
nsCOMPtr<nsILocalFile> mFile;
nsCOMPtr<nsILocalFile> mRootDir;
nsCOMPtr<nsILocalFile> mLocalDir;
nsIProfileLock* mLock;
};
@ -101,7 +104,8 @@ public:
NS_DECL_NSIPROFILELOCK
nsresult Init(nsToolkitProfile* aProfile, nsIProfileUnlocker* *aUnlocker);
nsresult Init(nsILocalFile* aDirectory, nsIProfileUnlocker* *aUnlocker);
nsresult Init(nsILocalFile* aDirectory, nsILocalFile* aLocalDirectory,
nsIProfileUnlocker* *aUnlocker);
nsToolkitProfileLock() { }
~nsToolkitProfileLock();
@ -109,6 +113,7 @@ public:
private:
nsCOMPtr<nsToolkitProfile> mProfile;
nsCOMPtr<nsILocalFile> mDirectory;
nsCOMPtr<nsILocalFile> mLocalDirectory;
nsProfileLock mLock;
};
@ -146,6 +151,7 @@ private:
nsCOMPtr<nsToolkitProfile> mFirst;
nsCOMPtr<nsToolkitProfile> mChosen;
nsCOMPtr<nsILocalFile> mAppData;
nsCOMPtr<nsILocalFile> mTempData;
nsCOMPtr<nsILocalFile> mListFile;
PRBool mDirty;
PRBool mStartWithLast;
@ -167,14 +173,17 @@ private:
};
};
nsToolkitProfile::nsToolkitProfile(const nsACString& aName, nsILocalFile* aFile,
nsToolkitProfile::nsToolkitProfile(const nsACString& aName,
nsILocalFile* aRootDir,
nsILocalFile* aLocalDir,
nsToolkitProfile* aPrev) :
mPrev(aPrev),
mName(aName),
mFile(aFile),
mRootDir(aRootDir),
mLocalDir(aLocalDir),
mLock(nsnull)
{
NS_ASSERTION(aFile, "No file!");
NS_ASSERTION(aRootDir, "No file!");
if (aPrev)
aPrev->mNext = this;
@ -187,7 +196,14 @@ NS_IMPL_ISUPPORTS1(nsToolkitProfile, nsIToolkitProfile)
NS_IMETHODIMP
nsToolkitProfile::GetRootDir(nsILocalFile* *aResult)
{
NS_ADDREF(*aResult = mFile);
NS_ADDREF(*aResult = mRootDir);
return NS_OK;
}
NS_IMETHODIMP
nsToolkitProfile::GetLocalDir(nsILocalFile* *aResult)
{
NS_ADDREF(*aResult = mLocalDir);
return NS_OK;
}
@ -219,8 +235,19 @@ nsToolkitProfile::Remove(PRBool removeFiles)
if (mLock)
return NS_ERROR_FILE_IS_LOCKED;
if (removeFiles)
mFile->Remove(PR_TRUE);
if (removeFiles) {
PRBool equals;
nsresult rv = mRootDir->Equals(mLocalDir, &equals);
if (NS_FAILED(rv))
return rv;
// The root dir might contain the temp dir, so remove
// the temp dir first.
if (!equals)
mLocalDir->Remove(PR_TRUE);
mRootDir->Remove(PR_TRUE);
}
if (mPrev)
mPrev->mNext = mNext;
@ -265,7 +292,7 @@ nsresult
nsToolkitProfileLock::Init(nsToolkitProfile* aProfile, nsIProfileUnlocker* *aUnlocker)
{
nsresult rv;
rv = Init(aProfile->mFile, aUnlocker);
rv = Init(aProfile->mRootDir, aProfile->mLocalDir, aUnlocker);
if (NS_SUCCEEDED(rv))
mProfile = aProfile;
@ -273,14 +300,17 @@ nsToolkitProfileLock::Init(nsToolkitProfile* aProfile, nsIProfileUnlocker* *aUnl
}
nsresult
nsToolkitProfileLock::Init(nsILocalFile* aDirectory, nsIProfileUnlocker* *aUnlocker)
nsToolkitProfileLock::Init(nsILocalFile* aDirectory, nsILocalFile* aLocalDirectory,
nsIProfileUnlocker* *aUnlocker)
{
nsresult rv;
rv = mLock.Lock(aDirectory, aUnlocker);
if (NS_SUCCEEDED(rv))
if (NS_SUCCEEDED(rv)) {
mDirectory = aDirectory;
mLocalDirectory = aLocalDirectory;
}
return rv;
}
@ -297,6 +327,18 @@ nsToolkitProfileLock::GetDirectory(nsILocalFile* *aResult)
return NS_OK;
}
NS_IMETHODIMP
nsToolkitProfileLock::GetLocalDirectory(nsILocalFile* *aResult)
{
if (!mLocalDirectory) {
NS_ERROR("Not initialized, or unlocked!");
return NS_ERROR_NOT_INITIALIZED;
}
NS_ADDREF(*aResult = mLocalDirectory);
return NS_OK;
}
NS_IMETHODIMP
nsToolkitProfileLock::Unlock()
{
@ -312,6 +354,7 @@ nsToolkitProfileLock::Unlock()
mProfile = nsnull;
}
mDirectory = nsnull;
mLocalDirectory = nsnull;
return NS_OK;
}
@ -339,6 +382,9 @@ nsToolkitProfileService::Init()
rv = gDirServiceProvider->GetUserAppDataDirectory(getter_AddRefs(mAppData));
NS_ENSURE_SUCCESS(rv, rv);
rv = gDirServiceProvider->GetUserLocalDataDirectory(getter_AddRefs(mTempData));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFile> listFile;
rv = mAppData->Clone(getter_AddRefs(listFile));
NS_ENSURE_SUCCESS(rv, rv);
@ -405,8 +451,20 @@ nsToolkitProfileService::Init()
}
if (NS_FAILED(rv)) continue;
nsCOMPtr<nsILocalFile> localDir;
if (isRelative) {
rv = NS_NewNativeLocalFile(EmptyCString(), PR_TRUE,
getter_AddRefs(localDir));
NS_ENSURE_SUCCESS(rv, rv);
rv = localDir->SetRelativeDescriptor(mTempData, filePath);
} else {
localDir = rootDir;
}
currentProfile = new nsToolkitProfile(nsDependentCString(parserBuf),
rootDir, currentProfile);
rootDir, localDir,
currentProfile);
NS_ENSURE_TRUE(currentProfile, NS_ERROR_OUT_OF_MEMORY);
rv = parser.GetString(profileID, "Default", parserBuf, MAXPATHLEN);
@ -521,19 +579,20 @@ nsToolkitProfileService::GetProfileByName(const nsACString& aName,
NS_IMETHODIMP
nsToolkitProfileService::LockProfilePath(nsILocalFile* aDirectory,
nsILocalFile* aLocalDirectory,
nsIProfileLock* *aResult)
{
return NS_LockProfilePath(aDirectory, nsnull, aResult);
return NS_LockProfilePath(aDirectory, aLocalDirectory, nsnull, aResult);
}
nsresult
NS_LockProfilePath(nsILocalFile* aPath, nsIProfileUnlocker* *aUnlocker,
nsIProfileLock* *aResult)
NS_LockProfilePath(nsILocalFile* aPath, nsILocalFile* aTempPath,
nsIProfileUnlocker* *aUnlocker, nsIProfileLock* *aResult)
{
nsCOMPtr<nsToolkitProfileLock> lock = new nsToolkitProfileLock();
if (!lock) return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = lock->Init(aPath, aUnlocker);
nsresult rv = lock->Init(aPath, aTempPath, aUnlocker);
if (NS_FAILED(rv)) return rv;
NS_ADDREF(*aResult = lock);
@ -566,6 +625,7 @@ static void SaltProfileName(nsACString& aName)
NS_IMETHODIMP
nsToolkitProfileService::CreateProfile(nsILocalFile* aRootDir,
nsILocalFile* aLocalDir,
const nsACString& aName,
nsIToolkitProfile* *aResult)
{
@ -576,6 +636,7 @@ nsToolkitProfileService::CreateProfile(nsILocalFile* aRootDir,
nsCOMPtr<nsILocalFile> rootDir (aRootDir);
nsCAutoString dirName;
if (!rootDir) {
nsCOMPtr<nsIFile> file;
PRBool dummy;
@ -586,12 +647,33 @@ nsToolkitProfileService::CreateProfile(nsILocalFile* aRootDir,
rootDir = do_QueryInterface(file);
NS_ENSURE_TRUE(rootDir, NS_ERROR_UNEXPECTED);
nsCAutoString dirName(aName);
dirName = aName;
SaltProfileName(dirName);
rootDir->AppendNative(dirName);
}
nsCOMPtr<nsILocalFile> localDir (aLocalDir);
if (!localDir) {
if (aRootDir) {
localDir = aRootDir;
}
else {
nsCOMPtr<nsIFile> file;
PRBool dummy;
rv = gDirServiceProvider->GetFile(NS_APP_USER_PROFILES_LOCAL_ROOT_DIR,
&dummy, getter_AddRefs(file));
NS_ENSURE_SUCCESS(rv, rv);
localDir = do_QueryInterface(file);
NS_ENSURE_TRUE(localDir, NS_ERROR_UNEXPECTED);
// use same salting
localDir->AppendNative(dirName);
}
}
PRBool exists;
rv = rootDir->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
@ -631,6 +713,14 @@ nsToolkitProfileService::CreateProfile(nsILocalFile* aRootDir,
NS_ENSURE_SUCCESS(rv, rv);
}
rv = localDir->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
if (!exists) {
rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
NS_ENSURE_SUCCESS(rv, rv);
}
nsToolkitProfile* last = mFirst;
if (last) {
while (last->mNext)
@ -638,7 +728,7 @@ nsToolkitProfileService::CreateProfile(nsILocalFile* aRootDir,
}
nsCOMPtr<nsIToolkitProfile> profile =
new nsToolkitProfile(aName, rootDir, last);
new nsToolkitProfile(aName, rootDir, localDir, last);
if (!profile) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult = profile);
@ -691,13 +781,13 @@ nsToolkitProfileService::Flush()
while (cur) {
// if the profile dir is relative to appdir...
PRBool isRelative;
rv = mAppData->Contains(cur->mFile, PR_TRUE, &isRelative);
rv = mAppData->Contains(cur->mRootDir, PR_TRUE, &isRelative);
if (NS_SUCCEEDED(rv) && isRelative) {
// we use a relative descriptor
rv = cur->mFile->GetRelativeDescriptor(mAppData, path);
rv = cur->mRootDir->GetRelativeDescriptor(mAppData, path);
} else {
// otherwise, a persistent descriptor
rv = cur->mFile->GetPersistentDescriptor(path);
rv = cur->mRootDir->GetPersistentDescriptor(path);
NS_ENSURE_SUCCESS(rv, rv);
}

Просмотреть файл

@ -1054,7 +1054,8 @@ static const char kProfileProperties[] =
"chrome://mozapps/locale/profile/profileSelection.properties";
static nsresult
ProfileLockedDialog(nsILocalFile* aProfileDir, nsIProfileUnlocker* aUnlocker,
ProfileLockedDialog(nsILocalFile* aProfileDir, nsILocalFile* aProfileLocalDir,
nsIProfileUnlocker* aUnlocker,
nsINativeAppSupport* aNative, nsIProfileLock* *aResult)
{
nsresult rv;
@ -1113,7 +1114,7 @@ ProfileLockedDialog(nsILocalFile* aProfileDir, nsIProfileUnlocker* aUnlocker,
rv = aUnlocker->Unlock(nsIProfileUnlocker::FORCE_QUIT);
if (NS_FAILED(rv)) return rv;
return NS_LockProfilePath(aProfileDir, nsnull, aResult);
return NS_LockProfilePath(aProfileDir, aProfileLocalDir, nsnull, aResult);
}
return NS_ERROR_ABORT;
@ -1129,7 +1130,7 @@ ShowProfileManager(nsIToolkitProfileService* aProfileSvc,
{
nsresult rv;
nsCOMPtr<nsILocalFile> lf;
nsCOMPtr<nsILocalFile> profD, profLD;
{
ScopedXPCOMStartup xpcom;
@ -1181,19 +1182,26 @@ ShowProfileManager(nsIToolkitProfileService* aProfileSvc,
getter_AddRefs(lock));
NS_ENSURE_SUCCESS(rv, rv);
rv = lock->GetDirectory(getter_AddRefs(lf));
rv = lock->GetDirectory(getter_AddRefs(profD));
NS_ENSURE_SUCCESS(rv, rv);
rv = lock->GetLocalDirectory(getter_AddRefs(profLD));
NS_ENSURE_SUCCESS(rv, rv);
lock->Unlock();
}
}
nsCAutoString path;
lf->GetNativePath(path);
nsCAutoString path1;
nsCAutoString path2;
profD->GetNativePath(path1);
profLD->GetNativePath(path2);
static char kEnvVar[MAXPATHLEN];
sprintf(kEnvVar, "XRE_PROFILE_PATH=%s", path.get());
PR_SetEnv(kEnvVar);
static char kEnvVar1[MAXPATHLEN], kEnvVar2[MAXPATHLEN];
sprintf(kEnvVar1, "XRE_PROFILE_PATH=%s", path1.get());
sprintf(kEnvVar2, "XRE_PROFILE_LOCAL_PATH=%s", path2.get());
PR_SetEnv(kEnvVar1);
PR_SetEnv(kEnvVar2);
PRBool offline = PR_FALSE;
aProfileSvc->GetStartOffline(&offline);
@ -1264,7 +1272,17 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
getter_AddRefs(lf));
NS_ENSURE_SUCCESS(rv, rv);
return NS_LockProfilePath(lf, nsnull, aResult);
nsCOMPtr<nsILocalFile> localDir;
arg = PR_GetEnv("XRE_PROFILE_LOCAL_PATH");
if (arg && *arg) {
rv = NS_NewNativeLocalFile(nsDependentCString(arg), PR_TRUE,
getter_AddRefs(localDir));
NS_ENSURE_SUCCESS(rv, rv);
} else {
localDir = lf;
}
return NS_LockProfilePath(lf, localDir, nsnull, aResult);
}
if (CheckArg("migration"))
@ -1282,11 +1300,13 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
nsCOMPtr<nsIProfileUnlocker> unlocker;
rv = NS_LockProfilePath(lf, getter_AddRefs(unlocker), aResult);
// If a profile path is specified directory on the command line, then
// assume that the temp directory is the same as the given directory.
rv = NS_LockProfilePath(lf, lf, getter_AddRefs(unlocker), aResult);
if (NS_SUCCEEDED(rv))
return rv;
return ProfileLockedDialog(lf, unlocker, aNative, aResult);
return ProfileLockedDialog(lf, lf, unlocker, aNative, aResult);
}
nsCOMPtr<nsIToolkitProfileService> profileSvc;
@ -1311,10 +1331,12 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
return rv;
}
rv = profileSvc->CreateProfile(lf, nsDependentCSubstring(arg, delim),
// As with -profile, assume that the given path will be used for both the
// main profile directory and the temp profile directory.
rv = profileSvc->CreateProfile(lf, lf, nsDependentCSubstring(arg, delim),
getter_AddRefs(profile));
} else {
rv = profileSvc->CreateProfile(nsnull, nsDependentCString(arg),
rv = profileSvc->CreateProfile(nsnull, nsnull, nsDependentCString(arg),
getter_AddRefs(profile));
}
if (NS_SUCCEEDED(rv)) {
@ -1332,6 +1354,7 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
prefsJSFile->Exists(&exists);
if (!exists)
prefsJSFile->Create(nsIFile::NORMAL_FILE_TYPE, 0644);
// XXXdarin perhaps 0600 would be better?
return rv;
}
@ -1340,9 +1363,11 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
rv = profileSvc->GetProfileCount(&count);
NS_ENSURE_SUCCESS(rv, rv);
arg = PR_GetEnv("XRE_IMPORT_PROFILES");
if (!count && (!arg || !*arg)) {
return ImportProfiles(profileSvc, aNative);
if (gAppData->flags & NS_XRE_ENABLE_PROFILE_MIGRATOR) {
arg = PR_GetEnv("XRE_IMPORT_PROFILES");
if (!count && (!arg || !*arg)) {
return ImportProfiles(profileSvc, aNative);
}
}
ar = CheckArg("p", &arg);
@ -1363,7 +1388,12 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
rv = profile->GetRootDir(getter_AddRefs(profileDir));
NS_ENSURE_SUCCESS(rv, rv);
return ProfileLockedDialog(profileDir, unlocker, aNative, aResult);
nsCOMPtr<nsILocalFile> profileLocalDir;
rv = profile->GetLocalDir(getter_AddRefs(profileLocalDir));
NS_ENSURE_SUCCESS(rv, rv);
return ProfileLockedDialog(profileDir, profileLocalDir, unlocker,
aNative, aResult);
}
return ShowProfileManager(profileSvc, aNative);
@ -1379,6 +1409,7 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
// create a default profile
nsCOMPtr<nsIToolkitProfile> profile;
nsresult rv = profileSvc->CreateProfile(nsnull, // choose a default dir for us
nsnull, // choose a default dir for us
NS_LITERAL_CSTRING("default"),
getter_AddRefs(profile));
if (NS_SUCCEEDED(rv)) {
@ -1407,7 +1438,12 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
rv = profile->GetRootDir(getter_AddRefs(profileDir));
NS_ENSURE_SUCCESS(rv, rv);
return ProfileLockedDialog(profileDir, unlocker, aNative, aResult);
nsCOMPtr<nsILocalFile> profileLocalDir;
rv = profile->GetRootDir(getter_AddRefs(profileLocalDir));
NS_ENSURE_SUCCESS(rv, rv);
return ProfileLockedDialog(profileDir, profileLocalDir, unlocker,
aNative, aResult);
}
}
@ -1525,6 +1561,11 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
nsresult rv;
NS_TIMELINE_MARK("enter main");
#ifdef DEBUG
if (PR_GetEnv("XRE_MAIN_BREAK"))
NS_BREAK();
#endif
#ifdef XP_WIN32
// Suppress the "DLL Foo could not be found" dialog, such that if dependent
// libraries (such as GDI+) are not preset, we gracefully fail to load those
@ -1742,11 +1783,15 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
rv == NS_ERROR_ABORT) return 0;
if (NS_FAILED(rv)) return 1;
nsCOMPtr<nsILocalFile> lf;
rv = profileLock->GetDirectory(getter_AddRefs(lf));
nsCOMPtr<nsILocalFile> profD;
rv = profileLock->GetDirectory(getter_AddRefs(profD));
NS_ENSURE_SUCCESS(rv, 1);
rv = dirProvider.SetProfileDir(lf);
nsCOMPtr<nsILocalFile> profLD;
rv = profileLock->GetLocalDirectory(getter_AddRefs(profLD));
NS_ENSURE_SUCCESS(rv, 1);
rv = dirProvider.SetProfile(profD, profLD);
NS_ENSURE_SUCCESS(rv, 1);
//////////////////////// NOW WE HAVE A PROFILE ////////////////////////
@ -1758,7 +1803,7 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
// profile was started with. The format of the version stamp is defined
// by the BuildVersion function.
char lastVersion[MAXPATHLEN];
GetVersion(lf, lastVersion, MAXPATHLEN);
GetVersion(profD, lastVersion, MAXPATHLEN);
// Build the version stamp for the running application.
nsCAutoString version;
@ -1772,13 +1817,13 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
// re-generated to prevent mysterious component loading failures.
//
if (version.Equals(lastVersion)) {
componentsListChanged = ComponentsListChanged(lf);
componentsListChanged = ComponentsListChanged(profD);
if (componentsListChanged) {
// Remove compreg.dat and xpti.dat, forcing component re-registration,
// with the new list of additional components directories specified
// in "components.ini" which we have just discovered changed since the
// last time the application was run.
RemoveComponentRegistries(lf);
RemoveComponentRegistries(profD);
}
// Nothing need be done for the normal startup case.
}
@ -1786,7 +1831,7 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
// Remove compreg.dat and xpti.dat, forcing component re-registration
// with the default set of components (this disables any potentially
// troublesome incompatible XPCOM components).
RemoveComponentRegistries(lf);
RemoveComponentRegistries(profD);
// Tell the Extension Manager it should check for incompatible
// Extensions and re-write the Components manifest ("components.ini")
@ -1794,7 +1839,7 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
upgraded = PR_TRUE;
// Write out version
WriteVersion(lf, version);
WriteVersion(profD, version);
}
PRBool needsRestart = PR_FALSE;
@ -1907,6 +1952,7 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
// clear out any environment variables which may have been set
// during the relaunch process now that we know we won't be relaunching.
PR_SetEnv("XRE_PROFILE_PATH=");
PR_SetEnv("XRE_PROFILE_TEMP_PATH=");
PR_SetEnv("XRE_START_OFFLINE=");
PR_SetEnv("XRE_IMPORT_PROFILES=");
PR_SetEnv("NO_EM_RESTART=");
@ -1997,12 +2043,15 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
// After this restart, we don't want to restart any more!
PR_SetEnv("NO_EM_RESTART=1");
nsCAutoString path;
lf->GetNativePath(path);
nsCAutoString path1, path2;
profD->GetNativePath(path1);
profLD->GetNativePath(path2);
static char kEnvVar[MAXPATHLEN];
sprintf(kEnvVar, "XRE_PROFILE_PATH=%s", path.get());
PR_SetEnv(kEnvVar);
static char kEnvVar1[MAXPATHLEN], kEnvVar2[MAXPATHLEN];
sprintf(kEnvVar1, "XRE_PROFILE_PATH=%s", path1.get());
sprintf(kEnvVar2, "XRE_PROFILE_LOCAL_PATH=%s", path2.get());
PR_SetEnv(kEnvVar1);
PR_SetEnv(kEnvVar2);
return LaunchChild(nativeApp) == NS_ERROR_LAUNCHED_CHILD_PROCESS ? 0 : 1;
}

Просмотреть файл

@ -87,9 +87,26 @@ nsresult NS_CreateNativeAppSupport(nsINativeAppSupport* *aResult);
NS_HIDDEN_(nsresult)
NS_NewToolkitProfileService(nsIToolkitProfileService* *aResult);
/**
* Try to acquire exclusive access to the specified profile directory.
*
* @param aPath
* The profile directory to lock.
* @param aTempPath
* The corresponding profile temporary directory.
* @param aUnlocker
* A callback interface used to attempt to unlock a profile that
* appears to be locked.
* @param aResult
* The resulting profile lock object (or null if the profile could
* not be locked).
*
* @return NS_ERROR_FILE_ACCESS_DENIED to indicate that the profile
* directory cannot be unlocked.
*/
NS_HIDDEN_(nsresult)
NS_LockProfilePath(nsILocalFile* aPath, nsIProfileUnlocker* *aUnlocker,
nsIProfileLock* *aResult);
NS_LockProfilePath(nsILocalFile* aPath, nsILocalFile* aTempPath,
nsIProfileUnlocker* *aUnlocker, nsIProfileLock* *aResult);
#define NS_NATIVEAPPSUPPORT_CONTRACTID "@mozilla.org/toolkit/native-app-support;1"

Просмотреть файл

@ -190,17 +190,29 @@ nsXREDirProvider::Initialize(nsIFile *aXULAppDir)
}
nsresult
nsXREDirProvider::SetProfileDir(nsIFile* aDir)
nsXREDirProvider::SetProfile(nsIFile* aDir, nsIFile* aLocalDir)
{
NS_ASSERTION(aDir, "We don't support no-profile apps yet!");
NS_ASSERTION(aDir && aLocalDir, "We don't support no-profile apps yet!");
#ifdef DEBUG_bsmedberg
nsCAutoString path;
nsCAutoString path, path2;
aDir->GetNativePath(path);
printf("nsXREDirProvider::SetProfileDir('%s')\n", path.get());
aLocalDir->GetNativePath(path2);
printf("nsXREDirProvider::SetProfile('%s', '%s')\n", path.get(), path2.get());
#endif
nsresult rv;
rv = EnsureDirectoryExists(aDir);
if (NS_FAILED(rv))
return rv;
rv = EnsureDirectoryExists(aLocalDir);
if (NS_FAILED(rv))
return rv;
mProfileDir = aDir;
mProfileLocalDir = aLocalDir;
return NS_OK;
}
@ -258,6 +270,16 @@ nsXREDirProvider::GetFile(const char* aProperty, PRBool* aPersistent,
else if (!strcmp(aProperty, NS_APP_USER_PROFILES_ROOT_DIR)) {
rv = GetUserAppDataDirectory((nsILocalFile**)(nsIFile**) getter_AddRefs(file));
#if !defined(XP_UNIX) || defined(XP_MACOSX)
rv |= file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
#endif
// 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 !defined(XP_UNIX) || defined(XP_MACOSX)
rv |= file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
#endif
@ -291,6 +313,9 @@ nsXREDirProvider::GetFile(const char* aProperty, PRBool* aPersistent,
!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"));
@ -641,7 +666,7 @@ GetProfileFolderName(char* aProfileFolderName, const char* aSource)
}
nsresult
nsXREDirProvider::GetUserAppDataDirectory(nsILocalFile** aFile)
nsXREDirProvider::GetUserDataDirectory(nsILocalFile** aFile, PRBool aLocal)
{
NS_ASSERTION(gAppData, "gAppData not initialized!");
@ -650,13 +675,19 @@ nsXREDirProvider::GetUserAppDataDirectory(nsILocalFile** aFile)
nsCOMPtr<nsILocalFile> localDir;
#if defined(XP_MACOSX)
FSRef fsRef;
FSRef fsRef;
OSType folderType;
if (aLocal) {
folderType = kCachedDataFolderType;
} else {
#ifdef MOZ_THUNDERBIRD
OSErr err = ::FSFindFolder(kUserDomain, kDomainLibraryFolderType, kCreateFolder, &fsRef);
folderType = kDomainLibraryFolderType;
#else
OSErr err = ::FSFindFolder(kUserDomain, kApplicationSupportFolderType, kCreateFolder, &fsRef);
folderType = kApplicationSupportFolderType;
#endif
if (err) return NS_ERROR_FAILURE;
}
OSErr err = ::FSFindFolder(kUserDomain, folderType, kCreateFolder, &fsRef);
NS_ENSURE_TRUE(err, NS_ERROR_FAILURE);
rv = NS_NewNativeLocalFile(EmptyCString(), PR_TRUE, getter_AddRefs(localDir));
NS_ENSURE_SUCCESS(rv, rv);
@ -681,7 +712,9 @@ nsXREDirProvider::GetUserAppDataDirectory(nsILocalFile** aFile)
char appDataPath[MAXPATHLEN];
if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pItemIDList)) &&
int folder = aLocal ? CSIDL_LOCAL_APPDATA : CSIDL_APPDATA;
if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, folder, &pItemIDList)) &&
SUCCEEDED(SHGetPathFromIDList(pItemIDList, appDataPath))) {
} else {
if (!GetWindowsDirectory(appDataPath, MAXPATHLEN)) {
@ -804,7 +837,7 @@ nsXREDirProvider::EnsureDirectoryExists(nsIFile* aDirectory)
nsresult rv = aDirectory->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
if (!exists)
rv = aDirectory->Create(nsIFile::DIRECTORY_TYPE, 0775);
rv = aDirectory->Create(nsIFile::DIRECTORY_TYPE, 0700);
return rv;
}

Просмотреть файл

@ -64,23 +64,31 @@ public:
// that is the responsibility of the toolkit profile service.
// We also don't fire profile-changed notifications... that is
// the responsibility of the apprunner.
nsresult SetProfileDir(nsIFile* aProfileDir);
nsresult SetProfile(nsIFile* aProfileDir, nsIFile* aProfileLocalDir);
void DoShutdown();
nsresult GetProfileDefaultsDir(nsIFile* *aResult);
static nsresult GetUserAppDataDirectory(nsILocalFile* *aFile);
static nsresult GetUserAppDataDirectory(nsILocalFile* *aFile) {
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* GetAppDir() { return mAppDir; }
protected:
static nsresult GetUserDataDirectory(nsILocalFile* *aFile, PRBool aLocal);
static nsresult EnsureDirectoryExists(nsIFile* aDirectory);
void EnsureProfileFileExists(nsIFile* aFile);
nsCOMPtr<nsILocalFile> mAppDir;
nsCOMPtr<nsIFile> mXULAppDir;
nsCOMPtr<nsIFile> mProfileDir;
nsCOMPtr<nsIFile> mProfileLocalDir;
PRBool mProfileNotified;
};

Просмотреть файл

@ -69,7 +69,8 @@
// installed locale. Second choice
// when above is not available.
#define NS_APP_USER_PROFILES_ROOT_DIR "DefProfRt" // The dir where user profile dirs get created.
#define NS_APP_USER_PROFILES_ROOT_DIR "DefProfRt" // The dir where user profile dirs live.
#define NS_APP_USER_PROFILES_LOCAL_ROOT_DIR "DefProfLRt" // The dir where user profile temp dirs live.
#define NS_APP_RES_DIR "ARes"
#define NS_APP_CHROME_DIR "AChrom"
@ -96,6 +97,7 @@
#define NS_APP_PREFS_DEFAULTS_DIR_LIST "PrefDL"
#define NS_APP_USER_PROFILE_50_DIR "ProfD"
#define NS_APP_USER_PROFILE_LOCAL_50_DIR "ProfLD"
#define NS_APP_USER_CHROME_DIR "UChrm"

Просмотреть файл

@ -135,10 +135,21 @@ nsresult
nsFastLoadService::NewFastLoadFile(const char* aBaseName, nsIFile* *aResult)
{
nsresult rv;
nsCOMPtr<nsIFile> file;
nsCOMPtr<nsIFile> profFile;
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
getter_AddRefs(profFile));
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIFile> file;
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_LOCAL_50_DIR,
getter_AddRefs(file));
if (NS_FAILED(rv))
file = profFile;
PRBool sameDir;
rv = file->Equals(profFile, &sameDir);
if (NS_FAILED(rv))
return rv;
@ -149,6 +160,15 @@ nsFastLoadService::NewFastLoadFile(const char* aBaseName, nsIFile* *aResult)
if (NS_FAILED(rv))
return rv;
if (!sameDir) {
// Cleanup any pre-existing fastload files that may live in the profile
// directory from previous versions of the code that didn't store them
// in the profile temp directory.
rv = profFile->AppendNative(name);
if (NS_SUCCEEDED(rv))
profFile->Remove(PR_FALSE); // OK if this fails
}
*aResult = file;
NS_ADDREF(*aResult);
return NS_OK;