292 lines
10 KiB
JavaScript
292 lines
10 KiB
JavaScript
/* 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 kMainKey = "Software\\Microsoft\\Internet Explorer\\Main";
|
|
|
|
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.import("resource:///modules/MSMigrationUtils.jsm");
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
|
"resource://gre/modules/PlacesUtils.jsm");
|
|
XPCOMUtils.defineLazyModuleGetter(this, "WindowsRegistry",
|
|
"resource://gre/modules/WindowsRegistry.jsm");
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//// Resources
|
|
|
|
|
|
function History() {
|
|
}
|
|
|
|
History.prototype = {
|
|
type: MigrationUtils.resourceTypes.HISTORY,
|
|
|
|
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 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 = this._typedURLs[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();
|
|
|
|
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;
|
|
}
|
|
|
|
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 Settings() {
|
|
}
|
|
|
|
Settings.prototype = {
|
|
type: MigrationUtils.resourceTypes.SETTINGS,
|
|
|
|
get exists() true,
|
|
|
|
migrate: function S_migrate(aCallback) {
|
|
// Converts from yes/no to a boolean.
|
|
function 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 qA < qB ? 1 : qA == qB ? 0 : -1;
|
|
})
|
|
.map(function(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",
|
|
function (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",
|
|
function (v) !Boolean(v) ? 0 : 2);
|
|
this._set("Software\\Microsoft\\Internet Explorer\\Settings",
|
|
"Always Use My Font Face",
|
|
"browser.display.use_document_fonts",
|
|
function (v) !Boolean(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",
|
|
function (v) !Boolean(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));
|
|
}
|
|
}
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//// Migrator
|
|
|
|
function IEProfileMigrator()
|
|
{
|
|
}
|
|
|
|
IEProfileMigrator.prototype = Object.create(MigratorPrototype);
|
|
|
|
IEProfileMigrator.prototype.getResources = function IE_getResources() {
|
|
let resources = [
|
|
MSMigrationUtils.getBookmarksMigrator()
|
|
, new History()
|
|
, MSMigrationUtils.getCookiesMigrator()
|
|
, new Settings()
|
|
];
|
|
return [r for each (r in resources) if (r.exists)];
|
|
};
|
|
|
|
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]);
|