1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/components/migration/content/migration.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,462 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +const Cc = Components.classes; 1.9 +const Ci = Components.interfaces; 1.10 +const Cu = Components.utils; 1.11 + 1.12 +const kIMig = Ci.nsIBrowserProfileMigrator; 1.13 +const kIPStartup = Ci.nsIProfileStartup; 1.14 + 1.15 +Cu.import("resource:///modules/MigrationUtils.jsm"); 1.16 + 1.17 +var MigrationWizard = { 1.18 + _source: "", // Source Profile Migrator ContractID suffix 1.19 + _itemsFlags: kIMig.ALL, // Selected Import Data Sources (16-bit bitfield) 1.20 + _selectedProfile: null, // Selected Profile name to import from 1.21 + _wiz: null, 1.22 + _migrator: null, 1.23 + _autoMigrate: null, 1.24 + 1.25 + init: function () 1.26 + { 1.27 + var os = Components.classes["@mozilla.org/observer-service;1"] 1.28 + .getService(Components.interfaces.nsIObserverService); 1.29 + os.addObserver(this, "Migration:Started", false); 1.30 + os.addObserver(this, "Migration:ItemBeforeMigrate", false); 1.31 + os.addObserver(this, "Migration:ItemAfterMigrate", false); 1.32 + os.addObserver(this, "Migration:ItemError", false); 1.33 + os.addObserver(this, "Migration:Ended", false); 1.34 + 1.35 + this._wiz = document.documentElement; 1.36 + 1.37 + if ("arguments" in window && window.arguments.length > 1) { 1.38 + this._source = window.arguments[0]; 1.39 + this._migrator = window.arguments[1] instanceof kIMig ? 1.40 + window.arguments[1] : null; 1.41 + this._autoMigrate = window.arguments[2].QueryInterface(kIPStartup); 1.42 + this._skipImportSourcePage = window.arguments[3]; 1.43 + 1.44 + if (this._autoMigrate) { 1.45 + // Show the "nothing" option in the automigrate case to provide an 1.46 + // easily identifiable way to avoid migration and create a new profile. 1.47 + var nothing = document.getElementById("nothing"); 1.48 + nothing.hidden = false; 1.49 + } 1.50 + } 1.51 + 1.52 + this.onImportSourcePageShow(); 1.53 + }, 1.54 + 1.55 + uninit: function () 1.56 + { 1.57 + var os = Components.classes["@mozilla.org/observer-service;1"] 1.58 + .getService(Components.interfaces.nsIObserverService); 1.59 + os.removeObserver(this, "Migration:Started"); 1.60 + os.removeObserver(this, "Migration:ItemBeforeMigrate"); 1.61 + os.removeObserver(this, "Migration:ItemAfterMigrate"); 1.62 + os.removeObserver(this, "Migration:ItemError"); 1.63 + os.removeObserver(this, "Migration:Ended"); 1.64 + MigrationUtils.finishMigration(); 1.65 + }, 1.66 + 1.67 + // 1 - Import Source 1.68 + onImportSourcePageShow: function () 1.69 + { 1.70 + this._wiz.canRewind = false; 1.71 + 1.72 + var selectedMigrator = null; 1.73 + 1.74 + // Figure out what source apps are are available to import from: 1.75 + var group = document.getElementById("importSourceGroup"); 1.76 + for (var i = 0; i < group.childNodes.length; ++i) { 1.77 + var migratorKey = group.childNodes[i].id; 1.78 + if (migratorKey != "nothing") { 1.79 + var migrator = MigrationUtils.getMigrator(migratorKey); 1.80 + if (migrator) { 1.81 + // Save this as the first selectable item, if we don't already have 1.82 + // one, or if it is the migrator that was passed to us. 1.83 + if (!selectedMigrator || this._source == migratorKey) 1.84 + selectedMigrator = group.childNodes[i]; 1.85 + } else { 1.86 + // Hide this option 1.87 + group.childNodes[i].hidden = true; 1.88 + } 1.89 + } 1.90 + } 1.91 + 1.92 + if (selectedMigrator) 1.93 + group.selectedItem = selectedMigrator; 1.94 + else { 1.95 + // We didn't find a migrator, notify the user 1.96 + document.getElementById("noSources").hidden = false; 1.97 + 1.98 + this._wiz.canAdvance = false; 1.99 + 1.100 + document.getElementById("importBookmarks").hidden = true; 1.101 + document.getElementById("importAll").hidden = true; 1.102 + } 1.103 + 1.104 + // Advance to the next page if the caller told us to. 1.105 + if (this._migrator && this._skipImportSourcePage) { 1.106 + this._wiz.advance(); 1.107 + this._wiz.canRewind = false; 1.108 + } 1.109 + }, 1.110 + 1.111 + onImportSourcePageAdvanced: function () 1.112 + { 1.113 + var newSource = document.getElementById("importSourceGroup").selectedItem.id; 1.114 + 1.115 + if (newSource == "nothing") { 1.116 + document.documentElement.cancel(); 1.117 + return false; 1.118 + } 1.119 + 1.120 + if (!this._migrator || (newSource != this._source)) { 1.121 + // Create the migrator for the selected source. 1.122 + this._migrator = MigrationUtils.getMigrator(newSource); 1.123 + 1.124 + this._itemsFlags = kIMig.ALL; 1.125 + this._selectedProfile = null; 1.126 + } 1.127 + this._source = newSource; 1.128 + 1.129 + // check for more than one source profile 1.130 + var sourceProfiles = this._migrator.sourceProfiles; 1.131 + if (sourceProfiles && sourceProfiles.length > 1) { 1.132 + this._wiz.currentPage.next = "selectProfile"; 1.133 + } 1.134 + else { 1.135 + if (this._autoMigrate) 1.136 + this._wiz.currentPage.next = "homePageImport"; 1.137 + else 1.138 + this._wiz.currentPage.next = "importItems"; 1.139 + 1.140 + if (sourceProfiles && sourceProfiles.length == 1) 1.141 + this._selectedProfile = sourceProfiles[0]; 1.142 + else 1.143 + this._selectedProfile = ""; 1.144 + } 1.145 + }, 1.146 + 1.147 + // 2 - [Profile Selection] 1.148 + onSelectProfilePageShow: function () 1.149 + { 1.150 + // Disabling this for now, since we ask about import sources in automigration 1.151 + // too and don't want to disable the back button 1.152 + // if (this._autoMigrate) 1.153 + // document.documentElement.getButton("back").disabled = true; 1.154 + 1.155 + var profiles = document.getElementById("profiles"); 1.156 + while (profiles.hasChildNodes()) 1.157 + profiles.removeChild(profiles.firstChild); 1.158 + 1.159 + // Note that this block is still reached even if the user chose 'From File' 1.160 + // and we canceled the dialog. When that happens, _migrator will be null. 1.161 + if (this._migrator) { 1.162 + var sourceProfiles = this._migrator.sourceProfiles; 1.163 + for (var i = 0; i < sourceProfiles.length; ++i) { 1.164 + var item = document.createElement("radio"); 1.165 + item.id = sourceProfiles[i]; 1.166 + item.setAttribute("label", sourceProfiles[i]); 1.167 + profiles.appendChild(item); 1.168 + } 1.169 + } 1.170 + 1.171 + profiles.selectedItem = this._selectedProfile ? document.getElementById(this._selectedProfile) : profiles.firstChild; 1.172 + }, 1.173 + 1.174 + onSelectProfilePageRewound: function () 1.175 + { 1.176 + var profiles = document.getElementById("profiles"); 1.177 + this._selectedProfile = profiles.selectedItem.id; 1.178 + }, 1.179 + 1.180 + onSelectProfilePageAdvanced: function () 1.181 + { 1.182 + var profiles = document.getElementById("profiles"); 1.183 + this._selectedProfile = profiles.selectedItem.id; 1.184 + 1.185 + // If we're automigrating or just doing bookmarks don't show the item selection page 1.186 + if (this._autoMigrate) 1.187 + this._wiz.currentPage.next = "homePageImport"; 1.188 + }, 1.189 + 1.190 + // 3 - ImportItems 1.191 + onImportItemsPageShow: function () 1.192 + { 1.193 + var dataSources = document.getElementById("dataSources"); 1.194 + while (dataSources.hasChildNodes()) 1.195 + dataSources.removeChild(dataSources.firstChild); 1.196 + 1.197 + var items = this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate); 1.198 + for (var i = 0; i < 16; ++i) { 1.199 + var itemID = (items >> i) & 0x1 ? Math.pow(2, i) : 0; 1.200 + if (itemID > 0) { 1.201 + var checkbox = document.createElement("checkbox"); 1.202 + checkbox.id = itemID; 1.203 + checkbox.setAttribute("label", 1.204 + MigrationUtils.getLocalizedString(itemID + "_" + this._source)); 1.205 + dataSources.appendChild(checkbox); 1.206 + if (!this._itemsFlags || this._itemsFlags & itemID) 1.207 + checkbox.checked = true; 1.208 + } 1.209 + } 1.210 + }, 1.211 + 1.212 + onImportItemsPageRewound: function () 1.213 + { 1.214 + this._wiz.canAdvance = true; 1.215 + this.onImportItemsPageAdvanced(); 1.216 + }, 1.217 + 1.218 + onImportItemsPageAdvanced: function () 1.219 + { 1.220 + var dataSources = document.getElementById("dataSources"); 1.221 + this._itemsFlags = 0; 1.222 + for (var i = 0; i < dataSources.childNodes.length; ++i) { 1.223 + var checkbox = dataSources.childNodes[i]; 1.224 + if (checkbox.localName == "checkbox" && checkbox.checked) 1.225 + this._itemsFlags |= parseInt(checkbox.id); 1.226 + } 1.227 + }, 1.228 + 1.229 + onImportItemCommand: function (aEvent) 1.230 + { 1.231 + var items = document.getElementById("dataSources"); 1.232 + var checkboxes = items.getElementsByTagName("checkbox"); 1.233 + 1.234 + var oneChecked = false; 1.235 + for (var i = 0; i < checkboxes.length; ++i) { 1.236 + if (checkboxes[i].checked) { 1.237 + oneChecked = true; 1.238 + break; 1.239 + } 1.240 + } 1.241 + 1.242 + this._wiz.canAdvance = oneChecked; 1.243 + }, 1.244 + 1.245 + // 4 - Home Page Selection 1.246 + onHomePageMigrationPageShow: function () 1.247 + { 1.248 + // only want this on the first run 1.249 + if (!this._autoMigrate) { 1.250 + this._wiz.advance(); 1.251 + return; 1.252 + } 1.253 + 1.254 + var brandBundle = document.getElementById("brandBundle"); 1.255 + // These strings don't exist when not using official branding. If that's 1.256 + // the case, just skip this page. 1.257 + try { 1.258 + var pageTitle = brandBundle.getString("homePageMigrationPageTitle"); 1.259 + var pageDesc = brandBundle.getString("homePageMigrationDescription"); 1.260 + var mainStr = brandBundle.getString("homePageSingleStartMain"); 1.261 + } 1.262 + catch (e) { 1.263 + this._wiz.advance(); 1.264 + return; 1.265 + } 1.266 + 1.267 + document.getElementById("homePageImport").setAttribute("label", pageTitle); 1.268 + document.getElementById("homePageImportDesc").setAttribute("value", pageDesc); 1.269 + 1.270 + this._wiz._adjustWizardHeader(); 1.271 + 1.272 + var singleStart = document.getElementById("homePageSingleStart"); 1.273 + singleStart.setAttribute("label", mainStr); 1.274 + singleStart.setAttribute("value", "DEFAULT"); 1.275 + 1.276 + var source = null; 1.277 + switch (this._source) { 1.278 + case "ie": 1.279 + source = "sourceNameIE"; 1.280 + break; 1.281 + case "safari": 1.282 + source = "sourceNameSafari"; 1.283 + break; 1.284 + case "chrome": 1.285 + source = "sourceNameChrome"; 1.286 + break; 1.287 + case "firefox": 1.288 + source = "sourceNameFirefox"; 1.289 + break; 1.290 + } 1.291 + 1.292 + // semi-wallpaper for crash when multiple profiles exist, since we haven't initialized mSourceProfile in places 1.293 + this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate); 1.294 + 1.295 + var oldHomePageURL = this._migrator.sourceHomePageURL; 1.296 + 1.297 + if (oldHomePageURL && source) { 1.298 + var appName = MigrationUtils.getLocalizedString(source); 1.299 + var oldHomePageLabel = 1.300 + brandBundle.getFormattedString("homePageImport", [appName]); 1.301 + var oldHomePage = document.getElementById("oldHomePage"); 1.302 + oldHomePage.setAttribute("label", oldHomePageLabel); 1.303 + oldHomePage.setAttribute("value", oldHomePageURL); 1.304 + oldHomePage.removeAttribute("hidden"); 1.305 + } 1.306 + else { 1.307 + // if we don't have at least two options, just advance 1.308 + this._wiz.advance(); 1.309 + } 1.310 + }, 1.311 + 1.312 + onHomePageMigrationPageAdvanced: function () 1.313 + { 1.314 + // we might not have a selectedItem if we're in fallback mode 1.315 + try { 1.316 + var radioGroup = document.getElementById("homePageRadiogroup"); 1.317 + 1.318 + this._newHomePage = radioGroup.selectedItem.value; 1.319 + } catch(ex) {} 1.320 + }, 1.321 + 1.322 + // 5 - Migrating 1.323 + onMigratingPageShow: function () 1.324 + { 1.325 + this._wiz.getButton("cancel").disabled = true; 1.326 + this._wiz.canRewind = false; 1.327 + this._wiz.canAdvance = false; 1.328 + 1.329 + // When automigrating, show all of the data that can be received from this source. 1.330 + if (this._autoMigrate) 1.331 + this._itemsFlags = this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate); 1.332 + 1.333 + this._listItems("migratingItems"); 1.334 + setTimeout(this.onMigratingMigrate, 0, this); 1.335 + }, 1.336 + 1.337 + onMigratingMigrate: function (aOuter) 1.338 + { 1.339 + aOuter._migrator.migrate(aOuter._itemsFlags, aOuter._autoMigrate, aOuter._selectedProfile); 1.340 + }, 1.341 + 1.342 + _listItems: function (aID) 1.343 + { 1.344 + var items = document.getElementById(aID); 1.345 + while (items.hasChildNodes()) 1.346 + items.removeChild(items.firstChild); 1.347 + 1.348 + var brandBundle = document.getElementById("brandBundle"); 1.349 + var itemID; 1.350 + for (var i = 0; i < 16; ++i) { 1.351 + var itemID = (this._itemsFlags >> i) & 0x1 ? Math.pow(2, i) : 0; 1.352 + if (itemID > 0) { 1.353 + var label = document.createElement("label"); 1.354 + label.id = itemID + "_migrated"; 1.355 + try { 1.356 + label.setAttribute("value", 1.357 + MigrationUtils.getLocalizedString(itemID + "_" + this._source)); 1.358 + items.appendChild(label); 1.359 + } 1.360 + catch (e) { 1.361 + // if the block above throws, we've enumerated all the import data types we 1.362 + // currently support and are now just wasting time, break. 1.363 + break; 1.364 + } 1.365 + } 1.366 + } 1.367 + }, 1.368 + 1.369 + observe: function (aSubject, aTopic, aData) 1.370 + { 1.371 + switch (aTopic) { 1.372 + case "Migration:Started": 1.373 + break; 1.374 + case "Migration:ItemBeforeMigrate": 1.375 + var label = document.getElementById(aData + "_migrated"); 1.376 + if (label) 1.377 + label.setAttribute("style", "font-weight: bold"); 1.378 + break; 1.379 + case "Migration:ItemAfterMigrate": 1.380 + var label = document.getElementById(aData + "_migrated"); 1.381 + if (label) 1.382 + label.removeAttribute("style"); 1.383 + break; 1.384 + case "Migration:Ended": 1.385 + if (this._autoMigrate) { 1.386 + if (this._newHomePage) { 1.387 + try { 1.388 + // set homepage properly 1.389 + var prefSvc = Components.classes["@mozilla.org/preferences-service;1"] 1.390 + .getService(Components.interfaces.nsIPrefService); 1.391 + var prefBranch = prefSvc.getBranch(null); 1.392 + 1.393 + if (this._newHomePage == "DEFAULT") { 1.394 + prefBranch.clearUserPref("browser.startup.homepage"); 1.395 + } 1.396 + else { 1.397 + var str = Components.classes["@mozilla.org/supports-string;1"] 1.398 + .createInstance(Components.interfaces.nsISupportsString); 1.399 + str.data = this._newHomePage; 1.400 + prefBranch.setComplexValue("browser.startup.homepage", 1.401 + Components.interfaces.nsISupportsString, 1.402 + str); 1.403 + } 1.404 + 1.405 + var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"] 1.406 + .getService(Components.interfaces.nsIProperties); 1.407 + var prefFile = dirSvc.get("ProfDS", Components.interfaces.nsIFile); 1.408 + prefFile.append("prefs.js"); 1.409 + prefSvc.savePrefFile(prefFile); 1.410 + } catch(ex) { 1.411 + dump(ex); 1.412 + } 1.413 + } 1.414 + 1.415 + // We're done now. 1.416 + this._wiz.canAdvance = true; 1.417 + this._wiz.advance(); 1.418 + 1.419 + setTimeout(close, 5000); 1.420 + } 1.421 + else { 1.422 + this._wiz.canAdvance = true; 1.423 + var nextButton = this._wiz.getButton("next"); 1.424 + nextButton.click(); 1.425 + } 1.426 + break; 1.427 + case "Migration:ItemError": 1.428 + var type = "undefined"; 1.429 + switch (parseInt(aData)) { 1.430 + case Ci.nsIBrowserProfileMigrator.SETTINGS: 1.431 + type = "settings"; 1.432 + break; 1.433 + case Ci.nsIBrowserProfileMigrator.COOKIES: 1.434 + type = "cookies"; 1.435 + break; 1.436 + case Ci.nsIBrowserProfileMigrator.HISTORY: 1.437 + type = "history"; 1.438 + break; 1.439 + case Ci.nsIBrowserProfileMigrator.FORMDATA: 1.440 + type = "form data"; 1.441 + break; 1.442 + case Ci.nsIBrowserProfileMigrator.PASSWORDS: 1.443 + type = "passwords"; 1.444 + break; 1.445 + case Ci.nsIBrowserProfileMigrator.BOOKMARKS: 1.446 + type = "bookmarks"; 1.447 + break; 1.448 + case Ci.nsIBrowserProfileMigrator.OTHERDATA: 1.449 + type = "misc. data"; 1.450 + break; 1.451 + } 1.452 + Cc["@mozilla.org/consoleservice;1"] 1.453 + .getService(Ci.nsIConsoleService) 1.454 + .logStringMessage("some " + type + " did not successfully migrate."); 1.455 + break; 1.456 + } 1.457 + }, 1.458 + 1.459 + onDonePageShow: function () 1.460 + { 1.461 + this._wiz.getButton("cancel").disabled = true; 1.462 + this._wiz.canRewind = false; 1.463 + this._listItems("doneItems"); 1.464 + } 1.465 +};