summaryrefslogtreecommitdiffstats
path: root/comm/suite/components/migration/content
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--comm/suite/components/migration/content/migration.js413
-rw-r--r--comm/suite/components/migration/content/migration.xul95
2 files changed, 508 insertions, 0 deletions
diff --git a/comm/suite/components/migration/content/migration.js b/comm/suite/components/migration/content/migration.js
new file mode 100644
index 0000000000..b106e51e22
--- /dev/null
+++ b/comm/suite/components/migration/content/migration.js
@@ -0,0 +1,413 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+const NS_PROFILE_MIGRATOR_CONTRACTID =
+ "@mozilla.org/profile/migrator;1?app=suite&type=";
+
+var MigrationWizard = {
+ _source: "", // Source Profile Migrator ContractID suffix
+ _itemsFlags: Ci.nsISuiteProfileMigrator.ALL, // Selected Import Data Sources
+ _selectedProfile: null, // Selected Profile name to import from
+ _wiz: null, // Shortcut to the wizard
+ _migrator: null, // The actual profile migrator.
+ _autoMigrate: null, // Whether or not we are actually migrating.
+ _singleItem: false, // Are we choosing just to import a single
+ // item into the current profile?
+ _newHomePage: null, // Are we setting a new home page - what to?
+
+ init: function() {
+ Services.obs.addObserver(this, "Migration:Started");
+ Services.obs.addObserver(this, "Migration:ItemBeforeMigrate");
+ Services.obs.addObserver(this, "Migration:ItemAfterMigrate");
+ Services.obs.addObserver(this, "Migration:Ended");
+ Services.obs.addObserver(this, "Migration:Progress");
+
+ this._wiz = document.documentElement;
+ this._wiz.canRewind = false;
+
+ if ("arguments" in window) {
+ if ("arguments" in window && window.arguments[0] == "bookmarks") {
+ this._singleItem = true;
+ this._itemsFlags = Ci.nsISuiteProfileMigrator.BOOKMARKS;
+ document.getElementById("fromFile").hidden = false;
+ document.getElementById("importBookmarks").hidden = false;
+ document.getElementById("importAll").hidden = true;
+ }
+ else if (window.arguments.length > 1) {
+ this._source = window.arguments[0];
+ this._migrator =
+ window.arguments[1] instanceof Ci.nsISuiteProfileMigrator ?
+ window.arguments[1] : null;
+ this._autoMigrate = window.arguments[2]
+ .QueryInterface(Ci.nsIProfileStartup);
+ // Show the "nothing" option in the automigrate case to provide an
+ // easily identifiable way to avoid migration and create a new profile.
+ document.getElementById("nothing").hidden = false;
+ }
+ }
+
+ this.onImportSourcePageShow();
+ },
+
+ uninit: function() {
+ Services.obs.removeObserver(this, "Migration:Started");
+ Services.obs.removeObserver(this, "Migration:ItemBeforeMigrate");
+ Services.obs.removeObserver(this, "Migration:ItemAfterMigrate");
+ Services.obs.removeObserver(this, "Migration:Ended");
+ Services.obs.removeObserver(this, "Migration:Progress");
+ },
+
+ // 1 - Import Source
+ onImportSourcePageShow: function() {
+ // Figure out what source apps are are available to import from:
+ var group = document.getElementById("importSourceGroup");
+ var firstSelectable = null;
+ for (var i = 0; i < group.childNodes.length; ++i) {
+ var suffix = group.childNodes[i].id;
+ if (suffix != "nothing" && suffix != "fromFile") {
+ var contractID = NS_PROFILE_MIGRATOR_CONTRACTID + suffix;
+ var migrator = null;
+ if (contractID in Cc) {
+ migrator = Cc[contractID]
+ .createInstance(Ci.nsISuiteProfileMigrator);
+ } else {
+ dump("*** invalid contractID =" + contractID + "\n");
+ // This is an invalid contract id, therefore hide this element
+ // and allow things to continue - that way we should be able to
+ // copy with anything happening.
+ group.childNodes[i].hidden = true;
+ break;
+ }
+
+ // Ensure that we only allow import selections for profile
+ // migrators that support the requested action.
+ if (!migrator.sourceExists ||
+ !(migrator.supportedItems & this._itemsFlags)) {
+ group.childNodes[i].hidden = true;
+ break;
+ }
+
+ if (!firstSelectable && !group.childNodes[i].disabled &&
+ !group.childNodes[i].hidden) {
+ firstSelectable = group.childNodes[i];
+ }
+ }
+ }
+
+ if (this._source) {
+ // Somehow the Profile Migrator got confused, and gave us a migrate source
+ // that doesn't actually exist. This could be because of a bogus registry
+ // state. Set the _source property to null so the first visible item in
+ // the list is selected instead.
+ if (document.getElementById(this._source).hidden)
+ this._source = null;
+ }
+ group.selectedItem = this._source ?
+ document.getElementById(this._source) : firstSelectable;
+ },
+
+ onImportSourcePageAdvanced: function() {
+ var newSource = document.getElementById("importSourceGroup").value;
+
+ if (newSource == "nothing" || newSource == "fromFile") {
+ if (newSource == "fromFile") {
+ window.opener.fromFile = true;
+ }
+ document.documentElement.cancel();
+ // Don't let the wizard migrate to the next page event though we've
+ // called cancel - cancel may not get processed first.
+ return false;
+ }
+
+ if (!this._migrator || newSource != this._source) {
+ // Create the migrator for the selected source.
+ var contractID = NS_PROFILE_MIGRATOR_CONTRACTID + newSource;
+ this._migrator = Cc[contractID]
+ .createInstance(Ci.nsISuiteProfileMigrator);
+
+ this._selectedProfile = null;
+ }
+ this._source = newSource;
+
+ // check for more than one source profile
+ if (this._migrator.sourceHasMultipleProfiles)
+ this._wiz.currentPage.next = "selectProfile";
+ else {
+ if (this._autoMigrate)
+ this._wiz.currentPage.next = "homePageImport";
+ else if (this._singleItem)
+ this._wiz.currentPage.next = "migrating";
+ else
+ this._wiz.currentPage.next = "importItems";
+
+ var sourceProfiles = this._migrator.sourceProfiles;
+ if (sourceProfiles && sourceProfiles.length == 1) {
+ this._selectedProfile = sourceProfiles
+ .queryElementAt(0, Ci.nsISupportsString).data;
+ }
+ else
+ this._selectedProfile = "";
+ }
+ return true;
+ },
+
+ // 2 - [Profile Selection]
+ onSelectProfilePageShow: function() {
+ var profiles = document.getElementById("profiles");
+ while (profiles.hasChildNodes())
+ profiles.lastChild.remove();
+
+ var sourceProfiles = this._migrator.sourceProfiles;
+ var count = sourceProfiles.length;
+ for (var i = 0; i < count; ++i) {
+ var item = document.createElement("radio");
+ item.id = sourceProfiles.queryElementAt(i, Ci.nsISupportsString).data;
+ item.setAttribute("label", item.id);
+ profiles.appendChild(item);
+ }
+
+ profiles.selectedItem = this._selectedProfile ?
+ document.getElementById(this._selectedProfile) : profiles.firstChild;
+ },
+
+ onSelectProfilePageAdvanced: function() {
+ this._selectedProfile = document.getElementById("profiles").selectedItem.id;
+
+ // If we're automigrating or just doing bookmarks don't show the item
+ // selection page
+ if (this._autoMigrate)
+ this._wiz.currentPage.next = "homePageImport";
+ else if (this._singleItem)
+ this._wiz.currentPage.next = "migrating"
+ },
+
+ // 3 - ImportItems
+ onImportItemsPageShow: function() {
+ var dataSources = document.getElementById("dataSources");
+ while (dataSources.hasChildNodes())
+ dataSources.lastChild.remove();
+
+ var bundle = document.getElementById("bundle");
+
+ var items = this._migrator.getMigrateData(this._selectedProfile,
+ this._autoMigrate);
+
+ for (var i = 0; i < 16; ++i) {
+ var itemID = items & (1 << i);
+ if (itemID) {
+ var checkbox = document.createElement("checkbox");
+ checkbox.id = itemID;
+ try {
+ checkbox.setAttribute("label",
+ bundle.getString(itemID + "_" + this._source));
+ }
+ catch (ex) {
+ checkbox.setAttribute("label",
+ bundle.getString(itemID + "_generic"));
+ }
+ dataSources.appendChild(checkbox);
+ if (this._itemsFlags & itemID)
+ checkbox.setAttribute("checked", true);
+ }
+ }
+ },
+
+ onImportItemsPageRewound: function() {
+ this._wiz.canAdvance = true;
+ this.onImportItemsPageAdvanced();
+ },
+
+ onImportItemsPageAdvanced: function() {
+ var dataSources = document.getElementById("dataSources");
+ this._itemsFlags = 0;
+ for (var i = 0; i < dataSources.childNodes.length; ++i) {
+ var checkbox = dataSources.childNodes[i];
+ if (checkbox.checked)
+ this._itemsFlags |= checkbox.id;
+ }
+ },
+
+ onImportItemCommand: function(aEvent) {
+ this._wiz.canAdvance = document
+ .getElementById("dataSources")
+ .getElementsByAttribute("checked", "true").item(0) != null;
+ },
+
+ // 4 - Home Page Selection
+ onHomePageMigrationPageShow: function() {
+ // only want this on the first run
+ if (!this._autoMigrate) {
+ this._wiz.advance();
+ return;
+ }
+
+ var bundle = document.getElementById("bundle");
+ var pageTitle = bundle.getString("homePageMigrationPageTitle");
+ var pageDesc = bundle.getString("homePageMigrationDescription");
+
+ document.getElementById("homePageImport").setAttribute("label", pageTitle);
+ document.getElementById("homePageImportDesc")
+ .setAttribute("value", pageDesc);
+
+ this._wiz._adjustWizardHeader();
+
+ var homePageStart = document.getElementById("homePageStart");
+
+ // Find out if the target profile already has a homepage or not
+ var mainStr = this.targetHasHomePageURL() ?
+ bundle.getString("homePageStartCurrent") :
+ bundle.getString("homePageStartDefault");
+
+ homePageStart.setAttribute("label", mainStr);
+
+ var source = null;
+ if (this._source != "") {
+ source = "sourceName" + this._source;
+ }
+
+ var availableItems = this._migrator.getMigrateData(this._selectedProfile,
+ this._autoMigrate);
+
+ if (source && (availableItems & Ci.nsISuiteProfileMigrator.HOMEPAGEDATA)) {
+ var appName = document.getElementById("bundle").getString(source);
+ var oldHomePageLabel = bundle.getFormattedString("homePageImport",
+ [appName]);
+ var oldHomePage = document.getElementById("oldHomePage");
+ oldHomePage.setAttribute("label", oldHomePageLabel);
+ oldHomePage.setAttribute("value", "source");
+ oldHomePage.removeAttribute("hidden");
+ oldHomePage.focus();
+
+ document.getElementById("homePageRadioGroup").selectedItem = oldHomePage;
+ }
+ else {
+ // if we don't have at least two options, just advance
+ this._wiz.advance();
+ }
+ },
+
+ onHomePageMigrationPageAdvanced: function() {
+ // we might not have a selectedItem if we're in fallback mode
+ try {
+ this._newHomePage = document.getElementById("homePageRadioGroup")
+ .value;
+ } catch(ex) {}
+ },
+
+ // 5 - Migrating
+ onMigratingPageShow: function() {
+ this._wiz.getButton("cancel").disabled = true;
+ this._wiz.canRewind = false;
+ this._wiz.canAdvance = false;
+
+ // When migrating a profile on startup, show all of the data that can be
+ // received from this source, but exclude home pages if the user didn't
+ // want to migrate it.
+ if (this._autoMigrate) {
+ this._itemsFlags = this._migrator.getMigrateData(this._selectedProfile,
+ this._autoMigrate);
+ if (!this._newHomePage)
+ this._itemsFlags &= ~Ci.nsISuiteProfileMigrator.HOMEPAGEDATA;
+ }
+
+ this._listItems("migratingItems");
+ setTimeout(this.onMigratingMigrate, 0, this);
+ },
+
+ onMigratingMigrate: function(aOuter) {
+ aOuter._migrator.migrate(aOuter._itemsFlags,
+ aOuter._autoMigrate,
+ aOuter._selectedProfile);
+ },
+
+ _listItems: function(aID) {
+ var items = document.getElementById(aID);
+ while (items.hasChildNodes())
+ items.lastChild.remove();
+
+ var bundle = document.getElementById("bundle");
+ var itemID;
+ for (var x = 1; x < Ci.nsISuiteProfileMigrator.ALL;
+ x = x << 1) {
+ if (x & this._itemsFlags) {
+ var label = document.createElement("label");
+ label.id = x + "_migrated";
+ try {
+ label.setAttribute("value",
+ bundle.stringBundle
+ .GetStringFromName(x + "_"+ this._source));
+ label.setAttribute("class", "migration-pending");
+ items.appendChild(label);
+ }
+ catch (ex) {
+ try {
+ label.setAttribute("value", bundle.getString(x + "_generic"));
+ label.setAttribute("class", "migration-pending");
+ items.appendChild(label);
+ }
+ catch (e) {
+ // if the block above throws, we've enumerated all the import
+ // data types we currently support and are now just wasting time.
+ break;
+ }
+ }
+ }
+ }
+ },
+
+ observe: function(aSubject, aTopic, aData) {
+ switch (aTopic) {
+ case "Migration:Progress":
+ document.getElementById("progressBar").value = aData;
+ break;
+ case "Migration:Started":
+ break;
+ case "Migration:ItemBeforeMigrate":
+ var label = document.getElementById(aData + "_migrated");
+ if (label)
+ label.setAttribute("class", "migration-in-progress");
+ break;
+ case "Migration:ItemAfterMigrate":
+ var label = document.getElementById(aData + "_migrated");
+ if (label)
+ label.setAttribute("class", "migration-finished");
+ break;
+ case "Migration:Ended":
+ // We're done now.
+ this._wiz.canAdvance = true;
+ this._wiz.advance();
+
+ if (this._autoMigrate)
+ setTimeout(close, 5000);
+
+ break;
+ }
+ },
+
+ onDonePageShow: function() {
+ this._wiz.getButton("cancel").disabled = true;
+ this._wiz.canRewind = false;
+ this._listItems("doneItems");
+ },
+
+ targetHasHomePageURL: function() {
+ var targetPrefsFile = this._autoMigrate.directory;
+
+ targetPrefsFile.append("prefs.js");
+
+ // If the target prefs file doesn't exist, then we can't have a
+ // homepage set in the target profile.
+ if (!targetPrefsFile.exists())
+ return false;
+
+ Services.prefs.resetPrefs();
+
+ Services.prefs.readUserPrefsFromFile(targetPrefsFile);
+
+ return Services.prefs.prefHasUserValue("browser.startup.homepage");
+ }
+};
diff --git a/comm/suite/components/migration/content/migration.xul b/comm/suite/components/migration/content/migration.xul
new file mode 100644
index 0000000000..ad8b279361
--- /dev/null
+++ b/comm/suite/components/migration/content/migration.xul
@@ -0,0 +1,95 @@
+<?xml version="1.0"?>
+<!-- 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/. -->
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://communicator/locale/migration/migration.dtd" >
+
+<wizard id="migrationWizard"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="&migrationWizard.title;"
+ onload="MigrationWizard.init()"
+ onunload="MigrationWizard.uninit()"
+ style="width: 40em; height: 32em;"
+ branded="true"
+ buttons="accept,cancel"
+ xmlns:xhtml="http://www.w3.org/1999/xhtml">
+
+ <script src="chrome://communicator/content/migration/migration.js"/>
+
+ <stringbundle id="bundle"
+ src="chrome://communicator/locale/migration/migration.properties"/>
+
+ <wizardpage id="importSource" pageid="importSource" next="selectProfile"
+ label="&importSource.title;"
+ onpageadvanced="return MigrationWizard.onImportSourcePageAdvanced();">
+ <label id="importAll"
+ control="importSourceGroup">&importAllFrom.label;</label>
+ <label id="importBookmarks" control="importSourceGroup"
+ hidden="true">&importBookmarksFrom.label;</label>
+
+ <radiogroup id="importSourceGroup" align="start">
+ <radio id="thunderbird" label="&importFromThunderbird.label;"
+ accesskey="&importFromThunderbird.accesskey;"
+ value="thunderbird"/>
+ <!-- fromfile is used for bookmark importing -->
+ <radio id="fromFile" label="&importFromFile.label;" value="fromFile"
+ accesskey="&importFromFile.accesskey;" hidden="true"/>
+ <radio id="nothing" label="&importFromNothing.label;" value="nothing"
+ accesskey="&importFromNothing.accesskey;" hidden="true"/>
+ </radiogroup>
+ </wizardpage>
+
+ <wizardpage id="selectProfile" pageid="selectProfile"
+ label="&selectProfile.title;" next="importItems"
+ onpageshow="return MigrationWizard.onSelectProfilePageShow();"
+ onpageadvanced="return MigrationWizard.onSelectProfilePageAdvanced();">
+ <label control="profiles">&selectProfile.label;</label>
+
+ <radiogroup id="profiles" align="left"/>
+ </wizardpage>
+
+ <wizardpage id="importItems" pageid="importItems" label="&importItems.title;"
+ next="homePageImport"
+ onpageshow="return MigrationWizard.onImportItemsPageShow();"
+ onpageadvanced="return MigrationWizard.onImportItemsPageAdvanced();"
+ oncommand="MigrationWizard.onImportItemCommand();">
+ <label control="dataSources">&importItems.label;</label>
+
+ <vbox id="dataSources" style="overflow-y: auto;"
+ align="left" flex="1" role="group"/>
+ </wizardpage>
+
+ <wizardpage id="homePageImport" pageid="homePageImport"
+ next="migrating"
+ onpageshow="return MigrationWizard.onHomePageMigrationPageShow();"
+ onpageadvanced="return MigrationWizard.onHomePageMigrationPageAdvanced();">
+
+ <label id="homePageImportDesc" control="homePageRadioGroup"/>
+ <radiogroup id="homePageRadioGroup" align="start">
+ <radio id="oldHomePage" hidden="true"/>
+ <radio id="homePageStart" selected="true"/>
+ </radiogroup>
+ </wizardpage>
+
+ <wizardpage id="migrating" pageid="migrating" label="&migrating.title;"
+ next="done" onpageshow="MigrationWizard.onMigratingPageShow();">
+ <label control="migratingItems">&migrating.label;</label>
+
+ <vbox id="migratingItems" style="overflow-y: auto;" align="left" role="group"/>
+
+ <hbox>
+ <progressmeter class="progressmeter-statusbar" id="progressBar"
+ flex="1" mode="normal" value="0"/>
+ </hbox>
+ </wizardpage>
+
+ <wizardpage id="done" pageid="done" label="&done.title;"
+ onpageshow="MigrationWizard.onDonePageShow();">
+ <label control="doneItems">&done.label;</label>
+
+ <vbox id="doneItems" style="overflow-y: auto;" align="left" role="group"/>
+ </wizardpage>
+</wizard>