summaryrefslogtreecommitdiffstats
path: root/browser/components/migration/EdgeProfileMigrator.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/migration/EdgeProfileMigrator.js')
-rw-r--r--browser/components/migration/EdgeProfileMigrator.js450
1 files changed, 0 insertions, 450 deletions
diff --git a/browser/components/migration/EdgeProfileMigrator.js b/browser/components/migration/EdgeProfileMigrator.js
deleted file mode 100644
index afdcc2773..000000000
--- a/browser/components/migration/EdgeProfileMigrator.js
+++ /dev/null
@@ -1,450 +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 { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
-
-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, "PlacesUtils",
- "resource://gre/modules/PlacesUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "ESEDBReader",
- "resource:///modules/ESEDBReader.jsm");
-
-const kEdgeRegistryRoot = "SOFTWARE\\Classes\\Local Settings\\Software\\" +
- "Microsoft\\Windows\\CurrentVersion\\AppContainer\\Storage\\" +
- "microsoft.microsoftedge_8wekyb3d8bbwe\\MicrosoftEdge";
-const kEdgeDatabasePath = "AC\\MicrosoftEdge\\User\\Default\\DataStore\\Data\\";
-
-XPCOMUtils.defineLazyGetter(this, "gEdgeDatabase", function() {
- let edgeDir = MSMigrationUtils.getEdgeLocalDataFolder();
- if (!edgeDir) {
- return null;
- }
- edgeDir.appendRelativePath(kEdgeDatabasePath);
- if (!edgeDir.exists() || !edgeDir.isReadable() || !edgeDir.isDirectory()) {
- return null;
- }
- let expectedLocation = edgeDir.clone();
- expectedLocation.appendRelativePath("nouser1\\120712-0049\\DBStore\\spartan.edb");
- if (expectedLocation.exists() && expectedLocation.isReadable() && expectedLocation.isFile()) {
- return expectedLocation;
- }
- // We used to recurse into arbitrary subdirectories here, but that code
- // went unused, so it likely isn't necessary, even if we don't understand
- // where the magic folders above come from, they seem to be the same for
- // everyone. Just return null if they're not there:
- return null;
-});
-
-/**
- * Get rows from a table in the Edge DB as an array of JS objects.
- *
- * @param {String} tableName the name of the table to read.
- * @param {String[]|function} columns a list of column specifiers
- * (see ESEDBReader.jsm) or a function that
- * generates them based on the database
- * reference once opened.
- * @param {function} filterFn a function that is called for each row.
- * Only rows for which it returns a truthy
- * value are included in the result.
- * @param {nsIFile} dbFile the database file to use. Defaults to
- * the main Edge database.
- * @returns {Array} An array of row objects.
- */
-function readTableFromEdgeDB(tableName, columns, filterFn, dbFile = gEdgeDatabase) {
- let database;
- let rows = [];
- try {
- let logFile = dbFile.parent;
- logFile.append("LogFiles");
- database = ESEDBReader.openDB(dbFile.parent, dbFile, logFile);
-
- if (typeof columns == "function") {
- columns = columns(database);
- }
-
- let tableReader = database.tableItems(tableName, columns);
- for (let row of tableReader) {
- if (filterFn(row)) {
- rows.push(row);
- }
- }
- } catch (ex) {
- Cu.reportError("Failed to extract items from table " + tableName + " in Edge database at " +
- dbFile.path + " due to the following error: " + ex);
- // Deliberately make this fail so we expose failure in the UI:
- throw ex;
- } finally {
- if (database) {
- ESEDBReader.closeDB(database);
- }
- }
- return rows;
-}
-
-function EdgeTypedURLMigrator() {
-}
-
-EdgeTypedURLMigrator.prototype = {
- type: MigrationUtils.resourceTypes.HISTORY,
-
- get _typedURLs() {
- if (!this.__typedURLs) {
- this.__typedURLs = MSMigrationUtils.getTypedURLs(kEdgeRegistryRoot);
- }
- return this.__typedURLs;
- },
-
- get exists() {
- return this._typedURLs.size > 0;
- },
-
- migrate: function(aCallback) {
- let typedURLs = this._typedURLs;
- let places = [];
- for (let [urlString, time] of typedURLs) {
- let uri;
- try {
- uri = Services.io.newURI(urlString, null, null);
- if (["http", "https", "ftp"].indexOf(uri.scheme) == -1) {
- continue;
- }
- } catch (ex) {
- Cu.reportError(ex);
- continue;
- }
-
- // Note that the time will be 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 visitDate = time || (Date.now() * 1000);
- places.push({
- uri,
- visits: [{ transitionType: Ci.nsINavHistoryService.TRANSITION_TYPED,
- visitDate}]
- });
- }
-
- if (places.length == 0) {
- aCallback(typedURLs.size == 0);
- 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);
- }
- });
- },
-};
-
-function EdgeReadingListMigrator() {
-}
-
-EdgeReadingListMigrator.prototype = {
- type: MigrationUtils.resourceTypes.BOOKMARKS,
-
- get exists() {
- return !!gEdgeDatabase;
- },
-
- migrate(callback) {
- this._migrateReadingList(PlacesUtils.bookmarks.menuGuid).then(
- () => callback(true),
- ex => {
- Cu.reportError(ex);
- callback(false);
- }
- );
- },
-
- _migrateReadingList: Task.async(function*(parentGuid) {
- let columnFn = db => {
- let columns = [
- {name: "URL", type: "string"},
- {name: "Title", type: "string"},
- {name: "AddedDate", type: "date"}
- ];
-
- // Later versions have an IsDeleted column:
- let isDeletedColumn = db.checkForColumn("ReadingList", "IsDeleted");
- if (isDeletedColumn && isDeletedColumn.dbType == ESEDBReader.COLUMN_TYPES.JET_coltypBit) {
- columns.push({name: "IsDeleted", type: "boolean"});
- }
- return columns;
- };
-
- let filterFn = row => {
- return !row.IsDeleted;
- };
-
- let readingListItems = readTableFromEdgeDB("ReadingList", columnFn, filterFn);
- if (!readingListItems.length) {
- return;
- }
-
- let destFolderGuid = yield this._ensureReadingListFolder(parentGuid);
- let exceptionThrown;
- for (let item of readingListItems) {
- let dateAdded = item.AddedDate || new Date();
- yield MigrationUtils.insertBookmarkWrapper({
- parentGuid: destFolderGuid, url: item.URL, title: item.Title, dateAdded
- }).catch(ex => {
- if (!exceptionThrown) {
- exceptionThrown = ex;
- }
- Cu.reportError(ex);
- });
- }
- if (exceptionThrown) {
- throw exceptionThrown;
- }
- }),
-
- _ensureReadingListFolder: Task.async(function*(parentGuid) {
- if (!this.__readingListFolderGuid) {
- let folderTitle = MigrationUtils.getLocalizedString("importedEdgeReadingList");
- let folderSpec = {type: PlacesUtils.bookmarks.TYPE_FOLDER, parentGuid, title: folderTitle};
- this.__readingListFolderGuid = (yield MigrationUtils.insertBookmarkWrapper(folderSpec)).guid;
- }
- return this.__readingListFolderGuid;
- }),
-};
-
-function EdgeBookmarksMigrator(dbOverride) {
- this.dbOverride = dbOverride;
-}
-
-EdgeBookmarksMigrator.prototype = {
- type: MigrationUtils.resourceTypes.BOOKMARKS,
-
- get db() { return this.dbOverride || gEdgeDatabase },
-
- get TABLE_NAME() { return "Favorites" },
-
- get exists() {
- if (!("_exists" in this)) {
- this._exists = !!this.db;
- }
- return this._exists;
- },
-
- migrate(callback) {
- this._migrateBookmarks(PlacesUtils.bookmarks.menuGuid).then(
- () => callback(true),
- ex => {
- Cu.reportError(ex);
- callback(false);
- }
- );
- },
-
- _migrateBookmarks: Task.async(function*(rootGuid) {
- let {bookmarks, folderMap} = this._fetchBookmarksFromDB();
- if (!bookmarks.length) {
- return;
- }
- yield this._importBookmarks(bookmarks, folderMap, rootGuid);
- }),
-
- _importBookmarks: Task.async(function*(bookmarks, folderMap, rootGuid) {
- if (!MigrationUtils.isStartupMigration) {
- rootGuid =
- yield MigrationUtils.createImportedBookmarksFolder("Edge", rootGuid);
- }
-
- let exceptionThrown;
- for (let bookmark of bookmarks) {
- // If this is a folder, we might have created it already to put other bookmarks in.
- if (bookmark.IsFolder && bookmark._guid) {
- continue;
- }
-
- // If this is a folder, just create folders up to and including that folder.
- // Otherwise, create folders until we have a parent for this bookmark.
- // This avoids duplicating logic for the bookmarks bar.
- let folderId = bookmark.IsFolder ? bookmark.ItemId : bookmark.ParentId;
- let parentGuid = yield this._getGuidForFolder(folderId, folderMap, rootGuid).catch(ex => {
- if (!exceptionThrown) {
- exceptionThrown = ex;
- }
- Cu.reportError(ex);
- });
-
- // If this was a folder, we're done with this item
- if (bookmark.IsFolder) {
- continue;
- }
-
- if (!parentGuid) {
- // If we couldn't sort out a parent, fall back to importing on the root:
- parentGuid = rootGuid;
- }
- let placesInfo = {
- parentGuid,
- url: bookmark.URL,
- dateAdded: bookmark.DateUpdated || new Date(),
- title: bookmark.Title,
- };
-
- yield MigrationUtils.insertBookmarkWrapper(placesInfo).catch(ex => {
- if (!exceptionThrown) {
- exceptionThrown = ex;
- }
- Cu.reportError(ex);
- });
- }
-
- if (exceptionThrown) {
- throw exceptionThrown;
- }
- }),
-
- _fetchBookmarksFromDB() {
- let folderMap = new Map();
- let columns = [
- {name: "URL", type: "string"},
- {name: "Title", type: "string"},
- {name: "DateUpdated", type: "date"},
- {name: "IsFolder", type: "boolean"},
- {name: "IsDeleted", type: "boolean"},
- {name: "ParentId", type: "guid"},
- {name: "ItemId", type: "guid"}
- ];
- let filterFn = row => {
- if (row.IsDeleted) {
- return false;
- }
- if (row.IsFolder) {
- folderMap.set(row.ItemId, row);
- }
- return true;
- };
- let bookmarks = readTableFromEdgeDB(this.TABLE_NAME, columns, filterFn, this.db);
- return {bookmarks, folderMap};
- },
-
- _getGuidForFolder: Task.async(function*(folderId, folderMap, rootGuid) {
- // If the folderId is not known as a folder in the folder map, we assume
- // we just need the root
- if (!folderMap.has(folderId)) {
- return rootGuid;
- }
- let folder = folderMap.get(folderId);
- // If the folder already has a places guid, just return that.
- if (folder._guid) {
- return folder._guid;
- }
-
- // Hacks! The bookmarks bar is special:
- if (folder.Title == "_Favorites_Bar_") {
- let toolbarGuid = PlacesUtils.bookmarks.toolbarGuid;
- if (!MigrationUtils.isStartupMigration) {
- toolbarGuid =
- yield MigrationUtils.createImportedBookmarksFolder("Edge", toolbarGuid);
- }
- folder._guid = toolbarGuid;
- return folder._guid;
- }
- // Otherwise, get the right parent guid recursively:
- let parentGuid = yield this._getGuidForFolder(folder.ParentId, folderMap, rootGuid);
- let folderInfo = {
- title: folder.Title,
- type: PlacesUtils.bookmarks.TYPE_FOLDER,
- dateAdded: folder.DateUpdated || new Date(),
- parentGuid,
- };
- // and add ourselves as a kid, and return the guid we got.
- let parentBM = yield MigrationUtils.insertBookmarkWrapper(folderInfo);
- folder._guid = parentBM.guid;
- return folder._guid;
- }),
-};
-
-function EdgeProfileMigrator() {
- this.wrappedJSObject = this;
-}
-
-EdgeProfileMigrator.prototype = Object.create(MigratorPrototype);
-
-EdgeProfileMigrator.prototype.getESEMigratorForTesting = function(dbOverride) {
- return new EdgeBookmarksMigrator(dbOverride);
-};
-
-EdgeProfileMigrator.prototype.getResources = function() {
- let resources = [
- new EdgeBookmarksMigrator(),
- MSMigrationUtils.getCookiesMigrator(MSMigrationUtils.MIGRATION_TYPE_EDGE),
- new EdgeTypedURLMigrator(),
- new EdgeReadingListMigrator(),
- ];
- let windowsVaultFormPasswordsMigrator =
- MSMigrationUtils.getWindowsVaultFormPasswordsMigrator();
- windowsVaultFormPasswordsMigrator.name = "EdgeVaultFormPasswords";
- resources.push(windowsVaultFormPasswordsMigrator);
- return resources.filter(r => r.exists);
-};
-
-EdgeProfileMigrator.prototype.getLastUsedDate = function() {
- // Don't do this if we don't have a single profile (see the comment for
- // sourceProfiles) or if we can't find the database file:
- if (this.sourceProfiles !== null || !gEdgeDatabase) {
- return Promise.resolve(new Date(0));
- }
- let logFilePath = OS.Path.join(gEdgeDatabase.parent.path, "LogFiles", "edb.log");
- let dbPath = gEdgeDatabase.path;
- let cookieMigrator = MSMigrationUtils.getCookiesMigrator(MSMigrationUtils.MIGRATION_TYPE_EDGE);
- let cookiePaths = cookieMigrator._cookiesFolders.map(f => f.path);
- let datePromises = [logFilePath, dbPath, ... cookiePaths].map(path => {
- 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(kEdgeRegistryRoot);
- } catch (ex) {}
- let times = [0, ... typedURLs.values()];
- resolve(Math.max.apply(Math, times));
- }));
- return Promise.all(datePromises).then(dates => {
- return new Date(Math.max.apply(Math, dates));
- });
-};
-
-/* Somewhat counterintuitively, this returns:
- * - |null| to indicate "There is only 1 (default) profile" (on win10+)
- * - |[]| to indicate "There are no profiles" (on <=win8.1) which will avoid using this migrator.
- * See MigrationUtils.jsm for slightly more info on how sourceProfiles is used.
- */
-EdgeProfileMigrator.prototype.__defineGetter__("sourceProfiles", function() {
- let isWin10OrHigher = AppConstants.isPlatformAndVersionAtLeast("win", "10");
- return isWin10OrHigher ? null : [];
-});
-
-EdgeProfileMigrator.prototype.__defineGetter__("sourceLocked", function() {
- // There is an exclusive lock on some databases. Assume they are locked for now.
- return true;
-});
-
-
-EdgeProfileMigrator.prototype.classDescription = "Edge Profile Migrator";
-EdgeProfileMigrator.prototype.contractID = "@mozilla.org/profile/migrator;1?app=browser&type=edge";
-EdgeProfileMigrator.prototype.classID = Components.ID("{62e8834b-2d17-49f5-96ff-56344903a2ae}");
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([EdgeProfileMigrator]);