зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1205053 - use registry typedURLs to import rudimentary history from MS Edge, r=dolske
--HG-- extra : commitid : 5c0aDxUWRp0 extra : rebase_source : 2762ed6466d7f0ab13e619c52f1cebdf6d3073b1
This commit is contained in:
Родитель
b45c5702f2
Коммит
4e2577e37c
|
@ -5,9 +5,79 @@
|
|||
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||
Cu.import("resource:///modules/MigrationUtils.jsm");
|
||||
Cu.import("resource:///modules/MSMigrationUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
"resource://gre/modules/PlacesUtils.jsm");
|
||||
|
||||
const kEdgeRegistryRoot = "SOFTWARE\\Classes\\Local Settings\\Software\\" +
|
||||
"Microsoft\\Windows\\CurrentVersion\\AppContainer\\Storage\\" +
|
||||
"microsoft.microsoftedge_8wekyb3d8bbwe\\MicrosoftEdge";
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
function EdgeProfileMigrator() {
|
||||
}
|
||||
|
@ -18,6 +88,7 @@ EdgeProfileMigrator.prototype.getResources = function() {
|
|||
let resources = [
|
||||
MSMigrationUtils.getBookmarksMigrator(MSMigrationUtils.MIGRATION_TYPE_EDGE),
|
||||
MSMigrationUtils.getCookiesMigrator(MSMigrationUtils.MIGRATION_TYPE_EDGE),
|
||||
new EdgeTypedURLMigrator(),
|
||||
];
|
||||
let windowsVaultFormPasswordsMigrator =
|
||||
MSMigrationUtils.getWindowsVaultFormPasswordsMigrator();
|
||||
|
|
|
@ -46,34 +46,9 @@ History.prototype = {
|
|||
|
||||
get exists() true,
|
||||
|
||||
__typedURLs: null,
|
||||
get _typedURLs() {
|
||||
if (!this.__typedURLs) {
|
||||
// The list of typed URLs is a sort of annotation stored in the registry.
|
||||
// Currently, IE stores 25 entries and this value is not configurable,
|
||||
// but we just keep reading up to the first non-existing entry to support
|
||||
// possible future bumps of this limit.
|
||||
this.__typedURLs = {};
|
||||
let registry = Cc["@mozilla.org/windows-registry-key;1"].
|
||||
createInstance(Ci.nsIWindowsRegKey);
|
||||
try {
|
||||
registry.open(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Microsoft\\Internet Explorer\\TypedURLs",
|
||||
Ci.nsIWindowsRegKey.ACCESS_READ);
|
||||
for (let entry = 1; registry.hasValue("url" + entry); entry++) {
|
||||
let url = registry.readStringValue("url" + entry);
|
||||
this.__typedURLs[url] = true;
|
||||
}
|
||||
} catch (ex) {
|
||||
} finally {
|
||||
registry.close();
|
||||
}
|
||||
}
|
||||
return this.__typedURLs;
|
||||
},
|
||||
|
||||
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()) {
|
||||
|
@ -93,11 +68,14 @@ History.prototype = {
|
|||
}
|
||||
|
||||
// The typed urls are already fixed-up, so we can use them for comparison.
|
||||
let transitionType = this._typedURLs[uri.spec] ?
|
||||
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
|
||||
let lastVisitTime = entry.get("time") || Date.now();
|
||||
// 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,
|
||||
|
|
|
@ -686,8 +686,15 @@ Cookies.prototype = {
|
|||
host = "." + host;
|
||||
}
|
||||
|
||||
let expireTime = this.ctypesKernelHelpers.fileTimeToSecondsSinceEpoch(Number(expireTimeHi),
|
||||
Number(expireTimeLo));
|
||||
// Fallback: expire in 1h
|
||||
let expireTime = (Date.now() + 3600 * 1000) * 1000;
|
||||
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,
|
||||
|
@ -700,6 +707,69 @@ Cookies.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
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 CtypesHelpers();
|
||||
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);
|
||||
timeTyped = cTypes.fileTimeToSecondsSinceEpoch(hi, lo);
|
||||
// Callers expect PRTime, which is microseconds since epoch:
|
||||
timeTyped *= 1000 * 1000;
|
||||
} catch (ex) {}
|
||||
}
|
||||
}
|
||||
typedURLs.set(url, timeTyped);
|
||||
}
|
||||
} catch (ex) {
|
||||
Cu.reportError("Error reading typed URL history: " + ex);
|
||||
} finally {
|
||||
typedURLKey.close();
|
||||
typedURLTimeKey.close();
|
||||
cTypes.finalize();
|
||||
}
|
||||
return typedURLs;
|
||||
}
|
||||
|
||||
|
||||
// Migrator for form passwords on Windows 8 and higher.
|
||||
function WindowsVaultFormPasswords () {
|
||||
}
|
||||
|
@ -850,4 +920,5 @@ var MSMigrationUtils = {
|
|||
getWindowsVaultFormPasswordsMigrator() {
|
||||
return new WindowsVaultFormPasswords();
|
||||
},
|
||||
getTypedURLs,
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
const EDGE_AVAILABLE_MIGRATIONS =
|
||||
MigrationUtils.resourceTypes.COOKIES |
|
||||
MigrationUtils.resourceTypes.BOOKMARKS |
|
||||
MigrationUtils.resourceTypes.HISTORY |
|
||||
MigrationUtils.resourceTypes.PASSWORDS;
|
||||
|
||||
add_task(function* () {
|
||||
|
|
Загрузка…
Ссылка в новой задаче