From ddb302c5079128194bcd97dd7665ff520f1bdc4a Mon Sep 17 00:00:00 2001 From: "darin%meer.net" Date: Tue, 26 Apr 2005 00:37:23 +0000 Subject: [PATCH] fixes bug 291033 "Enable support for profile temp directory on local filesystem" aka "delete my cache please" r=bsmedberg a=chofmann git-svn-id: svn://10.0.0.236/trunk@172714 18797224-902f-48f8-a5cc-f745e15eee43 --- .../migration/src/nsProfileMigrator.cpp | 3 +- .../migration/src/nsProfileMigrator.cpp | 3 +- mozilla/netwerk/cache/src/Makefile.in | 1 + mozilla/netwerk/cache/src/nsCacheService.cpp | 35 ++- mozilla/netwerk/cache/src/nsDeleteDir.cpp | 122 ++++++++ mozilla/netwerk/cache/src/nsDeleteDir.h | 68 +++++ .../netwerk/cache/src/nsDiskCacheDevice.cpp | 271 +++--------------- mozilla/netwerk/cache/src/nsDiskCacheDevice.h | 5 - .../profile/content/createProfileWizard.js | 2 +- .../profile/public/nsIToolkitProfile.idl | 40 ++- .../public/nsIToolkitProfileService.idl | 20 +- .../profile/src/nsToolkitProfileService.cpp | 134 +++++++-- mozilla/toolkit/xre/nsAppRunner.cpp | 113 +++++--- mozilla/toolkit/xre/nsAppRunner.h | 21 +- mozilla/toolkit/xre/nsXREDirProvider.cpp | 55 +++- mozilla/toolkit/xre/nsXREDirProvider.h | 12 +- mozilla/xpcom/io/nsAppDirectoryServiceDefs.h | 4 +- mozilla/xpcom/io/nsFastLoadService.cpp | 22 +- 18 files changed, 603 insertions(+), 328 deletions(-) create mode 100644 mozilla/netwerk/cache/src/nsDeleteDir.cpp create mode 100644 mozilla/netwerk/cache/src/nsDeleteDir.h diff --git a/mozilla/browser/components/migration/src/nsProfileMigrator.cpp b/mozilla/browser/components/migration/src/nsProfileMigrator.cpp index 124cb071c84..59f4240dda6 100644 --- a/mozilla/browser/components/migration/src/nsProfileMigrator.cpp +++ b/mozilla/browser/components/migration/src/nsProfileMigrator.cpp @@ -385,7 +385,8 @@ nsProfileMigrator::ImportRegistryProfiles(const nsACString& aAppName) if (NS_FAILED(rv)) continue; nsCOMPtr tprofile; - profileSvc->CreateProfile(profileFile, nsDependentCString(profileName), + profileSvc->CreateProfile(profileFile, nsnull, + nsDependentCString(profileName), getter_AddRefs(tprofile)); migrated = PR_TRUE; } diff --git a/mozilla/mail/components/migration/src/nsProfileMigrator.cpp b/mozilla/mail/components/migration/src/nsProfileMigrator.cpp index 3b52324967c..cff19f115e3 100644 --- a/mozilla/mail/components/migration/src/nsProfileMigrator.cpp +++ b/mozilla/mail/components/migration/src/nsProfileMigrator.cpp @@ -253,7 +253,8 @@ nsProfileMigrator::ImportRegistryProfiles(const nsACString& aAppName) if (NS_FAILED(rv)) continue; nsCOMPtr tprofile; - profileSvc->CreateProfile(profileFile, nsDependentCString(profileName), + profileSvc->CreateProfile(profileFile, nsnull, + nsDependentCString(profileName), getter_AddRefs(tprofile)); migrated = PR_TRUE; } diff --git a/mozilla/netwerk/cache/src/Makefile.in b/mozilla/netwerk/cache/src/Makefile.in index 2b5a04b62ce..6c73cc43854 100644 --- a/mozilla/netwerk/cache/src/Makefile.in +++ b/mozilla/netwerk/cache/src/Makefile.in @@ -83,6 +83,7 @@ CPPSRCS += \ nsDiskCacheEntry.cpp \ nsDiskCacheMap.cpp \ nsDiskCacheStreams.cpp \ + nsDeleteDir.cpp \ $(NULL) endif endif diff --git a/mozilla/netwerk/cache/src/nsCacheService.cpp b/mozilla/netwerk/cache/src/nsCacheService.cpp index 6cba5ffc756..0494d8b2039 100644 --- a/mozilla/netwerk/cache/src/nsCacheService.cpp +++ b/mozilla/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 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); } diff --git a/mozilla/netwerk/cache/src/nsDeleteDir.cpp b/mozilla/netwerk/cache/src/nsDeleteDir.cpp new file mode 100644 index 00000000000..8c0ef9c807d --- /dev/null +++ b/mozilla/netwerk/cache/src/nsDeleteDir.cpp @@ -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 + * + * 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 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 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 *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); +} diff --git a/mozilla/netwerk/cache/src/nsDeleteDir.h b/mozilla/netwerk/cache/src/nsDeleteDir.h new file mode 100644 index 00000000000..e6f79d1ce94 --- /dev/null +++ b/mozilla/netwerk/cache/src/nsDeleteDir.h @@ -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 + * + * 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 *result); + +#endif // nsDeleteDir_h__ diff --git a/mozilla/netwerk/cache/src/nsDiskCacheDevice.cpp b/mozilla/netwerk/cache/src/nsDiskCacheDevice.cpp index a99971addc4..d96a3f238d1 100644 --- a/mozilla/netwerk/cache/src/nsDiskCacheDevice.cpp +++ b/mozilla/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 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 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 * 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 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 trashDir; - nsCOMArray * deleteList = new nsCOMArray; - 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 * fileList = NS_STATIC_CAST(nsCOMArray *, arg); - nsresult rv; - - // iterate over items in fileList, recursively deleting each - PRInt32 count = fileList->Count(); - for (PRInt32 i=0; iObjectAt(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 * 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 ** result) -{ - nsresult rv; - nsCOMPtr 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 * array = new nsCOMArray; - if (!array) return NS_ERROR_OUT_OF_MEMORY; - - // iterate over trash directory building array of directory objects - nsCOMPtr dirEntries; - nsCOMPtr 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 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 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 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(); } diff --git a/mozilla/netwerk/cache/src/nsDiskCacheDevice.h b/mozilla/netwerk/cache/src/nsDiskCacheDevice.h index 1b60469f9e5..c1e329869fb 100644 --- a/mozilla/netwerk/cache/src/nsDiskCacheDevice.h +++ b/mozilla/netwerk/cache/src/nsDiskCacheDevice.h @@ -110,12 +110,8 @@ private: * Private methods */ - nsresult GetCacheTrashDirectory(nsIFile ** result); nsresult OpenDiskCache(); nsresult ClearDiskCache(); - nsresult DeleteFiles(nsCOMArray * fileList); - nsresult ListTrashContents(nsCOMArray ** 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_ diff --git a/mozilla/toolkit/profile/content/createProfileWizard.js b/mozilla/toolkit/profile/content/createProfileWizard.js index 42342508dcf..f7bea049ee1 100644 --- a/mozilla/toolkit/profile/content/createProfileWizard.js +++ b/mozilla/toolkit/profile/content/createProfileWizard.js @@ -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 = diff --git a/mozilla/toolkit/profile/public/nsIToolkitProfile.idl b/mozilla/toolkit/profile/public/nsIToolkitProfile.idl index 35dd6f03d03..4b083aed66e 100644 --- a/mozilla/toolkit/profile/public/nsIToolkitProfile.idl +++ b/mozilla/toolkit/profile/public/nsIToolkitProfile.idl @@ -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); /** diff --git a/mozilla/toolkit/profile/public/nsIToolkitProfileService.idl b/mozilla/toolkit/profile/public/nsIToolkitProfileService.idl index 13c322e5699..7c101ce5445 100644 --- a/mozilla/toolkit/profile/public/nsIToolkitProfileService.idl +++ b/mozilla/toolkit/profile/public/nsIToolkitProfileService.idl @@ -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. diff --git a/mozilla/toolkit/profile/src/nsToolkitProfileService.cpp b/mozilla/toolkit/profile/src/nsToolkitProfileService.cpp index 2144de56099..86fb830ee1c 100644 --- a/mozilla/toolkit/profile/src/nsToolkitProfileService.cpp +++ b/mozilla/toolkit/profile/src/nsToolkitProfileService.cpp @@ -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 mFile; + nsCOMPtr mRootDir; + nsCOMPtr 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 mProfile; nsCOMPtr mDirectory; + nsCOMPtr mLocalDirectory; nsProfileLock mLock; }; @@ -146,6 +151,7 @@ private: nsCOMPtr mFirst; nsCOMPtr mChosen; nsCOMPtr mAppData; + nsCOMPtr mTempData; nsCOMPtr 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 listFile; rv = mAppData->Clone(getter_AddRefs(listFile)); NS_ENSURE_SUCCESS(rv, rv); @@ -405,8 +451,20 @@ nsToolkitProfileService::Init() } if (NS_FAILED(rv)) continue; + nsCOMPtr 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 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 rootDir (aRootDir); + nsCAutoString dirName; if (!rootDir) { nsCOMPtr 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 localDir (aLocalDir); + + if (!localDir) { + if (aRootDir) { + localDir = aRootDir; + } + else { + nsCOMPtr 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 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); } diff --git a/mozilla/toolkit/xre/nsAppRunner.cpp b/mozilla/toolkit/xre/nsAppRunner.cpp index 5f432f17980..483cdf53d76 100644 --- a/mozilla/toolkit/xre/nsAppRunner.cpp +++ b/mozilla/toolkit/xre/nsAppRunner.cpp @@ -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 lf; + nsCOMPtr 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 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 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 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 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 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 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 lf; - rv = profileLock->GetDirectory(getter_AddRefs(lf)); + nsCOMPtr profD; + rv = profileLock->GetDirectory(getter_AddRefs(profD)); NS_ENSURE_SUCCESS(rv, 1); - rv = dirProvider.SetProfileDir(lf); + nsCOMPtr 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; } diff --git a/mozilla/toolkit/xre/nsAppRunner.h b/mozilla/toolkit/xre/nsAppRunner.h index 2e3a32c4446..ec670948a8c 100644 --- a/mozilla/toolkit/xre/nsAppRunner.h +++ b/mozilla/toolkit/xre/nsAppRunner.h @@ -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" diff --git a/mozilla/toolkit/xre/nsXREDirProvider.cpp b/mozilla/toolkit/xre/nsXREDirProvider.cpp index a23756e9a40..9f126f1be8f 100644 --- a/mozilla/toolkit/xre/nsXREDirProvider.cpp +++ b/mozilla/toolkit/xre/nsXREDirProvider.cpp @@ -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 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; } diff --git a/mozilla/toolkit/xre/nsXREDirProvider.h b/mozilla/toolkit/xre/nsXREDirProvider.h index 05df65a940e..28535480cbc 100644 --- a/mozilla/toolkit/xre/nsXREDirProvider.h +++ b/mozilla/toolkit/xre/nsXREDirProvider.h @@ -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 mAppDir; nsCOMPtr mXULAppDir; nsCOMPtr mProfileDir; + nsCOMPtr mProfileLocalDir; PRBool mProfileNotified; }; diff --git a/mozilla/xpcom/io/nsAppDirectoryServiceDefs.h b/mozilla/xpcom/io/nsAppDirectoryServiceDefs.h index 33c70038da4..587a7933166 100755 --- a/mozilla/xpcom/io/nsAppDirectoryServiceDefs.h +++ b/mozilla/xpcom/io/nsAppDirectoryServiceDefs.h @@ -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" diff --git a/mozilla/xpcom/io/nsFastLoadService.cpp b/mozilla/xpcom/io/nsFastLoadService.cpp index 8176c897088..34e22f02bd3 100644 --- a/mozilla/xpcom/io/nsFastLoadService.cpp +++ b/mozilla/xpcom/io/nsFastLoadService.cpp @@ -135,10 +135,21 @@ nsresult nsFastLoadService::NewFastLoadFile(const char* aBaseName, nsIFile* *aResult) { nsresult rv; - nsCOMPtr file; + nsCOMPtr profFile; rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, + getter_AddRefs(profFile)); + if (NS_FAILED(rv)) + return rv; + + nsCOMPtr 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;