|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 "use strict"; |
|
6 |
|
7 let Cc = Components.classes; |
|
8 let Ci = Components.interfaces; |
|
9 let Cu = Components.utils; |
|
10 |
|
11 Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
12 Cu.import("resource://gre/modules/FileUtils.jsm"); |
|
13 Cu.import("resource://gre/modules/Services.jsm"); |
|
14 Cu.import("resource:///modules/MigrationUtils.jsm"); |
|
15 |
|
16 XPCOMUtils.defineLazyModuleGetter(this, "PropertyListUtils", |
|
17 "resource://gre/modules/PropertyListUtils.jsm"); |
|
18 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", |
|
19 "resource://gre/modules/PlacesUtils.jsm"); |
|
20 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", |
|
21 "resource://gre/modules/NetUtil.jsm"); |
|
22 XPCOMUtils.defineLazyModuleGetter(this, "FormHistory", |
|
23 "resource://gre/modules/FormHistory.jsm"); |
|
24 |
|
25 function Bookmarks(aBookmarksFile) { |
|
26 this._file = aBookmarksFile; |
|
27 } |
|
28 Bookmarks.prototype = { |
|
29 type: MigrationUtils.resourceTypes.BOOKMARKS, |
|
30 |
|
31 migrate: function B_migrate(aCallback) { |
|
32 PropertyListUtils.read(this._file, |
|
33 MigrationUtils.wrapMigrateFunction(function migrateBookmarks(aDict) { |
|
34 if (!aDict) |
|
35 throw new Error("Could not read Bookmarks.plist"); |
|
36 |
|
37 let children = aDict.get("Children");; |
|
38 if (!children) |
|
39 throw new Error("Invalid Bookmarks.plist format"); |
|
40 |
|
41 PlacesUtils.bookmarks.runInBatchMode({ |
|
42 runBatched: function() { |
|
43 let collection = aDict.get("Title") == "com.apple.ReadingList" ? |
|
44 this.READING_LIST_COLLECTION : this.ROOT_COLLECTION; |
|
45 this._migrateCollection(children, collection); |
|
46 }.bind(this) |
|
47 }, null); |
|
48 }.bind(this), aCallback)); |
|
49 }, |
|
50 |
|
51 // Bookmarks collections in Safari. Constants for migrateCollection. |
|
52 ROOT_COLLECTION: 0, |
|
53 MENU_COLLECTION: 1, |
|
54 TOOLBAR_COLLECTION: 2, |
|
55 READING_LIST_COLLECTION: 3, |
|
56 |
|
57 /** |
|
58 * Recursively migrate a Safari collection of bookmarks. |
|
59 * |
|
60 * @param aEntries |
|
61 * the collection's children |
|
62 * @param aCollection |
|
63 * one of the values above. |
|
64 */ |
|
65 _migrateCollection: function B__migrateCollection(aEntries, aCollection) { |
|
66 // A collection of bookmarks in Safari resembles places roots. In the |
|
67 // property list files (Bookmarks.plist, ReadingList.plist) they are |
|
68 // stored as regular bookmarks folders, and thus can only be distinguished |
|
69 // from by their names and places in the hierarchy. |
|
70 |
|
71 let entriesFiltered = []; |
|
72 if (aCollection == this.ROOT_COLLECTION) { |
|
73 for (let entry of aEntries) { |
|
74 let type = entry.get("WebBookmarkType"); |
|
75 if (type == "WebBookmarkTypeList" && entry.has("Children")) { |
|
76 let title = entry.get("Title"); |
|
77 let children = entry.get("Children"); |
|
78 if (title == "BookmarksBar") |
|
79 this._migrateCollection(children, this.TOOLBAR_COLLECTION); |
|
80 else if (title == "BookmarksMenu") |
|
81 this._migrateCollection(children, this.MENU_COLLECTION); |
|
82 else if (title == "com.apple.ReadingList") |
|
83 this._migrateCollection(children, this.READING_LIST_COLLECTION); |
|
84 else if (entry.get("ShouldOmitFromUI") !== true) |
|
85 entriesFiltered.push(entry); |
|
86 } |
|
87 else if (type == "WebBookmarkTypeLeaf") { |
|
88 entriesFiltered.push(entry); |
|
89 } |
|
90 } |
|
91 } |
|
92 else { |
|
93 entriesFiltered = aEntries; |
|
94 } |
|
95 |
|
96 if (entriesFiltered.length == 0) |
|
97 return; |
|
98 |
|
99 let folder = -1; |
|
100 switch (aCollection) { |
|
101 case this.ROOT_COLLECTION: { |
|
102 // In Safari, it is possible (though quite cumbersome) to move |
|
103 // bookmarks to the bookmarks root, which is the parent folder of |
|
104 // all bookmarks "collections". That is somewhat in parallel with |
|
105 // both the places root and the unfiled-bookmarks root. |
|
106 // Because the former is only an implementation detail in our UI, |
|
107 // the unfiled root seems to be the best choice. |
|
108 folder = PlacesUtils.unfiledBookmarksFolderId; |
|
109 break; |
|
110 } |
|
111 case this.MENU_COLLECTION: { |
|
112 folder = PlacesUtils.bookmarksMenuFolderId; |
|
113 if (!MigrationUtils.isStartupMigration) { |
|
114 folder = MigrationUtils.createImportedBookmarksFolder("Safari", |
|
115 folder); |
|
116 } |
|
117 break; |
|
118 } |
|
119 case this.TOOLBAR_COLLECTION: { |
|
120 folder = PlacesUtils.toolbarFolderId; |
|
121 if (!MigrationUtils.isStartupMigration) { |
|
122 folder = MigrationUtils.createImportedBookmarksFolder("Safari", |
|
123 folder); |
|
124 } |
|
125 break; |
|
126 } |
|
127 case this.READING_LIST_COLLECTION: { |
|
128 // Reading list items are imported as regular bookmarks. |
|
129 // They are imported under their own folder, created either under the |
|
130 // bookmarks menu (in the case of startup migration). |
|
131 folder = PlacesUtils.bookmarks.createFolder( |
|
132 PlacesUtils.bookmarksMenuFolderId, |
|
133 MigrationUtils.getLocalizedString("importedSafariReadingList"), |
|
134 PlacesUtils.bookmarks.DEFAULT_INDEX); |
|
135 break; |
|
136 } |
|
137 default: |
|
138 throw new Error("Unexpected value for aCollection!"); |
|
139 } |
|
140 |
|
141 this._migrateEntries(entriesFiltered, folder); |
|
142 }, |
|
143 |
|
144 // migrate the given array of safari bookmarks to the given places |
|
145 // folder. |
|
146 _migrateEntries: function B__migrateEntries(aEntries, aFolderId) { |
|
147 for (let entry of aEntries) { |
|
148 let type = entry.get("WebBookmarkType"); |
|
149 if (type == "WebBookmarkTypeList" && entry.has("Children")) { |
|
150 let title = entry.get("Title"); |
|
151 let folderId = PlacesUtils.bookmarks.createFolder( |
|
152 aFolderId, title, PlacesUtils.bookmarks.DEFAULT_INDEX); |
|
153 |
|
154 // Empty folders may not have a children array. |
|
155 if (entry.has("Children")) |
|
156 this._migrateEntries(entry.get("Children"), folderId, false); |
|
157 } |
|
158 else if (type == "WebBookmarkTypeLeaf" && entry.has("URLString")) { |
|
159 let title, uri; |
|
160 if (entry.has("URIDictionary")) |
|
161 title = entry.get("URIDictionary").get("title"); |
|
162 |
|
163 try { |
|
164 uri = NetUtil.newURI(entry.get("URLString")); |
|
165 } |
|
166 catch(ex) { |
|
167 Cu.reportError("Invalid uri set for Safari bookmark: " + entry.get("URLString")); |
|
168 } |
|
169 if (uri) { |
|
170 PlacesUtils.bookmarks.insertBookmark(aFolderId, uri, |
|
171 PlacesUtils.bookmarks.DEFAULT_INDEX, title); |
|
172 } |
|
173 } |
|
174 } |
|
175 } |
|
176 }; |
|
177 |
|
178 function History(aHistoryFile) { |
|
179 this._file = aHistoryFile; |
|
180 } |
|
181 History.prototype = { |
|
182 type: MigrationUtils.resourceTypes.HISTORY, |
|
183 |
|
184 // Helper method for converting the visit date property to a PRTime value. |
|
185 // The visit date is stored as a string, so it's not read as a Date |
|
186 // object by PropertyListUtils. |
|
187 _parseCocoaDate: function H___parseCocoaDate(aCocoaDateStr) { |
|
188 let asDouble = parseFloat(aCocoaDateStr); |
|
189 if (!isNaN(asDouble)) { |
|
190 // reference date of NSDate. |
|
191 let date = new Date("1 January 2001, GMT"); |
|
192 date.setMilliseconds(asDouble * 1000); |
|
193 return date * 1000; |
|
194 } |
|
195 return 0; |
|
196 }, |
|
197 |
|
198 migrate: function H_migrate(aCallback) { |
|
199 PropertyListUtils.read(this._file, function migrateHistory(aDict) { |
|
200 try { |
|
201 if (!aDict) |
|
202 throw new Error("Could not read history property list"); |
|
203 if (!aDict.has("WebHistoryDates")) |
|
204 throw new Error("Unexpected history-property list format"); |
|
205 |
|
206 // Safari's History file contains only top-level urls. It does not |
|
207 // distinguish between typed urls and linked urls. |
|
208 let transType = PlacesUtils.history.TRANSITION_LINK; |
|
209 |
|
210 let places = []; |
|
211 let entries = aDict.get("WebHistoryDates"); |
|
212 for (let entry of entries) { |
|
213 if (entry.has("lastVisitedDate")) { |
|
214 let visitDate = this._parseCocoaDate(entry.get("lastVisitedDate")); |
|
215 try { |
|
216 places.push({ uri: NetUtil.newURI(entry.get("")), |
|
217 title: entry.get("title"), |
|
218 visits: [{ transitionType: transType, |
|
219 visitDate: visitDate }] }); |
|
220 } |
|
221 catch(ex) { |
|
222 // Safari's History file may contain malformed URIs which |
|
223 // will be ignored. |
|
224 Cu.reportError(ex) |
|
225 } |
|
226 } |
|
227 } |
|
228 if (places.length > 0) { |
|
229 PlacesUtils.asyncHistory.updatePlaces(places, { |
|
230 _success: false, |
|
231 handleResult: function() { |
|
232 // Importing any entry is considered a successful import. |
|
233 this._success = true; |
|
234 }, |
|
235 handleError: function() {}, |
|
236 handleCompletion: function() { |
|
237 aCallback(this._success); |
|
238 } |
|
239 }); |
|
240 } |
|
241 else { |
|
242 aCallback(false); |
|
243 } |
|
244 } |
|
245 catch(ex) { |
|
246 Cu.reportError(ex); |
|
247 aCallback(false); |
|
248 } |
|
249 }.bind(this)); |
|
250 } |
|
251 }; |
|
252 |
|
253 /** |
|
254 * Safari's preferences property list is independently used for three purposes: |
|
255 * (a) importation of preferences |
|
256 * (b) importation of search strings |
|
257 * (c) retrieving the home page. |
|
258 * |
|
259 * So, rather than reading it three times, it's cached and managed here. |
|
260 */ |
|
261 function MainPreferencesPropertyList(aPreferencesFile) { |
|
262 this._file = aPreferencesFile; |
|
263 this._callbacks = []; |
|
264 } |
|
265 MainPreferencesPropertyList.prototype = { |
|
266 /** |
|
267 * @see PropertyListUtils.read |
|
268 */ |
|
269 read: function MPPL_read(aCallback) { |
|
270 if ("_dict" in this) { |
|
271 aCallback(this._dict); |
|
272 return; |
|
273 } |
|
274 |
|
275 let alreadyReading = this._callbacks.length > 0; |
|
276 this._callbacks.push(aCallback); |
|
277 if (!alreadyReading) { |
|
278 PropertyListUtils.read(this._file, function readPrefs(aDict) { |
|
279 this._dict = aDict; |
|
280 for (let callback of this._callbacks) { |
|
281 try { |
|
282 callback(aDict); |
|
283 } |
|
284 catch(ex) { |
|
285 Cu.reportError(ex); |
|
286 } |
|
287 } |
|
288 this._callbacks.splice(0); |
|
289 }.bind(this)); |
|
290 } |
|
291 }, |
|
292 |
|
293 // Workaround for nsIBrowserProfileMigrator.sourceHomePageURL until |
|
294 // it's replaced with an async method. |
|
295 _readSync: function MPPL__readSync() { |
|
296 if ("_dict" in this) |
|
297 return this._dict; |
|
298 |
|
299 let inputStream = Cc["@mozilla.org/network/file-input-stream;1"]. |
|
300 createInstance(Ci.nsIFileInputStream); |
|
301 inputStream.init(this._file, -1, -1, 0); |
|
302 let binaryStream = Cc["@mozilla.org/binaryinputstream;1"]. |
|
303 createInstance(Ci.nsIBinaryInputStream); |
|
304 binaryStream.setInputStream(inputStream); |
|
305 let bytes = binaryStream.readByteArray(inputStream.available()); |
|
306 this._dict = PropertyListUtils._readFromArrayBufferSync( |
|
307 new Uint8Array(bytes).buffer); |
|
308 return this._dict; |
|
309 } |
|
310 }; |
|
311 |
|
312 function Preferences(aMainPreferencesPropertyListInstance) { |
|
313 this._mainPreferencesPropertyList = aMainPreferencesPropertyListInstance; |
|
314 } |
|
315 Preferences.prototype = { |
|
316 type: MigrationUtils.resourceTypes.SETTINGS, |
|
317 |
|
318 migrate: function MPR_migrate(aCallback) { |
|
319 this._mainPreferencesPropertyList.read( |
|
320 MigrationUtils.wrapMigrateFunction(function migratePrefs(aDict) { |
|
321 if (!aDict) |
|
322 throw new Error("Could not read preferences file"); |
|
323 |
|
324 this._dict = aDict; |
|
325 |
|
326 let invert = function(webkitVal) !webkitVal; |
|
327 this._set("AutoFillPasswords", "signon.rememberSignons"); |
|
328 this._set("OpenNewTabsInFront", "browser.tabs.loadInBackground", invert); |
|
329 this._set("WebKitJavaScriptCanOpenWindowsAutomatically", |
|
330 "dom.disable_open_during_load", invert); |
|
331 |
|
332 // layout.spellcheckDefault is a boolean stored as a number. |
|
333 this._set("WebContinuousSpellCheckingEnabled", |
|
334 "layout.spellcheckDefault", Number); |
|
335 |
|
336 // Auto-load images |
|
337 // Firefox has an elaborate set of Image preferences. The correlation is: |
|
338 // Mode: Safari Firefox |
|
339 // Blocked FALSE 2 |
|
340 // Allowed TRUE 1 |
|
341 // Allowed, originating site only -- 3 |
|
342 this._set("WebKitDisplayImagesKey", "permissions.default.image", |
|
343 function(webkitVal) webkitVal ? 1 : 2); |
|
344 |
|
345 #ifdef XP_WIN |
|
346 // Cookie-accept policy. |
|
347 // For the OS X version, see WebFoundationCookieBehavior. |
|
348 // Setting Safari Firefox |
|
349 // Always Accept 0 0 |
|
350 // Accept from Originating 2 1 |
|
351 // Never Accept 1 2 |
|
352 this._set("WebKitCookieStorageAcceptPolicy", |
|
353 "network.cookie.cookieBehavior", |
|
354 function(webkitVal) webkitVal == 0 ? 0 : webkitVal == 1 ? 2 : 1); |
|
355 #endif |
|
356 |
|
357 this._migrateFontSettings(); |
|
358 this._migrateDownloadsFolder(); |
|
359 }.bind(this), aCallback)); |
|
360 }, |
|
361 |
|
362 /** |
|
363 * Attempts to migrates a preference from Safari. Returns whether the preference |
|
364 * has been migrated. |
|
365 * @param aSafariKey |
|
366 * The dictionary key for the preference of Safari. |
|
367 * @param aMozPref |
|
368 * The gecko/firefox preference to which aSafariKey should be migrated |
|
369 * @param [optional] aConvertFunction(aSafariValue) |
|
370 * a function that converts the safari-preference value to the |
|
371 * appropriate value for aMozPref. If it's not passed, then the |
|
372 * Safari value is set as is. |
|
373 * If aConvertFunction returns undefined, then aMozPref is not set |
|
374 * at all. |
|
375 * @return whether or not aMozPref was set. |
|
376 */ |
|
377 _set: function MPR_set(aSafariKey, aMozPref, aConvertFunction) { |
|
378 if (this._dict.has(aSafariKey)) { |
|
379 let safariVal = this._dict.get(aSafariKey); |
|
380 let mozVal = aConvertFunction !== undefined ? |
|
381 aConvertFunction(safariVal) : safariVal; |
|
382 switch (typeof(mozVal)) { |
|
383 case "string": |
|
384 Services.prefs.setCharPref(aMozPref, mozVal); |
|
385 break; |
|
386 case "number": |
|
387 Services.prefs.setIntPref(aMozPref, mozVal); |
|
388 break; |
|
389 case "boolean": |
|
390 Services.prefs.setBoolPref(aMozPref, mozVal); |
|
391 break; |
|
392 case "undefined": |
|
393 return false; |
|
394 default: |
|
395 throw new Error("Unexpected value type: " + typeof(mozVal)); |
|
396 } |
|
397 } |
|
398 return true; |
|
399 }, |
|
400 |
|
401 // Fonts settings are quite problematic for migration, for a couple of |
|
402 // reasons: |
|
403 // (a) Every font preference in Gecko is set for a particular language. |
|
404 // In Safari, each font preference applies to all languages. |
|
405 // (b) The current underlying implementation of nsIFontEnumerator cannot |
|
406 // really tell you anything about a font: no matter what language or type |
|
407 // you try to enumerate with EnumerateFonts, you get an array of all |
|
408 // fonts in the systems (This also breaks our fonts dialog). |
|
409 // (c) In Gecko, each langauge has a distinct serif and sans-serif font |
|
410 // preference. Safari has only one default font setting. It seems that |
|
411 // it checks if it's a serif or sans serif font, and when a site |
|
412 // explicitly asks to use serif/sans-serif font, it uses the default font |
|
413 // only if it applies to this type. |
|
414 // (d) The solution of guessing the lang-group out of the default charset (as |
|
415 // done in the old Safari migrator) can only work when: |
|
416 // (1) The default charset preference is set. |
|
417 // (2) It's not a unicode charset. |
|
418 // For now, we use the language implied by the system locale as the |
|
419 // lang-group. The only exception is minimal font size, which is an |
|
420 // accessibility preference in Safari (under the Advanced tab). If it is set, |
|
421 // we set it for all languages. |
|
422 // As for the font type of the default font (serif/sans-serif), the default |
|
423 // type for the given language is used (set in font.default.LANGGROUP). |
|
424 _migrateFontSettings: function MPR__migrateFontSettings() { |
|
425 // If "Never use font sizes smaller than [ ] is set", migrate it for all |
|
426 // languages. |
|
427 if (this._dict.has("WebKitMinimumFontSize")) { |
|
428 let minimumSize = this._dict.get("WebKitMinimumFontSize"); |
|
429 if (typeof(minimumSize) == "number") { |
|
430 let prefs = Services.prefs.getChildList("font.minimum-size"); |
|
431 for (let pref of prefs) { |
|
432 Services.prefs.setIntPref(pref, minimumSize); |
|
433 } |
|
434 } |
|
435 else { |
|
436 Cu.reportError("WebKitMinimumFontSize was set to an invalid value: " + |
|
437 minimumSize); |
|
438 } |
|
439 } |
|
440 |
|
441 // In theory, the lang group could be "x-unicode". This will result |
|
442 // in setting the fonts for "Other Languages". |
|
443 let lang = this._getLocaleLangGroup(); |
|
444 |
|
445 let anySet = false; |
|
446 let fontType = Services.prefs.getCharPref("font.default." + lang); |
|
447 anySet |= this._set("WebKitFixedFont", "font.name.monospace." + lang); |
|
448 anySet |= this._set("WebKitDefaultFixedFontSize", "font.size.fixed." + lang); |
|
449 anySet |= this._set("WebKitStandardFont", |
|
450 "font.name." + fontType + "." + lang); |
|
451 anySet |= this._set("WebKitDefaultFontSize", "font.size.variable." + lang); |
|
452 |
|
453 // If we set font settings for a particular language, we'll also set the |
|
454 // fonts dialog to open with the fonts settings for that langauge. |
|
455 if (anySet) |
|
456 Services.prefs.setCharPref("font.language.group", lang); |
|
457 }, |
|
458 |
|
459 // Get the language group for the system locale. |
|
460 _getLocaleLangGroup: function MPR__getLocaleLangGroup() { |
|
461 let locale = Services.locale.getLocaleComponentForUserAgent(); |
|
462 |
|
463 // See nsLanguageAtomService::GetLanguageGroup |
|
464 let localeLangGroup = "x-unicode"; |
|
465 let bundle = Services.strings.createBundle( |
|
466 "resource://gre/res/langGroups.properties"); |
|
467 try { |
|
468 localeLangGroup = bundle.GetStringFromName(locale); |
|
469 } |
|
470 catch(ex) { |
|
471 let hyphenAt = locale.indexOf("-"); |
|
472 if (hyphenAt != -1) { |
|
473 try { |
|
474 localeLangGroup = bundle.GetStringFromName(locale.substr(0, hyphenAt)); |
|
475 } |
|
476 catch(ex2) { } |
|
477 } |
|
478 } |
|
479 return localeLangGroup; |
|
480 }, |
|
481 |
|
482 _migrateDownloadsFolder: function MPR__migrateDownloadsFolder() { |
|
483 // Windows Safari uses DownloadPath while Mac uses DownloadsPath. |
|
484 // Check both for future compatibility. |
|
485 let key; |
|
486 if (this._dict.has("DownloadsPath")) |
|
487 key = "DownloadsPath"; |
|
488 else if (this._dict.has("DownloadPath")) |
|
489 key = "DownloadPath"; |
|
490 else |
|
491 return; |
|
492 |
|
493 let downloadsFolder = FileUtils.File(this._dict.get(key)); |
|
494 |
|
495 // If the download folder is set to the Desktop or to ~/Downloads, set the |
|
496 // folderList pref appropriately so that "Desktop"/Downloads is shown with |
|
497 // pretty name in the preferences dialog. |
|
498 let folderListVal = 2; |
|
499 if (downloadsFolder.equals(FileUtils.getDir("Desk", []))) { |
|
500 folderListVal = 0; |
|
501 } |
|
502 else { |
|
503 let dnldMgr = Cc["@mozilla.org/download-manager;1"]. |
|
504 getService(Ci.nsIDownloadManager); |
|
505 if (downloadsFolder.equals(dnldMgr.defaultDownloadsDirectory)) |
|
506 folderListVal = 1; |
|
507 } |
|
508 Services.prefs.setIntPref("browser.download.folderList", folderListVal); |
|
509 Services.prefs.setComplexValue("browser.download.dir", Ci.nsILocalFile, |
|
510 downloadsFolder); |
|
511 } |
|
512 }; |
|
513 |
|
514 function SearchStrings(aMainPreferencesPropertyListInstance) { |
|
515 this._mainPreferencesPropertyList = aMainPreferencesPropertyListInstance; |
|
516 } |
|
517 SearchStrings.prototype = { |
|
518 type: MigrationUtils.resourceTypes.OTHERDATA, |
|
519 |
|
520 migrate: function SS_migrate(aCallback) { |
|
521 this._mainPreferencesPropertyList.read(MigrationUtils.wrapMigrateFunction( |
|
522 function migrateSearchStrings(aDict) { |
|
523 if (!aDict) |
|
524 throw new Error("Could not get preferences dictionary"); |
|
525 |
|
526 if (aDict.has("RecentSearchStrings")) { |
|
527 let recentSearchStrings = aDict.get("RecentSearchStrings"); |
|
528 if (recentSearchStrings && recentSearchStrings.length > 0) { |
|
529 let changes = [{op: "add", |
|
530 fieldname: "searchbar-history", |
|
531 value: searchString} |
|
532 for (searchString of recentSearchStrings)]; |
|
533 FormHistory.update(changes); |
|
534 } |
|
535 } |
|
536 }.bind(this), aCallback)); |
|
537 } |
|
538 }; |
|
539 |
|
540 #ifdef XP_MACOSX |
|
541 // On OS X, the cookie-accept policy preference is stored in a separate |
|
542 // property list. |
|
543 // For the Windows version, check Preferences.migrate. |
|
544 function WebFoundationCookieBehavior(aWebFoundationFile) { |
|
545 this._file = aWebFoundationFile; |
|
546 } |
|
547 WebFoundationCookieBehavior.prototype = { |
|
548 type: MigrationUtils.resourceTypes.SETTINGS, |
|
549 |
|
550 migrate: function WFPL_migrate(aCallback) { |
|
551 PropertyListUtils.read(this._file, MigrationUtils.wrapMigrateFunction( |
|
552 function migrateCookieBehavior(aDict) { |
|
553 if (!aDict) |
|
554 throw new Error("Could not read com.apple.WebFoundation.plist"); |
|
555 |
|
556 if (aDict.has("NSHTTPAcceptCookies")) { |
|
557 // Setting Safari Firefox |
|
558 // Always Accept always 0 |
|
559 // Accept from Originating current page 1 |
|
560 // Never Accept never 2 |
|
561 let acceptCookies = aDict.get("NSHTTPAcceptCookies"); |
|
562 let cookieValue = acceptCookies == "never" ? 2 : |
|
563 acceptCookies == "current page" ? 1 : 0; |
|
564 Services.prefs.setIntPref("network.cookie.cookieBehavior", |
|
565 cookieValue); |
|
566 } |
|
567 }.bind(this), aCallback)); |
|
568 } |
|
569 }; |
|
570 #endif |
|
571 |
|
572 function SafariProfileMigrator() { |
|
573 } |
|
574 |
|
575 SafariProfileMigrator.prototype = Object.create(MigratorPrototype); |
|
576 |
|
577 SafariProfileMigrator.prototype.getResources = function SM_getResources() { |
|
578 let profileDir = |
|
579 #ifdef XP_MACOSX |
|
580 FileUtils.getDir("ULibDir", ["Safari"], false); |
|
581 #else |
|
582 FileUtils.getDir("AppData", ["Apple Computer", "Safari"], false); |
|
583 #endif |
|
584 if (!profileDir.exists()) |
|
585 return null; |
|
586 |
|
587 let resources = []; |
|
588 let pushProfileFileResource = function(aFileName, aConstructor) { |
|
589 let file = profileDir.clone(); |
|
590 file.append(aFileName); |
|
591 if (file.exists()) |
|
592 resources.push(new aConstructor(file)); |
|
593 }; |
|
594 |
|
595 pushProfileFileResource("History.plist", History); |
|
596 pushProfileFileResource("Bookmarks.plist", Bookmarks); |
|
597 |
|
598 // The Reading List feature was introduced at the same time in Windows and |
|
599 // Mac versions of Safari. Not surprisingly, they are stored in the same |
|
600 // format in both versions. Surpsingly, only on Windows there is a |
|
601 // separate property list for it. This isn't #ifdefed out on mac, because |
|
602 // Apple may fix this at some point. |
|
603 pushProfileFileResource("ReadingList.plist", Bookmarks); |
|
604 |
|
605 let prefsDir = |
|
606 #ifdef XP_MACOSX |
|
607 FileUtils.getDir("UsrPrfs", [], false); |
|
608 #else |
|
609 FileUtils.getDir("AppData", ["Apple Computer", "Preferences"], false); |
|
610 #endif |
|
611 |
|
612 let prefs = this.mainPreferencesPropertyList; |
|
613 if (prefs) { |
|
614 resources.push(new Preferences(prefs)); |
|
615 resources.push(new SearchStrings(prefs)); |
|
616 } |
|
617 |
|
618 #ifdef XP_MACOSX |
|
619 // On OS X, the cookie-accept policy preference is stored in a separate |
|
620 // property list. |
|
621 let wfFile = FileUtils.getFile("UsrPrfs", ["com.apple.WebFoundation.plist"]); |
|
622 if (wfFile.exists()) |
|
623 resources.push(new WebFoundationCookieBehavior(wfFile)); |
|
624 #endif |
|
625 |
|
626 return resources; |
|
627 }; |
|
628 |
|
629 Object.defineProperty(SafariProfileMigrator.prototype, "mainPreferencesPropertyList", { |
|
630 get: function get_mainPreferencesPropertyList() { |
|
631 if (this._mainPreferencesPropertyList === undefined) { |
|
632 let file = |
|
633 #ifdef XP_MACOSX |
|
634 FileUtils.getDir("UsrPrfs", [], false); |
|
635 #else |
|
636 FileUtils.getDir("AppData", ["Apple Computer", "Preferences"], false); |
|
637 #endif |
|
638 if (file.exists()) { |
|
639 file.append("com.apple.Safari.plist"); |
|
640 if (file.exists()) { |
|
641 return this._mainPreferencesPropertyList = |
|
642 new MainPreferencesPropertyList(file); |
|
643 } |
|
644 } |
|
645 return this._mainPreferencesPropertyList = null; |
|
646 } |
|
647 return this._mainPreferencesPropertyList; |
|
648 } |
|
649 }); |
|
650 |
|
651 Object.defineProperty(SafariProfileMigrator.prototype, "sourceHomePageURL", { |
|
652 get: function get_sourceHomePageURL() { |
|
653 if (this.mainPreferencesPropertyList) { |
|
654 let dict = this.mainPreferencesPropertyList._readSync(); |
|
655 if (dict.has("HomePage")) |
|
656 return dict.get("HomePage"); |
|
657 } |
|
658 return ""; |
|
659 } |
|
660 }); |
|
661 |
|
662 SafariProfileMigrator.prototype.classDescription = "Safari Profile Migrator"; |
|
663 SafariProfileMigrator.prototype.contractID = "@mozilla.org/profile/migrator;1?app=browser&type=safari"; |
|
664 SafariProfileMigrator.prototype.classID = Components.ID("{4b609ecf-60b2-4655-9df4-dc149e474da1}"); |
|
665 |
|
666 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SafariProfileMigrator]); |