migration.js
Go to the documentation of this file.
1 # ***** BEGIN LICENSE BLOCK *****
2 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 #
4 # The contents of this file are subject to the Mozilla Public License Version
5 # 1.1 (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 # http://www.mozilla.org/MPL/
8 #
9 # Software distributed under the License is distributed on an "AS IS" basis,
10 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 # for the specific language governing rights and limitations under the
12 # License.
13 #
14 # The Original Code is The Browser Profile Migrator.
15 #
16 # The Initial Developer of the Original Code is Ben Goodger.
17 # Portions created by the Initial Developer are Copyright (C) 2004
18 # the Initial Developer. All Rights Reserved.
19 #
20 # Contributor(s):
21 # Ben Goodger <ben@bengoodger.com>
22 #
23 # Alternatively, the contents of this file may be used under the terms of
24 # either the GNU General Public License Version 2 or later (the "GPL"), or
25 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 # in which case the provisions of the GPL or the LGPL are applicable instead
27 # of those above. If you wish to allow use of your version of this file only
28 # under the terms of either the GPL or the LGPL, and not to allow others to
29 # use your version of this file under the terms of the MPL, indicate your
30 # decision by deleting the provisions above and replace them with the notice
31 # and other provisions required by the GPL or the LGPL. If you do not delete
32 # the provisions above, a recipient may use your version of this file under
33 # the terms of any one of the MPL, the GPL or the LGPL.
34 #
35 # ***** END LICENSE BLOCK *****
36 
37 const kIMig = Components.interfaces.nsIBrowserProfileMigrator;
38 const kIPStartup = Components.interfaces.nsIProfileStartup;
39 const kProfileMigratorContractIDPrefix = "@mozilla.org/profile/migrator;1?app=browser&type=";
40 
42  _source: "", // Source Profile Migrator ContractID suffix
43  _itemsFlags: kIMig.ALL, // Selected Import Data Sources (16-bit bitfield)
44  _selectedProfile: null, // Selected Profile name to import from
45  _wiz: null,
46  _migrator: null,
47  _autoMigrate: null,
48  _bookmarks: false,
49 
50  init: function ()
51  {
52  var os = Components.classes["@mozilla.org/observer-service;1"]
53  .getService(Components.interfaces.nsIObserverService);
54  os.addObserver(this, "Migration:Started", false);
55  os.addObserver(this, "Migration:ItemBeforeMigrate", false);
56  os.addObserver(this, "Migration:ItemAfterMigrate", false);
57  os.addObserver(this, "Migration:Ended", false);
58 
59  this._wiz = document.documentElement;
60 
61  if ("arguments" in window && window.arguments.length > 1) {
62  this._source = window.arguments[0];
63  this._migrator = window.arguments[1].QueryInterface(kIMig);
64  this._autoMigrate = window.arguments[2].QueryInterface(kIPStartup);
65 
66  if (this._autoMigrate) {
67  // Show the "nothing" option in the automigrate case to provide an
68  // easily identifiable way to avoid migration and create a new profile.
69  var nothing = document.getElementById("nothing");
70  nothing.hidden = false;
71  }
72  }
73 
74  this.onImportSourcePageShow();
75  },
76 
77  uninit: function ()
78  {
79  var os = Components.classes["@mozilla.org/observer-service;1"]
80  .getService(Components.interfaces.nsIObserverService);
81  os.removeObserver(this, "Migration:Started");
82  os.removeObserver(this, "Migration:ItemBeforeMigrate");
83  os.removeObserver(this, "Migration:ItemAfterMigrate");
84  os.removeObserver(this, "Migration:Ended");
85  },
86 
87  // 1 - Import Source
88  onImportSourcePageShow: function ()
89  {
90  // Reference to the "From File" radio button
91  var fromfile = null;
92 
93  //XXXquark This function is called before init, so check for bookmarks here
94  if ("arguments" in window && window.arguments[0] == "bookmarks") {
95  this._bookmarks = true;
96 
97  fromfile = document.getElementById("fromfile");
98  fromfile.hidden = false;
99 
100  var importBookmarks = document.getElementById("importBookmarks");
101  importBookmarks.hidden = false;
102 
103  var importAll = document.getElementById("importAll");
104  importAll.hidden = true;
105  }
106 
107  this._wiz.canRewind = false;
108 
109  // The migrator to select. If the "fromfile" migrator is available, use it
110  // as the default in case we have no other migrators.
111  var selectedMigrator = fromfile;
112 
113  // Figure out what source apps are are available to import from:
114  var group = document.getElementById("importSourceGroup");
115  for (var i = 0; i < group.childNodes.length; ++i) {
116  var suffix = group.childNodes[i].id;
117  if (suffix != "nothing" && suffix != "fromfile") {
119  try {
120  var migrator = Components.classes[contractID].createInstance(kIMig);
121  }
122  catch (e) {
123  dump("*** invalid contractID =" + contractID + "\n");
124  return;
125  }
126 
127  if (migrator.sourceExists &&
128  !(suffix == "phoenix" && !this._autoMigrate)) {
129  // Save this as the first selectable item, if we don't already have
130  // one, or if it is the migrator that was passed to us.
131  if (!selectedMigrator || this._source == suffix)
132  selectedMigrator = group.childNodes[i];
133  } else {
134  // Hide this option
135  group.childNodes[i].hidden = true;
136  }
137  }
138  }
139 
140  if (selectedMigrator)
141  group.selectedItem = selectedMigrator;
142  else {
143  // We didn't find a migrator, notify the user
144  document.getElementById("noSources").hidden = false;
145 
146  this._wiz.canAdvance = false;
147 
148  document.getElementById("importBookmarks").hidden = true;
149  document.getElementById("importAll").hidden = true;
150  }
151  },
152 
153  onImportSourcePageAdvanced: function ()
154  {
155  var newSource = document.getElementById("importSourceGroup").selectedItem.id;
156 
157  if (newSource == "nothing" || newSource == "fromfile") {
158  if(newSource == "fromfile")
159  window.opener.fromFile = true;
160  document.documentElement.cancel();
161  return false;
162  }
163 
164  if (!this._migrator || (newSource != this._source)) {
165  // Create the migrator for the selected source.
167  this._migrator = Components.classes[contractID].createInstance(kIMig);
168 
169  this._itemsFlags = kIMig.ALL;
170  this._selectedProfile = null;
171  }
172  this._source = newSource;
173 
174  // check for more than one source profile
175  if (this._migrator.sourceHasMultipleProfiles)
176  this._wiz.currentPage.next = "selectProfile";
177  else {
178  if (this._autoMigrate)
179  this._wiz.currentPage.next = "homePageImport";
180  else if (this._bookmarks)
181  this._wiz.currentPage.next = "migrating"
182  else
183  this._wiz.currentPage.next = "importItems";
184 
185  var sourceProfiles = this._migrator.sourceProfiles;
186  if (sourceProfiles && sourceProfiles.Count() == 1) {
187  var profileName = sourceProfiles.QueryElementAt(0, Components.interfaces.nsISupportsString);
188  this._selectedProfile = profileName.data;
189  }
190  else
191  this._selectedProfile = "";
192  }
193  },
194 
195  // 2 - [Profile Selection]
196  onSelectProfilePageShow: function ()
197  {
198  // Disabling this for now, since we ask about import sources in automigration
199  // too and don't want to disable the back button
200  // if (this._autoMigrate)
201  // document.documentElement.getButton("back").disabled = true;
202 
203  var profiles = document.getElementById("profiles");
204  while (profiles.hasChildNodes())
205  profiles.removeChild(profiles.firstChild);
206 
207  // Note that this block is still reached even if the user chose 'From File'
208  // and we canceled the dialog. When that happens, _migrator will be null.
209  if (this._migrator) {
210  var sourceProfiles = this._migrator.sourceProfiles;
211  var count = sourceProfiles.Count();
212  for (var i = 0; i < count; ++i) {
213  var item = document.createElement("radio");
214  var str = sourceProfiles.QueryElementAt(i, Components.interfaces.nsISupportsString);
215  item.id = str.data;
216  item.setAttribute("label", str.data);
217  profiles.appendChild(item);
218  }
219  }
220 
221  profiles.selectedItem = this._selectedProfile ? document.getElementById(this._selectedProfile) : profiles.firstChild;
222  },
223 
224  onSelectProfilePageRewound: function ()
225  {
226  var profiles = document.getElementById("profiles");
227  this._selectedProfile = profiles.selectedItem.id;
228  },
229 
230  onSelectProfilePageAdvanced: function ()
231  {
232  var profiles = document.getElementById("profiles");
233  this._selectedProfile = profiles.selectedItem.id;
234 
235  // If we're automigrating or just doing bookmarks don't show the item selection page
236  if (this._autoMigrate)
237  this._wiz.currentPage.next = "homePageImport";
238  else if (this._bookmarks)
239  this._wiz.currentPage.next = "migrating"
240  },
241 
242  // 3 - ImportItems
243  onImportItemsPageShow: function ()
244  {
245  var dataSources = document.getElementById("dataSources");
246  while (dataSources.hasChildNodes())
247  dataSources.removeChild(dataSources.firstChild);
248 
249  var bundle = document.getElementById("bundle");
250 
251  var items = this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate);
252  for (var i = 0; i < 16; ++i) {
253  var itemID = (items >> i) & 0x1 ? Math.pow(2, i) : 0;
254  if (itemID > 0) {
255  var checkbox = document.createElement("checkbox");
256  checkbox.id = itemID;
257  checkbox.setAttribute("label", bundle.getString(itemID + "_" + this._source));
258  dataSources.appendChild(checkbox);
259  if (!this._itemsFlags || this._itemsFlags & itemID)
260  checkbox.checked = true;
261  }
262  }
263  },
264 
265  onImportItemsPageRewound: function ()
266  {
267  this._wiz.canAdvance = true;
268  this.onImportItemsPageAdvanced();
269  },
270 
271  onImportItemsPageAdvanced: function ()
272  {
273  var dataSources = document.getElementById("dataSources");
274  this._itemsFlags = 0;
275  for (var i = 0; i < dataSources.childNodes.length; ++i) {
276  var checkbox = dataSources.childNodes[i];
277  if (checkbox.localName == "checkbox" && checkbox.checked)
278  this._itemsFlags |= parseInt(checkbox.id);
279  }
280  },
281 
282  onImportItemCommand: function (aEvent)
283  {
284  var items = document.getElementById("dataSources");
285  var checkboxes = items.getElementsByTagName("checkbox");
286 
287  var oneChecked = false;
288  for (var i = 0; i < checkboxes.length; ++i) {
289  if (checkboxes[i].checked) {
290  oneChecked = true;
291  break;
292  }
293  }
294 
295  this._wiz.canAdvance = oneChecked;
296  },
297 
298  // 4 - Home Page Selection
299  onHomePageMigrationPageShow: function ()
300  {
301  // only want this on the first run
302  if (!this._autoMigrate) {
303  this._wiz.advance();
304  return;
305  }
306 
307  var bundle = document.getElementById("brandBundle");
308  // These strings don't exist when not using official branding. If that's
309  // the case, just skip this page.
310  try {
311  var pageTitle = bundle.getString("homePageMigrationPageTitle");
312  var pageDesc = bundle.getString("homePageMigrationDescription");
313  var mainStr = bundle.getString("homePageSingleStartMain");
314  }
315  catch (e) {
316  this._wiz.advance();
317  return;
318  }
319 
320  document.getElementById("homePageImport").setAttribute("label", pageTitle);
321  document.getElementById("homePageImportDesc").setAttribute("value", pageDesc);
322 
323  this._wiz._adjustWizardHeader();
324 
325  var singleStart = document.getElementById("homePageSingleStart");
326  singleStart.setAttribute("label", mainStr);
327  singleStart.setAttribute("value", "DEFAULT");
328 
329  var source = null;
330  switch (this._source) {
331  case "ie":
332  case "macie":
333  source = "sourceNameIE";
334  break;
335  case "opera":
336  source = "sourceNameOpera";
337  break;
338  case "dogbert":
339  source = "sourceNameDogbert";
340  break;
341  case "safari":
342  source = "sourceNameSafari";
343  break;
344  case "seamonkey":
345  source = "sourceNameSeamonkey";
346  break;
347  }
348 
349  // semi-wallpaper for crash when multiple profiles exist, since we haven't initialized mSourceProfile in places
350  this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate);
351 
352  var oldHomePageURL = this._migrator.sourceHomePageURL;
353 
354  if (oldHomePageURL && source) {
355  var bundle2 = document.getElementById("bundle");
356  var appName = bundle2.getString(source);
357  var oldHomePageLabel = bundle.getFormattedString("homePageImport",
358  [appName]);
359  var oldHomePage = document.getElementById("oldHomePage");
360  oldHomePage.setAttribute("label", oldHomePageLabel);
361  oldHomePage.setAttribute("value", oldHomePageURL);
362  oldHomePage.removeAttribute("hidden");
363  }
364  else {
365  // if we don't have at least two options, just advance
366  this._wiz.advance();
367  }
368  },
369 
370  onHomePageMigrationPageAdvanced: function ()
371  {
372  // we might not have a selectedItem if we're in fallback mode
373  try {
374  var radioGroup = document.getElementById("homePageRadiogroup");
375 
376  this._newHomePage = radioGroup.selectedItem.value;
377  } catch(ex) {}
378  },
379 
380  // 5 - Migrating
381  onMigratingPageShow: function ()
382  {
383  this._wiz.getButton("cancel").disabled = true;
384  this._wiz.canRewind = false;
385  this._wiz.canAdvance = false;
386 
387  // When automigrating, show all of the data that can be received from this source.
388  if (this._autoMigrate)
389  this._itemsFlags = this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate);
390 
391  // When importing bookmarks, show only bookmarks
392  if (this._bookmarks)
393  this._itemsFlags = 32;
394 
395  this._listItems("migratingItems");
396  setTimeout(this.onMigratingMigrate, 0, this);
397  },
398 
399  onMigratingMigrate: function (aOuter)
400  {
401  aOuter._migrator.migrate(aOuter._itemsFlags, aOuter._autoMigrate, aOuter._selectedProfile);
402  },
403 
404  _listItems: function (aID)
405  {
406  var items = document.getElementById(aID);
407  while (items.hasChildNodes())
408  items.removeChild(items.firstChild);
409 
410  var bundle = document.getElementById("bundle");
411  var brandBundle = document.getElementById("brandBundle");
412  var itemID;
413  for (var i = 0; i < 16; ++i) {
414  var itemID = (this._itemsFlags >> i) & 0x1 ? Math.pow(2, i) : 0;
415  if (itemID > 0) {
416  var label = document.createElement("label");
417  label.id = itemID + "_migrated";
418  try {
419  label.setAttribute("value", bundle.getString(itemID + "_" + this._source));
420  items.appendChild(label);
421  }
422  catch (e) {
423  // if the block above throws, we've enumerated all the import data types we
424  // currently support and are now just wasting time, break.
425  break;
426  }
427  }
428  }
429  },
430 
431  observe: function (aSubject, aTopic, aData)
432  {
433  switch (aTopic) {
434  case "Migration:Started":
435  break;
436  case "Migration:ItemBeforeMigrate":
437  var label = document.getElementById(aData + "_migrated");
438  if (label)
439  label.setAttribute("style", "font-weight: bold");
440  break;
441  case "Migration:ItemAfterMigrate":
442  var label = document.getElementById(aData + "_migrated");
443  if (label)
444  label.removeAttribute("style");
445  break;
446  case "Migration:Ended":
447  if (this._autoMigrate) {
448  if (this._newHomePage) {
449  try {
450  // set homepage properly
451  var prefSvc = Components.classes["@mozilla.org/preferences-service;1"]
452  .getService(Components.interfaces.nsIPrefService);
453  var prefBranch = prefSvc.getBranch(null);
454 
455  if (this._newHomePage == "DEFAULT") {
456  try {
457  prefBranch.clearUserPref("browser.startup.homepage");
458  }
459  catch (e) { }
460  }
461  else {
462  var str = Components.classes["@mozilla.org/supports-string;1"]
463  .createInstance(Components.interfaces.nsISupportsString);
464  str.data = this._newHomePage;
465  prefBranch.setComplexValue("browser.startup.homepage",
466  Components.interfaces.nsISupportsString,
467  str);
468  }
469 
470  var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
471  .getService(Components.interfaces.nsIProperties);
472  var prefFile = dirSvc.get("ProfDS", Components.interfaces.nsIFile);
473  prefFile.append("prefs.js");
474  prefSvc.savePrefFile(prefFile);
475  } catch(ex) {
476  dump(ex);
477  }
478  }
479 
480  // We're done now.
481  this._wiz.canAdvance = true;
482  this._wiz.advance();
483 
484  setTimeout(close, 5000);
485  }
486  else {
487  this._wiz.canAdvance = true;
488  var nextButton = this._wiz.getButton("next");
489  nextButton.click();
490  }
491  break;
492  }
493  },
494 
495  onDonePageShow: function ()
496  {
497  this._wiz.getButton("cancel").disabled = true;
498  this._wiz.canRewind = false;
499  this._listItems("doneItems");
500  }
501 };
let prefSvc
var dirSvc
sbDeviceFirmwareAutoCheckForUpdate prototype contractID
var MigrationWizard
Definition: migration.js:41
const kIMig
Definition: migration.js:37
let window
_window init
Definition: FeedWriter.js:1144
this _contentSandbox label
Definition: FeedWriter.js:814
var bundle
var count
Definition: test_bug7406.js:32
aWindow setTimeout(function(){_this.restoreHistory(aWindow, aTabs, aTabData, aIdMap);}, 0)
const kProfileMigratorContractIDPrefix
Definition: migration.js:39
return null
Definition: FeedWriter.js:1143
var os
function uninit(aEvent)
Definition: aboutDialog.js:89
_getSelectedPageStyle s i
var brandBundle
Definition: xpInstallHat.js:37
var group
_updateTextAndScrollDataForFrame aData
sbDeviceFirmwareAutoCheckForUpdate prototype observe
const kIPStartup
Definition: migration.js:38