зеркало из https://github.com/mozilla/pjs.git
fix for #137886. Detect defunct previously migrated profiles and offer to re-migrate.
this is pref controlled, "profile.seconds_until_defunct. by default, we'll never offer to remigrate. initial patch by ccarlen. r=ccarlen,racham,sr=bienvenu
This commit is contained in:
Родитель
3faab993b1
Коммит
a376f9f56c
|
@ -623,6 +623,15 @@ pref("mousewheel.withaltkey.sysnumlines",false);
|
|||
|
||||
pref("profile.confirm_automigration",true);
|
||||
|
||||
// the amount of time (in seconds) that must elapse
|
||||
// before we think your mozilla profile is defunct
|
||||
// and you'd benefit from re-migrating from 4.x
|
||||
// see bug #137886 for more details
|
||||
//
|
||||
// if -1, we never think your profile is defunct
|
||||
// and users will never see the remigrate UI.
|
||||
pref("profile.seconds_until_defunct", -1);
|
||||
|
||||
// Customizable toolbar stuff
|
||||
pref("custtoolbar.personal_toolbar_folder", "");
|
||||
|
||||
|
|
|
@ -87,7 +87,8 @@ interface nsIProfileInternal : nsIProfile {
|
|||
|
||||
void migrateProfileInfo();
|
||||
void migrateAllProfiles();
|
||||
void migrateProfile(in wstring profileName, in boolean showProgressAsModalWindow);
|
||||
void migrateProfile(in wstring profileName);
|
||||
void remigrateProfile(in wstring profileName);
|
||||
void forgetCurrentProfile();
|
||||
|
||||
/**
|
||||
|
@ -108,6 +109,12 @@ interface nsIProfileInternal : nsIProfile {
|
|||
*/
|
||||
nsILocalFile getOriginalProfileDir(in wstring profileName);
|
||||
|
||||
/**
|
||||
* Returns the date on which a profile was last used.
|
||||
* value is in milliseconds since midnight Jan 1, 1970 GMT (same as nsIFile)
|
||||
*/
|
||||
PRInt64 getProfileLastModTime(in wstring profileName);
|
||||
|
||||
attribute boolean automigrate;
|
||||
readonly attribute nsIFile defaultProfileParentDir;
|
||||
readonly attribute wstring firstProfile;
|
||||
|
|
|
@ -76,7 +76,7 @@ function RenameProfile()
|
|||
}
|
||||
}
|
||||
}
|
||||
profile.migrateProfile( profilename, true );
|
||||
profile.migrateProfile( profilename );
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
|
|
@ -183,7 +183,7 @@ function onStart()
|
|||
}
|
||||
}
|
||||
}
|
||||
profile.migrateProfile( profilename, true );
|
||||
profile.migrateProfile( profilename );
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
|
|
@ -9,3 +9,7 @@ mailDirName=Mail
|
|||
# newsDirName needs to be set to the same value as in 4.x
|
||||
# see bug #55449
|
||||
newsDirName=News
|
||||
# see nsAppShellService::CheckAndRemigrateDefunctProfile()
|
||||
# for where the confirmRemigration entries are used
|
||||
# LOCALIZATION NOTE: Do not translate Unicode (\uXXXX) characters.
|
||||
confirmRemigration=A more recent Netscape 4.5+ version of this profile (which contains your bookmarks, email settings, address books and preferences) was found.\u000aWould you like to use the more recent profile?
|
||||
|
|
|
@ -328,7 +328,6 @@ nsProfile::~nsProfile()
|
|||
if (--gInstanceCount == 0) {
|
||||
|
||||
delete gProfileDataAccess;
|
||||
|
||||
delete gLocaleProfiles;
|
||||
|
||||
NS_IF_RELEASE(sApp_PrefsDirectory50);
|
||||
|
@ -1058,9 +1057,43 @@ NS_IMETHODIMP nsProfile::GetOriginalProfileDir(const PRUnichar *profileName, nsI
|
|||
NS_ENSURE_ARG_POINTER(originalDir);
|
||||
*originalDir = nsnull;
|
||||
|
||||
Update4xProfileInfo();
|
||||
return gProfileDataAccess->GetOriginalProfileDir(profileName, originalDir);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsProfile::GetProfileLastModTime(const PRUnichar *profileName, PRInt64 *_retval)
|
||||
{
|
||||
NS_ENSURE_ARG(profileName);
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
nsresult rv;
|
||||
|
||||
// First, see if we can get the lastModTime from the registry.
|
||||
// We only started putting it there from mozilla1.0.1
|
||||
// The mod time will be zero if it has not been set.
|
||||
ProfileStruct *profileInfo = nsnull;
|
||||
rv = gProfileDataAccess->GetValue(profileName, &profileInfo);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PRInt64 lastModTime = profileInfo->lastModTime;
|
||||
delete profileInfo;
|
||||
if (!LL_IS_ZERO(lastModTime)) {
|
||||
*_retval = lastModTime;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Since we couldn't get a valid mod time from the registry,
|
||||
// check the date of prefs.js. Since August, 2000 it is always
|
||||
// written out on quitting the application.
|
||||
nsCOMPtr<nsIFile> profileDir;
|
||||
rv = GetProfileDir(profileName, getter_AddRefs(profileDir));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
rv = profileDir->Append("prefs.js");
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
return profileDir->GetLastModifiedTime(_retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsProfile::GetDefaultProfileParentDir(nsIFile **aDefaultProfileParentDir)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDefaultProfileParentDir);
|
||||
|
@ -1172,9 +1205,12 @@ nsProfile::SetCurrentProfile(const PRUnichar * aCurrentProfile)
|
|||
|
||||
// Phase 3: Notify observers of a profile change
|
||||
observerService->NotifyObservers(subject, "profile-before-change", context.get());
|
||||
|
||||
UpdateCurrentProfileModTime(PR_FALSE);
|
||||
}
|
||||
|
||||
// Do the profile switch
|
||||
mCurrentProfileName.Assign(aCurrentProfile);
|
||||
gProfileDataAccess->SetCurrentProfile(aCurrentProfile);
|
||||
gProfileDataAccess->mProfileDataChanged = PR_TRUE;
|
||||
gProfileDataAccess->UpdateRegistry(nsnull);
|
||||
|
@ -1233,31 +1269,37 @@ NS_IMETHODIMP nsProfile::ShutDownCurrentProfile(PRUint32 shutDownType)
|
|||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
do_GetService("@mozilla.org/observer-service;1", &rv);
|
||||
NS_ENSURE_TRUE(observerService, NS_ERROR_FAILURE);
|
||||
|
||||
nsISupports *subject = (nsISupports *)((nsIProfile *)this);
|
||||
|
||||
NS_NAMED_LITERAL_STRING(cleanseString, "shutdown-cleanse");
|
||||
NS_NAMED_LITERAL_STRING(persistString, "shutdown-persist");
|
||||
const nsAFlatString& context = (shutDownType == SHUTDOWN_CLEANSE) ? cleanseString : persistString;
|
||||
|
||||
// Phase 1: See if anybody objects to the profile being changed.
|
||||
mProfileChangeVetoed = PR_FALSE;
|
||||
observerService->NotifyObservers(subject, "profile-approve-change", context.get());
|
||||
if (mProfileChangeVetoed)
|
||||
// if shutDownType is not a well know value, skip the notifications
|
||||
// see DoOnShutdown() in nsAppRunner.cpp for where we use this behaviour to our benefit
|
||||
if (shutDownType == SHUTDOWN_PERSIST || shutDownType == SHUTDOWN_CLEANSE) {
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
do_GetService("@mozilla.org/observer-service;1", &rv);
|
||||
NS_ENSURE_TRUE(observerService, NS_ERROR_FAILURE);
|
||||
|
||||
nsISupports *subject = (nsISupports *)((nsIProfile *)this);
|
||||
|
||||
NS_NAMED_LITERAL_STRING(cleanseString, "shutdown-cleanse");
|
||||
NS_NAMED_LITERAL_STRING(persistString, "shutdown-persist");
|
||||
const nsAFlatString& context = (shutDownType == SHUTDOWN_CLEANSE) ? cleanseString : persistString;
|
||||
|
||||
// Phase 1: See if anybody objects to the profile being changed.
|
||||
mProfileChangeVetoed = PR_FALSE;
|
||||
observerService->NotifyObservers(subject, "profile-approve-change", context.get());
|
||||
if (mProfileChangeVetoed)
|
||||
return NS_OK;
|
||||
|
||||
// Phase 2: Send the "teardown" notification
|
||||
observerService->NotifyObservers(subject, "profile-change-teardown", context.get());
|
||||
|
||||
// Phase 3: Notify observers of a profile change
|
||||
observerService->NotifyObservers(subject, "profile-before-change", context.get());
|
||||
|
||||
// Phase 2: Send the "teardown" notification
|
||||
observerService->NotifyObservers(subject, "profile-change-teardown", context.get());
|
||||
|
||||
// Phase 3: Notify observers of a profile change
|
||||
observerService->NotifyObservers(subject, "profile-before-change", context.get());
|
||||
}
|
||||
|
||||
rv = UndefineFileLocations();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Could not undefine file locations");
|
||||
UpdateCurrentProfileModTime(PR_TRUE);
|
||||
mCurrentProfileAvailable = PR_FALSE;
|
||||
mCurrentProfileName.Truncate(0);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1440,7 +1482,8 @@ nsresult nsProfile::SetProfileDir(const PRUnichar *profileName, nsIFile *profile
|
|||
rv = profileDir->Exists(&exists);
|
||||
if (NS_SUCCEEDED(rv) && !exists)
|
||||
rv = profileDir->Create(nsIFile::DIRECTORY_TYPE, 0775);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(profileDir));
|
||||
NS_ENSURE_TRUE(localFile, NS_ERROR_FAILURE);
|
||||
|
@ -1448,12 +1491,16 @@ nsresult nsProfile::SetProfileDir(const PRUnichar *profileName, nsIFile *profile
|
|||
ProfileStruct* aProfile = new ProfileStruct();
|
||||
NS_ENSURE_TRUE(aProfile, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
|
||||
aProfile->profileName = profileName;
|
||||
aProfile->profileName = profileName;
|
||||
aProfile->SetResolvedProfileDir(localFile);
|
||||
aProfile->isMigrated = PR_TRUE;
|
||||
aProfile->isImportType = PR_FALSE;
|
||||
|
||||
// convert "now" from microsecs to millisecs
|
||||
PRInt64 oneThousand = LL_INIT(0, 1000);
|
||||
PRInt64 nowInMilliSecs = PR_Now();
|
||||
LL_DIV(aProfile->creationTime, nowInMilliSecs, oneThousand);
|
||||
|
||||
gProfileDataAccess->SetValue(aProfile);
|
||||
|
||||
delete aProfile;
|
||||
|
@ -1771,6 +1818,7 @@ NS_IMETHODIMP nsProfile::ForgetCurrentProfile()
|
|||
|
||||
gProfileDataAccess->mForgetProfileCalled = PR_TRUE;
|
||||
mCurrentProfileAvailable = PR_FALSE;
|
||||
mCurrentProfileName.Truncate(0);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -1943,6 +1991,22 @@ char * nsProfile::GetOldRegLocation()
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult nsProfile::UpdateCurrentProfileModTime(PRBool updateRegistry)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// convert "now" from microsecs to millisecs
|
||||
PRInt64 oneThousand = LL_INIT(0, 1000);
|
||||
PRInt64 nowInMilliSecs = PR_Now();
|
||||
LL_DIV(nowInMilliSecs, nowInMilliSecs, oneThousand);
|
||||
|
||||
rv = gProfileDataAccess->SetProfileLastModTime(mCurrentProfileName.get(), nowInMilliSecs);
|
||||
if (NS_SUCCEEDED(rv) && updateRegistry) {
|
||||
gProfileDataAccess->mProfileDataChanged = PR_TRUE;
|
||||
gProfileDataAccess->UpdateRegistry(nsnull);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Migrate profile information from the 4x registry to 5x registry.
|
||||
NS_IMETHODIMP nsProfile::MigrateProfileInfo()
|
||||
|
@ -2080,41 +2144,22 @@ nsresult nsProfile::UndefineFileLocations()
|
|||
// Set the profile to the current profile....debatable.
|
||||
// Calls PrefMigration service to do the Copy and Diverge
|
||||
// of 4x Profile information
|
||||
NS_IMETHODIMP
|
||||
nsProfile::MigrateProfile(const PRUnichar* profileName, PRBool showProgressAsModalWindow)
|
||||
nsresult
|
||||
nsProfile::MigrateProfileInternal(const PRUnichar* profileName,
|
||||
nsIFile* oldProfDir,
|
||||
nsIFile* newProfDir)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(profileName);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
#if defined(DEBUG_profile)
|
||||
printf("Inside Migrate Profile routine.\n" );
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIFile> oldProfDir;
|
||||
nsCOMPtr<nsIFile> newProfDir;
|
||||
|
||||
rv = GetProfileDir(profileName, getter_AddRefs(oldProfDir));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILES_ROOT_DIR, getter_AddRefs(newProfDir));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = newProfDir->AppendUnicode(profileName);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// This is unfortunate: There is no CreateUniqueUnicode
|
||||
rv = newProfDir->CreateUnique(nsIFile::DIRECTORY_TYPE, 0775);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// always create level indirection when migrating
|
||||
rv = AddLevelOfIndirection(newProfDir);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Call migration service to do the work.
|
||||
nsCOMPtr <nsIPrefMigration> pPrefMigrator;
|
||||
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kPrefMigrationCID,
|
||||
nsresult rv = nsComponentManager::CreateInstance(kPrefMigrationCID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsIPrefMigration),
|
||||
getter_AddRefs(pPrefMigrator));
|
||||
|
@ -2137,7 +2182,7 @@ nsProfile::MigrateProfile(const PRUnichar* profileName, PRBool showProgressAsMod
|
|||
// you can do this a bunch of times.
|
||||
rv = pPrefMigrator->AddProfilePaths(oldProfDirStr, newProfDirStr);
|
||||
|
||||
rv = pPrefMigrator->ProcessPrefs(showProgressAsModalWindow);
|
||||
rv = pPrefMigrator->ProcessPrefs(PR_TRUE); // param is ignored
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// check for diskspace errors
|
||||
|
@ -2198,12 +2243,90 @@ nsProfile::MigrateProfile(const PRUnichar* profileName, PRBool showProgressAsMod
|
|||
rv = SetProfileDir(profileName, newProfDir);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
gProfileDataAccess->SetMigratedFromDir(profileName, oldProfDirLocal);
|
||||
gProfileDataAccess->mProfileDataChanged = PR_TRUE;
|
||||
gProfileDataAccess->UpdateRegistry(nsnull);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsProfile::MigrateProfile(const PRUnichar* profileName)
|
||||
{
|
||||
NS_ENSURE_ARG(profileName);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsCOMPtr<nsIFile> oldProfDir;
|
||||
nsCOMPtr<nsIFile> newProfDir;
|
||||
|
||||
rv = GetProfileDir(profileName, getter_AddRefs(oldProfDir));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILES_ROOT_DIR, getter_AddRefs(newProfDir));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = newProfDir->AppendUnicode(profileName);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = newProfDir->CreateUnique(nsIFile::DIRECTORY_TYPE, 0775);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// always create level indirection when migrating
|
||||
rv = AddLevelOfIndirection(newProfDir);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
return MigrateProfileInternal(profileName, oldProfDir, newProfDir);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsProfile::RemigrateProfile(const PRUnichar* profileName)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(profileName);
|
||||
|
||||
nsCOMPtr<nsIFile> profileDir;
|
||||
nsresult rv = GetProfileDir(profileName, getter_AddRefs(profileDir));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
nsCOMPtr<nsIFile> newProfileDir;
|
||||
rv = profileDir->Clone(getter_AddRefs(newProfileDir));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
// The profile list used by GetOriginalProfileDir is the one with ALL 4.x
|
||||
// profiles - even ones for which there's a moz profile of the same name.
|
||||
nsCOMPtr<nsILocalFile> oldProfileDir;
|
||||
rv = GetOriginalProfileDir(profileName, getter_AddRefs(oldProfileDir));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
// In case of error, we'll restore what we've renamed.
|
||||
nsXPIDLCString origDirLeafName;
|
||||
rv = profileDir->GetLeafName(getter_Copies(origDirLeafName));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
// Backup what we're remigrating by renaming it and leaving in place
|
||||
// XXX todo: what if <xxxxxxxx>.slt-old already exists?
|
||||
nsCAutoString newDirLeafName(origDirLeafName + NS_LITERAL_CSTRING("-old"));
|
||||
rv = profileDir->MoveTo(nsnull, newDirLeafName.get());
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
// Create a new directory for the remigrated profile
|
||||
rv = newProfileDir->Create(nsIFile::DIRECTORY_TYPE, 0775);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create new directory for the remigrated profile");
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = MigrateProfileInternal(profileName, oldProfileDir, newProfileDir);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
newProfileDir->Remove(PR_TRUE);
|
||||
profileDir->MoveTo(nsnull, origDirLeafName);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsProfile::ShowProfileWizard(void)
|
||||
{
|
||||
|
@ -2266,7 +2389,7 @@ NS_IMETHODIMP nsProfile::MigrateAllProfiles()
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
for (PRUint32 i = 0; i < numOldProfiles; i++)
|
||||
{
|
||||
rv = MigrateProfile(nameArray[i], PR_FALSE /* don't show progress as modal window */);
|
||||
rv = MigrateProfile(nameArray[i]);
|
||||
if (NS_FAILED(rv)) break;
|
||||
}
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(numOldProfiles, nameArray);
|
||||
|
|
|
@ -87,6 +87,9 @@ private:
|
|||
nsresult UndefineFileLocations();
|
||||
nsresult Update4xProfileInfo();
|
||||
char * GetOldRegLocation();
|
||||
nsresult UpdateCurrentProfileModTime(PRBool updateRegistry);
|
||||
nsresult MigrateProfileInternal(const PRUnichar *profileName,
|
||||
nsIFile *oldProfDir, nsIFile *newProfDir);
|
||||
|
||||
PRBool mStartingUp;
|
||||
PRBool mAutomigrate;
|
||||
|
@ -94,13 +97,14 @@ private:
|
|||
PRBool mDiskSpaceErrorQuitCalled;
|
||||
PRBool mProfileChangeVetoed;
|
||||
|
||||
nsString mCurrentProfileName;
|
||||
PRBool mCurrentProfileAvailable;
|
||||
|
||||
PRBool mIsUILocaleSpecified;
|
||||
nsAutoString mUILocaleName;
|
||||
nsString mUILocaleName;
|
||||
|
||||
PRBool mIsContentLocaleSpecified;
|
||||
nsAutoString mContentLocaleName;
|
||||
nsString mContentLocaleName;
|
||||
|
||||
public:
|
||||
nsProfile();
|
||||
|
|
|
@ -42,9 +42,6 @@
|
|||
#include "nsICharsetConverterManager.h"
|
||||
#include "nsIPlatformCharset.h"
|
||||
|
||||
#define MAX_PERSISTENT_DATA_SIZE 1000
|
||||
#define NUM_HEX_BYTES 8
|
||||
#define ISHEX(c) ( ((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F') )
|
||||
|
||||
#if defined (XP_UNIX)
|
||||
#define USER_ENVIRONMENT_VARIABLE "USER"
|
||||
|
@ -76,7 +73,9 @@ static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CI
|
|||
#define kRegistryDirectoryString (NS_LITERAL_STRING("directory"))
|
||||
#define kRegistryNeedMigrationString (NS_LITERAL_STRING("NeedMigration"))
|
||||
#define kRegistryMozRegDataMovedString (NS_LITERAL_STRING("OldRegDataMoved"))
|
||||
|
||||
#define kRegistryCreationTimeString (NS_LITERAL_CSTRING("CreationTime"))
|
||||
#define kRegistryLastModTimeString (NS_LITERAL_CSTRING("LastModTime"))
|
||||
#define kRegistryMigratedFromString (NS_LITERAL_CSTRING("MigFromDir"))
|
||||
#define kRegistryVersionString (NS_LITERAL_STRING("Version"))
|
||||
#define kRegistryVersion_1_0 (NS_LITERAL_STRING("1.0"))
|
||||
#define kRegistryCurrentVersion (NS_LITERAL_STRING("1.0"))
|
||||
|
@ -223,10 +222,9 @@ nsProfileAccess::GetValue(const PRUnichar* profileName, ProfileStruct** aProfile
|
|||
nsresult
|
||||
nsProfileAccess::SetValue(ProfileStruct* aProfile)
|
||||
{
|
||||
NS_ASSERTION(aProfile, "Invalid profile");
|
||||
NS_ENSURE_ARG(aProfile);
|
||||
|
||||
PRInt32 index = 0;
|
||||
PRBool isNewProfile = PR_FALSE;
|
||||
ProfileStruct* profileItem;
|
||||
|
||||
index = FindProfileIndex(aProfile->profileName.get(), aProfile->isImportType);
|
||||
|
@ -234,43 +232,21 @@ nsProfileAccess::SetValue(ProfileStruct* aProfile)
|
|||
if (index >= 0)
|
||||
{
|
||||
profileItem = (ProfileStruct *) (mProfiles->ElementAt(index));
|
||||
*profileItem = *aProfile;
|
||||
profileItem->updateProfileEntry = PR_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
isNewProfile = PR_TRUE;
|
||||
|
||||
profileItem = new ProfileStruct();
|
||||
profileItem = new ProfileStruct(*aProfile);
|
||||
if (!profileItem)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
profileItem->profileName = aProfile->profileName;
|
||||
}
|
||||
|
||||
aProfile->CopyProfileLocation(profileItem);
|
||||
|
||||
profileItem->isMigrated = aProfile->isMigrated;
|
||||
|
||||
profileItem->isImportType = aProfile->isImportType;
|
||||
|
||||
profileItem->updateProfileEntry = PR_TRUE;
|
||||
|
||||
if (!aProfile->NCProfileName.IsEmpty())
|
||||
profileItem->NCProfileName = aProfile->NCProfileName;
|
||||
|
||||
if (!aProfile->NCDeniedService.IsEmpty())
|
||||
profileItem->NCDeniedService = aProfile->NCDeniedService;
|
||||
|
||||
if (!aProfile->NCEmailAddress.IsEmpty())
|
||||
profileItem->NCEmailAddress = aProfile->NCEmailAddress;
|
||||
|
||||
if (!aProfile->NCHavePregInfo.IsEmpty())
|
||||
profileItem->NCHavePregInfo = aProfile->NCHavePregInfo;
|
||||
|
||||
|
||||
if (isNewProfile) {
|
||||
if (!mProfiles) {
|
||||
mProfiles = new nsVoidArray;
|
||||
if (!mProfiles)
|
||||
mProfiles = new nsVoidArray();
|
||||
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
mProfiles->AppendElement((void*)profileItem);
|
||||
}
|
||||
|
||||
|
@ -350,12 +326,6 @@ nsProfileAccess::FillProfileInfo(nsIFile* regName)
|
|||
kRegistryVersionString.get(),
|
||||
getter_Copies(tmpVersion));
|
||||
|
||||
if (tmpVersion == nsnull)
|
||||
{
|
||||
fixRegEntries = PR_TRUE;
|
||||
mProfileDataChanged = PR_TRUE;
|
||||
}
|
||||
|
||||
// Get the preg info
|
||||
rv = registry->GetString(profilesTreeKey,
|
||||
kRegistryHavePREGInfoString.get(),
|
||||
|
@ -440,8 +410,23 @@ nsProfileAccess::FillProfileInfo(nsIFile* regName)
|
|||
profileItem->updateProfileEntry = PR_TRUE;
|
||||
profileItem->profileName = NS_STATIC_CAST(const PRUnichar*, profile);
|
||||
|
||||
rv = profileItem->InternalizeLocation(registry, profKey, PR_FALSE, fixRegEntries);
|
||||
PRInt64 tmpLongLong;
|
||||
rv = registry->GetLongLong(profKey,
|
||||
kRegistryCreationTimeString.get(),
|
||||
&tmpLongLong);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
profileItem->creationTime = tmpLongLong;
|
||||
|
||||
rv = registry->GetLongLong(profKey,
|
||||
kRegistryLastModTimeString.get(),
|
||||
&tmpLongLong);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
profileItem->lastModTime = tmpLongLong;
|
||||
|
||||
rv = profileItem->InternalizeLocation(registry, profKey, PR_FALSE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Internalizing profile location failed");
|
||||
// Not checking the error since most won't have this info
|
||||
profileItem->InternalizeMigratedFromLocation(registry, profKey);
|
||||
|
||||
profileItem->isMigrated = isMigratedString.Equals(kRegistryYesString);
|
||||
|
||||
|
@ -768,6 +753,14 @@ nsProfileAccess::UpdateRegistry(nsIFile* regName)
|
|||
kRegistryNCHavePREGInfoString.get(),
|
||||
profileItem->NCHavePregInfo.get());
|
||||
|
||||
registry->SetLongLong(profKey,
|
||||
kRegistryCreationTimeString.get(),
|
||||
&profileItem->creationTime);
|
||||
|
||||
registry->SetLongLong(profKey,
|
||||
kRegistryLastModTimeString.get(),
|
||||
&profileItem->lastModTime);
|
||||
|
||||
rv = profileItem->ExternalizeLocation(registry, profKey);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ASSERTION(PR_FALSE, "Could not update profile location");
|
||||
|
@ -775,6 +768,7 @@ nsProfileAccess::UpdateRegistry(nsIFile* regName)
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
continue;
|
||||
}
|
||||
profileItem->ExternalizeMigratedFromLocation(registry, profKey);
|
||||
|
||||
profileItem->updateProfileEntry = PR_FALSE;
|
||||
}
|
||||
|
@ -818,11 +812,20 @@ nsProfileAccess::UpdateRegistry(nsIFile* regName)
|
|||
kRegistryNCHavePREGInfoString.get(),
|
||||
profileItem->NCHavePregInfo.get());
|
||||
|
||||
registry->SetLongLong(profKey,
|
||||
kRegistryCreationTimeString.get(),
|
||||
&profileItem->creationTime);
|
||||
|
||||
registry->SetLongLong(profKey,
|
||||
kRegistryLastModTimeString.get(),
|
||||
&profileItem->lastModTime);
|
||||
|
||||
rv = profileItem->ExternalizeLocation(registry, profKey);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ASSERTION(PR_FALSE, "Could not update profile location");
|
||||
continue;
|
||||
}
|
||||
profileItem->ExternalizeMigratedFromLocation(registry, profKey);
|
||||
|
||||
profileItem->updateProfileEntry = PR_FALSE;
|
||||
}
|
||||
|
@ -873,6 +876,40 @@ nsProfileAccess::GetOriginalProfileDir(const PRUnichar *profileName, nsILocalFil
|
|||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsProfileAccess::SetMigratedFromDir(const PRUnichar *profileName, nsILocalFile *originalDir)
|
||||
{
|
||||
NS_ENSURE_ARG(profileName);
|
||||
NS_ENSURE_ARG(originalDir);
|
||||
|
||||
PRInt32 index = FindProfileIndex(profileName, PR_FALSE);
|
||||
if (index >= 0)
|
||||
{
|
||||
ProfileStruct* profileItem = (ProfileStruct *) (mProfiles->ElementAt(index));
|
||||
profileItem->migratedFrom = originalDir;
|
||||
profileItem->updateProfileEntry = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsProfileAccess::SetProfileLastModTime(const PRUnichar *profileName, PRInt64 lastModTime)
|
||||
{
|
||||
NS_ENSURE_ARG(profileName);
|
||||
|
||||
PRInt32 index = FindProfileIndex(profileName, PR_FALSE);
|
||||
if (index >= 0)
|
||||
{
|
||||
ProfileStruct* profileItem = (ProfileStruct *) (mProfiles->ElementAt(index));
|
||||
profileItem->lastModTime = lastModTime;
|
||||
profileItem->updateProfileEntry = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Return the list of profiles, 4x, 5x, or both.
|
||||
nsresult
|
||||
nsProfileAccess::GetProfileList(PRInt32 whichKind, PRUint32 *length, PRUnichar ***result)
|
||||
|
@ -1063,7 +1100,7 @@ nsProfileAccess::Get4xProfileInfo(const char *registryName, PRBool fromImport)
|
|||
|
||||
profileItem->updateProfileEntry = PR_TRUE;
|
||||
profileItem->profileName = convertedProfName;
|
||||
rv = profileItem->InternalizeLocation(oldReg, key, PR_TRUE, PR_FALSE);
|
||||
rv = profileItem->InternalizeLocation(oldReg, key, PR_TRUE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Could not get 4x profile location");
|
||||
profileItem->isMigrated = PR_FALSE;
|
||||
profileItem->isImportType = fromImport;
|
||||
|
@ -1218,20 +1255,53 @@ nsProfileAccess::DetermineForceMigration(PRBool *forceMigration)
|
|||
// class ProfileStruct
|
||||
// **********************************************************************
|
||||
|
||||
ProfileStruct::ProfileStruct(const ProfileStruct& src) :
|
||||
profileName(src.profileName), isMigrated(src.isMigrated),
|
||||
NCProfileName(src.NCProfileName), NCDeniedService(src.NCDeniedService),
|
||||
NCEmailAddress(src.NCEmailAddress), NCHavePregInfo(src.NCHavePregInfo),
|
||||
updateProfileEntry(src.updateProfileEntry),
|
||||
isImportType(src.isImportType),
|
||||
regLocationData(src.regLocationData)
|
||||
ProfileStruct::ProfileStruct() :
|
||||
isMigrated(PR_FALSE), updateProfileEntry(PR_FALSE),
|
||||
isImportType(PR_FALSE),
|
||||
creationTime(LL_ZERO), lastModTime(LL_ZERO)
|
||||
{
|
||||
if (src.resolvedLocation) {
|
||||
}
|
||||
|
||||
ProfileStruct::ProfileStruct(const ProfileStruct& src)
|
||||
{
|
||||
*this = src;
|
||||
}
|
||||
|
||||
ProfileStruct& ProfileStruct::operator=(const ProfileStruct& rhs)
|
||||
{
|
||||
profileName = rhs.profileName;
|
||||
isMigrated = rhs.isMigrated;
|
||||
NCProfileName = rhs.NCProfileName;
|
||||
NCDeniedService = rhs.NCDeniedService;
|
||||
NCEmailAddress = rhs.NCEmailAddress;
|
||||
NCHavePregInfo = rhs.NCHavePregInfo;
|
||||
updateProfileEntry = rhs.updateProfileEntry;
|
||||
isImportType = rhs.isImportType;
|
||||
creationTime = rhs.creationTime;
|
||||
lastModTime = rhs.lastModTime;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIFile> file;
|
||||
nsresult rv = src.resolvedLocation->Clone(getter_AddRefs(file));
|
||||
|
||||
resolvedLocation = nsnull;
|
||||
if (rhs.resolvedLocation) {
|
||||
regLocationData.Truncate(0);
|
||||
rv = rhs.resolvedLocation->Clone(getter_AddRefs(file));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
resolvedLocation = do_QueryInterface(file);
|
||||
file = nsnull;
|
||||
}
|
||||
else
|
||||
regLocationData = rhs.regLocationData;
|
||||
|
||||
migratedFrom = nsnull;
|
||||
if (rhs.migratedFrom) {
|
||||
rv = rhs.migratedFrom->Clone(getter_AddRefs(file));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
migratedFrom = do_QueryInterface(file);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
nsresult ProfileStruct::GetResolvedProfileDir(nsILocalFile **aDirectory)
|
||||
|
@ -1270,7 +1340,7 @@ nsresult ProfileStruct::CopyProfileLocation(ProfileStruct *destStruct)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult ProfileStruct::InternalizeLocation(nsIRegistry *aRegistry, nsRegistryKey profKey, PRBool is4x, PRBool isOld50)
|
||||
nsresult ProfileStruct::InternalizeLocation(nsIRegistry *aRegistry, nsRegistryKey profKey, PRBool is4x)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsILocalFile> tempLocal;
|
||||
|
@ -1315,90 +1385,24 @@ nsresult ProfileStruct::InternalizeLocation(nsIRegistry *aRegistry, nsRegistryKe
|
|||
{
|
||||
nsXPIDLString regData;
|
||||
|
||||
if (isOld50) // Some format which was used around M10-M11. Can we forget about it?
|
||||
{
|
||||
|
||||
rv = aRegistry->GetString(profKey,
|
||||
kRegistryDirectoryString.get(),
|
||||
getter_Copies(regData));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRBool haveHexBytes = PR_TRUE;
|
||||
|
||||
// Decode the directory name to return the ordinary string
|
||||
nsCAutoString regDataCString; regDataCString.AssignWithConversion(regData);
|
||||
nsInputStringStream stream(regDataCString.get());
|
||||
|
||||
char bigBuffer[MAX_PERSISTENT_DATA_SIZE + 1];
|
||||
// The first 8 bytes of the data should be a hex version of the data size to follow.
|
||||
PRInt32 bytesRead = NUM_HEX_BYTES;
|
||||
bytesRead = stream.read(bigBuffer, bytesRead);
|
||||
|
||||
if (bytesRead != NUM_HEX_BYTES)
|
||||
haveHexBytes = PR_FALSE;
|
||||
|
||||
if (haveHexBytes)
|
||||
{
|
||||
bigBuffer[NUM_HEX_BYTES] = '\0';
|
||||
|
||||
for (int i = 0; i < NUM_HEX_BYTES; i++)
|
||||
{
|
||||
if (!(ISHEX(bigBuffer[i])))
|
||||
{
|
||||
haveHexBytes = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoString dirNameString;
|
||||
if (haveHexBytes)
|
||||
{
|
||||
PR_sscanf(bigBuffer, "%x", (PRUint32*)&bytesRead);
|
||||
if (bytesRead > MAX_PERSISTENT_DATA_SIZE)
|
||||
{
|
||||
// Try to tolerate encoded values with no length header
|
||||
bytesRead = NUM_HEX_BYTES +
|
||||
stream.read(bigBuffer + NUM_HEX_BYTES,
|
||||
MAX_PERSISTENT_DATA_SIZE - NUM_HEX_BYTES);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Now we know how many bytes to read, do it.
|
||||
bytesRead = stream.read(bigBuffer, bytesRead);
|
||||
}
|
||||
|
||||
// Make sure we are null terminated
|
||||
bigBuffer[bytesRead]='\0';
|
||||
|
||||
dirNameString.AssignWithConversion(nsDependentCString(bigBuffer, bytesRead).get());
|
||||
}
|
||||
else
|
||||
dirNameString = regData;
|
||||
|
||||
rv = NS_NewUnicodeLocalFile(dirNameString.get(), PR_TRUE, getter_AddRefs(tempLocal));
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = aRegistry->GetString(profKey,
|
||||
kRegistryDirectoryString.get(),
|
||||
getter_Copies(regData));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
regLocationData = regData;
|
||||
rv = aRegistry->GetString(profKey,
|
||||
kRegistryDirectoryString.get(),
|
||||
getter_Copies(regData));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
regLocationData = regData;
|
||||
|
||||
#ifdef XP_MAC
|
||||
// For a brief time, this was a unicode path
|
||||
PRInt32 firstColon = regLocationData.FindChar(PRUnichar(':'));
|
||||
if (firstColon == -1)
|
||||
{
|
||||
rv = NS_NewLocalFile(nsnull, PR_TRUE, getter_AddRefs(tempLocal));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = tempLocal->SetPersistentDescriptor(NS_ConvertUCS2toUTF8(regLocationData).get());
|
||||
}
|
||||
else
|
||||
#endif
|
||||
rv = NS_NewUnicodeLocalFile(regLocationData.get(), PR_TRUE, getter_AddRefs(tempLocal));
|
||||
// For a brief time, this was a unicode path
|
||||
PRInt32 firstColon = regLocationData.FindChar(PRUnichar(':'));
|
||||
if (firstColon == -1)
|
||||
{
|
||||
rv = NS_NewLocalFile(nsnull, PR_TRUE, getter_AddRefs(tempLocal));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = tempLocal->SetPersistentDescriptor(NS_ConvertUCS2toUTF8(regLocationData).get());
|
||||
}
|
||||
else
|
||||
#endif
|
||||
rv = NS_NewUnicodeLocalFile(regLocationData.get(), PR_TRUE, getter_AddRefs(tempLocal));
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && tempLocal)
|
||||
|
@ -1459,6 +1463,59 @@ nsresult ProfileStruct::ExternalizeLocation(nsIRegistry *aRegistry, nsRegistryKe
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult ProfileStruct::InternalizeMigratedFromLocation(nsIRegistry *aRegistry, nsRegistryKey profKey)
|
||||
{
|
||||
nsresult rv;
|
||||
nsXPIDLCString regData;
|
||||
nsCOMPtr<nsILocalFile> tempLocal;
|
||||
|
||||
rv = aRegistry->GetStringUTF8(profKey,
|
||||
kRegistryMigratedFromString.get(),
|
||||
getter_Copies(regData));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
#ifdef XP_MAC
|
||||
rv = NS_NewLocalFile(nsnull, PR_TRUE, getter_AddRefs(tempLocal));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
// The persistent desc on Mac is base64 encoded so plain ASCII
|
||||
rv = tempLocal->SetPersistentDescriptor(regData.get());
|
||||
if (NS_SUCCEEDED(rv))
|
||||
migratedFrom = tempLocal;
|
||||
}
|
||||
#else
|
||||
rv = NS_NewUnicodeLocalFile(NS_ConvertUTF8toUCS2(regData).get(), PR_TRUE, getter_AddRefs(tempLocal));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
migratedFrom = tempLocal;
|
||||
#endif
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult ProfileStruct::ExternalizeMigratedFromLocation(nsIRegistry *aRegistry, nsRegistryKey profKey)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsXPIDLCString regData;
|
||||
|
||||
if (migratedFrom)
|
||||
{
|
||||
#if XP_MAC
|
||||
rv = migratedFrom->GetPersistentDescriptor(getter_Copies(regData));
|
||||
#else
|
||||
nsXPIDLString ucPath;
|
||||
rv = resolvedLocation->GetUnicodePath(getter_Copies(ucPath));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
regData = NS_ConvertUCS2toUTF8(ucPath);
|
||||
#endif
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = aRegistry->SetStringUTF8(profKey,
|
||||
kRegistryMigratedFromString.get(),
|
||||
regData.get());
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult ProfileStruct::EnsureDirPathExists(nsILocalFile *aDir, PRBool *wasCreated)
|
||||
{
|
||||
NS_ENSURE_ARG(aDir);
|
||||
|
|
|
@ -33,11 +33,13 @@
|
|||
class ProfileStruct
|
||||
{
|
||||
public:
|
||||
explicit ProfileStruct() { }
|
||||
ProfileStruct();
|
||||
ProfileStruct(const ProfileStruct& src);
|
||||
|
||||
~ProfileStruct() { }
|
||||
|
||||
ProfileStruct& operator=(const ProfileStruct& rhs);
|
||||
|
||||
/*
|
||||
* GetResolvedProfileDir returns the directory specified in the
|
||||
* registry. It will return NULL if the spec in the registry
|
||||
|
@ -63,12 +65,19 @@ public:
|
|||
* Methods used by routines which internalize
|
||||
* and externalize profile info.
|
||||
*/
|
||||
nsresult InternalizeLocation(nsIRegistry *aRegistry, nsRegistryKey profKey, PRBool is4x, PRBool isOld50);
|
||||
nsresult InternalizeLocation(nsIRegistry *aRegistry, nsRegistryKey profKey, PRBool is4x);
|
||||
nsresult ExternalizeLocation(nsIRegistry *aRegistry, nsRegistryKey profKey);
|
||||
nsresult InternalizeMigratedFromLocation(nsIRegistry *aRegistry, nsRegistryKey profKey);
|
||||
nsresult ExternalizeMigratedFromLocation(nsIRegistry *aRegistry, nsRegistryKey profKey);
|
||||
|
||||
public:
|
||||
nsString profileName;
|
||||
PRBool isMigrated;
|
||||
|
||||
// The directory from which this profile was migrated from (if any)
|
||||
// Added in mozilla1.0.1 and maintained in the registry
|
||||
nsCOMPtr<nsILocalFile> migratedFrom;
|
||||
|
||||
nsString NCProfileName;
|
||||
nsString NCDeniedService;
|
||||
nsString NCEmailAddress;
|
||||
|
@ -76,6 +85,11 @@ public:
|
|||
PRBool updateProfileEntry;
|
||||
// this flag detemines if we added this profile to the list for the import module.
|
||||
PRBool isImportType;
|
||||
// These fields were added in mozilla1.0.1 and maintained in the registry.
|
||||
// Values are in milliseconds since midnight Jan 1, 1970 GMT (same as nsIFile)
|
||||
// Their values will be LL_ZERO if undefined.
|
||||
PRInt64 creationTime;
|
||||
PRInt64 lastModTime;
|
||||
|
||||
private:
|
||||
nsresult EnsureDirPathExists(nsILocalFile *aFile, PRBool *wasCreated);
|
||||
|
@ -115,6 +129,8 @@ public:
|
|||
void GetFirstProfile(PRUnichar **firstProfile);
|
||||
nsresult GetProfileList(PRInt32 whichKind, PRUint32 *length, PRUnichar ***result);
|
||||
nsresult GetOriginalProfileDir(const PRUnichar *profileName, nsILocalFile **orginalDir);
|
||||
nsresult SetMigratedFromDir(const PRUnichar *profileName, nsILocalFile *orginalDir);
|
||||
nsresult SetProfileLastModTime(const PRUnichar *profileName, PRInt64 lastModTime);
|
||||
|
||||
// if fromImport is true all the 4.x profiles will be added to mProfiles with the isImportType flag set.
|
||||
// pass fromImport as True only if you are calling from the Import Module.
|
||||
|
|
|
@ -80,6 +80,12 @@ PRBool OnMacOSX();
|
|||
#include "nsIScriptContext.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
/* for the "remigration" stuff */
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPromptService.h"
|
||||
#include "nsIStringBundle.h"
|
||||
|
||||
#include "nsAppShellService.h"
|
||||
#include "nsIProfileInternal.h"
|
||||
|
||||
|
@ -234,8 +240,7 @@ nsAppShellService::DoProfileStartup(nsICmdLineService *aCmdLineService, PRBool c
|
|||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIProfileInternal> profileMgr(do_GetService(NS_PROFILE_CONTRACTID, &rv));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get profile manager");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
PRBool saveQuitOnLastWindowClosing = mQuitOnLastWindowClosing;
|
||||
mQuitOnLastWindowClosing = PR_FALSE;
|
||||
|
@ -247,11 +252,148 @@ nsAppShellService::DoProfileStartup(nsICmdLineService *aCmdLineService, PRBool c
|
|||
rv = NS_OK;
|
||||
}
|
||||
|
||||
mQuitOnLastWindowClosing = saveQuitOnLastWindowClosing;
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = CheckAndRemigrateDefunctProfile();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to check and remigrate profile");
|
||||
rv = NS_OK;
|
||||
}
|
||||
|
||||
mQuitOnLastWindowClosing = saveQuitOnLastWindowClosing;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAppShellService::CheckAndRemigrateDefunctProfile()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch;
|
||||
nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
rv = prefs->GetBranch(nsnull, getter_AddRefs(prefBranch));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
PRInt32 secondsBeforeDefunct;
|
||||
rv = prefBranch->GetIntPref("profile.seconds_until_defunct", &secondsBeforeDefunct);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
// -1 is the value for "never go defunct"
|
||||
// if the pref is set to -1, we'll never prompt the user to remigrate
|
||||
// see all.js (and all-ns.js)
|
||||
if (secondsBeforeDefunct == -1)
|
||||
return NS_OK;
|
||||
|
||||
// used for converting
|
||||
// seconds -> millisecs
|
||||
// and microsecs -> millisecs
|
||||
PRInt64 oneThousand = LL_INIT(0, 1000);
|
||||
|
||||
PRInt64 defunctInterval;
|
||||
// Init as seconds
|
||||
LL_I2L(defunctInterval, secondsBeforeDefunct);
|
||||
// Convert secs to millisecs
|
||||
LL_MUL(defunctInterval, defunctInterval, oneThousand);
|
||||
|
||||
nsCOMPtr<nsIProfileInternal> profileMgr(do_GetService(NS_PROFILE_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
nsXPIDLString profileName;
|
||||
PRInt64 lastModTime;
|
||||
profileMgr->GetCurrentProfile(getter_Copies(profileName));
|
||||
rv = profileMgr->GetProfileLastModTime(profileName.get(), &lastModTime);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
// convert "now" from microsecs to millisecs
|
||||
PRInt64 nowInMilliSecs = PR_Now();
|
||||
LL_DIV(nowInMilliSecs, nowInMilliSecs, oneThousand);
|
||||
|
||||
// determine (using the pref value) when the profile would be considered defunct
|
||||
PRInt64 defunctIntervalAgo;
|
||||
LL_SUB(defunctIntervalAgo, nowInMilliSecs, defunctInterval);
|
||||
|
||||
// if we've used our current 6.x / mozilla profile more recently than
|
||||
// when we'd consider it defunct, don't remigrate
|
||||
if (LL_CMP(lastModTime, >, defunctIntervalAgo))
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsILocalFile> origProfileDir;
|
||||
rv = profileMgr->GetOriginalProfileDir(profileName, getter_AddRefs(origProfileDir));
|
||||
// if this fails
|
||||
// then the current profile is a new one (not from 4.x)
|
||||
// so we are done.
|
||||
if (NS_FAILED(rv))
|
||||
return NS_OK;
|
||||
|
||||
// Now, we know that a matching 4.x profile exists
|
||||
// See if it has any newer files in it than our defunct profile.
|
||||
nsCOMPtr<nsISimpleEnumerator> dirEnum;
|
||||
rv = origProfileDir->GetDirectoryEntries(getter_AddRefs(dirEnum));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
PRBool promptForRemigration = PR_FALSE;
|
||||
PRBool hasMore;
|
||||
while (NS_SUCCEEDED(dirEnum->HasMoreElements(&hasMore)) && hasMore) {
|
||||
nsCOMPtr<nsILocalFile> currElem;
|
||||
rv = dirEnum->GetNext(getter_AddRefs(currElem));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
PRInt64 currElemModTime;
|
||||
rv = currElem->GetLastModifiedTime(&currElemModTime);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
// if this file in our 4.x profile is more recent than when we last used our mozilla / 6.x profile
|
||||
// we should prompt for re-migration
|
||||
if (LL_CMP(currElemModTime, >, lastModTime)) {
|
||||
promptForRemigration = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If nothing in the 4.x dir is newer than our defunct profile, return.
|
||||
if (!promptForRemigration)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIStringBundleService> stringBundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
nsCOMPtr<nsIStringBundle> migrationBundle, brandBundle;
|
||||
rv = stringBundleService->CreateBundle("chrome://communicator/locale/profile/migration.properties", getter_AddRefs(migrationBundle));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
rv = stringBundleService->CreateBundle("chrome://global/locale/brand.properties", getter_AddRefs(brandBundle));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
nsXPIDLString brandName;
|
||||
rv = brandBundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(), getter_Copies(brandName));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
nsXPIDLString dialogText;
|
||||
rv = migrationBundle->GetStringFromName(NS_LITERAL_STRING("confirmRemigration").get(), getter_Copies(dialogText));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
nsCOMPtr<nsIPromptService> promptService(do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
PRInt32 buttonPressed;
|
||||
rv = promptService->ConfirmEx(nsnull, brandName.get(),
|
||||
dialogText.get(),
|
||||
(nsIPromptService::BUTTON_POS_0 *
|
||||
nsIPromptService::BUTTON_TITLE_YES) +
|
||||
(nsIPromptService::BUTTON_POS_1 *
|
||||
nsIPromptService::BUTTON_TITLE_NO),
|
||||
nsnull, nsnull, nsnull, nsnull, nsnull, &buttonPressed);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
if (buttonPressed == 0) {
|
||||
// Need to shut down the current profile before remigrating it
|
||||
profileMgr->ShutDownCurrentProfile(nsIProfile::SHUTDOWN_PERSIST);
|
||||
// If this fails, it will restore what was there.
|
||||
rv = profileMgr->RemigrateProfile(profileName.get());
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Remigration of profile failed.");
|
||||
// Whether or not we succeeded or failed, need to reset this.
|
||||
profileMgr->SetCurrentProfile(profileName.get());
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAppShellService::CreateHiddenWindow()
|
||||
{
|
||||
|
|
|
@ -96,6 +96,9 @@ protected:
|
|||
|
||||
static void* PR_CALLBACK HandleExitEvent(PLEvent* aEvent);
|
||||
static void PR_CALLBACK DestroyExitEvent(PLEvent* aEvent);
|
||||
|
||||
private:
|
||||
nsresult CheckAndRemigrateDefunctProfile();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -52,6 +52,7 @@ REQUIRES = xpcom \
|
|||
uconv \
|
||||
locale \
|
||||
xremoteservice \
|
||||
profile \
|
||||
$(NULL)
|
||||
# for jprof
|
||||
REQUIRES += jprof
|
||||
|
|
|
@ -96,6 +96,9 @@
|
|||
#include "nsIXRemoteService.h"
|
||||
#endif
|
||||
|
||||
// see DoOnShutdown()
|
||||
#include "nsIProfile.h"
|
||||
|
||||
#ifdef NS_TRACE_MALLOC
|
||||
#include "nsTraceMalloc.h"
|
||||
#endif
|
||||
|
@ -106,7 +109,7 @@
|
|||
|
||||
#include "nsITimelineService.h"
|
||||
|
||||
#if defined(DEBUG_sspitzer) || defined(DEBUG_seth) || defined(DEBUG_pra)
|
||||
#if defined(DEBUG_pra)
|
||||
#define DEBUG_CMD_LINE
|
||||
#endif
|
||||
|
||||
|
@ -773,6 +776,17 @@ static nsresult DoOnShutdown()
|
|||
{
|
||||
nsresult rv;
|
||||
|
||||
// call ShutDownCurrentProfile() so we update the last modified time of the profile
|
||||
{
|
||||
// scoping this in a block to force release
|
||||
nsCOMPtr<nsIProfile> profileMgr(do_GetService(NS_PROFILE_CONTRACTID, &rv));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get profile manager, so unable to update last modified time");
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// 0 is undefined, we use this secret value so that we don't notify
|
||||
profileMgr->ShutDownCurrentProfile(0);
|
||||
}
|
||||
}
|
||||
|
||||
// save the prefs, in case they weren't saved
|
||||
{
|
||||
// scoping this in a block to force release
|
||||
|
|
Загрузка…
Ссылка в новой задаче