1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/components/migration/src/FirefoxProfileMigrator.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,134 @@ 1.4 +/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * vim: sw=2 ts=2 sts=2 et */ 1.6 + /* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +"use strict"; 1.11 + 1.12 +/* 1.13 + * Migrates from a Firefox profile in a lossy manner in order to clean up a 1.14 + * user's profile. Data is only migrated where the benefits outweigh the 1.15 + * potential problems caused by importing undesired/invalid configurations 1.16 + * from the source profile. 1.17 + */ 1.18 + 1.19 +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); 1.20 +Components.utils.import("resource:///modules/MigrationUtils.jsm"); 1.21 +Components.utils.import("resource://gre/modules/Services.jsm"); 1.22 +XPCOMUtils.defineLazyModuleGetter(this, "PlacesBackups", 1.23 + "resource://gre/modules/PlacesBackups.jsm"); 1.24 +XPCOMUtils.defineLazyModuleGetter(this, "SessionMigration", 1.25 + "resource:///modules/sessionstore/SessionMigration.jsm"); 1.26 + 1.27 +function FirefoxProfileMigrator() { } 1.28 + 1.29 +FirefoxProfileMigrator.prototype = Object.create(MigratorPrototype); 1.30 + 1.31 +FirefoxProfileMigrator.prototype._getFileObject = function(dir, fileName) { 1.32 + let file = dir.clone(); 1.33 + file.append(fileName); 1.34 + 1.35 + // File resources are monolithic. We don't make partial copies since 1.36 + // they are not expected to work alone. Return null to avoid trying to 1.37 + // copy non-existing files. 1.38 + return file.exists() ? file : null; 1.39 +} 1.40 + 1.41 +FirefoxProfileMigrator.prototype.getResources = function() { 1.42 + // Only allow migrating from the default (selected) profile since this will 1.43 + // be the only one returned by the toolkit profile service after bug 214675. 1.44 + let sourceProfile = 1.45 + Components.classes["@mozilla.org/toolkit/profile-service;1"] 1.46 + .getService(Components.interfaces.nsIToolkitProfileService) 1.47 + .selectedProfile; 1.48 + if (!sourceProfile) 1.49 + return null; 1.50 + 1.51 + let sourceProfileDir = sourceProfile.rootDir; 1.52 + if (!sourceProfileDir || !sourceProfileDir.exists() || 1.53 + !sourceProfileDir.isReadable()) 1.54 + return null; 1.55 + 1.56 + // Being a startup-only migrator, we can rely on 1.57 + // MigrationUtils.profileStartup being set. 1.58 + let currentProfileDir = MigrationUtils.profileStartup.directory; 1.59 + 1.60 + // Surely data cannot be imported from the current profile. 1.61 + if (sourceProfileDir.equals(currentProfileDir)) 1.62 + return null; 1.63 + 1.64 + let getFileResource = function(aMigrationType, aFileNames) { 1.65 + let files = []; 1.66 + for (let fileName of aFileNames) { 1.67 + let file = this._getFileObject(sourceProfileDir, fileName); 1.68 + if (!file) 1.69 + return null; 1.70 + files.push(file); 1.71 + } 1.72 + return { 1.73 + type: aMigrationType, 1.74 + migrate: function(aCallback) { 1.75 + for (let file of files) { 1.76 + file.copyTo(currentProfileDir, ""); 1.77 + } 1.78 + aCallback(true); 1.79 + } 1.80 + }; 1.81 + }.bind(this); 1.82 + 1.83 + let types = MigrationUtils.resourceTypes; 1.84 + let places = getFileResource(types.HISTORY, ["places.sqlite"]); 1.85 + let cookies = getFileResource(types.COOKIES, ["cookies.sqlite"]); 1.86 + let passwords = getFileResource(types.PASSWORDS, 1.87 + ["signons.sqlite", "key3.db"]); 1.88 + let formData = getFileResource(types.FORMDATA, ["formhistory.sqlite"]); 1.89 + let bookmarksBackups = getFileResource(types.OTHERDATA, 1.90 + [PlacesBackups.profileRelativeFolderPath]); 1.91 + let dictionary = getFileResource(types.OTHERDATA, ["persdict.dat"]); 1.92 + 1.93 + let sessionFile = this._getFileObject(sourceProfileDir, "sessionstore.js"); 1.94 + let session; 1.95 + if (sessionFile) { 1.96 + session = { 1.97 + type: types.SESSION, 1.98 + migrate: function(aCallback) { 1.99 + let newSessionFile = currentProfileDir.clone(); 1.100 + newSessionFile.append("sessionstore.js"); 1.101 + let migrationPromise = SessionMigration.migrate(sessionFile.path, newSessionFile.path); 1.102 + migrationPromise.then(function() { 1.103 + let buildID = Services.appinfo.platformBuildID; 1.104 + let mstone = Services.appinfo.platformVersion; 1.105 + // Force the browser to one-off resume the session that we give it: 1.106 + Services.prefs.setBoolPref("browser.sessionstore.resume_session_once", true); 1.107 + // Reset the homepage_override prefs so that the browser doesn't override our 1.108 + // session with the "what's new" page: 1.109 + Services.prefs.setCharPref("browser.startup.homepage_override.mstone", mstone); 1.110 + Services.prefs.setCharPref("browser.startup.homepage_override.buildID", buildID); 1.111 + // It's too early in startup for the pref service to have a profile directory, 1.112 + // so we have to manually tell it where to save the prefs file. 1.113 + let newPrefsFile = currentProfileDir.clone(); 1.114 + newPrefsFile.append("prefs.js"); 1.115 + Services.prefs.savePrefFile(newPrefsFile); 1.116 + aCallback(true); 1.117 + }, function() { 1.118 + aCallback(false); 1.119 + }); 1.120 + } 1.121 + } 1.122 + } 1.123 + 1.124 + return [r for each (r in [places, cookies, passwords, formData, 1.125 + dictionary, bookmarksBackups, session]) if (r)]; 1.126 +} 1.127 + 1.128 +Object.defineProperty(FirefoxProfileMigrator.prototype, "startupOnlyMigrator", { 1.129 + get: function() true 1.130 +}); 1.131 + 1.132 + 1.133 +FirefoxProfileMigrator.prototype.classDescription = "Firefox Profile Migrator"; 1.134 +FirefoxProfileMigrator.prototype.contractID = "@mozilla.org/profile/migrator;1?app=browser&type=firefox"; 1.135 +FirefoxProfileMigrator.prototype.classID = Components.ID("{91185366-ba97-4438-acba-48deaca63386}"); 1.136 + 1.137 +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([FirefoxProfileMigrator]);