forked from mirrors/gecko-dev
		
	 a80925cf2f
			
		
	
	
		a80925cf2f
		
	
	
	
	
		
			
			--HG-- extra : commitid : 9jirohhjOQ7 extra : rebase_source : e790d293ad5f9211e4da401dbe1be0175aa18097
		
			
				
	
	
		
			673 lines
		
	
	
	
		
			24 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			673 lines
		
	
	
	
		
			24 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";
 | |
| 
 | |
| var Cc = Components.classes;
 | |
| var Ci = Components.interfaces;
 | |
| var Cu = Components.utils;
 | |
| 
 | |
| Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 | |
| Cu.import("resource://gre/modules/FileUtils.jsm");
 | |
| Cu.import("resource://gre/modules/Services.jsm");
 | |
| Cu.import("resource://gre/modules/Task.jsm");
 | |
| Cu.import("resource:///modules/MigrationUtils.jsm");
 | |
| 
 | |
| 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 PlacesUtils.bookmarks.insert({
 | |
|             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 PlacesUtils.bookmarks.insert({
 | |
|           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 PlacesUtils.bookmarks.insert({
 | |
|             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) {
 | |
|           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);
 | |
|             }
 | |
|           });
 | |
|         }
 | |
|         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);
 | |
| 
 | |
| #ifdef XP_WIN
 | |
|         // Cookie-accept policy.
 | |
|         // For the OS X version, see WebFoundationCookieBehavior.
 | |
|         // Setting                    Safari          Firefox
 | |
|         // Always Accept              0               0
 | |
|         // Accept from Originating    2               1
 | |
|         // Never Accept               1               2
 | |
|         this._set("WebKitCookieStorageAcceptPolicy",
 | |
|           "network.cookie.cookieBehavior",
 | |
|           webkitVal => webkitVal == 0 ? 0 : webkitVal == 1 ? 2 : 1);
 | |
| #endif
 | |
| 
 | |
|         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* () {
 | |
|     // Windows Safari uses DownloadPath while Mac uses DownloadsPath.
 | |
|     // Check both for future compatibility.
 | |
|     let key;
 | |
|     if (this._dict.has("DownloadsPath"))
 | |
|       key = "DownloadsPath";
 | |
|     else if (this._dict.has("DownloadPath"))
 | |
|       key = "DownloadPath";
 | |
|     else
 | |
|       return;
 | |
| 
 | |
|     let downloadsFolder = FileUtils.File(this._dict.get(key));
 | |
| 
 | |
|     // 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 = [{op: "add",
 | |
|                             fieldname: "searchbar-history",
 | |
|                             value: searchString}
 | |
|                            for (searchString of recentSearchStrings)];
 | |
|             FormHistory.update(changes);
 | |
|           }
 | |
|         }
 | |
|       }.bind(this), aCallback));
 | |
|   }
 | |
| };
 | |
| 
 | |
| #ifdef XP_MACOSX
 | |
| // On OS X, the cookie-accept policy preference is stored in a separate
 | |
| // property list.
 | |
| // For the Windows version, check Preferences.migrate.
 | |
| 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 = acceptCookies == "never" ? 2 :
 | |
|                             acceptCookies == "current page" ? 1 : 0;
 | |
|           Services.prefs.setIntPref("network.cookie.cookieBehavior",
 | |
|                                     cookieValue);
 | |
|         }
 | |
|       }.bind(this), aCallback));
 | |
|   }
 | |
| };
 | |
| #endif
 | |
| 
 | |
| function SafariProfileMigrator() {
 | |
| }
 | |
| 
 | |
| SafariProfileMigrator.prototype = Object.create(MigratorPrototype);
 | |
| 
 | |
| SafariProfileMigrator.prototype.getResources = function SM_getResources() {
 | |
|   let profileDir =
 | |
| #ifdef XP_MACOSX
 | |
|     FileUtils.getDir("ULibDir", ["Safari"], false);
 | |
| #else
 | |
|     FileUtils.getDir("AppData", ["Apple Computer", "Safari"], false);
 | |
| #endif
 | |
|   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 isn't #ifdefed out on mac, because
 | |
|   // Apple may fix this at some point.
 | |
|   pushProfileFileResource("ReadingList.plist", Bookmarks);
 | |
| 
 | |
|   let prefsDir = 
 | |
| #ifdef XP_MACOSX
 | |
|     FileUtils.getDir("UsrPrfs", [], false);
 | |
| #else
 | |
|     FileUtils.getDir("AppData", ["Apple Computer", "Preferences"], false);
 | |
| #endif
 | |
| 
 | |
|   let prefs = this.mainPreferencesPropertyList;
 | |
|   if (prefs) {
 | |
|     resources.push(new Preferences(prefs));
 | |
|     resources.push(new SearchStrings(prefs));
 | |
|   }
 | |
| 
 | |
| #ifdef XP_MACOSX
 | |
|   // On OS X, the cookie-accept policy preference is stored in a separate
 | |
|   // property list.
 | |
|   let wfFile = FileUtils.getFile("UsrPrfs", ["com.apple.WebFoundation.plist"]);
 | |
|   if (wfFile.exists())
 | |
|     resources.push(new WebFoundationCookieBehavior(wfFile));
 | |
| #endif
 | |
| 
 | |
|   return resources;
 | |
| };
 | |
| 
 | |
| Object.defineProperty(SafariProfileMigrator.prototype, "mainPreferencesPropertyList", {
 | |
|   get: function get_mainPreferencesPropertyList() {
 | |
|     if (this._mainPreferencesPropertyList === undefined) {
 | |
|       let file = 
 | |
| #ifdef XP_MACOSX
 | |
|         FileUtils.getDir("UsrPrfs", [], false);
 | |
| #else
 | |
|         FileUtils.getDir("AppData", ["Apple Computer", "Preferences"], false);
 | |
| #endif
 | |
|       if (file.exists()) {
 | |
|         file.append("com.apple.Safari.plist");
 | |
|         if (file.exists()) {
 | |
|           return this._mainPreferencesPropertyList =
 | |
|             new MainPreferencesPropertyList(file);
 | |
|         }
 | |
|       }
 | |
|       return this._mainPreferencesPropertyList = null;
 | |
|     }
 | |
|     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]);
 |