2015-08-26 14:34:02 +00:00
|
|
|
/* 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/. */
|
|
|
|
|
|
|
|
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
|
|
|
|
2015-09-08 15:16:56 +00:00
|
|
|
Cu.import("resource://gre/modules/AppConstants.jsm");
|
2016-05-30 16:10:54 +00:00
|
|
|
Cu.import("resource://gre/modules/osfile.jsm");
|
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
2015-11-18 11:56:02 +00:00
|
|
|
Cu.import("resource://gre/modules/Task.jsm");
|
2016-05-30 16:10:54 +00:00
|
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
2015-08-26 14:34:02 +00:00
|
|
|
Cu.import("resource:///modules/MigrationUtils.jsm");
|
|
|
|
Cu.import("resource:///modules/MSMigrationUtils.jsm");
|
2015-09-15 21:18:41 +00:00
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
|
|
|
"resource://gre/modules/PlacesUtils.jsm");
|
2015-12-01 20:24:54 +00:00
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "ESEDBReader",
|
|
|
|
"resource:///modules/ESEDBReader.jsm");
|
2015-09-15 21:18:41 +00:00
|
|
|
|
|
|
|
const kEdgeRegistryRoot = "SOFTWARE\\Classes\\Local Settings\\Software\\" +
|
|
|
|
"Microsoft\\Windows\\CurrentVersion\\AppContainer\\Storage\\" +
|
|
|
|
"microsoft.microsoftedge_8wekyb3d8bbwe\\MicrosoftEdge";
|
2016-01-30 11:22:19 +00:00
|
|
|
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.
|
2016-02-11 18:46:32 +00:00
|
|
|
* @param {nsIFile} dbFile the database file to use. Defaults to
|
|
|
|
* the main Edge database.
|
2016-01-30 11:22:19 +00:00
|
|
|
* @returns {Array} An array of row objects.
|
|
|
|
*/
|
2016-02-11 18:46:32 +00:00
|
|
|
function readTableFromEdgeDB(tableName, columns, filterFn, dbFile=gEdgeDatabase) {
|
2016-01-30 11:22:19 +00:00
|
|
|
let database;
|
|
|
|
let rows = [];
|
|
|
|
try {
|
2016-02-11 18:46:32 +00:00
|
|
|
let logFile = dbFile.parent;
|
2016-01-30 11:22:19 +00:00
|
|
|
logFile.append("LogFiles");
|
2016-02-11 18:46:32 +00:00
|
|
|
database = ESEDBReader.openDB(dbFile.parent, dbFile, logFile);
|
2016-01-30 11:22:19 +00:00
|
|
|
|
|
|
|
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 " +
|
2016-02-11 18:46:32 +00:00
|
|
|
dbFile.path + " due to the following error: " + ex);
|
2016-01-30 11:22:19 +00:00
|
|
|
// Deliberately make this fail so we expose failure in the UI:
|
|
|
|
throw ex;
|
|
|
|
} finally {
|
|
|
|
if (database) {
|
|
|
|
ESEDBReader.closeDB(database);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rows;
|
|
|
|
}
|
2015-09-15 21:18:41 +00:00
|
|
|
|
|
|
|
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 rv = true;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
PlacesUtils.asyncHistory.updatePlaces(places, {
|
|
|
|
_success: false,
|
|
|
|
handleResult: function() {
|
|
|
|
// Importing any entry is considered a successful import.
|
|
|
|
this._success = true;
|
|
|
|
},
|
|
|
|
handleError: function() {},
|
|
|
|
handleCompletion: function() {
|
|
|
|
aCallback(this._success);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
}
|
2015-08-26 14:34:02 +00:00
|
|
|
|
2015-11-18 11:56:02 +00:00
|
|
|
function EdgeReadingListMigrator() {
|
|
|
|
}
|
|
|
|
|
|
|
|
EdgeReadingListMigrator.prototype = {
|
|
|
|
type: MigrationUtils.resourceTypes.BOOKMARKS,
|
|
|
|
|
|
|
|
get exists() {
|
2016-01-30 11:22:19 +00:00
|
|
|
return !!gEdgeDatabase;
|
2015-11-18 11:56:02 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
migrate(callback) {
|
|
|
|
this._migrateReadingList(PlacesUtils.bookmarks.menuGuid).then(
|
|
|
|
() => callback(true),
|
|
|
|
ex => {
|
|
|
|
Cu.reportError(ex);
|
|
|
|
callback(false);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
|
|
|
|
|
|
|
_migrateReadingList: Task.async(function*(parentGuid) {
|
2016-01-30 11:22:19 +00:00
|
|
|
let columnFn = db => {
|
2015-12-01 20:24:54 +00:00
|
|
|
let columns = [
|
|
|
|
{name: "URL", type: "string"},
|
|
|
|
{name: "Title", type: "string"},
|
|
|
|
{name: "AddedDate", type: "date"}
|
|
|
|
];
|
|
|
|
|
2016-01-30 11:22:19 +00:00
|
|
|
// Later versions have an IsDeleted column:
|
|
|
|
let isDeletedColumn = db.checkForColumn("ReadingList", "IsDeleted");
|
2015-12-01 20:24:54 +00:00
|
|
|
if (isDeletedColumn && isDeletedColumn.dbType == ESEDBReader.COLUMN_TYPES.JET_coltypBit) {
|
2016-01-30 11:22:19 +00:00
|
|
|
columns.push({name: "IsDeleted", type: "boolean"});
|
2015-11-18 11:56:02 +00:00
|
|
|
}
|
2016-01-30 11:22:19 +00:00
|
|
|
return columns;
|
|
|
|
};
|
2015-11-18 11:56:02 +00:00
|
|
|
|
2016-01-30 11:22:19 +00:00
|
|
|
let filterFn = row => {
|
|
|
|
return !row.IsDeleted;
|
|
|
|
};
|
|
|
|
|
|
|
|
let readingListItems = readTableFromEdgeDB("ReadingList", columnFn, filterFn);
|
2015-11-18 11:56:02 +00:00
|
|
|
if (!readingListItems.length) {
|
|
|
|
return;
|
|
|
|
}
|
2016-01-30 11:22:19 +00:00
|
|
|
|
2015-11-18 11:56:02 +00:00
|
|
|
let destFolderGuid = yield this._ensureReadingListFolder(parentGuid);
|
2015-12-01 20:24:54 +00:00
|
|
|
let exceptionThrown;
|
|
|
|
for (let item of readingListItems) {
|
|
|
|
let dateAdded = item.AddedDate || new Date();
|
2015-11-18 11:56:02 +00:00
|
|
|
yield PlacesUtils.bookmarks.insert({
|
2015-12-01 20:24:54 +00:00
|
|
|
parentGuid: destFolderGuid, url: item.URL, title: item.Title, dateAdded
|
|
|
|
}).catch(ex => {
|
|
|
|
if (!exceptionThrown) {
|
|
|
|
exceptionThrown = ex;
|
|
|
|
}
|
|
|
|
Cu.reportError(ex);
|
2015-11-18 11:56:02 +00:00
|
|
|
});
|
|
|
|
}
|
2015-12-01 20:24:54 +00:00
|
|
|
if (exceptionThrown) {
|
|
|
|
throw exceptionThrown;
|
|
|
|
}
|
2015-11-18 11:56:02 +00:00
|
|
|
}),
|
|
|
|
|
|
|
|
_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 PlacesUtils.bookmarks.insert(folderSpec)).guid;
|
|
|
|
}
|
|
|
|
return this.__readingListFolderGuid;
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
|
2016-02-11 18:46:32 +00:00
|
|
|
function EdgeBookmarksMigrator(dbOverride) {
|
|
|
|
this.dbOverride = dbOverride;
|
2016-01-30 11:22:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
EdgeBookmarksMigrator.prototype = {
|
|
|
|
type: MigrationUtils.resourceTypes.BOOKMARKS,
|
|
|
|
|
2016-02-11 18:46:32 +00:00
|
|
|
get db() { return this.dbOverride || gEdgeDatabase; },
|
|
|
|
|
2016-02-03 14:46:36 +00:00
|
|
|
get TABLE_NAME() { return "Favorites" },
|
|
|
|
|
2016-01-30 11:22:19 +00:00
|
|
|
get exists() {
|
2016-02-03 14:46:36 +00:00
|
|
|
if ("_exists" in this) {
|
|
|
|
return this._exists;
|
|
|
|
}
|
2016-02-11 18:46:32 +00:00
|
|
|
return this._exists = (!!this.db && this._checkTableExists());
|
2016-02-03 14:46:36 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
_checkTableExists() {
|
|
|
|
let database;
|
|
|
|
let rv;
|
|
|
|
try {
|
2016-02-11 18:46:32 +00:00
|
|
|
let logFile = this.db.parent;
|
2016-02-03 14:46:36 +00:00
|
|
|
logFile.append("LogFiles");
|
2016-02-11 18:46:32 +00:00
|
|
|
database = ESEDBReader.openDB(this.db.parent, this.db, logFile);
|
2016-02-03 14:46:36 +00:00
|
|
|
|
|
|
|
rv = database.tableExists(this.TABLE_NAME);
|
|
|
|
} catch (ex) {
|
2016-02-11 18:46:32 +00:00
|
|
|
Cu.reportError("Failed to check for table " + this.TABLE_NAME + " in Edge database at " +
|
|
|
|
this.db.path + " due to the following error: " + ex);
|
2016-02-03 14:46:36 +00:00
|
|
|
return false;
|
|
|
|
} finally {
|
|
|
|
if (database) {
|
|
|
|
ESEDBReader.closeDB(database);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rv;
|
2016-01-30 11:22:19 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
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 PlacesUtils.bookmarks.insert(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;
|
|
|
|
}
|
2016-02-11 18:46:32 +00:00
|
|
|
let bookmarks = readTableFromEdgeDB(this.TABLE_NAME, columns, filterFn, this.db);
|
2016-01-30 11:22:19 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
return folder._guid = toolbarGuid;
|
|
|
|
}
|
|
|
|
// 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 PlacesUtils.bookmarks.insert(folderInfo);
|
|
|
|
return folder._guid = parentBM.guid;
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
|
2015-08-26 14:34:02 +00:00
|
|
|
function EdgeProfileMigrator() {
|
2016-02-11 18:46:32 +00:00
|
|
|
this.wrappedJSObject = this;
|
2015-08-26 14:34:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
EdgeProfileMigrator.prototype = Object.create(MigratorPrototype);
|
|
|
|
|
2016-02-11 18:46:32 +00:00
|
|
|
EdgeProfileMigrator.prototype.getESEMigratorForTesting = function(dbOverride) {
|
|
|
|
return new EdgeBookmarksMigrator(dbOverride);
|
|
|
|
};
|
|
|
|
|
2015-08-26 14:34:02 +00:00
|
|
|
EdgeProfileMigrator.prototype.getResources = function() {
|
2016-02-03 14:46:36 +00:00
|
|
|
let bookmarksMigrator = new EdgeBookmarksMigrator();
|
|
|
|
if (!bookmarksMigrator.exists) {
|
|
|
|
bookmarksMigrator = MSMigrationUtils.getBookmarksMigrator(MSMigrationUtils.MIGRATION_TYPE_EDGE);
|
|
|
|
}
|
2015-08-26 14:34:02 +00:00
|
|
|
let resources = [
|
2016-02-03 14:46:36 +00:00
|
|
|
bookmarksMigrator,
|
2015-08-26 14:34:02 +00:00
|
|
|
MSMigrationUtils.getCookiesMigrator(MSMigrationUtils.MIGRATION_TYPE_EDGE),
|
2015-09-15 21:18:41 +00:00
|
|
|
new EdgeTypedURLMigrator(),
|
2015-11-18 11:56:02 +00:00
|
|
|
new EdgeReadingListMigrator(),
|
2015-08-26 14:34:02 +00:00
|
|
|
];
|
2015-09-17 00:34:26 +00:00
|
|
|
let windowsVaultFormPasswordsMigrator =
|
|
|
|
MSMigrationUtils.getWindowsVaultFormPasswordsMigrator();
|
|
|
|
windowsVaultFormPasswordsMigrator.name = "EdgeVaultFormPasswords";
|
|
|
|
resources.push(windowsVaultFormPasswordsMigrator);
|
2015-08-26 14:34:02 +00:00
|
|
|
return resources.filter(r => r.exists);
|
|
|
|
};
|
|
|
|
|
2016-05-30 16:10:54 +00:00
|
|
|
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));
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2015-09-08 15:16:56 +00:00
|
|
|
/* 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() {
|
2015-10-20 13:56:17 +00:00
|
|
|
let isWin10OrHigher = AppConstants.isPlatformAndVersionAtLeast("win", "10");
|
2015-09-08 15:16:56 +00:00
|
|
|
return isWin10OrHigher ? null : [];
|
|
|
|
});
|
|
|
|
|
2016-01-28 16:35:04 +00:00
|
|
|
EdgeProfileMigrator.prototype.__defineGetter__("sourceLocked", function() {
|
|
|
|
// There is an exclusive lock on some databases. Assume they are locked for now.
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2015-08-26 14:34:02 +00:00
|
|
|
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]);
|