diff --git a/mozilla/profile/dirserviceprovider/src/nsProfileDirServiceProvider.cpp b/mozilla/profile/dirserviceprovider/src/nsProfileDirServiceProvider.cpp index a17e44e2972..c9b6831bd6a 100755 --- a/mozilla/profile/dirserviceprovider/src/nsProfileDirServiceProvider.cpp +++ b/mozilla/profile/dirserviceprovider/src/nsProfileDirServiceProvider.cpp @@ -136,7 +136,7 @@ nsProfileDirServiceProvider::SetProfileDir(nsIFile* aProfileDir) dirToLock = do_QueryInterface(mNonSharedProfileDir); else dirToLock = do_QueryInterface(mProfileDir); - rv = mProfileDirLock->Lock(dirToLock); + rv = mProfileDirLock->Lock(dirToLock, nsnull); if (NS_FAILED(rv)) return rv; #endif diff --git a/mozilla/profile/dirserviceprovider/src/nsProfileLock.cpp b/mozilla/profile/dirserviceprovider/src/nsProfileLock.cpp index 76667f9e7ff..f5114f582b6 100644 --- a/mozilla/profile/dirserviceprovider/src/nsProfileLock.cpp +++ b/mozilla/profile/dirserviceprovider/src/nsProfileLock.cpp @@ -390,7 +390,8 @@ PR_BEGIN_MACRO \ } #endif /* XP_UNIX */ -nsresult nsProfileLock::Lock(nsILocalFile* aFile) +nsresult nsProfileLock::Lock(nsILocalFile* aProfileDir, + nsIProfileUnlocker* *aUnlocker) { #if defined (XP_MACOSX) NS_NAMED_LITERAL_STRING(LOCKFILE_NAME, ".parentlock"); @@ -403,17 +404,20 @@ nsresult nsProfileLock::Lock(nsILocalFile* aFile) #endif nsresult rv; + if (aUnlocker) + *aUnlocker = nsnull; + NS_ENSURE_STATE(!mHaveLock); PRBool isDir; - rv = aFile->IsDirectory(&isDir); + rv = aProfileDir->IsDirectory(&isDir); if (NS_FAILED(rv)) return rv; if (!isDir) return NS_ERROR_FILE_NOT_DIRECTORY; nsCOMPtr lockFile; - rv = aFile->Clone((nsIFile **)((void **)getter_AddRefs(lockFile))); + rv = aProfileDir->Clone((nsIFile **)((void **)getter_AddRefs(lockFile))); if (NS_FAILED(rv)) return rv; @@ -491,8 +495,10 @@ nsresult nsProfileLock::Lock(nsILocalFile* aFile) OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, nsnull); - if (mLockFileHandle == INVALID_HANDLE_VALUE) + if (mLockFileHandle == INVALID_HANDLE_VALUE) { + // XXXbsmedberg: provide a profile-unlocker here! return NS_ERROR_FILE_ACCESS_DENIED; + } #elif defined(XP_OS2) nsCAutoString filePath; rv = lockFile->GetNativePath(filePath); @@ -535,7 +541,7 @@ nsresult nsProfileLock::Lock(nsILocalFile* aFile) } #elif defined(XP_UNIX) nsCOMPtr oldLockFile; - rv = aFile->Clone(getter_AddRefs(oldLockFile)); + rv = aProfileDir->Clone(getter_AddRefs(oldLockFile)); if (NS_SUCCEEDED(rv)) { rv = oldLockFile->Append(OLD_LOCKFILE_NAME); diff --git a/mozilla/profile/dirserviceprovider/src/nsProfileLock.h b/mozilla/profile/dirserviceprovider/src/nsProfileLock.h index a69e7180682..a5da7c125af 100644 --- a/mozilla/profile/dirserviceprovider/src/nsProfileLock.h +++ b/mozilla/profile/dirserviceprovider/src/nsProfileLock.h @@ -42,6 +42,8 @@ #include "nsILocalFile.h" +class nsIProfileUnlocker; + #if defined (XP_WIN) #include #endif @@ -69,7 +71,16 @@ public: nsProfileLock& operator=(nsProfileLock& rhs); - nsresult Lock(nsILocalFile* aFile); + /** + * Attempt to lock a profile directory. + * + * @param aProfileDir [in] The profile directory to lock. + * @param aUnlocker [out] Optional. This is only returned when locking + * fails with NS_ERROR_FILE_ACCESS_DENIED, and may not + * be returned at all. + * @throws NS_ERROR_FILE_ACCESS_DENIED if the profile is locked. + */ + nsresult Lock(nsILocalFile* aProfileDir, nsIProfileUnlocker* *aUnlocker); nsresult Unlock(); private: diff --git a/mozilla/profile/public/Makefile.in b/mozilla/profile/public/Makefile.in index 5214ecb81eb..9ef9f871c6c 100644 --- a/mozilla/profile/public/Makefile.in +++ b/mozilla/profile/public/Makefile.in @@ -53,6 +53,7 @@ XPIDLSRCS = \ nsIProfileInternal.idl \ nsIProfileStartupListener.idl \ nsISessionRoaming.idl \ + nsIProfileUnlocker.idl \ $(NULL) ifeq ($(OS_ARCH),WINNT) diff --git a/mozilla/profile/public/nsIProfileUnlocker.idl b/mozilla/profile/public/nsIProfileUnlocker.idl new file mode 100755 index 00000000000..8295ff0f478 --- /dev/null +++ b/mozilla/profile/public/nsIProfileUnlocker.idl @@ -0,0 +1,54 @@ +/* ***** 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 XULRunner. + * + * The Initial Developer of the Original Code is + * Benjamin Smedberg + * + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 "nsISupports.idl" + +[scriptable, uuid(08923af1-e7a3-4fae-ba02-128502193994)] +interface nsIProfileUnlocker : nsISupports +{ + const unsigned long ATTEMPT_QUIT = 0; + const unsigned long FORCE_QUIT = 1; + + /** + * Try to unlock the specified profile by attempting or forcing the + * process that currently holds the lock to quit. + * + * @param aSeverity either ATTEMPT_QUIT or FORCE_QUIT + * @throws NS_ERROR_FAILURE if unlocking failed. + */ + void unlock(in unsigned long aSeverity); +}; diff --git a/mozilla/profile/src/nsProfile.cpp b/mozilla/profile/src/nsProfile.cpp index 114439a856b..5f2420b9317 100644 --- a/mozilla/profile/src/nsProfile.cpp +++ b/mozilla/profile/src/nsProfile.cpp @@ -506,11 +506,11 @@ nsProfile::LoadDefaultProfileDir(nsCString & profileURLStr, PRBool canInteract) // If the profile is locked, we need the UI nsCOMPtr localFile(do_QueryInterface(curProfileDir)); nsProfileLock tempLock; - rv = tempLock.Lock(localFile); + rv = tempLock.Lock(localFile, nsnull); if (NS_FAILED(rv)) profileURLStr = PROFILE_MANAGER_URL; #endif - } + } } else profileURLStr = PROFILE_SELECTION_URL; diff --git a/mozilla/toolkit/locales/en-US/chrome/mozapps/profile/profileSelection.properties b/mozilla/toolkit/locales/en-US/chrome/mozapps/profile/profileSelection.properties index c6cb7fda07f..9b096595b07 100644 --- a/mozilla/toolkit/locales/en-US/chrome/mozapps/profile/profileSelection.properties +++ b/mozilla/toolkit/locales/en-US/chrome/mozapps/profile/profileSelection.properties @@ -1,12 +1,15 @@ # LOCALIZATION NOTE: Do not translate +restartTitle=Restart %S +restartMessage=%S is already running, but is not responding. To open a new window, you must restart %S. + profileTooltip=Profile: '%S' - Path: '%S' pleaseSelectTitle=Select Profile pleaseSelect=Please select a profile to begin %S, or create a new profile. profileLockedTitle=Profile In Use -profileLocked=%S cannot use the profile "%S" because it is in use.\n\nPlease choose another profile or create a new one. +profileLocked2=%S cannot use the profile "%S" because it is in use.\n\nTo continue, close the running instance of %S or choose a different profile. renameProfileTitle=Rename Profile renameProfilePrompt=Rename the profile "%S" to: diff --git a/mozilla/toolkit/profile/content/createProfileWizard.js b/mozilla/toolkit/profile/content/createProfileWizard.js index de5511a657a..42342508dcf 100644 --- a/mozilla/toolkit/profile/content/createProfileWizard.js +++ b/mozilla/toolkit/profile/content/createProfileWizard.js @@ -247,7 +247,7 @@ function onFinish() } else { // Use the newly created Profile. - var profileLock = profile.lock(); + var profileLock = profile.lock(null); var dialogParams = window.arguments[0].QueryInterface(I.nsIDialogParamBlock); dialogParams.objects.insertElementAt(profileLock, 0, false); diff --git a/mozilla/toolkit/profile/content/profileSelection.js b/mozilla/toolkit/profile/content/profileSelection.js index ea1ea582b4f..a813e4ccee6 100644 --- a/mozilla/toolkit/profile/content/profileSelection.js +++ b/mozilla/toolkit/profile/content/profileSelection.js @@ -117,12 +117,12 @@ function acceptDialog() var profileLock; try { - profileLock = selectedProfile.profile.lock(); + profileLock = selectedProfile.profile.lock({ value: null }); } catch (e) { var lockedTitle = gProfileManagerBundle.getString("profileLockedTitle"); var locked = - gProfileManagerBundle.getFormattedString("profileLocked", [appName, selectedProfile.profile.name]); + gProfileManagerBundle.getFormattedString("profileLocked2", [appName, selectedProfile.profile.name, appName]); gPromptService.alert(window, lockedTitle, locked); return false; diff --git a/mozilla/toolkit/profile/public/nsIToolkitProfile.idl b/mozilla/toolkit/profile/public/nsIToolkitProfile.idl index abcd5f9b988..35dd6f03d03 100644 --- a/mozilla/toolkit/profile/public/nsIToolkitProfile.idl +++ b/mozilla/toolkit/profile/public/nsIToolkitProfile.idl @@ -39,6 +39,7 @@ interface nsILocalFile; interface nsIToolkitProfile; +interface nsIProfileUnlocker; /** * Hold on to a profile lock. Once you release the last reference to this @@ -52,12 +53,29 @@ interface nsIProfileLock : nsISupports void unlock(); }; -[scriptable, uuid(87cea5c2-b9ed-44f9-8984-e75bc9f7134a)] +/** + * A interface representing a profile. + * @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)] interface nsIToolkitProfile : nsISupports { readonly attribute nsILocalFile rootDir; attribute AUTF8String name; void remove(in boolean removeFiles); - nsIProfileLock lock(); + + /** + * Lock this profile using platform-specific locking methods. + * + * @param lockFile If locking fails, this may return a lockFile object + * which can be used in platform-specific ways to + * determine which process has the file locked. Null + * may be passed. + * @return An interface which holds a profile lock as long as you reference + * it. + * @throws NS_ERROR_FILE_ACCESS_DENIED if the profile was already locked. + */ + nsIProfileLock lock(out nsIProfileUnlocker aUnlocker); }; diff --git a/mozilla/toolkit/profile/src/nsToolkitProfileService.cpp b/mozilla/toolkit/profile/src/nsToolkitProfileService.cpp index 682efaff776..a76241bd3ed 100644 --- a/mozilla/toolkit/profile/src/nsToolkitProfileService.cpp +++ b/mozilla/toolkit/profile/src/nsToolkitProfileService.cpp @@ -81,10 +81,11 @@ public: nsCOMPtr mNext; nsToolkitProfile *mPrev; + ~nsToolkitProfile() { } + private: nsToolkitProfile(const nsACString& aName, nsILocalFile* aFile, nsToolkitProfile* aPrev); - ~nsToolkitProfile() { } friend class nsToolkitProfileLock; @@ -99,14 +100,13 @@ public: NS_DECL_ISUPPORTS NS_DECL_NSIPROFILELOCK - nsresult Init(nsToolkitProfile* aProfile); - nsresult Init(nsILocalFile* aDirectory); + nsresult Init(nsToolkitProfile* aProfile, nsIProfileUnlocker* *aUnlocker); + nsresult Init(nsILocalFile* aDirectory, nsIProfileUnlocker* *aUnlocker); nsToolkitProfileLock() { } - -private: ~nsToolkitProfileLock(); +private: nsCOMPtr mProfile; nsCOMPtr mDirectory; @@ -242,7 +242,7 @@ nsToolkitProfile::Remove(PRBool removeFiles) } NS_IMETHODIMP -nsToolkitProfile::Lock(nsIProfileLock* *aResult) +nsToolkitProfile::Lock(nsIProfileUnlocker* *aUnlocker, nsIProfileLock* *aResult) { if (mLock) { NS_ADDREF(*aResult = mLock); @@ -252,7 +252,7 @@ nsToolkitProfile::Lock(nsIProfileLock* *aResult) nsCOMPtr lock = new nsToolkitProfileLock(); if (!lock) return NS_ERROR_OUT_OF_MEMORY; - nsresult rv = lock->Init(this); + nsresult rv = lock->Init(this, aUnlocker); if (NS_FAILED(rv)) return rv; NS_ADDREF(*aResult = lock); @@ -262,10 +262,10 @@ nsToolkitProfile::Lock(nsIProfileLock* *aResult) NS_IMPL_ISUPPORTS1(nsToolkitProfileLock, nsIProfileLock) nsresult -nsToolkitProfileLock::Init(nsToolkitProfile* aProfile) +nsToolkitProfileLock::Init(nsToolkitProfile* aProfile, nsIProfileUnlocker* *aUnlocker) { nsresult rv; - rv = Init(aProfile->mFile); + rv = Init(aProfile->mFile, aUnlocker); if (NS_SUCCEEDED(rv)) mProfile = aProfile; @@ -273,11 +273,11 @@ nsToolkitProfileLock::Init(nsToolkitProfile* aProfile) } nsresult -nsToolkitProfileLock::Init(nsILocalFile* aDirectory) +nsToolkitProfileLock::Init(nsILocalFile* aDirectory, nsIProfileUnlocker* *aUnlocker) { nsresult rv; - rv = mLock.Lock(aDirectory); + rv = mLock.Lock(aDirectory, aUnlocker); if (NS_SUCCEEDED(rv)) mDirectory = aDirectory; @@ -523,16 +523,17 @@ NS_IMETHODIMP nsToolkitProfileService::LockProfilePath(nsILocalFile* aDirectory, nsIProfileLock* *aResult) { - return NS_LockProfilePath(aDirectory, aResult); + return NS_LockProfilePath(aDirectory, nsnull, aResult); } nsresult -NS_LockProfilePath(nsILocalFile* aPath, nsIProfileLock* *aResult) +NS_LockProfilePath(nsILocalFile* aPath, nsIProfileUnlocker* *aUnlocker, + nsIProfileLock* *aResult) { nsCOMPtr lock = new nsToolkitProfileLock(); if (!lock) return NS_ERROR_OUT_OF_MEMORY; - nsresult rv = lock->Init(aPath); + nsresult rv = lock->Init(aPath, aUnlocker); if (NS_FAILED(rv)) return rv; NS_ADDREF(*aResult = lock); diff --git a/mozilla/toolkit/xre/Makefile.in b/mozilla/toolkit/xre/Makefile.in index 303ff5b6ad9..4a6834d9f18 100644 --- a/mozilla/toolkit/xre/Makefile.in +++ b/mozilla/toolkit/xre/Makefile.in @@ -59,6 +59,7 @@ REQUIRES = \ embedcomponents \ extensions \ gfx \ + intl \ js \ necko \ pref \ diff --git a/mozilla/toolkit/xre/nsAppRunner.cpp b/mozilla/toolkit/xre/nsAppRunner.cpp index 70de21f95e6..dcad82aac7e 100644 --- a/mozilla/toolkit/xre/nsAppRunner.cpp +++ b/mozilla/toolkit/xre/nsAppRunner.cpp @@ -74,7 +74,10 @@ #include "nsIObserverService.h" #include "nsINativeAppSupport.h" #include "nsIProcess.h" +#include "nsIProfileUnlocker.h" +#include "nsIPromptService.h" #include "nsIServiceManager.h" +#include "nsIStringBundle.h" #include "nsISupportsPrimitives.h" #include "nsITimelineService.h" #include "nsIToolkitChromeRegistry.h" @@ -90,6 +93,7 @@ #include "nsCOMPtr.h" #include "nsDirectoryServiceDefs.h" #include "nsDirectoryServiceUtils.h" +#include "nsEmbedCID.h" #include "nsNetUtil.h" #include "nsXPCOM.h" #include "nsXPIDLString.h" @@ -1082,7 +1086,78 @@ static nsresult LaunchChild(nsINativeAppSupport* aNative) return NS_ERROR_LAUNCHED_CHILD_PROCESS; } -static const char kProfileManagerURL[] = "chrome://mozapps/content/profile/profileSelection.xul"; +static const char kProfileProperties[] = + "chrome://mozapps/locale/profile/profileSelection.properties"; + +static nsresult +ProfileLockedDialog(nsILocalFile* aProfileDir, nsIProfileUnlocker* aUnlocker, + nsINativeAppSupport* aNative, nsIProfileLock* *aResult) +{ + nsresult rv; + + ScopedXPCOMStartup xpcom; + rv = xpcom.Initialize(); + NS_ENSURE_SUCCESS(rv, rv); + + rv = xpcom.DoAutoreg(); + rv |= xpcom.InitEventQueue(); + rv |= xpcom.SetWindowCreator(aNative); + NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); + + { //extra scoping is needed so we release these components before xpcom shutdown + nsCOMPtr sbs + (do_GetService(NS_STRINGBUNDLE_CONTRACTID)); + NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE); + + nsCOMPtr sb; + sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb)); + NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE); + + NS_ConvertUTF8toUTF16 appName(gAppData->appName); + const PRUnichar* params[] = {appName.get(), appName.get()}; + + nsXPIDLString killMessage; + sb->FormatStringFromName(NS_LITERAL_STRING("restartMessage").get(), + params, 2, getter_Copies(killMessage)); + + nsXPIDLString killTitle; + sb->FormatStringFromName(NS_LITERAL_STRING("restartTitle").get(), + params, 1, getter_Copies(killTitle)); + + if (!killMessage || !killTitle) + return NS_ERROR_FAILURE; + + nsCOMPtr ps + (do_GetService(NS_PROMPTSERVICE_CONTRACTID)); + NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE); + + PRUint32 flags = nsIPromptService::BUTTON_TITLE_OK * nsIPromptService::BUTTON_POS_0; + + if (aUnlocker) { + flags = + nsIPromptService::BUTTON_TITLE_CANCEL * nsIPromptService::BUTTON_POS_0 + + nsIPromptService::BUTTON_TITLE_IS_STRING * nsIPromptService::BUTTON_POS_1 + + nsIPromptService::BUTTON_POS_1_DEFAULT; + } + + PRInt32 button; + rv = ps->ConfirmEx(nsnull, killTitle, killMessage, flags, + killTitle, nsnull, nsnull, nsnull, nsnull, &button); + NS_ENSURE_SUCCESS(rv, rv); + + if (button == 1 && aUnlocker) { + rv = aUnlocker->Unlock(nsIProfileUnlocker::FORCE_QUIT); + if (NS_FAILED(rv)) return rv; + + return NS_LockProfilePath(aProfileDir, nsnull, aResult); + } + + return NS_ERROR_ABORT; + } +} + +static const char kProfileManagerURL[] = + "chrome://mozapps/content/profile/profileSelection.xul"; static nsresult ShowProfileManager(nsIToolkitProfileService* aProfileSvc, @@ -1225,7 +1300,7 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative, getter_AddRefs(lf)); NS_ENSURE_SUCCESS(rv, rv); - return NS_LockProfilePath(lf, aResult); + return NS_LockProfilePath(lf, nsnull, aResult); } if (CheckArg("migration")) @@ -1241,7 +1316,13 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative, rv = NS_GetFileFromPath(arg, getter_AddRefs(lf)); NS_ENSURE_SUCCESS(rv, rv); - return NS_LockProfilePath(lf, aResult); + nsCOMPtr unlocker; + + rv = NS_LockProfilePath(lf, getter_AddRefs(unlocker), aResult); + if (NS_SUCCEEDED(rv)) + return rv; + + return ProfileLockedDialog(lf, unlocker, aNative, aResult); } nsCOMPtr profileSvc; @@ -1309,9 +1390,16 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative, rv = profileSvc->GetProfileByName(nsDependentCString(arg), getter_AddRefs(profile)); if (NS_SUCCEEDED(rv)) { - rv = profile->Lock(aResult); + nsCOMPtr unlocker; + rv = profile->Lock(nsnull, aResult); if (NS_SUCCEEDED(rv)) return NS_OK; + + nsCOMPtr profileDir; + rv = profile->GetRootDir(getter_AddRefs(profileDir)); + NS_ENSURE_SUCCESS(rv, rv); + + return ProfileLockedDialog(profileDir, unlocker, aNative, aResult); } return ShowProfileManager(profileSvc, aNative); @@ -1321,7 +1409,6 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative, return ShowProfileManager(profileSvc, aNative); } - if (!count) { gDoMigration = PR_TRUE; @@ -1332,7 +1419,7 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative, getter_AddRefs(profile)); if (NS_SUCCEEDED(rv)) { profileSvc->Flush(); - rv = profile->Lock(aResult); + rv = profile->Lock(nsnull, aResult); if (NS_SUCCEEDED(rv)) return NS_OK; } @@ -1347,9 +1434,16 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative, // GetSelectedProfile will auto-select the only profile if there's just one profileSvc->GetSelectedProfile(getter_AddRefs(profile)); if (profile) { - rv = profile->Lock(aResult); + nsCOMPtr unlocker; + rv = profile->Lock(getter_AddRefs(unlocker), aResult); if (NS_SUCCEEDED(rv)) return NS_OK; + + nsCOMPtr profileDir; + rv = profile->GetRootDir(getter_AddRefs(profileDir)); + NS_ENSURE_SUCCESS(rv, rv); + + return ProfileLockedDialog(profileDir, unlocker, aNative, aResult); } } diff --git a/mozilla/toolkit/xre/nsAppRunner.h b/mozilla/toolkit/xre/nsAppRunner.h index 490574be41c..211fee5be12 100644 --- a/mozilla/toolkit/xre/nsAppRunner.h +++ b/mozilla/toolkit/xre/nsAppRunner.h @@ -65,6 +65,7 @@ class nsXREDirProvider; class nsIToolkitProfileService; class nsILocalFile; class nsIProfileLock; +class nsIProfileUnlocker; extern nsXREDirProvider* gDirServiceProvider; extern const nsXREAppData* gAppData; @@ -90,7 +91,8 @@ NS_HIDDEN_(nsresult) NS_GetFileFromPath(const char *aPath, nsILocalFile* *aResult); NS_HIDDEN_(nsresult) -NS_LockProfilePath(nsILocalFile* aPath, nsIProfileLock* *aResult); +NS_LockProfilePath(nsILocalFile* aPath, nsIProfileUnlocker* *aUnlocker, + nsIProfileLock* *aResult); #define NS_NATIVEAPPSUPPORT_CONTRACTID "@mozilla.org/toolkit/native-app-support;1"