summaryrefslogtreecommitdiffstats
path: root/application/basilisk/components/migration/MSMigrationUtils.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'application/basilisk/components/migration/MSMigrationUtils.jsm')
-rw-r--r--application/basilisk/components/migration/MSMigrationUtils.jsm889
1 files changed, 0 insertions, 889 deletions
diff --git a/application/basilisk/components/migration/MSMigrationUtils.jsm b/application/basilisk/components/migration/MSMigrationUtils.jsm
deleted file mode 100644
index 1e0250b06..000000000
--- a/application/basilisk/components/migration/MSMigrationUtils.jsm
+++ /dev/null
@@ -1,889 +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";
-
-this.EXPORTED_SYMBOLS = ["MSMigrationUtils"];
-
-const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
-
-Cu.import("resource://gre/modules/AppConstants.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
-Cu.import("resource:///modules/MigrationUtils.jsm");
-
-Cu.importGlobalProperties(["FileReader"]);
-
-XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
- "resource://gre/modules/PlacesUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "WindowsRegistry",
- "resource://gre/modules/WindowsRegistry.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "ctypes",
- "resource://gre/modules/ctypes.jsm");
-
-const EDGE_COOKIE_PATH_OPTIONS = ["", "#!001\\", "#!002\\"];
-const EDGE_COOKIES_SUFFIX = "MicrosoftEdge\\Cookies";
-const EDGE_FAVORITES = "AC\\MicrosoftEdge\\User\\Default\\Favorites";
-const FREE_CLOSE_FAILED = 0;
-const INTERNET_EXPLORER_EDGE_GUID = [0x3CCD5499,
- 0x4B1087A8,
- 0x886015A2,
- 0x553BDD88];
-const RESULT_SUCCESS = 0;
-const VAULT_ENUMERATE_ALL_ITEMS = 512;
-const WEB_CREDENTIALS_VAULT_ID = [0x4BF4C442,
- 0x41A09B8A,
- 0x4ADD80B3,
- 0x28DB4D70];
-
-Cu.importGlobalProperties(["File"]);
-
-const wintypes = {
- BOOL: ctypes.int,
- DWORD: ctypes.uint32_t,
- DWORDLONG: ctypes.uint64_t,
- CHAR: ctypes.char,
- PCHAR: ctypes.char.ptr,
- LPCWSTR: ctypes.char16_t.ptr,
- PDWORD: ctypes.uint32_t.ptr,
- VOIDP: ctypes.voidptr_t,
- WORD: ctypes.uint16_t,
-};
-
-// TODO: Bug 1202978 - Refactor MSMigrationUtils ctypes helpers
-function CtypesKernelHelpers() {
- this._structs = {};
- this._functions = {};
- this._libs = {};
-
- this._structs.SYSTEMTIME = new ctypes.StructType("SYSTEMTIME", [
- {wYear: wintypes.WORD},
- {wMonth: wintypes.WORD},
- {wDayOfWeek: wintypes.WORD},
- {wDay: wintypes.WORD},
- {wHour: wintypes.WORD},
- {wMinute: wintypes.WORD},
- {wSecond: wintypes.WORD},
- {wMilliseconds: wintypes.WORD}
- ]);
-
- this._structs.FILETIME = new ctypes.StructType("FILETIME", [
- {dwLowDateTime: wintypes.DWORD},
- {dwHighDateTime: wintypes.DWORD}
- ]);
-
- try {
- this._libs.kernel32 = ctypes.open("Kernel32");
-
- this._functions.FileTimeToSystemTime =
- this._libs.kernel32.declare("FileTimeToSystemTime",
- ctypes.default_abi,
- wintypes.BOOL,
- this._structs.FILETIME.ptr,
- this._structs.SYSTEMTIME.ptr);
- } catch (ex) {
- this.finalize();
- }
-}
-
-CtypesKernelHelpers.prototype = {
- /**
- * Must be invoked once after last use of any of the provided helpers.
- */
- finalize() {
- this._structs = {};
- this._functions = {};
- for (let key in this._libs) {
- let lib = this._libs[key];
- try {
- lib.close();
- } catch (ex) {}
- }
- this._libs = {};
- },
-
- /**
- * Converts a FILETIME struct (2 DWORDS), to a SYSTEMTIME struct,
- * and then deduces the number of seconds since the epoch (which
- * is the data we want for the cookie expiry date).
- *
- * @param aTimeHi
- * Least significant DWORD.
- * @param aTimeLo
- * Most significant DWORD.
- * @return the number of seconds since the epoch
- */
- fileTimeToSecondsSinceEpoch(aTimeHi, aTimeLo) {
- let fileTime = this._structs.FILETIME();
- fileTime.dwLowDateTime = aTimeLo;
- fileTime.dwHighDateTime = aTimeHi;
- let systemTime = this._structs.SYSTEMTIME();
- let result = this._functions.FileTimeToSystemTime(fileTime.address(),
- systemTime.address());
- if (result == 0)
- throw new Error(ctypes.winLastError);
-
- // System time is in UTC, so we use Date.UTC to get milliseconds from epoch,
- // then divide by 1000 to get seconds, and round down:
- return Math.floor(Date.UTC(systemTime.wYear,
- systemTime.wMonth - 1,
- systemTime.wDay,
- systemTime.wHour,
- systemTime.wMinute,
- systemTime.wSecond,
- systemTime.wMilliseconds) / 1000);
- }
-};
-
-function CtypesVaultHelpers() {
- this._structs = {};
- this._functions = {};
-
- this._structs.GUID = new ctypes.StructType("GUID", [
- {id: wintypes.DWORD.array(4)},
- ]);
-
- this._structs.VAULT_ITEM_ELEMENT = new ctypes.StructType("VAULT_ITEM_ELEMENT", [
- // not documented
- {schemaElementId: wintypes.DWORD},
- // not documented
- {unknown1: wintypes.DWORD},
- // vault type
- {type: wintypes.DWORD},
- // not documented
- {unknown2: wintypes.DWORD},
- // value of the item
- {itemValue: wintypes.LPCWSTR},
- // not documented
- {unknown3: wintypes.CHAR.array(12)},
- ]);
-
- this._structs.VAULT_ELEMENT = new ctypes.StructType("VAULT_ELEMENT", [
- // vault item schemaId
- {schemaId: this._structs.GUID},
- // a pointer to the name of the browser VAULT_ITEM_ELEMENT
- {pszCredentialFriendlyName: wintypes.LPCWSTR},
- // a pointer to the url VAULT_ITEM_ELEMENT
- {pResourceElement: this._structs.VAULT_ITEM_ELEMENT.ptr},
- // a pointer to the username VAULT_ITEM_ELEMENT
- {pIdentityElement: this._structs.VAULT_ITEM_ELEMENT.ptr},
- // not documented
- {pAuthenticatorElement: this._structs.VAULT_ITEM_ELEMENT.ptr},
- // not documented
- {pPackageSid: this._structs.VAULT_ITEM_ELEMENT.ptr},
- // time stamp in local format
- {lowLastModified: wintypes.DWORD},
- {highLastModified: wintypes.DWORD},
- // not documented
- {flags: wintypes.DWORD},
- // not documented
- {dwPropertiesCount: wintypes.DWORD},
- // not documented
- {pPropertyElements: this._structs.VAULT_ITEM_ELEMENT.ptr},
- ]);
-
- try {
- this._vaultcliLib = ctypes.open("vaultcli.dll");
-
- this._functions.VaultOpenVault =
- this._vaultcliLib.declare("VaultOpenVault",
- ctypes.winapi_abi,
- wintypes.DWORD,
- // GUID
- this._structs.GUID.ptr,
- // Flags
- wintypes.DWORD,
- // Vault Handle
- wintypes.VOIDP.ptr);
- this._functions.VaultEnumerateItems =
- this._vaultcliLib.declare("VaultEnumerateItems",
- ctypes.winapi_abi,
- wintypes.DWORD,
- // Vault Handle
- wintypes.VOIDP,
- // Flags
- wintypes.DWORD,
- // Items Count
- wintypes.PDWORD,
- // Items
- ctypes.voidptr_t);
- this._functions.VaultCloseVault =
- this._vaultcliLib.declare("VaultCloseVault",
- ctypes.winapi_abi,
- wintypes.DWORD,
- // Vault Handle
- wintypes.VOIDP);
- this._functions.VaultGetItem =
- this._vaultcliLib.declare("VaultGetItem",
- ctypes.winapi_abi,
- wintypes.DWORD,
- // Vault Handle
- wintypes.VOIDP,
- // Schema Id
- this._structs.GUID.ptr,
- // Resource
- this._structs.VAULT_ITEM_ELEMENT.ptr,
- // Identity
- this._structs.VAULT_ITEM_ELEMENT.ptr,
- // Package Sid
- this._structs.VAULT_ITEM_ELEMENT.ptr,
- // HWND Owner
- wintypes.DWORD,
- // Flags
- wintypes.DWORD,
- // Items
- this._structs.VAULT_ELEMENT.ptr.ptr);
- this._functions.VaultFree =
- this._vaultcliLib.declare("VaultFree",
- ctypes.winapi_abi,
- wintypes.DWORD,
- // Memory
- this._structs.VAULT_ELEMENT.ptr);
- } catch (ex) {
- this.finalize();
- }
-}
-
-CtypesVaultHelpers.prototype = {
- /**
- * Must be invoked once after last use of any of the provided helpers.
- */
- finalize() {
- this._structs = {};
- this._functions = {};
- try {
- this._vaultcliLib.close();
- } catch (ex) {}
- this._vaultcliLib = null;
- }
-};
-
-/**
- * Checks whether an host is an IP (v4 or v6) address.
- *
- * @param aHost
- * The host to check.
- * @return whether aHost is an IP address.
- */
-function hostIsIPAddress(aHost) {
- try {
- Services.eTLD.getBaseDomainFromHost(aHost);
- } catch (e) {
- return e.result == Cr.NS_ERROR_HOST_IS_IP_ADDRESS;
- }
- return false;
-}
-
-var gEdgeDir;
-function getEdgeLocalDataFolder() {
- if (gEdgeDir) {
- return gEdgeDir.clone();
- }
- let packages = Services.dirsvc.get("LocalAppData", Ci.nsIFile);
- packages.append("Packages");
- let edgeDir = packages.clone();
- edgeDir.append("Microsoft.MicrosoftEdge_8wekyb3d8bbwe");
- try {
- if (edgeDir.exists() && edgeDir.isReadable() && edgeDir.isDirectory()) {
- gEdgeDir = edgeDir;
- return edgeDir.clone();
- }
-
- // Let's try the long way:
- let dirEntries = packages.directoryEntries;
- while (dirEntries.hasMoreElements()) {
- let subDir = dirEntries.getNext();
- subDir.QueryInterface(Ci.nsIFile);
- if (subDir.leafName.startsWith("Microsoft.MicrosoftEdge") && subDir.isReadable() &&
- subDir.isDirectory()) {
- gEdgeDir = subDir;
- return subDir.clone();
- }
- }
- } catch (ex) {
- Cu.reportError("Exception trying to find the Edge favorites directory: " + ex);
- }
- return null;
-}
-
-
-function Bookmarks(migrationType) {
- this._migrationType = migrationType;
-}
-
-Bookmarks.prototype = {
- type: MigrationUtils.resourceTypes.BOOKMARKS,
-
- get exists() {
- return !!this._favoritesFolder;
- },
-
- get importedAppLabel() {
- return this._migrationType == MSMigrationUtils.MIGRATION_TYPE_IE ? "IE" : "Edge";
- },
-
- __favoritesFolder: null,
- get _favoritesFolder() {
- if (!this.__favoritesFolder) {
- if (this._migrationType == MSMigrationUtils.MIGRATION_TYPE_IE) {
- let favoritesFolder = Services.dirsvc.get("Favs", Ci.nsIFile);
- if (favoritesFolder.exists() && favoritesFolder.isReadable()) {
- this.__favoritesFolder = favoritesFolder;
- }
- } else if (this._migrationType == MSMigrationUtils.MIGRATION_TYPE_EDGE) {
- let edgeDir = getEdgeLocalDataFolder();
- if (edgeDir) {
- edgeDir.appendRelativePath(EDGE_FAVORITES);
- if (edgeDir.exists() && edgeDir.isReadable() && edgeDir.isDirectory()) {
- this.__favoritesFolder = edgeDir;
- }
- }
- }
- }
- return this.__favoritesFolder;
- },
-
- __toolbarFolderName: null,
- get _toolbarFolderName() {
- if (!this.__toolbarFolderName) {
- if (this._migrationType == MSMigrationUtils.MIGRATION_TYPE_IE) {
- // Retrieve the name of IE's favorites subfolder that holds the bookmarks
- // in the toolbar. This was previously stored in the registry and changed
- // in IE7 to always be called "Links".
- let folderName = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
- "Software\\Microsoft\\Internet Explorer\\Toolbar",
- "LinksFolderName");
- this.__toolbarFolderName = folderName || "Links";
- } else {
- this.__toolbarFolderName = "Links";
- }
- }
- return this.__toolbarFolderName;
- },
-
- migrate: function B_migrate(aCallback) {
- return Task.spawn(function* () {
- // Import to the bookmarks menu.
- let folderGuid = PlacesUtils.bookmarks.menuGuid;
- if (!MigrationUtils.isStartupMigration) {
- folderGuid =
- yield MigrationUtils.createImportedBookmarksFolder(this.importedAppLabel, folderGuid);
- }
- yield this._migrateFolder(this._favoritesFolder, folderGuid);
- }.bind(this)).then(() => aCallback(true),
- e => { Cu.reportError(e); aCallback(false) });
- },
-
- _migrateFolder: Task.async(function* (aSourceFolder, aDestFolderGuid) {
- // TODO (bug 741993): the favorites order is stored in the Registry, at
- // HCU\Software\Microsoft\Windows\CurrentVersion\Explorer\MenuOrder\Favorites
- // for IE, and in a similar location for Edge.
- // Until we support it, bookmarks are imported in alphabetical order.
- let entries = aSourceFolder.directoryEntries;
- let succeeded = true;
- while (entries.hasMoreElements()) {
- let entry = entries.getNext().QueryInterface(Ci.nsIFile);
- try {
- // Make sure that entry.path == entry.target to not follow .lnk folder
- // shortcuts which could lead to infinite cycles.
- // Don't use isSymlink(), since it would throw for invalid
- // lnk files pointing to URLs or to unresolvable paths.
- if (entry.path == entry.target && entry.isDirectory()) {
- let folderGuid;
- if (entry.leafName == this._toolbarFolderName &&
- entry.parent.equals(this._favoritesFolder)) {
- // Import to the bookmarks toolbar.
- folderGuid = PlacesUtils.bookmarks.toolbarGuid;
- if (!MigrationUtils.isStartupMigration) {
- folderGuid =
- yield MigrationUtils.createImportedBookmarksFolder(this.importedAppLabel, folderGuid);
- }
- }
- else {
- // Import to a new folder.
- folderGuid = (yield MigrationUtils.insertBookmarkWrapper({
- type: PlacesUtils.bookmarks.TYPE_FOLDER,
- parentGuid: aDestFolderGuid,
- title: entry.leafName
- })).guid;
- }
-
- if (entry.isReadable()) {
- // Recursively import the folder.
- yield this._migrateFolder(entry, folderGuid);
- }
- }
- else {
- // Strip the .url extension, to both check this is a valid link file,
- // and get the associated title.
- let matches = entry.leafName.match(/(.+)\.url$/i);
- if (matches) {
- let fileHandler = Cc["@mozilla.org/network/protocol;1?name=file"].
- getService(Ci.nsIFileProtocolHandler);
- let uri = fileHandler.readURLFile(entry);
- let title = matches[1];
-
- yield MigrationUtils.insertBookmarkWrapper({
- parentGuid: aDestFolderGuid, url: uri, title
- });
- }
- }
- } catch (ex) {
- Components.utils.reportError("Unable to import " + this.importedAppLabel + " favorite (" + entry.leafName + "): " + ex);
- succeeded = false;
- }
- }
- if (!succeeded) {
- throw new Error("Failed to import all bookmarks correctly.");
- }
- }),
-
-};
-
-function Cookies(migrationType) {
- this._migrationType = migrationType;
-}
-
-Cookies.prototype = {
- type: MigrationUtils.resourceTypes.COOKIES,
-
- get exists() {
- if (this._migrationType == MSMigrationUtils.MIGRATION_TYPE_IE) {
- return !!this._cookiesFolder;
- }
- return !!this._cookiesFolders;
- },
-
- __cookiesFolder: null,
- get _cookiesFolder() {
- // Edge stores cookies in a number of places, and this shouldn't get called:
- if (this._migrationType != MSMigrationUtils.MIGRATION_TYPE_IE) {
- throw new Error("Shouldn't be looking for a single cookie folder unless we're migrating IE");
- }
-
- // Cookies are stored in txt files, in a Cookies folder whose path varies
- // across the different OS versions. CookD takes care of most of these
- // cases, though, in Windows Vista/7, UAC makes a difference.
- // If UAC is enabled, the most common destination is CookD/Low. Though,
- // if the user runs the application in administrator mode or disables UAC,
- // cookies are stored in the original CookD destination. Cause running the
- // browser in administrator mode is unsafe and discouraged, we just care
- // about the UAC state.
- if (!this.__cookiesFolder) {
- let cookiesFolder = Services.dirsvc.get("CookD", Ci.nsIFile);
- if (cookiesFolder.exists() && cookiesFolder.isReadable()) {
- // Check if UAC is enabled.
- if (Services.appinfo.QueryInterface(Ci.nsIWinAppHelper).userCanElevate) {
- cookiesFolder.append("Low");
- }
- this.__cookiesFolder = cookiesFolder;
- }
- }
- return this.__cookiesFolder;
- },
-
- __cookiesFolders: null,
- get _cookiesFolders() {
- if (this._migrationType != MSMigrationUtils.MIGRATION_TYPE_EDGE) {
- throw new Error("Shouldn't be looking for multiple cookie folders unless we're migrating Edge");
- }
-
- let folders = [];
- let edgeDir = getEdgeLocalDataFolder();
- if (edgeDir) {
- edgeDir.append("AC");
- for (let path of EDGE_COOKIE_PATH_OPTIONS) {
- let folder = edgeDir.clone();
- let fullPath = path + EDGE_COOKIES_SUFFIX;
- folder.appendRelativePath(fullPath);
- if (folder.exists() && folder.isReadable() && folder.isDirectory()) {
- folders.push(folder);
- }
- }
- }
- this.__cookiesFolders = folders.length ? folders : null;
- return this.__cookiesFolders;
- },
-
- migrate(aCallback) {
- this.ctypesKernelHelpers = new CtypesKernelHelpers();
-
- let cookiesGenerator = (function* genCookie() {
- let success = false;
- let folders = this._migrationType == MSMigrationUtils.MIGRATION_TYPE_EDGE ?
- this.__cookiesFolders : [this.__cookiesFolder];
- for (let folder of folders) {
- let entries = folder.directoryEntries;
- while (entries.hasMoreElements()) {
- let entry = entries.getNext().QueryInterface(Ci.nsIFile);
- // Skip eventual bogus entries.
- if (!entry.isFile() || !/\.txt$/.test(entry.leafName))
- continue;
-
- this._readCookieFile(entry, function(aSuccess) {
- // Importing even a single cookie file is considered a success.
- if (aSuccess)
- success = true;
- try {
- cookiesGenerator.next();
- } catch (ex) {}
- });
-
- yield undefined;
- }
- }
-
- this.ctypesKernelHelpers.finalize();
-
- aCallback(success);
- }).apply(this);
- cookiesGenerator.next();
- },
-
- _readCookieFile(aFile, aCallback) {
- let fileReader = new FileReader();
- let onLoadEnd = () => {
- fileReader.removeEventListener("loadend", onLoadEnd, false);
-
- if (fileReader.readyState != fileReader.DONE) {
- Cu.reportError("Could not read cookie contents: " + fileReader.error);
- aCallback(false);
- return;
- }
-
- let success = true;
- try {
- this._parseCookieBuffer(fileReader.result);
- } catch (ex) {
- Components.utils.reportError("Unable to migrate cookie: " + ex);
- success = false;
- } finally {
- aCallback(success);
- }
- };
- fileReader.addEventListener("loadend", onLoadEnd, false);
- fileReader.readAsText(File.createFromNsIFile(aFile));
- },
-
- /**
- * Parses a cookie file buffer and returns an array of the contained cookies.
- *
- * The cookie file format is a newline-separated-values with a "*" used as
- * delimeter between multiple records.
- * Each cookie has the following fields:
- * - name
- * - value
- * - host/path
- * - flags
- * - Expiration time most significant integer
- * - Expiration time least significant integer
- * - Creation time most significant integer
- * - Creation time least significant integer
- * - Record delimiter "*"
- *
- * Unfortunately, "*" can also occur inside the value of the cookie, so we
- * can't rely exclusively on it as a record separator.
- *
- * @note All the times are in FILETIME format.
- */
- _parseCookieBuffer(aTextBuffer) {
- // Note the last record is an empty string...
- let records = [];
- let lines = aTextBuffer.split("\n");
- while (lines.length > 0) {
- let record = lines.splice(0, 9);
- // ... which means this is going to be a 1-element array for that record
- if (record.length > 1) {
- records.push(record);
- }
- }
- for (let record of records) {
- let [name, value, hostpath, flags,
- expireTimeLo, expireTimeHi] = record;
-
- // IE stores deleted cookies with a zero-length value, skip them.
- if (value.length == 0)
- continue;
-
- // IE sometimes has cookies created by apps that use "~~local~~/local/file/path"
- // as the hostpath, ignore those:
- if (hostpath.startsWith("~~local~~"))
- continue;
-
- let hostLen = hostpath.indexOf("/");
- let host = hostpath.substr(0, hostLen);
- let path = hostpath.substr(hostLen);
-
- // For a non-null domain, assume it's what Mozilla considers
- // a domain cookie. See bug 222343.
- if (host.length > 0) {
- // Fist delete any possible extant matching host cookie.
- Services.cookies.remove(host, name, path, false, {});
- // Now make it a domain cookie.
- if (host[0] != "." && !hostIsIPAddress(host))
- host = "." + host;
- }
-
- // Fallback: expire in 1h (NB: time is in seconds since epoch, so we have
- // to divide the result of Date.now() (which is in milliseconds) by 1000).
- let expireTime = Math.floor(Date.now() / 1000) + 3600;
- try {
- expireTime = this.ctypesKernelHelpers.fileTimeToSecondsSinceEpoch(Number(expireTimeHi),
- Number(expireTimeLo));
- } catch (ex) {
- Cu.reportError("Failed to get expiry time for cookie for " + host);
- }
-
- Services.cookies.add(host,
- path,
- name,
- value,
- Number(flags) & 0x1, // secure
- false, // httpOnly
- false, // session
- expireTime,
- {});
- }
- }
-};
-
-function getTypedURLs(registryKeyPath) {
- // The list of typed URLs is a sort of annotation stored in the registry.
- // The number of entries stored is not UI-configurable, but has changed
- // between different Windows versions. We just keep reading up to the first
- // non-existing entry to support different limits / states of the registry.
- let typedURLs = new Map();
- let typedURLKey = Cc["@mozilla.org/windows-registry-key;1"].
- createInstance(Ci.nsIWindowsRegKey);
- let typedURLTimeKey = Cc["@mozilla.org/windows-registry-key;1"].
- createInstance(Ci.nsIWindowsRegKey);
- let cTypes = new CtypesKernelHelpers();
- try {
- typedURLKey.open(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
- registryKeyPath + "\\TypedURLs",
- Ci.nsIWindowsRegKey.ACCESS_READ);
- try {
- typedURLTimeKey.open(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
- registryKeyPath + "\\TypedURLsTime",
- Ci.nsIWindowsRegKey.ACCESS_READ);
- } catch (ex) {
- typedURLTimeKey = null;
- }
- let entryName;
- for (let entry = 1; typedURLKey.hasValue((entryName = "url" + entry)); entry++) {
- let url = typedURLKey.readStringValue(entryName);
- let timeTyped = 0;
- if (typedURLTimeKey && typedURLTimeKey.hasValue(entryName)) {
- let urlTime = "";
- try {
- urlTime = typedURLTimeKey.readBinaryValue(entryName);
- } catch (ex) {
- Cu.reportError("Couldn't read url time for " + entryName);
- }
- if (urlTime.length == 8) {
- let urlTimeHex = [];
- for (let i = 0; i < 8; i++) {
- let c = urlTime.charCodeAt(i).toString(16);
- if (c.length == 1)
- c = "0" + c;
- urlTimeHex.unshift(c);
- }
- try {
- let hi = parseInt(urlTimeHex.slice(0, 4).join(""), 16);
- let lo = parseInt(urlTimeHex.slice(4, 8).join(""), 16);
- // Convert to seconds since epoch:
- timeTyped = cTypes.fileTimeToSecondsSinceEpoch(hi, lo);
- // Callers expect PRTime, which is microseconds since epoch:
- timeTyped *= 1000 * 1000;
- } catch (ex) {
- // Ignore conversion exceptions. Callers will have to deal
- // with the fallback value (0).
- }
- }
- }
- typedURLs.set(url, timeTyped);
- }
- } catch (ex) {
- Cu.reportError("Error reading typed URL history: " + ex);
- } finally {
- if (typedURLKey) {
- typedURLKey.close();
- }
- if (typedURLTimeKey) {
- typedURLTimeKey.close();
- }
- cTypes.finalize();
- }
- return typedURLs;
-}
-
-
-// Migrator for form passwords on Windows 8 and higher.
-function WindowsVaultFormPasswords () {
-}
-
-WindowsVaultFormPasswords.prototype = {
- type: MigrationUtils.resourceTypes.PASSWORDS,
-
- get exists() {
- // work only on windows 8+
- if (AppConstants.isPlatformAndVersionAtLeast("win", "6.2")) {
- // check if there are passwords available for migration.
- return this.migrate(() => {}, true);
- }
- return false;
- },
-
- /**
- * If aOnlyCheckExists is false, import the form passwords on Windows 8 and higher from the vault
- * and then call the aCallback.
- * Otherwise, check if there are passwords in the vault.
- * @param {function} aCallback - a callback called when the migration is done.
- * @param {boolean} [aOnlyCheckExists=false] - if aOnlyCheckExists is true, just check if there are some
- * passwords to migrate. Import the passwords from the vault and call aCallback otherwise.
- * @return true if there are passwords in the vault and aOnlyCheckExists is set to true,
- * false if there is no password in the vault and aOnlyCheckExists is set to true, undefined if
- * aOnlyCheckExists is set to false.
- */
- migrate(aCallback, aOnlyCheckExists = false) {
- // check if the vault item is an IE/Edge one
- function _isIEOrEdgePassword(id) {
- return id[0] == INTERNET_EXPLORER_EDGE_GUID[0] &&
- id[1] == INTERNET_EXPLORER_EDGE_GUID[1] &&
- id[2] == INTERNET_EXPLORER_EDGE_GUID[2] &&
- id[3] == INTERNET_EXPLORER_EDGE_GUID[3];
- }
-
- let ctypesVaultHelpers = new CtypesVaultHelpers();
- let ctypesKernelHelpers = new CtypesKernelHelpers();
- let migrationSucceeded = true;
- let successfulVaultOpen = false;
- let error, vault;
- try {
- // web credentials vault id
- let vaultGuid = new ctypesVaultHelpers._structs.GUID(WEB_CREDENTIALS_VAULT_ID);
- error = new wintypes.DWORD();
- // web credentials vault
- vault = new wintypes.VOIDP();
- // open the current vault using the vaultGuid
- error = ctypesVaultHelpers._functions.VaultOpenVault(vaultGuid.address(), 0, vault.address());
- if (error != RESULT_SUCCESS) {
- throw new Error("Unable to open Vault: " + error);
- }
- successfulVaultOpen = true;
-
- let item = new ctypesVaultHelpers._structs.VAULT_ELEMENT.ptr();
- let itemCount = new wintypes.DWORD();
- // enumerate all the available items. This api is going to return a table of all the
- // available items and item is going to point to the first element of this table.
- error = ctypesVaultHelpers._functions.VaultEnumerateItems(vault, VAULT_ENUMERATE_ALL_ITEMS,
- itemCount.address(),
- item.address());
- if (error != RESULT_SUCCESS) {
- throw new Error("Unable to enumerate Vault items: " + error);
- }
- for (let j = 0; j < itemCount.value; j++) {
- try {
- // if it's not an ie/edge password, skip it
- if (!_isIEOrEdgePassword(item.contents.schemaId.id)) {
- continue;
- }
- let url = item.contents.pResourceElement.contents.itemValue.readString();
- let realURL;
- try {
- realURL = Services.io.newURI(url, null, null);
- } catch (ex) { /* leave realURL as null */ }
- if (!realURL || ["http", "https", "ftp"].indexOf(realURL.scheme) == -1) {
- // Ignore items for non-URLs or URLs that aren't HTTP(S)/FTP
- continue;
- }
-
- // if aOnlyCheckExists is set to true, the purpose of the call is to return true if there is at
- // least a password which is true in this case because a password was by now already found
- if (aOnlyCheckExists) {
- return true;
- }
- let username = item.contents.pIdentityElement.contents.itemValue.readString();
- // the current login credential object
- let credential = new ctypesVaultHelpers._structs.VAULT_ELEMENT.ptr();
- error = ctypesVaultHelpers._functions.VaultGetItem(vault,
- item.contents.schemaId.address(),
- item.contents.pResourceElement,
- item.contents.pIdentityElement, null,
- 0, 0, credential.address());
- if (error != RESULT_SUCCESS) {
- throw new Error("Unable to get item: " + error);
- }
-
- let password = credential.contents.pAuthenticatorElement.contents.itemValue.readString();
- let creation = Date.now();
- try {
- // login manager wants time in milliseconds since epoch, so convert
- // to seconds since epoch and multiply to get milliseconds:
- creation = ctypesKernelHelpers.
- fileTimeToSecondsSinceEpoch(item.contents.highLastModified,
- item.contents.lowLastModified) * 1000;
- } catch (ex) {
- // Ignore exceptions in the dates and just create the login for right now.
- }
- // create a new login
- let login = {
- username, password,
- hostname: realURL.prePath,
- timeCreated: creation,
- };
- MigrationUtils.insertLoginWrapper(login);
-
- // close current item
- error = ctypesVaultHelpers._functions.VaultFree(credential);
- if (error == FREE_CLOSE_FAILED) {
- throw new Error("Unable to free item: " + error);
- }
- } catch (e) {
- migrationSucceeded = false;
- Cu.reportError(e);
- } finally {
- // move to next item in the table returned by VaultEnumerateItems
- item = item.increment();
- }
- }
- } catch (e) {
- Cu.reportError(e);
- migrationSucceeded = false;
- } finally {
- if (successfulVaultOpen) {
- // close current vault
- error = ctypesVaultHelpers._functions.VaultCloseVault(vault);
- if (error == FREE_CLOSE_FAILED) {
- Cu.reportError("Unable to close vault: " + error);
- }
- }
- ctypesKernelHelpers.finalize();
- ctypesVaultHelpers.finalize();
- aCallback(migrationSucceeded);
- }
- if (aOnlyCheckExists) {
- return false;
- }
- return undefined;
- }
-};
-
-var MSMigrationUtils = {
- MIGRATION_TYPE_IE: 1,
- MIGRATION_TYPE_EDGE: 2,
- CtypesKernelHelpers: CtypesKernelHelpers,
- getBookmarksMigrator(migrationType = this.MIGRATION_TYPE_IE) {
- return new Bookmarks(migrationType);
- },
- getCookiesMigrator(migrationType = this.MIGRATION_TYPE_IE) {
- return new Cookies(migrationType);
- },
- getWindowsVaultFormPasswordsMigrator() {
- return new WindowsVaultFormPasswords();
- },
- getTypedURLs,
- getEdgeLocalDataFolder,
-};