|
1 /* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
2 * vim: sw=2 ts=2 sts=2 et */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 "use strict"; |
|
8 |
|
9 /* |
|
10 * Migrates from a Firefox profile in a lossy manner in order to clean up a |
|
11 * user's profile. Data is only migrated where the benefits outweigh the |
|
12 * potential problems caused by importing undesired/invalid configurations |
|
13 * from the source profile. |
|
14 */ |
|
15 |
|
16 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
17 Components.utils.import("resource:///modules/MigrationUtils.jsm"); |
|
18 Components.utils.import("resource://gre/modules/Services.jsm"); |
|
19 XPCOMUtils.defineLazyModuleGetter(this, "PlacesBackups", |
|
20 "resource://gre/modules/PlacesBackups.jsm"); |
|
21 XPCOMUtils.defineLazyModuleGetter(this, "SessionMigration", |
|
22 "resource:///modules/sessionstore/SessionMigration.jsm"); |
|
23 |
|
24 function FirefoxProfileMigrator() { } |
|
25 |
|
26 FirefoxProfileMigrator.prototype = Object.create(MigratorPrototype); |
|
27 |
|
28 FirefoxProfileMigrator.prototype._getFileObject = function(dir, fileName) { |
|
29 let file = dir.clone(); |
|
30 file.append(fileName); |
|
31 |
|
32 // File resources are monolithic. We don't make partial copies since |
|
33 // they are not expected to work alone. Return null to avoid trying to |
|
34 // copy non-existing files. |
|
35 return file.exists() ? file : null; |
|
36 } |
|
37 |
|
38 FirefoxProfileMigrator.prototype.getResources = function() { |
|
39 // Only allow migrating from the default (selected) profile since this will |
|
40 // be the only one returned by the toolkit profile service after bug 214675. |
|
41 let sourceProfile = |
|
42 Components.classes["@mozilla.org/toolkit/profile-service;1"] |
|
43 .getService(Components.interfaces.nsIToolkitProfileService) |
|
44 .selectedProfile; |
|
45 if (!sourceProfile) |
|
46 return null; |
|
47 |
|
48 let sourceProfileDir = sourceProfile.rootDir; |
|
49 if (!sourceProfileDir || !sourceProfileDir.exists() || |
|
50 !sourceProfileDir.isReadable()) |
|
51 return null; |
|
52 |
|
53 // Being a startup-only migrator, we can rely on |
|
54 // MigrationUtils.profileStartup being set. |
|
55 let currentProfileDir = MigrationUtils.profileStartup.directory; |
|
56 |
|
57 // Surely data cannot be imported from the current profile. |
|
58 if (sourceProfileDir.equals(currentProfileDir)) |
|
59 return null; |
|
60 |
|
61 let getFileResource = function(aMigrationType, aFileNames) { |
|
62 let files = []; |
|
63 for (let fileName of aFileNames) { |
|
64 let file = this._getFileObject(sourceProfileDir, fileName); |
|
65 if (!file) |
|
66 return null; |
|
67 files.push(file); |
|
68 } |
|
69 return { |
|
70 type: aMigrationType, |
|
71 migrate: function(aCallback) { |
|
72 for (let file of files) { |
|
73 file.copyTo(currentProfileDir, ""); |
|
74 } |
|
75 aCallback(true); |
|
76 } |
|
77 }; |
|
78 }.bind(this); |
|
79 |
|
80 let types = MigrationUtils.resourceTypes; |
|
81 let places = getFileResource(types.HISTORY, ["places.sqlite"]); |
|
82 let cookies = getFileResource(types.COOKIES, ["cookies.sqlite"]); |
|
83 let passwords = getFileResource(types.PASSWORDS, |
|
84 ["signons.sqlite", "key3.db"]); |
|
85 let formData = getFileResource(types.FORMDATA, ["formhistory.sqlite"]); |
|
86 let bookmarksBackups = getFileResource(types.OTHERDATA, |
|
87 [PlacesBackups.profileRelativeFolderPath]); |
|
88 let dictionary = getFileResource(types.OTHERDATA, ["persdict.dat"]); |
|
89 |
|
90 let sessionFile = this._getFileObject(sourceProfileDir, "sessionstore.js"); |
|
91 let session; |
|
92 if (sessionFile) { |
|
93 session = { |
|
94 type: types.SESSION, |
|
95 migrate: function(aCallback) { |
|
96 let newSessionFile = currentProfileDir.clone(); |
|
97 newSessionFile.append("sessionstore.js"); |
|
98 let migrationPromise = SessionMigration.migrate(sessionFile.path, newSessionFile.path); |
|
99 migrationPromise.then(function() { |
|
100 let buildID = Services.appinfo.platformBuildID; |
|
101 let mstone = Services.appinfo.platformVersion; |
|
102 // Force the browser to one-off resume the session that we give it: |
|
103 Services.prefs.setBoolPref("browser.sessionstore.resume_session_once", true); |
|
104 // Reset the homepage_override prefs so that the browser doesn't override our |
|
105 // session with the "what's new" page: |
|
106 Services.prefs.setCharPref("browser.startup.homepage_override.mstone", mstone); |
|
107 Services.prefs.setCharPref("browser.startup.homepage_override.buildID", buildID); |
|
108 // It's too early in startup for the pref service to have a profile directory, |
|
109 // so we have to manually tell it where to save the prefs file. |
|
110 let newPrefsFile = currentProfileDir.clone(); |
|
111 newPrefsFile.append("prefs.js"); |
|
112 Services.prefs.savePrefFile(newPrefsFile); |
|
113 aCallback(true); |
|
114 }, function() { |
|
115 aCallback(false); |
|
116 }); |
|
117 } |
|
118 } |
|
119 } |
|
120 |
|
121 return [r for each (r in [places, cookies, passwords, formData, |
|
122 dictionary, bookmarksBackups, session]) if (r)]; |
|
123 } |
|
124 |
|
125 Object.defineProperty(FirefoxProfileMigrator.prototype, "startupOnlyMigrator", { |
|
126 get: function() true |
|
127 }); |
|
128 |
|
129 |
|
130 FirefoxProfileMigrator.prototype.classDescription = "Firefox Profile Migrator"; |
|
131 FirefoxProfileMigrator.prototype.contractID = "@mozilla.org/profile/migrator;1?app=browser&type=firefox"; |
|
132 FirefoxProfileMigrator.prototype.classID = Components.ID("{91185366-ba97-4438-acba-48deaca63386}"); |
|
133 |
|
134 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([FirefoxProfileMigrator]); |