summaryrefslogtreecommitdiffstats
path: root/browser/components/migration/IEProfileMigrator.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/migration/IEProfileMigrator.js')
-rw-r--r--browser/components/migration/IEProfileMigrator.js542
1 files changed, 0 insertions, 542 deletions
diff --git a/browser/components/migration/IEProfileMigrator.js b/browser/components/migration/IEProfileMigrator.js
deleted file mode 100644
index ac055686c..000000000
--- a/browser/components/migration/IEProfileMigrator.js
+++ /dev/null
@@ -1,542 +0,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/. */
-
-"use strict";
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-const Cr = Components.results;
-
-const kLoginsKey = "Software\\Microsoft\\Internet Explorer\\IntelliForms\\Storage2";
-const kMainKey = "Software\\Microsoft\\Internet Explorer\\Main";
-
-Cu.import("resource://gre/modules/AppConstants.jsm");
-Cu.import("resource://gre/modules/osfile.jsm"); /* globals OS */
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource:///modules/MigrationUtils.jsm"); /* globals MigratorPrototype */
-Cu.import("resource:///modules/MSMigrationUtils.jsm");
-
-
-XPCOMUtils.defineLazyModuleGetter(this, "ctypes",
- "resource://gre/modules/ctypes.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
- "resource://gre/modules/PlacesUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "OSCrypto",
- "resource://gre/modules/OSCrypto.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "WindowsRegistry",
- "resource://gre/modules/WindowsRegistry.jsm");
-
-Cu.importGlobalProperties(["URL"]);
-
-// Resources
-
-function History() {
-}
-
-History.prototype = {
- type: MigrationUtils.resourceTypes.HISTORY,
-
- get exists() {
- return true;
- },
-
- migrate: function H_migrate(aCallback) {
- let places = [];
- let typedURLs = MSMigrationUtils.getTypedURLs("Software\\Microsoft\\Internet Explorer");
- let historyEnumerator = Cc["@mozilla.org/profile/migrator/iehistoryenumerator;1"].
- createInstance(Ci.nsISimpleEnumerator);
- while (historyEnumerator.hasMoreElements()) {
- let entry = historyEnumerator.getNext().QueryInterface(Ci.nsIPropertyBag2);
- let uri = entry.get("uri").QueryInterface(Ci.nsIURI);
- // MSIE stores some types of URLs in its history that we don't handle,
- // like HTMLHelp and others. Since we don't properly map handling for
- // all of them we just avoid importing them.
- if (["http", "https", "ftp", "file"].indexOf(uri.scheme) == -1) {
- continue;
- }
-
- let title = entry.get("title");
- // Embed visits have no title and don't need to be imported.
- if (title.length == 0) {
- continue;
- }
-
- // The typed urls are already fixed-up, so we can use them for comparison.
- let transitionType = typedURLs.has(uri.spec) ?
- Ci.nsINavHistoryService.TRANSITION_TYPED :
- Ci.nsINavHistoryService.TRANSITION_LINK;
- // use the current date if we have no visits for this entry.
- // Note that the entry will have a time in microseconds (PRTime),
- // and Date.now() returns milliseconds. Places expects PRTime,
- // so we multiply the Date.now return value to make up the difference.
- let lastVisitTime = entry.get("time") || (Date.now() * 1000);
-
- places.push(
- { uri: uri,
- title: title,
- visits: [{ transitionType: transitionType,
- visitDate: lastVisitTime }]
- }
- );
- }
-
- // Check whether there is any history to import.
- if (places.length == 0) {
- aCallback(true);
- return;
- }
-
- MigrationUtils.insertVisitsWrapper(places, {
- _success: false,
- handleResult: function() {
- // Importing any entry is considered a successful import.
- this._success = true;
- },
- handleError: function() {},
- handleCompletion: function() {
- aCallback(this._success);
- }
- });
- }
-};
-
-// IE form password migrator supporting windows from XP until 7 and IE from 7 until 11
-function IE7FormPasswords() {
- // used to distinguish between this migrator and other passwords migrators in tests.
- this.name = "IE7FormPasswords";
-}
-
-IE7FormPasswords.prototype = {
- type: MigrationUtils.resourceTypes.PASSWORDS,
-
- get exists() {
- // work only on windows until 7
- if (AppConstants.isPlatformAndVersionAtLeast("win", "6.2")) {
- return false;
- }
-
- try {
- let nsIWindowsRegKey = Ci.nsIWindowsRegKey;
- let key = Cc["@mozilla.org/windows-registry-key;1"].
- createInstance(nsIWindowsRegKey);
- key.open(nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, kLoginsKey,
- nsIWindowsRegKey.ACCESS_READ);
- let count = key.valueCount;
- key.close();
- return count > 0;
- } catch (e) {
- return false;
- }
- },
-
- migrate(aCallback) {
- let historyEnumerator = Cc["@mozilla.org/profile/migrator/iehistoryenumerator;1"].
- createInstance(Ci.nsISimpleEnumerator);
- let uris = []; // the uris of the websites that are going to be migrated
- while (historyEnumerator.hasMoreElements()) {
- let entry = historyEnumerator.getNext().QueryInterface(Ci.nsIPropertyBag2);
- let uri = entry.get("uri").QueryInterface(Ci.nsIURI);
- // MSIE stores some types of URLs in its history that we don't handle, like HTMLHelp
- // and others. Since we are not going to import the logins that are performed in these URLs
- // we can just skip them.
- if (["http", "https", "ftp"].indexOf(uri.scheme) == -1) {
- continue;
- }
-
- uris.push(uri);
- }
- this._migrateURIs(uris);
- aCallback(true);
- },
-
- /**
- * Migrate the logins that were saved for the uris arguments.
- * @param {nsIURI[]} uris - the uris that are going to be migrated.
- */
- _migrateURIs(uris) {
- this.ctypesKernelHelpers = new MSMigrationUtils.CtypesKernelHelpers();
- this._crypto = new OSCrypto();
- let nsIWindowsRegKey = Ci.nsIWindowsRegKey;
- let key = Cc["@mozilla.org/windows-registry-key;1"].
- createInstance(nsIWindowsRegKey);
- key.open(nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, kLoginsKey,
- nsIWindowsRegKey.ACCESS_READ);
-
- let urlsSet = new Set(); // set of the already processed urls.
- // number of the successfully decrypted registry values
- let successfullyDecryptedValues = 0;
- /* The logins are stored in the registry, where the key is a hashed URL and its
- * value contains the encrypted details for all logins for that URL.
- *
- * First iterate through IE history, hashing each URL and looking for a match. If
- * found, decrypt the value, using the URL as a salt. Finally add any found logins
- * to the Firefox password manager.
- */
-
- for (let uri of uris) {
- try {
- // remove the query and the ref parts of the URL
- let urlObject = new URL(uri.spec);
- let url = urlObject.origin + urlObject.pathname;
- // if the current url is already processed, it should be skipped
- if (urlsSet.has(url)) {
- continue;
- }
- urlsSet.add(url);
- // hash value of the current uri
- let hashStr = this._crypto.getIELoginHash(url);
- if (!key.hasValue(hashStr)) {
- continue;
- }
- let value = key.readBinaryValue(hashStr);
- // if no value was found, the uri is skipped
- if (value == null) {
- continue;
- }
- let data;
- try {
- // the url is used as salt to decrypt the registry value
- data = this._crypto.decryptData(value, url, true);
- } catch (e) {
- continue;
- }
- // extract the login details from the decrypted data
- let ieLogins = this._extractDetails(data, uri);
- // if at least a credential was found in the current data, successfullyDecryptedValues should
- // be incremented by one
- if (ieLogins.length) {
- successfullyDecryptedValues++;
- }
- this._addLogins(ieLogins);
- } catch (e) {
- Cu.reportError("Error while importing logins for " + uri.spec + ": " + e);
- }
- }
- // if the number of the imported values is less than the number of values in the key, it means
- // that not all the values were imported and an error should be reported
- if (successfullyDecryptedValues < key.valueCount) {
- Cu.reportError("We failed to decrypt and import some logins. " +
- "This is likely because we didn't find the URLs where these " +
- "passwords were submitted in the IE history and which are needed to be used " +
- "as keys in the decryption.");
- }
-
- key.close();
- this._crypto.finalize();
- this.ctypesKernelHelpers.finalize();
- },
-
- _crypto: null,
-
- /**
- * Add the logins to the password manager.
- * @param {Object[]} logins - array of the login details.
- */
- _addLogins(ieLogins) {
- for (let ieLogin of ieLogins) {
- try {
- // create a new login
- let login = {
- username: ieLogin.username,
- password: ieLogin.password,
- hostname: ieLogin.url,
- timeCreated: ieLogin.creation,
- };
- MigrationUtils.insertLoginWrapper(login);
- } catch (e) {
- Cu.reportError(e);
- }
- }
- },
-
- /**
- * Extract the details of one or more logins from the raw decrypted data.
- * @param {string} data - the decrypted data containing raw information.
- * @param {nsURI} uri - the nsURI of page where the login has occur.
- * @returns {Object[]} array of objects where each of them contains the username, password, URL,
- * and creation time representing all the logins found in the data arguments.
- */
- _extractDetails(data, uri) {
- // the structure of the header of the IE7 decrypted data for all the logins sharing the same URL
- let loginData = new ctypes.StructType("loginData", [
- // Bytes 0-3 are not needed and not documented
- {"unknown1": ctypes.uint32_t},
- // Bytes 4-7 are the header size
- {"headerSize": ctypes.uint32_t},
- // Bytes 8-11 are the data size
- {"dataSize": ctypes.uint32_t},
- // Bytes 12-19 are not needed and not documented
- {"unknown2": ctypes.uint32_t},
- {"unknown3": ctypes.uint32_t},
- // Bytes 20-23 are the data count: each username and password is considered as a data
- {"dataMax": ctypes.uint32_t},
- // Bytes 24-35 are not needed and not documented
- {"unknown4": ctypes.uint32_t},
- {"unknown5": ctypes.uint32_t},
- {"unknown6": ctypes.uint32_t}
- ]);
-
- // the structure of a IE7 decrypted login item
- let loginItem = new ctypes.StructType("loginItem", [
- // Bytes 0-3 are the offset of the username
- {"usernameOffset": ctypes.uint32_t},
- // Bytes 4-11 are the date
- {"loDateTime": ctypes.uint32_t},
- {"hiDateTime": ctypes.uint32_t},
- // Bytes 12-15 are not needed and not documented
- {"foo": ctypes.uint32_t},
- // Bytes 16-19 are the offset of the password
- {"passwordOffset": ctypes.uint32_t},
- // Bytes 20-31 are not needed and not documented
- {"unknown1": ctypes.uint32_t},
- {"unknown2": ctypes.uint32_t},
- {"unknown3": ctypes.uint32_t}
- ]);
-
- let url = uri.prePath;
- let results = [];
- let arr = this._crypto.stringToArray(data);
- // convert data to ctypes.unsigned_char.array(arr.length)
- let cdata = ctypes.unsigned_char.array(arr.length)(arr);
- // Bytes 0-35 contain the loginData data structure for all the logins sharing the same URL
- let currentLoginData = ctypes.cast(cdata, loginData);
- let headerSize = currentLoginData.headerSize;
- let currentInfoIndex = loginData.size;
- // pointer to the current login item
- let currentLoginItemPointer = ctypes.cast(cdata.addressOfElement(currentInfoIndex),
- loginItem.ptr);
- // currentLoginData.dataMax is the data count: each username and password is considered as
- // a data. So, the number of logins is the number of data dived by 2
- let numLogins = currentLoginData.dataMax / 2;
- for (let n = 0; n < numLogins; n++) {
- // Bytes 0-31 starting from currentInfoIndex contain the loginItem data structure for the
- // current login
- let currentLoginItem = currentLoginItemPointer.contents;
- let creation = this.ctypesKernelHelpers.
- fileTimeToSecondsSinceEpoch(currentLoginItem.hiDateTime,
- currentLoginItem.loDateTime) * 1000;
- let currentResult = {
- creation: creation,
- url: url,
- };
- // The username is UTF-16 and null-terminated.
- currentResult.username =
- ctypes.cast(cdata.addressOfElement(headerSize + 12 + currentLoginItem.usernameOffset),
- ctypes.char16_t.ptr).readString();
- // The password is UTF-16 and null-terminated.
- currentResult.password =
- ctypes.cast(cdata.addressOfElement(headerSize + 12 + currentLoginItem.passwordOffset),
- ctypes.char16_t.ptr).readString();
- results.push(currentResult);
- // move to the next login item
- currentLoginItemPointer = currentLoginItemPointer.increment();
- }
- return results;
- },
-};
-
-function Settings() {
-}
-
-Settings.prototype = {
- type: MigrationUtils.resourceTypes.SETTINGS,
-
- get exists() {
- return true;
- },
-
- migrate: function S_migrate(aCallback) {
- // Converts from yes/no to a boolean.
- let yesNoToBoolean = v => v == "yes";
-
- // Converts source format like "en-us,ar-kw;q=0.7,ar-om;q=0.3" into
- // destination format like "en-us, ar-kw, ar-om".
- // Final string is sorted by quality (q=) param.
- function parseAcceptLanguageList(v) {
- return v.match(/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/gi)
- .sort(function(a, b) {
- let qA = parseFloat(a.split(";q=")[1]) || 1.0;
- let qB = parseFloat(b.split(";q=")[1]) || 1.0;
- return qB - qA;
- })
- .map(a => a.split(";")[0]);
- }
-
- // For reference on some of the available IE Registry settings:
- // * http://msdn.microsoft.com/en-us/library/cc980058%28v=prot.13%29.aspx
- // * http://msdn.microsoft.com/en-us/library/cc980059%28v=prot.13%29.aspx
-
- // Note that only settings exposed in our UI should be migrated.
-
- this._set("Software\\Microsoft\\Internet Explorer\\International",
- "AcceptLanguage",
- "intl.accept_languages",
- parseAcceptLanguageList);
- // TODO (bug 745853): For now, only x-western font is translated.
- this._set("Software\\Microsoft\\Internet Explorer\\International\\Scripts\\3",
- "IEFixedFontName",
- "font.name.monospace.x-western");
- this._set(kMainKey,
- "Use FormSuggest",
- "browser.formfill.enable",
- yesNoToBoolean);
- this._set(kMainKey,
- "FormSuggest Passwords",
- "signon.rememberSignons",
- yesNoToBoolean);
- this._set(kMainKey,
- "Anchor Underline",
- "browser.underline_anchors",
- yesNoToBoolean);
- this._set(kMainKey,
- "Display Inline Images",
- "permissions.default.image",
- v => yesNoToBoolean(v) ? 1 : 2);
- this._set(kMainKey,
- "Move System Caret",
- "accessibility.browsewithcaret",
- yesNoToBoolean);
- this._set("Software\\Microsoft\\Internet Explorer\\Settings",
- "Always Use My Colors",
- "browser.display.document_color_use",
- v => (!v ? 0 : 2));
- this._set("Software\\Microsoft\\Internet Explorer\\Settings",
- "Always Use My Font Face",
- "browser.display.use_document_fonts",
- v => !v);
- this._set(kMainKey,
- "SmoothScroll",
- "general.smoothScroll",
- Boolean);
- this._set("Software\\Microsoft\\Internet Explorer\\TabbedBrowsing\\",
- "WarnOnClose",
- "browser.tabs.warnOnClose",
- Boolean);
- this._set("Software\\Microsoft\\Internet Explorer\\TabbedBrowsing\\",
- "OpenInForeground",
- "browser.tabs.loadInBackground",
- v => !v);
-
- aCallback(true);
- },
-
- /**
- * Reads a setting from the Registry and stores the converted result into
- * the appropriate Firefox preference.
- *
- * @param aPath
- * Registry path under HKCU.
- * @param aKey
- * Name of the key.
- * @param aPref
- * Firefox preference.
- * @param [optional] aTransformFn
- * Conversion function from the Registry format to the pref format.
- */
- _set: function S__set(aPath, aKey, aPref, aTransformFn) {
- let value = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
- aPath, aKey);
- // Don't import settings that have never been flipped.
- if (value === undefined)
- return;
-
- if (aTransformFn)
- value = aTransformFn(value);
-
- switch (typeof value) {
- case "string":
- Services.prefs.setCharPref(aPref, value);
- break;
- case "number":
- Services.prefs.setIntPref(aPref, value);
- break;
- case "boolean":
- Services.prefs.setBoolPref(aPref, value);
- break;
- default:
- throw new Error("Unexpected value type: " + (typeof value));
- }
- }
-};
-
-function IEProfileMigrator()
-{
- this.wrappedJSObject = this; // export this to be able to use it in the unittest.
-}
-
-IEProfileMigrator.prototype = Object.create(MigratorPrototype);
-
-IEProfileMigrator.prototype.getResources = function IE_getResources() {
- let resources = [
- MSMigrationUtils.getBookmarksMigrator(),
- new History(),
- MSMigrationUtils.getCookiesMigrator(),
- new Settings(),
- ];
- // Only support the form password migrator for Windows XP to 7.
- if (AppConstants.isPlatformAndVersionAtMost("win", "6.1")) {
- resources.push(new IE7FormPasswords());
- }
- let windowsVaultFormPasswordsMigrator =
- MSMigrationUtils.getWindowsVaultFormPasswordsMigrator();
- windowsVaultFormPasswordsMigrator.name = "IEVaultFormPasswords";
- resources.push(windowsVaultFormPasswordsMigrator);
- return resources.filter(r => r.exists);
-};
-
-IEProfileMigrator.prototype.getLastUsedDate = function IE_getLastUsedDate() {
- let datePromises = ["Favs", "CookD"].map(dirId => {
- let {path} = Services.dirsvc.get(dirId, Ci.nsIFile);
- return OS.File.stat(path).catch(() => null).then(info => {
- return info ? info.lastModificationDate : 0;
- });
- });
- datePromises.push(new Promise(resolve => {
- let typedURLs = new Map();
- try {
- typedURLs = MSMigrationUtils.getTypedURLs("Software\\Microsoft\\Internet Explorer");
- } catch (ex) {}
- let dates = [0, ... typedURLs.values()];
- resolve(Math.max.apply(Math, dates));
- }));
- return Promise.all(datePromises).then(dates => {
- return new Date(Math.max.apply(Math, dates));
- });
-};
-
-Object.defineProperty(IEProfileMigrator.prototype, "sourceHomePageURL", {
- get: function IE_get_sourceHomePageURL() {
- let defaultStartPage = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
- kMainKey, "Default_Page_URL");
- let startPage = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
- kMainKey, "Start Page");
- // If the user didn't customize the Start Page, he is still on the default
- // page, that may be considered the equivalent of our about:home. There's
- // no reason to retain it, since it is heavily targeted to IE.
- let homepage = startPage != defaultStartPage ? startPage : "";
-
- // IE7+ supports secondary home pages located in a REG_MULTI_SZ key. These
- // are in addition to the Start Page, and no empty entries are possible,
- // thus a Start Page is always defined if any of these exists, though it
- // may be the default one.
- let secondaryPages = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
- kMainKey, "Secondary Start Pages");
- if (secondaryPages) {
- if (homepage)
- secondaryPages.unshift(homepage);
- homepage = secondaryPages.join("|");
- }
-
- return homepage;
- }
-});
-
-IEProfileMigrator.prototype.classDescription = "IE Profile Migrator";
-IEProfileMigrator.prototype.contractID = "@mozilla.org/profile/migrator;1?app=browser&type=ie";
-IEProfileMigrator.prototype.classID = Components.ID("{3d2532e3-4932-4774-b7ba-968f5899d3a4}");
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([IEProfileMigrator]);