--- a/browser/components/migration/EdgeProfileMigrator.js
+++ b/browser/components/migration/EdgeProfileMigrator.js
@@ -13,16 +13,17 @@ Cu.import("resource:///modules/MSMigrati
function EdgeProfileMigrator() {
}
EdgeProfileMigrator.prototype = Object.create(MigratorPrototype);
EdgeProfileMigrator.prototype.getResources = function() {
let resources = [
MSMigrationUtils.getBookmarksMigrator(MSMigrationUtils.MIGRATION_TYPE_EDGE),
+ MSMigrationUtils.getCookiesMigrator(MSMigrationUtils.MIGRATION_TYPE_EDGE),
];
return resources.filter(r => r.exists);
};
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}");
--- a/browser/components/migration/IEProfileMigrator.js
+++ b/browser/components/migration/IEProfileMigrator.js
@@ -14,131 +14,19 @@ const kMainKey = "Software\\Microsoft\\I
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, "ctypes",
- "resource://gre/modules/ctypes.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "WindowsRegistry",
"resource://gre/modules/WindowsRegistry.jsm");
-Cu.importGlobalProperties(["File"]);
-
-////////////////////////////////////////////////////////////////////////////////
-//// Helpers.
-
-let CtypesHelpers = {
- _structs: {},
- _functions: {},
- _libs: {},
-
- /**
- * Must be invoked once before first use of any of the provided helpers.
- */
- initialize: function CH_initialize() {
- const WORD = ctypes.uint16_t;
- const DWORD = ctypes.uint32_t;
- const BOOL = ctypes.int;
-
- this._structs.SYSTEMTIME = new ctypes.StructType('SYSTEMTIME', [
- {wYear: WORD},
- {wMonth: WORD},
- {wDayOfWeek: WORD},
- {wDay: WORD},
- {wHour: WORD},
- {wMinute: WORD},
- {wSecond: WORD},
- {wMilliseconds: WORD}
- ]);
-
- this._structs.FILETIME = new ctypes.StructType('FILETIME', [
- {dwLowDateTime: DWORD},
- {dwHighDateTime: DWORD}
- ]);
-
- try {
- this._libs.kernel32 = ctypes.open("Kernel32");
- this._functions.FileTimeToSystemTime =
- this._libs.kernel32.declare("FileTimeToSystemTime",
- ctypes.default_abi,
- BOOL,
- this._structs.FILETIME.ptr,
- this._structs.SYSTEMTIME.ptr);
- } catch (ex) {
- this.finalize();
- }
- },
-
- /**
- * Must be invoked once after last use of any of the provided helpers.
- */
- finalize: function CH_finalize() {
- this._structs = {};
- this._functions = {};
- for each (let lib in this._libs) {
- 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);
- }
-};
-
-/**
- * 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 if e.result == Cr.NS_ERROR_HOST_IS_IP_ADDRESS) {
- return true;
- } catch (e) {}
- return false;
-}
-
////////////////////////////////////////////////////////////////////////////////
//// Resources
function History() {
}
History.prototype = {
@@ -222,160 +110,16 @@ History.prototype = {
handleError: function() {},
handleCompletion: function() {
aCallback(this._success);
}
});
}
};
-function Cookies() {
-}
-
-Cookies.prototype = {
- type: MigrationUtils.resourceTypes.COOKIES,
-
- get exists() !!this._cookiesFolder,
-
- __cookiesFolder: null,
- get _cookiesFolder() {
- // 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;
- },
-
- migrate: function C_migrate(aCallback) {
- CtypesHelpers.initialize();
-
- let cookiesGenerator = (function genCookie() {
- let success = false;
- let entries = this._cookiesFolder.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;
- }
-
- CtypesHelpers.finalize();
-
- aCallback(success);
- }).apply(this);
- cookiesGenerator.next();
- },
-
- _readCookieFile: function C__readCookieFile(aFile, aCallback) {
- let fileReader = Cc["@mozilla.org/files/filereader;1"].
- createInstance(Ci.nsIDOMFileReader);
- fileReader.addEventListener("loadend", (function 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);
- }
- }).bind(this), false);
- fileReader.readAsText(new File(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 "*"
- *
- * @note All the times are in FILETIME format.
- */
- _parseCookieBuffer: function C__parseCookieBuffer(aTextBuffer) {
- // Note the last record is an empty string.
- let records = [r for each (r in aTextBuffer.split("*\n")) if (r)];
- for (let record of records) {
- let [name, value, hostpath, flags,
- expireTimeLo, expireTimeHi] = record.split("\n");
-
- // IE stores deleted cookies with a zero-length value, skip them.
- if (value.length == 0)
- 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;
- }
-
- let expireTime = CtypesHelpers.fileTimeToSecondsSinceEpoch(Number(expireTimeHi),
- Number(expireTimeLo));
- Services.cookies.add(host,
- path,
- name,
- value,
- Number(flags) & 0x1, // secure
- false, // httpOnly
- false, // session
- expireTime);
- }
- }
-};
-
function Settings() {
}
Settings.prototype = {
type: MigrationUtils.resourceTypes.SETTINGS,
get exists() true,
@@ -501,17 +245,17 @@ function IEProfileMigrator()
}
IEProfileMigrator.prototype = Object.create(MigratorPrototype);
IEProfileMigrator.prototype.getResources = function IE_getResources() {
let resources = [
MSMigrationUtils.getBookmarksMigrator()
, new History()
- , new Cookies()
+ , 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,
--- a/browser/components/migration/MSMigrationUtils.jsm
+++ b/browser/components/migration/MSMigrationUtils.jsm
@@ -12,19 +12,166 @@ Cu.import("resource://gre/modules/XPCOMU
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource:///modules/MigrationUtils.jsm");
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";
+Cu.importGlobalProperties(["File"]);
+
+////////////////////////////////////////////////////////////////////////////////
+//// Helpers.
+
+let CtypesHelpers = {
+ _structs: {},
+ _functions: {},
+ _libs: {},
+
+ /**
+ * Must be invoked once before first use of any of the provided helpers.
+ */
+ initialize: function CH_initialize() {
+ const WORD = ctypes.uint16_t;
+ const DWORD = ctypes.uint32_t;
+ const BOOL = ctypes.int;
+
+ this._structs.SYSTEMTIME = new ctypes.StructType('SYSTEMTIME', [
+ {wYear: WORD},
+ {wMonth: WORD},
+ {wDayOfWeek: WORD},
+ {wDay: WORD},
+ {wHour: WORD},
+ {wMinute: WORD},
+ {wSecond: WORD},
+ {wMilliseconds: WORD}
+ ]);
+
+ this._structs.FILETIME = new ctypes.StructType('FILETIME', [
+ {dwLowDateTime: DWORD},
+ {dwHighDateTime: DWORD}
+ ]);
+
+ try {
+ this._libs.kernel32 = ctypes.open("Kernel32");
+ this._functions.FileTimeToSystemTime =
+ this._libs.kernel32.declare("FileTimeToSystemTime",
+ ctypes.default_abi,
+ BOOL,
+ this._structs.FILETIME.ptr,
+ this._structs.SYSTEMTIME.ptr);
+ } catch (ex) {
+ this.finalize();
+ }
+ },
+
+ /**
+ * Must be invoked once after last use of any of the provided helpers.
+ */
+ finalize: function CH_finalize() {
+ this._structs = {};
+ this._functions = {};
+ for each (let lib in this._libs) {
+ 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);
+ }
+};
+
+/**
+ * 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 if e.result == Cr.NS_ERROR_HOST_IS_IP_ADDRESS) {
+ return true;
+ } catch (e) {}
+ return false;
+}
+
+let 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() !!this._favoritesFolder,
@@ -35,42 +182,22 @@ Bookmarks.prototype = {
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())
return this.__favoritesFolder = favoritesFolder;
}
if (this._migrationType == MSMigrationUtils.MIGRATION_TYPE_EDGE) {
- let appData = Services.dirsvc.get("LocalAppData", Ci.nsIFile);
- appData.append("Packages");
- try {
- let edgeDir = appData.clone();
- edgeDir.append("Microsoft.MicrosoftEdge_8wekyb3d8bbwe");
+ let edgeDir = getEdgeLocalDataFolder();
+ if (edgeDir) {
edgeDir.appendRelativePath(EDGE_FAVORITES);
- if (edgeDir.exists() && edgeDir.isDirectory()) {
+ if (edgeDir.exists() && edgeDir.isReadable() && edgeDir.isDirectory()) {
return this.__favoritesFolder = edgeDir;
}
- } catch (ex) {} /* Ignore e.g. permissions errors here. */
-
- // Let's try the long way:
- try {
- let dirEntries = appData.directoryEntries;
- while (dirEntries.hasMoreElements()) {
- let subDir = dirEntries.getNext();
- subDir.QueryInterface(Ci.nsIFile);
- if (subDir.leafName.startsWith("Microsoft.MicrosoftEdge")) {
- subDir.appendRelativePath(EDGE_FAVORITES);
- if (subDir.exists() && subDir.isDirectory()) {
- return this.__favoritesFolder = subDir;
- }
- }
- }
- } catch (ex) {
- Cu.reportError("Exception trying to find the Edge favorites directory: " + ex);
}
}
}
return this.__favoritesFolder;
},
__toolbarFolderName: null,
get _toolbarFolderName() {
@@ -158,15 +285,199 @@ Bookmarks.prototype = {
}
} catch (ex) {
Components.utils.reportError("Unable to import " + this.importedAppLabel + " favorite (" + entry.leafName + "): " + ex);
}
}
})
};
+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 "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 "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: function C_migrate(aCallback) {
+ CtypesHelpers.initialize();
+
+ 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;
+ }
+ }
+
+ CtypesHelpers.finalize();
+
+ aCallback(success);
+ }).apply(this);
+ cookiesGenerator.next();
+ },
+
+ _readCookieFile: function C__readCookieFile(aFile, aCallback) {
+ let fileReader = Cc["@mozilla.org/files/filereader;1"].
+ createInstance(Ci.nsIDOMFileReader);
+ fileReader.addEventListener("loadend", (function 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);
+ }
+ }).bind(this), false);
+ fileReader.readAsText(new File(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 "*"
+ *
+ * @note All the times are in FILETIME format.
+ */
+ _parseCookieBuffer: function C__parseCookieBuffer(aTextBuffer) {
+ // Note the last record is an empty string.
+ let records = [r for each (r in aTextBuffer.split("*\n")) if (r)];
+ for (let record of records) {
+ let [name, value, hostpath, flags,
+ expireTimeLo, expireTimeHi] = record.split("\n");
+
+ // IE stores deleted cookies with a zero-length value, skip them.
+ if (value.length == 0)
+ 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;
+ }
+
+ let expireTime = CtypesHelpers.fileTimeToSecondsSinceEpoch(Number(expireTimeHi),
+ Number(expireTimeLo));
+ Services.cookies.add(host,
+ path,
+ name,
+ value,
+ Number(flags) & 0x1, // secure
+ false, // httpOnly
+ false, // session
+ expireTime);
+ }
+ }
+};
+
+
let MSMigrationUtils = {
MIGRATION_TYPE_IE: 1,
MIGRATION_TYPE_EDGE: 2,
getBookmarksMigrator(migrationType = this.MIGRATION_TYPE_IE) {
return new Bookmarks(migrationType);
},
+ getCookiesMigrator(migrationType = this.MIGRATION_TYPE_IE) {
+ return new Cookies(migrationType);
+ },
};