зеркало из https://github.com/mozilla/pjs.git
Bug 273874 - Firefox migrator for new profiles r=mak
--HG-- rename : browser/components/migration/src/ChromeProfileMigrator.js => browser/components/migration/src/FirefoxProfileMigrator.js extra : rebase_source : d5dfea053ede5abb3a535296085bdfe93ece8511
This commit is contained in:
Родитель
eb7578d995
Коммит
b71831f2db
|
@ -339,6 +339,9 @@ var MigrationWizard = {
|
|||
case "chrome":
|
||||
source = "sourceNameChrome";
|
||||
break;
|
||||
case "firefox":
|
||||
source = "sourceNameFirefox";
|
||||
break;
|
||||
}
|
||||
|
||||
// semi-wallpaper for crash when multiple profiles exist, since we haven't initialized mSourceProfile in places
|
||||
|
|
|
@ -76,6 +76,7 @@
|
|||
#endif
|
||||
#endif
|
||||
<radio id="chrome" label="&importFromChrome.label;" accesskey="&importFromChrome.accesskey;"/>
|
||||
<radio id="firefox" label="&importFromFirefox.label;" accesskey="&importFromFirefox.accesskey;"/>
|
||||
<radio id="fromfile" label="&importFromHTMLFile.label;" accesskey="&importFromHTMLFile.accesskey;" hidden="true"/>
|
||||
<radio id="nothing" label="&importFromNothing.label;" accesskey="&importFromNothing.accesskey;" hidden="true"/>
|
||||
</radiogroup>
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
component {4cec1de4-1671-4fc3-a53e-6c539dc77a26} ChromeProfileMigrator.js
|
||||
contract @mozilla.org/profile/migrator;1?app=browser&type=chrome {4cec1de4-1671-4fc3-a53e-6c539dc77a26}
|
||||
component {91185366-ba97-4438-acba-48deaca63386} FirefoxProfileMigrator.js
|
||||
contract @mozilla.org/profile/migrator;1?app=browser&type=firefox {91185366-ba97-4438-acba-48deaca63386}
|
||||
|
|
|
@ -0,0 +1,404 @@
|
|||
/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 et
|
||||
* This Source Code is subject to the terms of the Mozilla Public License
|
||||
* version 2.0 (the "License"). You can obtain a copy of the License at
|
||||
* http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Migrates from a Firefox profile in a lossy manner in order to clean up a user's profile. Data
|
||||
* is only migrated where the benefits outweigh the potential problems caused by importing
|
||||
* undesired/invalid configurations from the source profile.
|
||||
*/
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
const MIGRATOR = Ci.nsIBrowserProfileMigrator;
|
||||
|
||||
const LOCAL_FILE_CID = "@mozilla.org/file/local;1";
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/NetUtil.jsm");
|
||||
Components.utils.import("resource://gre/modules/FileUtils.jsm");
|
||||
|
||||
function FirefoxProfileMigrator()
|
||||
{
|
||||
// profD is not available when the migrator is run during startup so use ProfDS.
|
||||
this._paths.currentProfile = FileUtils.getDir("ProfDS", []);
|
||||
}
|
||||
|
||||
FirefoxProfileMigrator.prototype = {
|
||||
_paths: {
|
||||
bookmarks : null,
|
||||
cookies : null,
|
||||
currentProfile: null, // The currently running (destination) profile.
|
||||
encryptionKey: null,
|
||||
history : null,
|
||||
passwords: null,
|
||||
},
|
||||
|
||||
_homepageURL : null,
|
||||
_replaceBookmarks : false,
|
||||
_sourceProfile: null,
|
||||
_profilesCache: null,
|
||||
|
||||
/**
|
||||
* Notify to observers to start migration
|
||||
*
|
||||
* @param aType
|
||||
* notification type such as MIGRATOR.BOOKMARKS
|
||||
*/
|
||||
_notifyStart : function Firefox_notifyStart(aType)
|
||||
{
|
||||
Services.obs.notifyObservers(null, "Migration:ItemBeforeMigrate", aType);
|
||||
this._pendingCount++;
|
||||
},
|
||||
|
||||
/**
|
||||
* Notify observers that a migration error occured with an item
|
||||
*
|
||||
* @param aType
|
||||
* notification type such as MIGRATOR.BOOKMARKS
|
||||
*/
|
||||
_notifyError : function Firefox_notifyError(aType)
|
||||
{
|
||||
Services.obs.notifyObservers(null, "Migration:ItemError", aType);
|
||||
},
|
||||
|
||||
/**
|
||||
* Notify to observers to finish migration for item
|
||||
* If all items are finished, it sends migration end notification.
|
||||
*
|
||||
* @param aType
|
||||
* notification type such as MIGRATOR.BOOKMARKS
|
||||
*/
|
||||
_notifyCompleted : function Firefox_notifyIfCompleted(aType)
|
||||
{
|
||||
Services.obs.notifyObservers(null, "Migration:ItemAfterMigrate", aType);
|
||||
if (--this._pendingCount == 0) {
|
||||
// All items are migrated, so we have to send end notification.
|
||||
Services.obs.notifyObservers(null, "Migration:Ended", null);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The directory used for bookmark backups
|
||||
* @return directory of the bookmark backups
|
||||
*/
|
||||
get _bookmarks_backup_folder()
|
||||
{
|
||||
let bookmarksBackupRelativePath = PlacesUtils.backups.profileRelativeFolderPath;
|
||||
let bookmarksBackupDir = this._sourceProfile.clone().QueryInterface(Ci.nsILocalFile);
|
||||
bookmarksBackupDir.appendRelativePath(bookmarksBackupRelativePath);
|
||||
return bookmarksBackupDir;
|
||||
},
|
||||
|
||||
/**
|
||||
* Migrating bookmark items
|
||||
*/
|
||||
_migrateBookmarks : function Firefox_migrateBookmarks()
|
||||
{
|
||||
this._notifyStart(MIGRATOR.BOOKMARKS);
|
||||
|
||||
try {
|
||||
let srcBackupsDir = this._bookmarks_backup_folder;
|
||||
let backupFolder = this._paths.currentProfile.clone();
|
||||
backupFolder.append(srcBackupsDir.leafName);
|
||||
if (!backupFolder.exists())
|
||||
srcBackupsDir.copyTo(this._paths.currentProfile, null);
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
// Don't notify about backup migration errors since actual bookmarks are
|
||||
// migrated with history.
|
||||
} finally {
|
||||
this._notifyCompleted(MIGRATOR.BOOKMARKS);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Migrating history
|
||||
*/
|
||||
_migrateHistory : function Firefox_migrateHistory()
|
||||
{
|
||||
this._notifyStart(MIGRATOR.HISTORY);
|
||||
|
||||
try {
|
||||
// access sqlite3 database of history
|
||||
let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
|
||||
file.initWithPath(this._paths.history);
|
||||
file.copyTo(this._paths.currentProfile, null);
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
this._notifyError(MIGRATOR.HISTORY);
|
||||
} finally {
|
||||
this._notifyCompleted(MIGRATOR.HISTORY);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Migrating cookies
|
||||
*
|
||||
* @note Cookie permissions are not migrated since they may be inadvertently set leading to
|
||||
* website login problems.
|
||||
*/
|
||||
_migrateCookies : function Firefox_migrateCookies()
|
||||
{
|
||||
this._notifyStart(MIGRATOR.COOKIES);
|
||||
|
||||
try {
|
||||
// Access sqlite3 database of cookies
|
||||
let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
|
||||
file.initWithPath(this._paths.cookies);
|
||||
file.copyTo(this._paths.currentProfile, null);
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
this._notifyError(MIGRATOR.COOKIES);
|
||||
} finally {
|
||||
this._notifyCompleted(MIGRATOR.COOKIES);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Migrating passwords
|
||||
*/
|
||||
_migratePasswords : function Firefox_migratePasswords()
|
||||
{
|
||||
this._notifyStart(MIGRATOR.PASSWORDS);
|
||||
|
||||
try {
|
||||
// Access sqlite3 database of passwords
|
||||
let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
|
||||
file.initWithPath(this._paths.passwords);
|
||||
file.copyTo(this._paths.currentProfile, null);
|
||||
|
||||
let encryptionKey = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
|
||||
encryptionKey.initWithPath(this._paths.encryptionKey);
|
||||
encryptionKey.copyTo(this._paths.currentProfile, null);
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
this._notifyError(MIGRATOR.PASSWORDS);
|
||||
} finally {
|
||||
this._notifyCompleted(MIGRATOR.PASSWORDS);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* nsIBrowserProfileMigrator interface implementation
|
||||
*/
|
||||
|
||||
/**
|
||||
* Let's migrate all items
|
||||
*
|
||||
* @param aItems
|
||||
* list of data items to migrate.
|
||||
* @param aStartup
|
||||
* non-null if called during startup.
|
||||
* @param aProfile
|
||||
* profile directory path to migrate from
|
||||
*/
|
||||
migrate : function Firefox_migrate(aItems, aStartup, aProfile)
|
||||
{
|
||||
if (aStartup) {
|
||||
aStartup.doStartup();
|
||||
this._replaceBookmarks = true;
|
||||
}
|
||||
|
||||
Services.obs.notifyObservers(null, "Migration:Started", null);
|
||||
|
||||
// Reset pending count. If this count becomes 0, "Migration:Ended"
|
||||
// notification is sent
|
||||
this._pendingCount = 1;
|
||||
|
||||
if (aItems & MIGRATOR.HISTORY)
|
||||
this._migrateHistory();
|
||||
|
||||
if (aItems & MIGRATOR.COOKIES)
|
||||
this._migrateCookies();
|
||||
|
||||
if (aItems & MIGRATOR.BOOKMARKS)
|
||||
this._migrateBookmarks();
|
||||
|
||||
if (aItems & MIGRATOR.PASSWORDS)
|
||||
this._migratePasswords();
|
||||
|
||||
if (--this._pendingCount == 0) {
|
||||
// When async imports are immediately completed unfortunately,
|
||||
// this will be called.
|
||||
// Usually, this notification is sent by _notifyCompleted()
|
||||
Services.obs.notifyObservers(null, "Migration:Ended", null);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* return supported migration types
|
||||
*
|
||||
* @param aProfile
|
||||
* the profile path to migrate from
|
||||
* @param aDoingStartup
|
||||
* non-null if called during startup.
|
||||
* @return supported migration types
|
||||
*
|
||||
* @todo Bug 715315 - make sure source databases are not in-use
|
||||
*/
|
||||
getMigrateData: function Firefox_getMigrateData(aProfile, aDoingStartup)
|
||||
{
|
||||
this._sourceProfile = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
|
||||
this._sourceProfile.initWithPath(aProfile);
|
||||
|
||||
let result = 0;
|
||||
if (!this._sourceProfile.exists() || !this._sourceProfile.isReadable()) {
|
||||
Cu.reportError("source profile directory doesn't exist or is not readable");
|
||||
return result;
|
||||
}
|
||||
|
||||
// Migration initiated from the UI is not supported.
|
||||
if (!aDoingStartup)
|
||||
return result;
|
||||
|
||||
// Bookmark backups in JSON format
|
||||
try {
|
||||
let file = this._bookmarks_backup_folder;
|
||||
if (file.exists()) {
|
||||
this._paths.bookmarks = file.path;
|
||||
result += MIGRATOR.BOOKMARKS;
|
||||
}
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
|
||||
// Bookmarks, history and favicons
|
||||
try {
|
||||
let file = this._sourceProfile.clone();
|
||||
file.append("places.sqlite");
|
||||
if (file.exists()) {
|
||||
this._paths.history = file.path;
|
||||
result += MIGRATOR.HISTORY;
|
||||
result |= MIGRATOR.BOOKMARKS;
|
||||
}
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
|
||||
// Cookies
|
||||
try {
|
||||
let file = this._sourceProfile.clone();
|
||||
file.append("cookies.sqlite");
|
||||
if (file.exists()) {
|
||||
this._paths.cookies = file.path;
|
||||
result += MIGRATOR.COOKIES;
|
||||
}
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
|
||||
// Passwords & encryption key
|
||||
try {
|
||||
let passwords = this._sourceProfile.clone();
|
||||
passwords.append("signons.sqlite");
|
||||
let encryptionKey = this._sourceProfile.clone();
|
||||
encryptionKey.append("key3.db");
|
||||
if (passwords.exists() && encryptionKey.exists()) {
|
||||
this._paths.passwords = passwords.path;
|
||||
this._paths.encryptionKey = encryptionKey.path;
|
||||
result += MIGRATOR.PASSWORDS;
|
||||
}
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether we support migration of Firefox
|
||||
*
|
||||
* @return true if supported
|
||||
*/
|
||||
get sourceExists()
|
||||
{
|
||||
let userData = Services.dirsvc.get("DefProfRt", Ci.nsIFile).path;
|
||||
let result = 0;
|
||||
try {
|
||||
let userDataDir = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
|
||||
userDataDir.initWithPath(userData);
|
||||
if (!userDataDir.exists() || !userDataDir.isReadable())
|
||||
return false;
|
||||
|
||||
let profiles = this.sourceProfiles;
|
||||
if (profiles.length < 1)
|
||||
return false;
|
||||
// Check that we can get data from at least one profile since profile selection has not
|
||||
// happened yet.
|
||||
for (let i = 0; i < profiles.length; i++) {
|
||||
result = this.getMigrateData(profiles.queryElementAt(i, Ci.nsISupportsString), true);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
return result > 0;
|
||||
},
|
||||
|
||||
get sourceHasMultipleProfiles()
|
||||
{
|
||||
return this.sourceProfiles.length > 1;
|
||||
},
|
||||
|
||||
get sourceProfiles()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!this._profilesCache)
|
||||
{
|
||||
this._profilesCache = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
|
||||
let profileService = Cc["@mozilla.org/toolkit/profile-service;1"]
|
||||
.getService(Ci.nsIToolkitProfileService);
|
||||
// Only allow migrating from the default (selected) profile since this will be the only one
|
||||
// returned by the toolkit profile service after bug 214675 has landed.
|
||||
var profile = profileService.selectedProfile;
|
||||
if (profile.rootDir.path === this._paths.currentProfile.path)
|
||||
return null;
|
||||
|
||||
let str = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
|
||||
str.data = profile.rootDir.path;
|
||||
this._profilesCache.appendElement(str, false);
|
||||
}
|
||||
} catch (e) {
|
||||
Cu.reportError("Error detecting Firefox profiles: " + e);
|
||||
}
|
||||
return this._profilesCache;
|
||||
},
|
||||
|
||||
/**
|
||||
* Return home page URL
|
||||
*
|
||||
* @return home page URL
|
||||
*
|
||||
* @todo Bug 715348 will migrate preferences such as the homepage
|
||||
*/
|
||||
get sourceHomePageURL()
|
||||
{
|
||||
try {
|
||||
if (this._homepageURL)
|
||||
return this._homepageURL;
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
return "";
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsIBrowserProfileMigrator
|
||||
]),
|
||||
|
||||
classDescription: "Firefox Profile Migrator",
|
||||
contractID: "@mozilla.org/profile/migrator;1?app=browser&type=firefox",
|
||||
classID: Components.ID("{91185366-ba97-4438-acba-48deaca63386}")
|
||||
};
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([FirefoxProfileMigrator]);
|
|
@ -65,6 +65,7 @@ endif
|
|||
|
||||
EXTRA_PP_COMPONENTS = \
|
||||
ChromeProfileMigrator.js \
|
||||
FirefoxProfileMigrator.js \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_COMPONENTS = \
|
||||
|
|
|
@ -140,6 +140,7 @@ NS_IMPL_ISUPPORTS1(nsProfileMigrator, nsIProfileMigrator)
|
|||
#define INTERNAL_NAME_IEXPLORE "iexplore"
|
||||
#define INTERNAL_NAME_MOZILLA_SUITE "apprunner"
|
||||
#define INTERNAL_NAME_CHROME "chrome"
|
||||
#define INTERNAL_NAME_FIREFOX "firefox"
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
|
@ -223,6 +224,10 @@ nsProfileMigrator::GetDefaultBrowserMigratorKey(nsACString& aKey,
|
|||
aKey = "chrome";
|
||||
return NS_OK;
|
||||
}
|
||||
else if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_FIREFOX)) {
|
||||
aKey = "firefox";
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#else
|
||||
bool exists = false;
|
||||
|
@ -239,6 +244,7 @@ nsProfileMigrator::GetDefaultBrowserMigratorKey(nsACString& aKey,
|
|||
CHECK_MIGRATOR("safari");
|
||||
#endif
|
||||
CHECK_MIGRATOR("chrome");
|
||||
CHECK_MIGRATOR("firefox");
|
||||
|
||||
#undef CHECK_MIGRATOR
|
||||
#endif
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#endif
|
||||
@BINPATH@/components/BrowserProfileMigrators.manifest
|
||||
@BINPATH@/components/ChromeProfileMigrator.js
|
||||
@BINPATH@/components/FirefoxProfileMigrator.js
|
||||
#ifdef XP_MACOSX
|
||||
@BINPATH@/components/libalerts_s.dylib
|
||||
#endif
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
<!ENTITY importFromSafari.accesskey "S">
|
||||
<!ENTITY importFromChrome.label "Chrome">
|
||||
<!ENTITY importFromChrome.accesskey "C">
|
||||
<!ENTITY importFromFirefox.label "Firefox">
|
||||
<!ENTITY importFromFirefox.accesskey "X">
|
||||
<!ENTITY importFromHTMLFile.label "From an HTML File">
|
||||
<!ENTITY importFromHTMLFile.accesskey "F">
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ profileName_format=%S %S
|
|||
sourceNameIE=Internet Explorer
|
||||
sourceNameSafari=Safari
|
||||
sourceNameChrome=Google Chrome
|
||||
sourceNameFirefox=Mozilla Firefox
|
||||
|
||||
importedBookmarksFolder=From %S
|
||||
importedSearchURLsFolder=Keyword Searches (From %S)
|
||||
|
@ -20,10 +21,12 @@ importedSafariBookmarks=From Safari
|
|||
2_ie=Cookies
|
||||
2_safari=Cookies
|
||||
2_chrome=Cookies
|
||||
2_firefox=Cookies
|
||||
|
||||
4_ie=Browsing History
|
||||
4_safari=Browsing History
|
||||
4_chrome=Browsing History
|
||||
4_firefox=Browsing History
|
||||
|
||||
8_ie=Saved Form History
|
||||
8_safari=Saved Form History
|
||||
|
@ -32,10 +35,12 @@ importedSafariBookmarks=From Safari
|
|||
16_ie=Saved Passwords
|
||||
16_safari=Saved Passwords
|
||||
16_chrome=Saved Passwords
|
||||
16_firefox=Saved Passwords
|
||||
|
||||
32_ie=Favorites
|
||||
32_safari=Bookmarks
|
||||
32_chrome=Bookmarks
|
||||
32_firefox=Bookmarks
|
||||
|
||||
64_ie=Other Data
|
||||
64_safari=Other Data
|
||||
|
|
|
@ -1818,7 +1818,7 @@ var PlacesUtils = {
|
|||
|
||||
get folder() {
|
||||
let bookmarksBackupDir = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
|
||||
bookmarksBackupDir.append("bookmarkbackups");
|
||||
bookmarksBackupDir.append(this.profileRelativeFolderPath);
|
||||
if (!bookmarksBackupDir.exists()) {
|
||||
bookmarksBackupDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0700);
|
||||
if (!bookmarksBackupDir.exists())
|
||||
|
@ -1828,6 +1828,8 @@ var PlacesUtils = {
|
|||
return this.folder = bookmarksBackupDir;
|
||||
},
|
||||
|
||||
get profileRelativeFolderPath() "bookmarkbackups",
|
||||
|
||||
/**
|
||||
* Cache current backups in a sorted (by date DESC) array.
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче