From a89acec32559c336ad7125a1620a2d35cd9ec3ce Mon Sep 17 00:00:00 2001 From: Matthew Noorenberghe Date: Thu, 23 Feb 2012 19:34:18 -0800 Subject: [PATCH 01/21] Bug 717070 - Profile reset - Part 1 - Backend to initiate profile reset. r=mano --- .../migration/src/ProfileMigrator.js | 32 ++- toolkit/profile/nsIProfileMigrator.idl | 9 +- toolkit/xre/nsAppRunner.cpp | 209 +++++++++++++++--- 3 files changed, 206 insertions(+), 44 deletions(-) diff --git a/browser/components/migration/src/ProfileMigrator.js b/browser/components/migration/src/ProfileMigrator.js index b713068cba37..ea6667531937 100644 --- a/browser/components/migration/src/ProfileMigrator.js +++ b/browser/components/migration/src/ProfileMigrator.js @@ -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; }, diff --git a/toolkit/profile/nsIProfileMigrator.idl b/toolkit/profile/nsIProfileMigrator.idl index f2b1ad23290e..e941336bfe7e 100644 --- a/toolkit/profile/nsIProfileMigrator.idl +++ b/toolkit/profile/nsIProfileMigrator.idl @@ -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" diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index a63dd5cc032c..32eef5c082a7 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -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 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 profiles; + nsresult rv = aProfileSvc->GetProfiles(getter_AddRefs(profiles)); + if (NS_FAILED(rv)) + return rv; + + bool foundMatchingProfile = false; + nsCOMPtr profile; + rv = profiles->GetNext(getter_AddRefs(profile)); + while (NS_SUCCEEDED(rv)) { + nsCOMPtr 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 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 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 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 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 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 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 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 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 newProfile; + rv = ResetProfile(aProfileSvc, getter_AddRefs(newProfile)); + if (NS_SUCCEEDED(rv)) + profile = newProfile; + else + gDoProfileReset = false; + } nsCOMPtr 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 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 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"); From fddcc117e9ee0e91d6dfd4b7fdd3899dcb22e64a Mon Sep 17 00:00:00 2001 From: Matthew Noorenberghe Date: Thu, 23 Feb 2012 19:34:18 -0800 Subject: [PATCH 02/21] Bug 717070 - Profile reset - Part 2 - migrator portion. r=mano --- browser/components/migration/content/migration.js | 9 ++++++++- .../migration/src/FirefoxProfileMigrator.js | 11 +++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/browser/components/migration/content/migration.js b/browser/components/migration/content/migration.js index 3bc34c76e877..ffb0c345eb71 100644 --- a/browser/components/migration/content/migration.js +++ b/browser/components/migration/content/migration.js @@ -65,6 +65,7 @@ var MigrationWizard = { this._source = window.arguments[0]; this._migrator = window.arguments[1].QueryInterface(kIMig); this._autoMigrate = window.arguments[2].QueryInterface(kIPStartup); + this._skipImportSourcePage = window.arguments[3]; if (this._autoMigrate) { // Show the "nothing" option in the automigrate case to provide an @@ -94,7 +95,7 @@ var MigrationWizard = { // Reference to the "From File" radio button var fromfile = null; - //XXXquark This function is called before init, so check for bookmarks here + // init is not called when openDialog opens the wizard, so check for bookmarks here. if ("arguments" in window && window.arguments[0] == "bookmarks") { this._bookmarks = true; @@ -151,6 +152,12 @@ var MigrationWizard = { document.getElementById("importBookmarks").hidden = true; document.getElementById("importAll").hidden = true; } + + // Advance to the next page if the caller told us to. + if (this._migrator && this._skipImportSourcePage) { + this._wiz.advance(); + this._wiz.canRewind = false; + } }, onImportSourcePageAdvanced: function () diff --git a/browser/components/migration/src/FirefoxProfileMigrator.js b/browser/components/migration/src/FirefoxProfileMigrator.js index dad4217347bf..7b4a6e4b7725 100644 --- a/browser/components/migration/src/FirefoxProfileMigrator.js +++ b/browser/components/migration/src/FirefoxProfileMigrator.js @@ -227,6 +227,12 @@ FirefoxProfileMigrator.prototype = { this._replaceBookmarks = true; } + // Ensure that aProfile is not the current profile. + if (this._paths.currentProfile.path === this._sourceProfile.path) { + throw new Exception("Source and destination profiles are the same"); + return; + } + Services.obs.notifyObservers(null, "Migration:Started", null); // Reset pending count. If this count becomes 0, "Migration:Ended" @@ -278,6 +284,11 @@ FirefoxProfileMigrator.prototype = { this._sourceProfile.initWithPath(aProfile); let result = 0; + + // Ensure that aProfile is not the current profile. + if (this._paths.currentProfile.path === this._sourceProfile.path) + return result; + if (!this._sourceProfile.exists() || !this._sourceProfile.isReadable()) { Cu.reportError("source profile directory doesn't exist or is not readable"); return result; From db730570090d850375b5e05e075c68cec3d4d8c1 Mon Sep 17 00:00:00 2001 From: Matthew Noorenberghe Date: Thu, 23 Feb 2012 19:34:18 -0800 Subject: [PATCH 03/21] Bug 717070 - Profile reset - Part 3 - about:support UI to reset profile. r=mak --- toolkit/content/Makefile.in | 2 + toolkit/content/aboutSupport.js | 50 +++++++++++++++++++ toolkit/content/aboutSupport.xhtml | 9 ++++ toolkit/content/jar.mn | 3 ++ toolkit/content/resetProfile.css | 11 ++++ toolkit/content/resetProfile.js | 35 +++++++++++++ toolkit/content/resetProfile.xul | 36 +++++++++++++ .../en-US/chrome/global/resetProfile.dtd | 13 +++++ toolkit/locales/jar.mn | 1 + .../themes/winstripe/global/aboutSupport.css | 26 ++++++++++ 10 files changed, 186 insertions(+) create mode 100644 toolkit/content/resetProfile.css create mode 100644 toolkit/content/resetProfile.js create mode 100644 toolkit/content/resetProfile.xul create mode 100644 toolkit/locales/en-US/chrome/global/resetProfile.dtd diff --git a/toolkit/content/Makefile.in b/toolkit/content/Makefile.in index 11c1ab5d00eb..50d633c9b5fe 100644 --- a/toolkit/content/Makefile.in +++ b/toolkit/content/Makefile.in @@ -55,6 +55,8 @@ DEFINES += \ -DCXX_VERSION="$(CXX_VERSION)" \ -DCXXFLAGS="$(CXXFLAGS)" \ -DCPPFLAGS="$(CPPFLAGS)" \ + -DMOZ_APP_NAME=$(MOZ_APP_NAME) \ + -DMOZ_BUILD_APP=$(MOZ_BUILD_APP) \ $(NULL) MOZ_SOURCE_STAMP ?= $(shell hg -R $(topsrcdir) parent --template="{node|short}\n" 2>/dev/null) diff --git a/toolkit/content/aboutSupport.js b/toolkit/content/aboutSupport.js index 1e648dad65da..8fbb2eb198a3 100644 --- a/toolkit/content/aboutSupport.js +++ b/toolkit/content/aboutSupport.js @@ -38,6 +38,7 @@ const Cc = Components.classes; const Ci = Components.interfaces; +const Cu = Components.utils; Components.utils.import("resource://gre/modules/AddonManager.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); @@ -113,6 +114,7 @@ window.onload = function () { document.getElementById("version-box").textContent = version; // Update the other sections. + populateResetBox(); populatePreferencesSection(); populateExtensionsSection(); populateGraphicsSection(); @@ -561,3 +563,51 @@ function openProfileDirectory() { "nsILocalFile", "initWithPath"); new nsLocalFile(profileDir).reveal(); } + +/** + * Profile reset is only supported for the default profile if the appropriate migrator exists. + */ +function populateResetBox() { + let profileService = Cc["@mozilla.org/toolkit/profile-service;1"] + .getService(Ci.nsIToolkitProfileService); + let currentProfileDir = Services.dirsvc.get("ProfD", Ci.nsIFile); + +#expand const MOZ_APP_NAME = "__MOZ_APP_NAME__"; +#expand const MOZ_BUILD_APP = "__MOZ_BUILD_APP__"; + + // Only show the reset box for the default profile if the self-migrator used for reset exists. + try { + if (!currentProfileDir.equals(profileService.selectedProfile.rootDir) || + !("@mozilla.org/profile/migrator;1?app=" + MOZ_BUILD_APP + "&type=" + MOZ_APP_NAME in Cc)) + return; + document.getElementById("reset-box").style.visibility = "visible"; + } catch (e) { + // Catch exception when there is no selected profile. + Cu.reportError(e); + } +} + +/** + * Restart the application to reset the profile. + */ +function resetProfileAndRestart() { + let branding = Services.strings.createBundle("chrome://branding/locale/brand.properties"); + let brandShortName = branding.GetStringFromName("brandShortName"); + + // Prompt the user to confirm. + let retVals = { + reset: false, + }; + window.openDialog("chrome://global/content/resetProfile.xul", null, + "chrome,modal,centerscreen,titlebar,dialog=yes", retVals); + if (!retVals.reset) + return; + + // Set the reset profile environment variable. + let env = Cc["@mozilla.org/process/environment;1"] + .getService(Ci.nsIEnvironment); + env.set("MOZ_RESET_PROFILE_RESTART", "1"); + + let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci.nsIAppStartup); + appStartup.quit(Ci.nsIAppStartup.eForceQuit | Ci.nsIAppStartup.eRestart); +} diff --git a/toolkit/content/aboutSupport.xhtml b/toolkit/content/aboutSupport.xhtml index e92194bdcc63..a392b9a14240 100644 --- a/toolkit/content/aboutSupport.xhtml +++ b/toolkit/content/aboutSupport.xhtml @@ -42,6 +42,7 @@ %globalDTD; %brandDTD; %aboutSupportDTD; + %resetProfileDTD; ]> @@ -57,6 +58,14 @@ + +

&aboutSupport.pageTitle;

diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn index afc8549acd06..6f0d2d6367ff 100644 --- a/toolkit/content/jar.mn +++ b/toolkit/content/jar.mn @@ -37,6 +37,9 @@ toolkit.jar: *+ content/global/globalOverlay.js (globalOverlay.js) + content/global/mozilla.xhtml (mozilla.xhtml) *+ content/global/nsDragAndDrop.js (nsDragAndDrop.js) + content/global/resetProfile.css (resetProfile.css) +* content/global/resetProfile.js (resetProfile.js) +* content/global/resetProfile.xul (resetProfile.xul) * content/global/treeUtils.js (treeUtils.js) *+ content/global/viewZoomOverlay.js (viewZoomOverlay.js) *+ content/global/bindings/autocomplete.xml (widgets/autocomplete.xml) diff --git a/toolkit/content/resetProfile.css b/toolkit/content/resetProfile.css new file mode 100644 index 000000000000..2a8114801a67 --- /dev/null +++ b/toolkit/content/resetProfile.css @@ -0,0 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#migratedItems { + -moz-margin-start: 1.5em; +} + +#resetProfileFooter { + font-weight: bold; +} diff --git a/toolkit/content/resetProfile.js b/toolkit/content/resetProfile.js new file mode 100644 index 000000000000..975a9edcb64e --- /dev/null +++ b/toolkit/content/resetProfile.js @@ -0,0 +1,35 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +Components.utils.import("resource://gre/modules/Services.jsm"); + +// based on onImportItemsPageShow from migration.js +function onResetProfileLoad() { +#expand const MOZ_BUILD_APP = "__MOZ_BUILD_APP__"; +#expand const MOZ_APP_NAME = "__MOZ_APP_NAME__"; + const MAX_MIGRATED_TYPES = 16; + + var migratedItems = document.getElementById("migratedItems"); + var bundle = Services.strings.createBundle("chrome://" + MOZ_BUILD_APP + + "/locale/migration/migration.properties"); + + // Loop over possible data to migrate to give the user a list of what will be preserved. This + // assumes that if the string for the data exists then it will be migrated since calling + // getMigrateData now won't give the correct result. + for (var i = 1; i < MAX_MIGRATED_TYPES; ++i) { + var itemID = Math.pow(2, i); + try { + var checkbox = document.createElement("label"); + checkbox.setAttribute("value", bundle.GetStringFromName(itemID + "_" + MOZ_APP_NAME)); + migratedItems.appendChild(checkbox); + } catch (x) { + // Catch exceptions when the string for a data type doesn't exist because it's not migrated + } + } +} + +function onResetProfileAccepted() { + var retVals = window.arguments[0]; + retVals.reset = true; +} diff --git a/toolkit/content/resetProfile.xul b/toolkit/content/resetProfile.xul new file mode 100644 index 000000000000..bd2ee2627b13 --- /dev/null +++ b/toolkit/content/resetProfile.xul @@ -0,0 +1,36 @@ + + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. + + +%brandDTD; + +%resetProfileDTD; +]> + + + + + + + @@ -42,12 +42,6 @@ let gLivemarks = [ function runTest() { - if (navigator.platform.indexOf("Lin") != -1) { - ok(true, "Bug 734044: This test is disabled on Linux for random timeouts."); - SimpleTest.finish(); - return; - } - addLivemarks(function () { reloadLivemarks(false, function () { reloadLivemarks(true, function () { @@ -132,11 +126,23 @@ resultObserver.prototype = { if (this._livemark.status == Ci.mozILivemark.STATUS_LOADING) return; - this._livemark.unregisterForUpdates(this._node); + this._terminate(); this._callback(); + }, + _terminate: function () { + if (!this._terminated) { + this._livemark.unregisterForUpdates(this._node); + this._terminated = true; + } } }; +function cleanup() { + gLivemarks.forEach(function(aLivemarkData) { + if (aLivemarkData._observer) + aLivemarkData._observer._terminate(); + }); +} ]]> From a5475a4e9cddbc517a76b50e22869f747a06f0ef Mon Sep 17 00:00:00 2001 From: Chris Lord Date: Fri, 9 Mar 2012 10:22:59 +0000 Subject: [PATCH 18/21] Bug 734175 - Fix uploading all tiles when subtextures are unsupported. r=bgirard The check for sub-texture support happens before iterating over tiles in TiledTextureImage, and forces the bounds to the boundaries of the TiledTextureImage. This causes any upload on a TiledTextureImage to re-upload every single tile, regardless of whether it intersects with the upload region. Fix this by moving this check inside of the tile iteration loop, and expanding individual tile upload regions to tile boundaries. --- gfx/gl/GLContext.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index 9afcd48a362d..acf9cb95740d 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -892,7 +892,7 @@ TiledTextureImage::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, { nsIntRegion region; - if (mTextureState != Valid || !mGL->CanUploadSubTextures()) { + if (mTextureState != Valid) { nsIntRect bounds = nsIntRect(0, 0, mSize.width, mSize.height); region = nsIntRegion(bounds); } else { @@ -904,10 +904,17 @@ TiledTextureImage::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, int xPos = (i % mColumns) * mTileSize; int yPos = (i / mColumns) * mTileSize; nsIntRegion tileRegion; - tileRegion.And(region, nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize())); // intersect with tile + nsIntRect tileRect = nsIntRect(nsIntPoint(xPos, yPos), mImages[i]->GetSize()); + tileRegion.And(region, tileRect); // intersect with tile if (tileRegion.IsEmpty()) continue; - tileRegion.MoveBy(-xPos, -yPos); // translate into tile local space + if (mGL->CanUploadSubTextures()) { + tileRegion.MoveBy(-xPos, -yPos); // translate into tile local space + } else { + // If sub-textures are unsupported, expand to tile boundaries + tileRect.x = tileRect.y = 0; + tileRegion = nsIntRegion(tileRect); + } result &= mImages[i]->DirectUpdate(aSurf, tileRegion, aFrom + nsIntPoint(xPos, yPos)); From 00aaba70c056d6e089bea5529df35cd007927ffc Mon Sep 17 00:00:00 2001 From: Etienne Segonzac Date: Fri, 9 Mar 2012 13:10:16 +0100 Subject: [PATCH 19/21] Bug 730323 - Adding missing white listed application for mozTelephony r=vingtetun --- b2g/app/b2g.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index ea78fb7a1472..cea04b8f81af 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -46,7 +46,7 @@ pref("browser.homescreenURL", "file:///data/local/homescreen.html,file:///system #endif // URL for the dialer application. -pref("dom.telephony.app.phone.url", "http://localhost:7777/data/local/apps/dialer/dialer.html"); +pref("dom.telephony.app.phone.url", "http://localhost:7777/data/local/apps/dialer/dialer.html http://localhost:7777/data/local/apps/homescreen/homescreen.html http://localhost:7777/apps/dialer/dialer.html http://localhost:7777/apps/homescreen/homescreen.html"); // Device pixel to CSS px ratio, in percent. Set to -1 to calculate based on display density. pref("browser.viewport.scaleRatio", -1); From d9ff4d837ff0a3c6185216c78914379bc085a361 Mon Sep 17 00:00:00 2001 From: Marco Bonardo Date: Fri, 9 Mar 2012 22:50:53 +0100 Subject: [PATCH 20/21] Bug 717070 follow-up - remove wrongly hardcoded Firefox brand. --- toolkit/locales/en-US/chrome/global/resetProfile.dtd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolkit/locales/en-US/chrome/global/resetProfile.dtd b/toolkit/locales/en-US/chrome/global/resetProfile.dtd index e9b15b6a13f8..8b27b7b6c3c9 100644 --- a/toolkit/locales/en-US/chrome/global/resetProfile.dtd +++ b/toolkit/locales/en-US/chrome/global/resetProfile.dtd @@ -3,7 +3,7 @@ - You can obtain one at http://mozilla.org/MPL/2.0/. --> - + From 303ac7cf78da15dfe1b290708bcbcb744e1b7315 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Fri, 9 Mar 2012 14:32:11 -0800 Subject: [PATCH 21/21] Bug 734288: Use double math instead of float math for computing surface sizes in nsSVGFE::SetupScalingFilter. r=longsonr --- content/svg/content/src/nsSVGFilters.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/content/svg/content/src/nsSVGFilters.cpp b/content/svg/content/src/nsSVGFilters.cpp index 624be8b8da73..f97e8e4035c2 100644 --- a/content/svg/content/src/nsSVGFilters.cpp +++ b/content/svg/content/src/nsSVGFilters.cpp @@ -144,12 +144,12 @@ nsSVGFE::SetupScalingFilter(nsSVGFilterInstance *aInstance, return result; } - float kernelX = aInstance->GetPrimitiveNumber(nsSVGUtils::X, - aKernelUnitLength, - nsSVGNumberPair::eFirst); - float kernelY = aInstance->GetPrimitiveNumber(nsSVGUtils::Y, - aKernelUnitLength, - nsSVGNumberPair::eSecond); + gfxFloat kernelX = aInstance->GetPrimitiveNumber(nsSVGUtils::X, + aKernelUnitLength, + nsSVGNumberPair::eFirst); + gfxFloat kernelY = aInstance->GetPrimitiveNumber(nsSVGUtils::Y, + aKernelUnitLength, + nsSVGNumberPair::eSecond); if (kernelX <= 0 || kernelY <= 0) return result;