summaryrefslogtreecommitdiffstats
path: root/browser/components/migration/SafariProfileMigrator.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/migration/SafariProfileMigrator.js')
-rw-r--r--browser/components/migration/SafariProfileMigrator.js650
1 files changed, 0 insertions, 650 deletions
diff --git a/browser/components/migration/SafariProfileMigrator.js b/browser/components/migration/SafariProfileMigrator.js
deleted file mode 100644
index 6a2dbfcb1..000000000
--- a/browser/components/migration/SafariProfileMigrator.js
+++ /dev/null
@@ -1,650 +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";
-
-var Cc = Components.classes;
-var Ci = Components.interfaces;
-var Cu = Components.utils;
-
-Cu.import("resource://gre/modules/AppConstants.jsm");
-Cu.import("resource://gre/modules/FileUtils.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 */
-
-XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
- "resource://gre/modules/Downloads.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PropertyListUtils",
- "resource://gre/modules/PropertyListUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
- "resource://gre/modules/PlacesUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
- "resource://gre/modules/NetUtil.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "FormHistory",
- "resource://gre/modules/FormHistory.jsm");
-
-function Bookmarks(aBookmarksFile) {
- this._file = aBookmarksFile;
-}
-Bookmarks.prototype = {
- type: MigrationUtils.resourceTypes.BOOKMARKS,
-
- migrate: function B_migrate(aCallback) {
- return Task.spawn(function* () {
- let dict = yield new Promise(resolve =>
- PropertyListUtils.read(this._file, resolve)
- );
- if (!dict)
- throw new Error("Could not read Bookmarks.plist");
- let children = dict.get("Children");
- if (!children)
- throw new Error("Invalid Bookmarks.plist format");
-
- let collection = dict.get("Title") == "com.apple.ReadingList" ?
- this.READING_LIST_COLLECTION : this.ROOT_COLLECTION;
- yield this._migrateCollection(children, collection);
- }.bind(this)).then(() => aCallback(true),
- e => { Cu.reportError(e); aCallback(false) });
- },
-
- // Bookmarks collections in Safari. Constants for migrateCollection.
- ROOT_COLLECTION: 0,
- MENU_COLLECTION: 1,
- TOOLBAR_COLLECTION: 2,
- READING_LIST_COLLECTION: 3,
-
- /**
- * Recursively migrate a Safari collection of bookmarks.
- *
- * @param aEntries
- * the collection's children
- * @param aCollection
- * one of the values above.
- */
- _migrateCollection: Task.async(function* (aEntries, aCollection) {
- // A collection of bookmarks in Safari resembles places roots. In the
- // property list files (Bookmarks.plist, ReadingList.plist) they are
- // stored as regular bookmarks folders, and thus can only be distinguished
- // from by their names and places in the hierarchy.
-
- let entriesFiltered = [];
- if (aCollection == this.ROOT_COLLECTION) {
- for (let entry of aEntries) {
- let type = entry.get("WebBookmarkType");
- if (type == "WebBookmarkTypeList" && entry.has("Children")) {
- let title = entry.get("Title");
- let children = entry.get("Children");
- if (title == "BookmarksBar")
- yield this._migrateCollection(children, this.TOOLBAR_COLLECTION);
- else if (title == "BookmarksMenu")
- yield this._migrateCollection(children, this.MENU_COLLECTION);
- else if (title == "com.apple.ReadingList")
- yield this._migrateCollection(children, this.READING_LIST_COLLECTION);
- else if (entry.get("ShouldOmitFromUI") !== true)
- entriesFiltered.push(entry);
- }
- else if (type == "WebBookmarkTypeLeaf") {
- entriesFiltered.push(entry);
- }
- }
- }
- else {
- entriesFiltered = aEntries;
- }
-
- if (entriesFiltered.length == 0)
- return;
-
- let folderGuid = -1;
- switch (aCollection) {
- case this.ROOT_COLLECTION: {
- // In Safari, it is possible (though quite cumbersome) to move
- // bookmarks to the bookmarks root, which is the parent folder of
- // all bookmarks "collections". That is somewhat in parallel with
- // both the places root and the unfiled-bookmarks root.
- // Because the former is only an implementation detail in our UI,
- // the unfiled root seems to be the best choice.
- folderGuid = PlacesUtils.bookmarks.unfiledGuid;
- break;
- }
- case this.MENU_COLLECTION: {
- folderGuid = PlacesUtils.bookmarks.menuGuid;
- if (!MigrationUtils.isStartupMigration) {
- folderGuid =
- yield MigrationUtils.createImportedBookmarksFolder("Safari", folderGuid);
- }
- break;
- }
- case this.TOOLBAR_COLLECTION: {
- folderGuid = PlacesUtils.bookmarks.toolbarGuid;
- if (!MigrationUtils.isStartupMigration) {
- folderGuid =
- yield MigrationUtils.createImportedBookmarksFolder("Safari", folderGuid);
- }
- break;
- }
- case this.READING_LIST_COLLECTION: {
- // Reading list items are imported as regular bookmarks.
- // They are imported under their own folder, created either under the
- // bookmarks menu (in the case of startup migration).
- folderGuid = (yield MigrationUtils.insertBookmarkWrapper({
- parentGuid: PlacesUtils.bookmarks.menuGuid,
- type: PlacesUtils.bookmarks.TYPE_FOLDER,
- title: MigrationUtils.getLocalizedString("importedSafariReadingList"),
- })).guid;
- break;
- }
- default:
- throw new Error("Unexpected value for aCollection!");
- }
- if (folderGuid == -1)
- throw new Error("Invalid folder GUID");
-
- yield this._migrateEntries(entriesFiltered, folderGuid);
- }),
-
- // migrate the given array of safari bookmarks to the given places
- // folder.
- _migrateEntries: Task.async(function* (entries, parentGuid) {
- for (let entry of entries) {
- let type = entry.get("WebBookmarkType");
- if (type == "WebBookmarkTypeList" && entry.has("Children")) {
- let title = entry.get("Title");
- let newFolderGuid = (yield MigrationUtils.insertBookmarkWrapper({
- parentGuid, type: PlacesUtils.bookmarks.TYPE_FOLDER, title
- })).guid;
-
- // Empty folders may not have a children array.
- if (entry.has("Children"))
- yield this._migrateEntries(entry.get("Children"), newFolderGuid, false);
- }
- else if (type == "WebBookmarkTypeLeaf" && entry.has("URLString")) {
- let title;
- if (entry.has("URIDictionary"))
- title = entry.get("URIDictionary").get("title");
-
- try {
- yield MigrationUtils.insertBookmarkWrapper({
- parentGuid, url: entry.get("URLString"), title
- });
- } catch (ex) {
- Cu.reportError("Invalid Safari bookmark: " + ex);
- }
- }
- }
- })
-};
-
-function History(aHistoryFile) {
- this._file = aHistoryFile;
-}
-History.prototype = {
- type: MigrationUtils.resourceTypes.HISTORY,
-
- // Helper method for converting the visit date property to a PRTime value.
- // The visit date is stored as a string, so it's not read as a Date
- // object by PropertyListUtils.
- _parseCocoaDate: function H___parseCocoaDate(aCocoaDateStr) {
- let asDouble = parseFloat(aCocoaDateStr);
- if (!isNaN(asDouble)) {
- // reference date of NSDate.
- let date = new Date("1 January 2001, GMT");
- date.setMilliseconds(asDouble * 1000);
- return date * 1000;
- }
- return 0;
- },
-
- migrate: function H_migrate(aCallback) {
- PropertyListUtils.read(this._file, function migrateHistory(aDict) {
- try {
- if (!aDict)
- throw new Error("Could not read history property list");
- if (!aDict.has("WebHistoryDates"))
- throw new Error("Unexpected history-property list format");
-
- // Safari's History file contains only top-level urls. It does not
- // distinguish between typed urls and linked urls.
- let transType = PlacesUtils.history.TRANSITION_LINK;
-
- let places = [];
- let entries = aDict.get("WebHistoryDates");
- for (let entry of entries) {
- if (entry.has("lastVisitedDate")) {
- let visitDate = this._parseCocoaDate(entry.get("lastVisitedDate"));
- try {
- places.push({ uri: NetUtil.newURI(entry.get("")),
- title: entry.get("title"),
- visits: [{ transitionType: transType,
- visitDate: visitDate }] });
- }
- catch (ex) {
- // Safari's History file may contain malformed URIs which
- // will be ignored.
- Cu.reportError(ex);
- }
- }
- }
- if (places.length > 0) {
- 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);
- }
- });
- }
- else {
- aCallback(false);
- }
- }
- catch (ex) {
- Cu.reportError(ex);
- aCallback(false);
- }
- }.bind(this));
- }
-};
-
-/**
- * Safari's preferences property list is independently used for three purposes:
- * (a) importation of preferences
- * (b) importation of search strings
- * (c) retrieving the home page.
- *
- * So, rather than reading it three times, it's cached and managed here.
- */
-function MainPreferencesPropertyList(aPreferencesFile) {
- this._file = aPreferencesFile;
- this._callbacks = [];
-}
-MainPreferencesPropertyList.prototype = {
- /**
- * @see PropertyListUtils.read
- */
- read: function MPPL_read(aCallback) {
- if ("_dict" in this) {
- aCallback(this._dict);
- return;
- }
-
- let alreadyReading = this._callbacks.length > 0;
- this._callbacks.push(aCallback);
- if (!alreadyReading) {
- PropertyListUtils.read(this._file, function readPrefs(aDict) {
- this._dict = aDict;
- for (let callback of this._callbacks) {
- try {
- callback(aDict);
- }
- catch (ex) {
- Cu.reportError(ex);
- }
- }
- this._callbacks.splice(0);
- }.bind(this));
- }
- },
-
- // Workaround for nsIBrowserProfileMigrator.sourceHomePageURL until
- // it's replaced with an async method.
- _readSync: function MPPL__readSync() {
- if ("_dict" in this)
- return this._dict;
-
- let inputStream = Cc["@mozilla.org/network/file-input-stream;1"].
- createInstance(Ci.nsIFileInputStream);
- inputStream.init(this._file, -1, -1, 0);
- let binaryStream = Cc["@mozilla.org/binaryinputstream;1"].
- createInstance(Ci.nsIBinaryInputStream);
- binaryStream.setInputStream(inputStream);
- let bytes = binaryStream.readByteArray(inputStream.available());
- this._dict = PropertyListUtils._readFromArrayBufferSync(
- new Uint8Array(bytes).buffer);
- return this._dict;
- }
-};
-
-function Preferences(aMainPreferencesPropertyListInstance) {
- this._mainPreferencesPropertyList = aMainPreferencesPropertyListInstance;
-}
-Preferences.prototype = {
- type: MigrationUtils.resourceTypes.SETTINGS,
-
- migrate: function MPR_migrate(aCallback) {
- this._mainPreferencesPropertyList.read(aDict => {
- Task.spawn(function* () {
- if (!aDict)
- throw new Error("Could not read preferences file");
-
- this._dict = aDict;
-
- let invert = webkitVal => !webkitVal;
- this._set("AutoFillPasswords", "signon.rememberSignons");
- this._set("OpenNewTabsInFront", "browser.tabs.loadInBackground", invert);
- this._set("WebKitJavaScriptCanOpenWindowsAutomatically",
- "dom.disable_open_during_load", invert);
-
- // layout.spellcheckDefault is a boolean stored as a number.
- this._set("WebContinuousSpellCheckingEnabled",
- "layout.spellcheckDefault", Number);
-
- // Auto-load images
- // Firefox has an elaborate set of Image preferences. The correlation is:
- // Mode: Safari Firefox
- // Blocked FALSE 2
- // Allowed TRUE 1
- // Allowed, originating site only -- 3
- this._set("WebKitDisplayImagesKey", "permissions.default.image",
- webkitVal => webkitVal ? 1 : 2);
-
- this._migrateFontSettings();
- yield this._migrateDownloadsFolder();
- }.bind(this)).then(() => aCallback(true), ex => {
- Cu.reportError(ex);
- aCallback(false);
- }).catch(Cu.reportError);
- });
- },
-
- /**
- * Attempts to migrates a preference from Safari. Returns whether the preference
- * has been migrated.
- * @param aSafariKey
- * The dictionary key for the preference of Safari.
- * @param aMozPref
- * The gecko/firefox preference to which aSafariKey should be migrated
- * @param [optional] aConvertFunction(aSafariValue)
- * a function that converts the safari-preference value to the
- * appropriate value for aMozPref. If it's not passed, then the
- * Safari value is set as is.
- * If aConvertFunction returns undefined, then aMozPref is not set
- * at all.
- * @return whether or not aMozPref was set.
- */
- _set: function MPR_set(aSafariKey, aMozPref, aConvertFunction) {
- if (this._dict.has(aSafariKey)) {
- let safariVal = this._dict.get(aSafariKey);
- let mozVal = aConvertFunction !== undefined ?
- aConvertFunction(safariVal) : safariVal;
- switch (typeof mozVal) {
- case "string":
- Services.prefs.setCharPref(aMozPref, mozVal);
- break;
- case "number":
- Services.prefs.setIntPref(aMozPref, mozVal);
- break;
- case "boolean":
- Services.prefs.setBoolPref(aMozPref, mozVal);
- break;
- case "undefined":
- return false;
- default:
- throw new Error("Unexpected value type: " + (typeof mozVal));
- }
- }
- return true;
- },
-
- // Fonts settings are quite problematic for migration, for a couple of
- // reasons:
- // (a) Every font preference in Gecko is set for a particular language.
- // In Safari, each font preference applies to all languages.
- // (b) The current underlying implementation of nsIFontEnumerator cannot
- // really tell you anything about a font: no matter what language or type
- // you try to enumerate with EnumerateFonts, you get an array of all
- // fonts in the systems (This also breaks our fonts dialog).
- // (c) In Gecko, each langauge has a distinct serif and sans-serif font
- // preference. Safari has only one default font setting. It seems that
- // it checks if it's a serif or sans serif font, and when a site
- // explicitly asks to use serif/sans-serif font, it uses the default font
- // only if it applies to this type.
- // (d) The solution of guessing the lang-group out of the default charset (as
- // done in the old Safari migrator) can only work when:
- // (1) The default charset preference is set.
- // (2) It's not a unicode charset.
- // For now, we use the language implied by the system locale as the
- // lang-group. The only exception is minimal font size, which is an
- // accessibility preference in Safari (under the Advanced tab). If it is set,
- // we set it for all languages.
- // As for the font type of the default font (serif/sans-serif), the default
- // type for the given language is used (set in font.default.LANGGROUP).
- _migrateFontSettings: function MPR__migrateFontSettings() {
- // If "Never use font sizes smaller than [ ] is set", migrate it for all
- // languages.
- if (this._dict.has("WebKitMinimumFontSize")) {
- let minimumSize = this._dict.get("WebKitMinimumFontSize");
- if (typeof minimumSize == "number") {
- let prefs = Services.prefs.getChildList("font.minimum-size");
- for (let pref of prefs) {
- Services.prefs.setIntPref(pref, minimumSize);
- }
- }
- else {
- Cu.reportError("WebKitMinimumFontSize was set to an invalid value: " +
- minimumSize);
- }
- }
-
- // In theory, the lang group could be "x-unicode". This will result
- // in setting the fonts for "Other Languages".
- let lang = this._getLocaleLangGroup();
-
- let anySet = false;
- let fontType = Services.prefs.getCharPref("font.default." + lang);
- anySet |= this._set("WebKitFixedFont", "font.name.monospace." + lang);
- anySet |= this._set("WebKitDefaultFixedFontSize", "font.size.fixed." + lang);
- anySet |= this._set("WebKitStandardFont",
- "font.name." + fontType + "." + lang);
- anySet |= this._set("WebKitDefaultFontSize", "font.size.variable." + lang);
-
- // If we set font settings for a particular language, we'll also set the
- // fonts dialog to open with the fonts settings for that langauge.
- if (anySet)
- Services.prefs.setCharPref("font.language.group", lang);
- },
-
- // Get the language group for the system locale.
- _getLocaleLangGroup: function MPR__getLocaleLangGroup() {
- let locale = Services.locale.getLocaleComponentForUserAgent();
-
- // See nsLanguageAtomService::GetLanguageGroup
- let localeLangGroup = "x-unicode";
- let bundle = Services.strings.createBundle(
- "resource://gre/res/langGroups.properties");
- try {
- localeLangGroup = bundle.GetStringFromName(locale);
- }
- catch (ex) {
- let hyphenAt = locale.indexOf("-");
- if (hyphenAt != -1) {
- try {
- localeLangGroup = bundle.GetStringFromName(locale.substr(0, hyphenAt));
- }
- catch (ex2) { }
- }
- }
- return localeLangGroup;
- },
-
- _migrateDownloadsFolder: Task.async(function* () {
- if (!this._dict.has("DownloadsPath"))
- return;
-
- let downloadsFolder = FileUtils.File(this._dict.get("DownloadsPath"));
-
- // If the download folder is set to the Desktop or to ~/Downloads, set the
- // folderList pref appropriately so that "Desktop"/Downloads is shown with
- // pretty name in the preferences dialog.
- let folderListVal = 2;
- if (downloadsFolder.equals(FileUtils.getDir("Desk", []))) {
- folderListVal = 0;
- }
- else {
- let systemDownloadsPath = yield Downloads.getSystemDownloadsDirectory();
- let systemDownloadsFolder = FileUtils.File(systemDownloadsPath);
- if (downloadsFolder.equals(systemDownloadsFolder))
- folderListVal = 1;
- }
- Services.prefs.setIntPref("browser.download.folderList", folderListVal);
- Services.prefs.setComplexValue("browser.download.dir", Ci.nsILocalFile,
- downloadsFolder);
- }),
-};
-
-function SearchStrings(aMainPreferencesPropertyListInstance) {
- this._mainPreferencesPropertyList = aMainPreferencesPropertyListInstance;
-}
-SearchStrings.prototype = {
- type: MigrationUtils.resourceTypes.OTHERDATA,
-
- migrate: function SS_migrate(aCallback) {
- this._mainPreferencesPropertyList.read(MigrationUtils.wrapMigrateFunction(
- function migrateSearchStrings(aDict) {
- if (!aDict)
- throw new Error("Could not get preferences dictionary");
-
- if (aDict.has("RecentSearchStrings")) {
- let recentSearchStrings = aDict.get("RecentSearchStrings");
- if (recentSearchStrings && recentSearchStrings.length > 0) {
- let changes = recentSearchStrings.map((searchString) => (
- {op: "add",
- fieldname: "searchbar-history",
- value: searchString}));
- FormHistory.update(changes);
- }
- }
- }.bind(this), aCallback));
- }
-};
-
-// On OS X, the cookie-accept policy preference is stored in a separate
-// property list.
-function WebFoundationCookieBehavior(aWebFoundationFile) {
- this._file = aWebFoundationFile;
-}
-WebFoundationCookieBehavior.prototype = {
- type: MigrationUtils.resourceTypes.SETTINGS,
-
- migrate: function WFPL_migrate(aCallback) {
- PropertyListUtils.read(this._file, MigrationUtils.wrapMigrateFunction(
- function migrateCookieBehavior(aDict) {
- if (!aDict)
- throw new Error("Could not read com.apple.WebFoundation.plist");
-
- if (aDict.has("NSHTTPAcceptCookies")) {
- // Setting Safari Firefox
- // Always Accept always 0
- // Accept from Originating current page 1
- // Never Accept never 2
- let acceptCookies = aDict.get("NSHTTPAcceptCookies");
- let cookieValue = 0;
- if (acceptCookies == "never") {
- cookieValue = 2;
- } else if (acceptCookies == "current page") {
- cookieValue = 1;
- }
- Services.prefs.setIntPref("network.cookie.cookieBehavior",
- cookieValue);
- }
- }.bind(this), aCallback));
- }
-};
-
-function SafariProfileMigrator() {
-}
-
-SafariProfileMigrator.prototype = Object.create(MigratorPrototype);
-
-SafariProfileMigrator.prototype.getResources = function SM_getResources() {
- let profileDir = FileUtils.getDir("ULibDir", ["Safari"], false);
- if (!profileDir.exists())
- return null;
-
- let resources = [];
- let pushProfileFileResource = function(aFileName, aConstructor) {
- let file = profileDir.clone();
- file.append(aFileName);
- if (file.exists())
- resources.push(new aConstructor(file));
- };
-
- pushProfileFileResource("History.plist", History);
- pushProfileFileResource("Bookmarks.plist", Bookmarks);
-
- // The Reading List feature was introduced at the same time in Windows and
- // Mac versions of Safari. Not surprisingly, they are stored in the same
- // format in both versions. Surpsingly, only on Windows there is a
- // separate property list for it. This code is used on mac too, because
- // Apple may fix this at some point.
- pushProfileFileResource("ReadingList.plist", Bookmarks);
-
- let prefs = this.mainPreferencesPropertyList;
- if (prefs) {
- resources.push(new Preferences(prefs));
- resources.push(new SearchStrings(prefs));
- }
-
- let wfFile = FileUtils.getFile("UsrPrfs", ["com.apple.WebFoundation.plist"]);
- if (wfFile.exists())
- resources.push(new WebFoundationCookieBehavior(wfFile));
-
- return resources;
-};
-
-SafariProfileMigrator.prototype.getLastUsedDate = function SM_getLastUsedDate() {
- let profileDir = FileUtils.getDir("ULibDir", ["Safari"], false);
- let datePromises = ["Bookmarks.plist", "History.plist"].map(file => {
- let path = OS.Path.join(profileDir.path, file);
- return OS.File.stat(path).catch(() => null).then(info => {
- return info ? info.lastModificationDate : 0;
- });
- });
- return Promise.all(datePromises).then(dates => {
- return new Date(Math.max.apply(Math, dates));
- });
-};
-
-Object.defineProperty(SafariProfileMigrator.prototype, "mainPreferencesPropertyList", {
- get: function get_mainPreferencesPropertyList() {
- if (this._mainPreferencesPropertyList === undefined) {
- let file = FileUtils.getDir("UsrPrfs", [], false);
- if (file.exists()) {
- file.append("com.apple.Safari.plist");
- if (file.exists()) {
- this._mainPreferencesPropertyList =
- new MainPreferencesPropertyList(file);
- return this._mainPreferencesPropertyList;
- }
- }
- this._mainPreferencesPropertyList = null;
- return this._mainPreferencesPropertyList;
- }
- return this._mainPreferencesPropertyList;
- }
-});
-
-Object.defineProperty(SafariProfileMigrator.prototype, "sourceHomePageURL", {
- get: function get_sourceHomePageURL() {
- if (this.mainPreferencesPropertyList) {
- let dict = this.mainPreferencesPropertyList._readSync();
- if (dict.has("HomePage"))
- return dict.get("HomePage");
- }
- return "";
- }
-});
-
-SafariProfileMigrator.prototype.classDescription = "Safari Profile Migrator";
-SafariProfileMigrator.prototype.contractID = "@mozilla.org/profile/migrator;1?app=browser&type=safari";
-SafariProfileMigrator.prototype.classID = Components.ID("{4b609ecf-60b2-4655-9df4-dc149e474da1}");
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SafariProfileMigrator]);