mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Bug 717070 - Profile reset - Part 1 - Backend to initiate profile reset. r=mano
This commit is contained in:
parent
52d2c4d950
commit
a89acec325
@ -16,10 +16,25 @@ function ProfileMigrator() {
|
||||
}
|
||||
|
||||
ProfileMigrator.prototype = {
|
||||
migrate: function PM_migrate(aStartup) {
|
||||
migrate: function PM_migrate(aStartup, aKey) {
|
||||
// By opening the wizard with a supplied migrator, it will automatically
|
||||
// migrate from it.
|
||||
let [key, migrator] = this._getDefaultMigrator();
|
||||
let key = null, migrator = null;
|
||||
let skipImportSourcePage = Cc["@mozilla.org/supports-PRBool;1"]
|
||||
.createInstance(Ci.nsISupportsPRBool);
|
||||
if (aKey) {
|
||||
key = aKey;
|
||||
migrator = this._getMigratorIfSourceExists(key);
|
||||
if (!migrator) {
|
||||
Cu.reportError("Invalid migrator key specified or source does not exist.");
|
||||
return;
|
||||
}
|
||||
// If the migrator was passed to us from the caller, use that migrator
|
||||
// and skip the import source page.
|
||||
skipImportSourcePage.data = true;
|
||||
} else {
|
||||
[key, migrator] = this._getDefaultMigrator();
|
||||
}
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
@ -27,6 +42,7 @@ ProfileMigrator.prototype = {
|
||||
params.appendElement(this._toCString(key), false);
|
||||
params.appendElement(migrator, false);
|
||||
params.appendElement(aStartup, false);
|
||||
params.appendElement(skipImportSourcePage, false);
|
||||
|
||||
Services.ww.openWindow(null,
|
||||
"chrome://browser/content/migration/migration.xul",
|
||||
@ -43,10 +59,14 @@ ProfileMigrator.prototype = {
|
||||
},
|
||||
|
||||
_getMigratorIfSourceExists: function PM__getMigratorIfSourceExists(aKey) {
|
||||
let cid = "@mozilla.org/profile/migrator;1?app=browser&type=" + aKey;
|
||||
let migrator = Cc[cid].createInstance(Ci.nsIBrowserProfileMigrator);
|
||||
if (migrator.sourceExists)
|
||||
return migrator;
|
||||
try {
|
||||
let cid = "@mozilla.org/profile/migrator;1?app=browser&type=" + aKey;
|
||||
let migrator = Cc[cid].createInstance(Ci.nsIBrowserProfileMigrator);
|
||||
if (migrator.sourceExists)
|
||||
return migrator;
|
||||
} catch (ex) {
|
||||
Cu.reportError("Could not get migrator: " + ex);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
|
@ -69,7 +69,7 @@ interface nsIProfileStartup : nsISupports
|
||||
* @client Toolkit (Startup code)
|
||||
* @obtainable service, contractid("@mozilla.org/toolkit/profile-migrator;1")
|
||||
*/
|
||||
[scriptable, uuid(24ce8b9d-b7ff-4279-aef4-26e158f03e34)]
|
||||
[scriptable, uuid(3df284a5-2258-4d46-a664-761ecdc04c22)]
|
||||
interface nsIProfileMigrator : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -86,10 +86,13 @@ interface nsIProfileMigrator : nsISupports
|
||||
* If your migrator needs to access services that use the profile (to
|
||||
* set profile prefs or bookmarks, for example), use aStartup.doStartup.
|
||||
*
|
||||
* @param aStartup nsIProfileStartup object to use during migration.
|
||||
* @param aKey optional key of a migrator to use to skip source selection.
|
||||
*
|
||||
* @note The startup code ignores COM exceptions thrown from this method.
|
||||
*/
|
||||
void migrate(in nsIProfileStartup aStartup);
|
||||
};
|
||||
void migrate(in nsIProfileStartup aStartup, in ACString aKey);
|
||||
};
|
||||
|
||||
%{C++
|
||||
#define NS_PROFILEMIGRATOR_CONTRACTID "@mozilla.org/toolkit/profile-migrator;1"
|
||||
|
@ -150,6 +150,7 @@ using mozilla::unused;
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsXPCOMCIDInternal.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsVersionComparator.h"
|
||||
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
@ -1911,9 +1912,72 @@ ShowProfileManager(nsIToolkitProfileService* aProfileSvc,
|
||||
// 6) display the profile-manager UI
|
||||
|
||||
static bool gDoMigration = false;
|
||||
static bool gDoProfileReset = false;
|
||||
|
||||
/**
|
||||
* Creates a new profile with a timestamp in the name to use for profile reset.
|
||||
*/
|
||||
static nsresult
|
||||
ResetProfile(nsIToolkitProfileService* aProfileSvc, nsIToolkitProfile* *aNewProfile)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aProfileSvc);
|
||||
|
||||
nsCOMPtr<nsIToolkitProfile> newProfile;
|
||||
// Make the new profile "default-" + the time in seconds since epoch for uniqueness.
|
||||
nsCAutoString newProfileName("default-");
|
||||
newProfileName.Append(nsPrintfCString("%lld", PR_Now() / 1000));
|
||||
nsresult rv = aProfileSvc->CreateProfile(nsnull, // choose a default dir for us
|
||||
nsnull, // choose a default dir for us
|
||||
newProfileName,
|
||||
getter_AddRefs(newProfile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aProfileSvc->Flush();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_IF_ADDREF(*aNewProfile = newProfile);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the currently running profile as the default/selected one.
|
||||
*
|
||||
* @param aCurrentProfileRoot The root directory of the current profile.
|
||||
* @return an error if aCurrentProfileRoot is not found or the profile could not
|
||||
* be set as the default.
|
||||
*/
|
||||
static nsresult
|
||||
SetCurrentProfileAsDefault(nsIToolkitProfileService* aProfileSvc,
|
||||
nsILocalFile* aCurrentProfileRoot)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aProfileSvc);
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> profiles;
|
||||
nsresult rv = aProfileSvc->GetProfiles(getter_AddRefs(profiles));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
bool foundMatchingProfile = false;
|
||||
nsCOMPtr<nsIToolkitProfile> profile;
|
||||
rv = profiles->GetNext(getter_AddRefs(profile));
|
||||
while (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsILocalFile> profileRoot;
|
||||
profile->GetRootDir(getter_AddRefs(profileRoot));
|
||||
profileRoot->Equals(aCurrentProfileRoot, &foundMatchingProfile);
|
||||
if (foundMatchingProfile && profile) {
|
||||
rv = aProfileSvc->SetSelectedProfile(profile);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = aProfileSvc->Flush();
|
||||
return rv;
|
||||
}
|
||||
rv = profiles->GetNext(getter_AddRefs(profile));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
|
||||
SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, nsINativeAppSupport* aNative,
|
||||
bool* aStartOffline, nsACString* aProfileName)
|
||||
{
|
||||
nsresult rv;
|
||||
@ -1931,6 +1995,28 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
|
||||
if (ar || EnvHasValue("XRE_START_OFFLINE"))
|
||||
*aStartOffline = true;
|
||||
|
||||
if (EnvHasValue("MOZ_RESET_PROFILE_RESTART")) {
|
||||
gDoProfileReset = true;
|
||||
gDoMigration = true;
|
||||
SaveToEnv("MOZ_RESET_PROFILE_RESTART=");
|
||||
}
|
||||
|
||||
// reset-profile and migration args need to be checked before any profiles are chosen below.
|
||||
ar = CheckArg("reset-profile", true);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument -reset-profile is invalid when argument -osint is specified\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
} else if (ar == ARG_FOUND) {
|
||||
gDoProfileReset = true;
|
||||
}
|
||||
|
||||
ar = CheckArg("migration", true);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument -migration is invalid when argument -osint is specified\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
} else if (ar == ARG_FOUND) {
|
||||
gDoMigration = true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILocalFile> lf = GetFileFromEnv("XRE_PROFILE_PATH");
|
||||
if (lf) {
|
||||
@ -1950,15 +2036,30 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
|
||||
CheckArg("profile", false, &dummy);
|
||||
CheckArg("profilemanager");
|
||||
|
||||
return NS_LockProfilePath(lf, localDir, nsnull, aResult);
|
||||
}
|
||||
if (gDoProfileReset) {
|
||||
// If we're resetting a profile, create a new one and use it to startup.
|
||||
nsCOMPtr<nsIToolkitProfile> newProfile;
|
||||
rv = ResetProfile(aProfileSvc, getter_AddRefs(newProfile));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = newProfile->GetRootDir(getter_AddRefs(lf));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
SaveFileToEnv("XRE_PROFILE_PATH", lf);
|
||||
|
||||
ar = CheckArg("migration", true);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument -migration is invalid when argument -osint is specified\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
} else if (ar == ARG_FOUND) {
|
||||
gDoMigration = true;
|
||||
rv = newProfile->GetLocalDir(getter_AddRefs(localDir));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", localDir);
|
||||
|
||||
rv = newProfile->GetName(*aProfileName);
|
||||
if (NS_FAILED(rv))
|
||||
aProfileName->Truncate(0);
|
||||
SaveWordToEnv("XRE_PROFILE_NAME", *aProfileName);
|
||||
} else {
|
||||
NS_WARNING("Profile reset failed.");
|
||||
gDoProfileReset = false;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_LockProfilePath(lf, localDir, nsnull, aResult);
|
||||
}
|
||||
|
||||
ar = CheckArg("profile", true, &arg);
|
||||
@ -1967,6 +2068,11 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (ar) {
|
||||
if (gDoProfileReset) {
|
||||
NS_WARNING("Profile reset is only supported for the default profile.");
|
||||
gDoProfileReset = false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILocalFile> lf;
|
||||
rv = XRE_GetFileFromPath(arg, getter_AddRefs(lf));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -1990,13 +2096,6 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
|
||||
return ProfileLockedDialog(lf, lf, unlocker, aNative, aResult);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIToolkitProfileService> profileSvc;
|
||||
rv = NS_NewToolkitProfileService(getter_AddRefs(profileSvc));
|
||||
if (rv == NS_ERROR_FILE_ACCESS_DENIED)
|
||||
PR_fprintf(PR_STDERR, "Error: Access was denied while trying to open files in " \
|
||||
"your profile directory.\n");
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ar = CheckArg("createprofile", true, &arg);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument -createprofile requires a profile name\n");
|
||||
@ -2017,10 +2116,10 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
|
||||
|
||||
// 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),
|
||||
rv = aProfileSvc->CreateProfile(lf, lf, nsDependentCSubstring(arg, delim),
|
||||
getter_AddRefs(profile));
|
||||
} else {
|
||||
rv = profileSvc->CreateProfile(nsnull, nsnull, nsDependentCString(arg),
|
||||
rv = aProfileSvc->CreateProfile(nsnull, nsnull, nsDependentCString(arg),
|
||||
getter_AddRefs(profile));
|
||||
}
|
||||
// Some pathological arguments can make it this far
|
||||
@ -2029,7 +2128,7 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
|
||||
return rv;
|
||||
}
|
||||
rv = NS_ERROR_ABORT;
|
||||
profileSvc->Flush();
|
||||
aProfileSvc->Flush();
|
||||
|
||||
// XXXben need to ensure prefs.js exists here so the tinderboxes will
|
||||
// not go orange.
|
||||
@ -2049,7 +2148,7 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
|
||||
}
|
||||
|
||||
PRUint32 count;
|
||||
rv = profileSvc->GetProfileCount(&count);
|
||||
rv = aProfileSvc->GetProfileCount(&count);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ar = CheckArg("p", false, &arg);
|
||||
@ -2059,7 +2158,7 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
|
||||
PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument -osint is specified\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return ShowProfileManager(profileSvc, aNative);
|
||||
return ShowProfileManager(aProfileSvc, aNative);
|
||||
}
|
||||
if (ar) {
|
||||
ar = CheckArg("osint");
|
||||
@ -2068,9 +2167,15 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsCOMPtr<nsIToolkitProfile> profile;
|
||||
rv = profileSvc->GetProfileByName(nsDependentCString(arg),
|
||||
rv = aProfileSvc->GetProfileByName(nsDependentCString(arg),
|
||||
getter_AddRefs(profile));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// If we're resetting a profile, create a new one and use it to startup.
|
||||
if (gDoProfileReset) {
|
||||
NS_WARNING("Profile reset is only supported for the default profile.");
|
||||
gDoProfileReset = false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIProfileUnlocker> unlocker;
|
||||
rv = profile->Lock(nsnull, aResult);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
@ -2091,7 +2196,7 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
|
||||
aNative, aResult);
|
||||
}
|
||||
|
||||
return ShowProfileManager(profileSvc, aNative);
|
||||
return ShowProfileManager(aProfileSvc, aNative);
|
||||
}
|
||||
|
||||
ar = CheckArg("profilemanager", true);
|
||||
@ -2099,20 +2204,21 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
|
||||
PR_fprintf(PR_STDERR, "Error: argument -profilemanager is invalid when argument -osint is specified\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
} else if (ar == ARG_FOUND) {
|
||||
return ShowProfileManager(profileSvc, aNative);
|
||||
return ShowProfileManager(aProfileSvc, aNative);
|
||||
}
|
||||
|
||||
if (!count) {
|
||||
gDoMigration = true;
|
||||
gDoProfileReset = false;
|
||||
|
||||
// create a default profile
|
||||
nsCOMPtr<nsIToolkitProfile> profile;
|
||||
nsresult rv = profileSvc->CreateProfile(nsnull, // choose a default dir for us
|
||||
nsnull, // choose a default dir for us
|
||||
NS_LITERAL_CSTRING("default"),
|
||||
getter_AddRefs(profile));
|
||||
nsresult rv = aProfileSvc->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)) {
|
||||
profileSvc->Flush();
|
||||
aProfileSvc->Flush();
|
||||
rv = profile->Lock(nsnull, aResult);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (aProfileName)
|
||||
@ -2124,13 +2230,22 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
|
||||
|
||||
bool useDefault = true;
|
||||
if (count > 1)
|
||||
profileSvc->GetStartWithLastProfile(&useDefault);
|
||||
aProfileSvc->GetStartWithLastProfile(&useDefault);
|
||||
|
||||
if (useDefault) {
|
||||
nsCOMPtr<nsIToolkitProfile> profile;
|
||||
// GetSelectedProfile will auto-select the only profile if there's just one
|
||||
profileSvc->GetSelectedProfile(getter_AddRefs(profile));
|
||||
aProfileSvc->GetSelectedProfile(getter_AddRefs(profile));
|
||||
if (profile) {
|
||||
// If we're resetting a profile, create a new one and use it to startup.
|
||||
if (gDoProfileReset) {
|
||||
nsCOMPtr<nsIToolkitProfile> newProfile;
|
||||
rv = ResetProfile(aProfileSvc, getter_AddRefs(newProfile));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
profile = newProfile;
|
||||
else
|
||||
gDoProfileReset = false;
|
||||
}
|
||||
nsCOMPtr<nsIProfileUnlocker> unlocker;
|
||||
rv = profile->Lock(getter_AddRefs(unlocker), aResult);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
@ -2156,7 +2271,7 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
|
||||
}
|
||||
}
|
||||
|
||||
return ShowProfileManager(profileSvc, aNative);
|
||||
return ShowProfileManager(aProfileSvc, aNative);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3200,7 +3315,19 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
|
||||
bool startOffline = false;
|
||||
nsCAutoString profileName;
|
||||
|
||||
rv = SelectProfile(getter_AddRefs(profileLock), nativeApp, &startOffline,
|
||||
nsCOMPtr<nsIToolkitProfileService> profileSvc;
|
||||
rv = NS_NewToolkitProfileService(getter_AddRefs(profileSvc));
|
||||
if (rv == NS_ERROR_FILE_ACCESS_DENIED) {
|
||||
PR_fprintf(PR_STDERR, "Error: Access was denied while trying to open files in " \
|
||||
"your profile directory.\n");
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
// We failed to choose or create profile - notify user and quit
|
||||
ProfileMissingDialog(nativeApp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
rv = SelectProfile(getter_AddRefs(profileLock), profileSvc, nativeApp, &startOffline,
|
||||
&profileName);
|
||||
if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ||
|
||||
rv == NS_ERROR_ABORT) return 0;
|
||||
@ -3429,8 +3556,20 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
|
||||
gDoMigration = false;
|
||||
nsCOMPtr<nsIProfileMigrator> pm
|
||||
(do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID));
|
||||
if (pm)
|
||||
pm->Migrate(&dirProvider);
|
||||
if (pm) {
|
||||
nsCAutoString aKey;
|
||||
if (gDoProfileReset) {
|
||||
// Automatically migrate from the current application if we just
|
||||
// reset the profile.
|
||||
aKey = MOZ_APP_NAME;
|
||||
pm->Migrate(&dirProvider, aKey);
|
||||
// Set the new profile as the default after migration.
|
||||
rv = SetCurrentProfileAsDefault(profileSvc, profD);
|
||||
if (NS_FAILED(rv)) NS_WARNING("Could not set current profile as the default");
|
||||
} else {
|
||||
pm->Migrate(&dirProvider, aKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_TIME_FUNCTION_MARK("Profile migration");
|
||||
|
Loading…
Reference in New Issue
Block a user