Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / browser / components / migration / src / nsSafariProfileMigrator.cpp
blobbec4a9995bd116bcb6d809c104cbffedacb127e7
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is The Browser Profile Migrator.
17 * The Initial Developer of the Original Code is Ben Goodger.
18 * Portions created by the Initial Developer are Copyright (C) 2004
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * Ben Goodger <ben@bengoodger.com>
23 * Asaf Romano <mozilla.mano@sent.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #include "nsAppDirectoryServiceDefs.h"
40 #include "nsBrowserProfileMigratorUtils.h"
41 #include "nsDirectoryServiceDefs.h"
42 #include "nsDirectoryServiceUtils.h"
43 #include "nsDocShellCID.h"
44 #include "nsINavBookmarksService.h"
45 #include "nsBrowserCompsCID.h"
46 #include "nsIBrowserHistory.h"
47 #include "nsICookieManager2.h"
48 #include "nsIFileProtocolHandler.h"
49 #include "nsIFormHistory.h"
50 #include "nsIIOService.h"
51 #include "nsILocalFileMac.h"
52 #include "nsIObserverService.h"
53 #include "nsIPrefService.h"
54 #include "nsIProfileMigrator.h"
55 #include "nsIProtocolHandler.h"
56 #include "nsIRDFContainer.h"
57 #include "nsIRDFDataSource.h"
58 #include "nsIRDFRemoteDataSource.h"
59 #include "nsIRDFService.h"
60 #include "nsIServiceManager.h"
61 #include "nsIStringBundle.h"
62 #include "nsISupportsArray.h"
63 #include "nsISupportsPrimitives.h"
64 #include "nsSafariProfileMigrator.h"
65 #include "nsToolkitCompsCID.h"
66 #include "nsNetUtil.h"
67 #include "nsTArray.h"
69 #include <Carbon/Carbon.h>
71 #define SAFARI_PREFERENCES_FILE_NAME NS_LITERAL_STRING("com.apple.Safari.plist")
72 #define SAFARI_BOOKMARKS_FILE_NAME NS_LITERAL_STRING("Bookmarks.plist")
73 #define SAFARI_HISTORY_FILE_NAME NS_LITERAL_STRING("History.plist")
74 #define SAFARI_COOKIES_FILE_NAME NS_LITERAL_STRING("Cookies.plist")
75 #define SAFARI_COOKIE_BEHAVIOR_FILE_NAME NS_LITERAL_STRING("com.apple.WebFoundation.plist")
76 #define SAFARI_DATE_OFFSET 978307200
77 #define SAFARI_HOME_PAGE_PREF "HomePage"
78 #define MIGRATION_BUNDLE "chrome://browser/locale/migration/migration.properties"
80 ///////////////////////////////////////////////////////////////////////////////
81 // nsSafariProfileMigrator
83 NS_IMPL_ISUPPORTS1(nsSafariProfileMigrator, nsIBrowserProfileMigrator)
85 nsSafariProfileMigrator::nsSafariProfileMigrator()
87 mObserverService = do_GetService("@mozilla.org/observer-service;1");
90 nsSafariProfileMigrator::~nsSafariProfileMigrator()
94 ///////////////////////////////////////////////////////////////////////////////
95 // nsIBrowserProfileMigrator
97 NS_IMETHODIMP
98 nsSafariProfileMigrator::Migrate(PRUint16 aItems, nsIProfileStartup* aStartup,
99 const PRUnichar* aProfile)
101 nsresult rv = NS_OK;
103 PRBool replace = PR_FALSE;
105 if (aStartup) {
106 replace = PR_TRUE;
107 rv = aStartup->DoStartup();
108 NS_ENSURE_SUCCESS(rv, rv);
111 NOTIFY_OBSERVERS(MIGRATION_STARTED, nsnull);
113 COPY_DATA(CopyPreferences, replace, nsIBrowserProfileMigrator::SETTINGS);
114 COPY_DATA(CopyCookies, replace, nsIBrowserProfileMigrator::COOKIES);
115 COPY_DATA(CopyHistory, replace, nsIBrowserProfileMigrator::HISTORY);
116 COPY_DATA(CopyBookmarks, replace, nsIBrowserProfileMigrator::BOOKMARKS);
117 COPY_DATA(CopyFormData, replace, nsIBrowserProfileMigrator::FORMDATA);
118 COPY_DATA(CopyOtherData, replace, nsIBrowserProfileMigrator::OTHERDATA);
120 NOTIFY_OBSERVERS(MIGRATION_ENDED, nsnull);
122 return rv;
125 NS_IMETHODIMP
126 nsSafariProfileMigrator::GetMigrateData(const PRUnichar* aProfile,
127 PRBool aReplace,
128 PRUint16* aResult)
130 *aResult = 0;
131 nsCOMPtr<nsIProperties> fileLocator(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
132 nsCOMPtr<nsILocalFile> safariSettingsDir, safariCookiesDir;
133 fileLocator->Get(NS_MAC_USER_LIB_DIR, NS_GET_IID(nsILocalFile),
134 getter_AddRefs(safariSettingsDir));
135 safariSettingsDir->Append(NS_LITERAL_STRING("Safari"));
136 fileLocator->Get(NS_MAC_USER_LIB_DIR, NS_GET_IID(nsILocalFile),
137 getter_AddRefs(safariCookiesDir));
138 safariCookiesDir->Append(NS_LITERAL_STRING("Cookies"));
140 // Safari stores most of its user settings under ~/Library/Safari/
141 MigrationData data[] = { { ToNewUnicode(SAFARI_HISTORY_FILE_NAME),
142 nsIBrowserProfileMigrator::HISTORY,
143 PR_FALSE },
144 { ToNewUnicode(SAFARI_BOOKMARKS_FILE_NAME),
145 nsIBrowserProfileMigrator::BOOKMARKS,
146 PR_FALSE } };
147 // Frees file name strings allocated above.
148 GetMigrateDataFromArray(data, sizeof(data)/sizeof(MigrationData),
149 aReplace, safariSettingsDir, aResult);
151 // Safari stores Cookies under ~/Library/Cookies/Cookies.plist
152 MigrationData data2[] = { { ToNewUnicode(SAFARI_COOKIES_FILE_NAME),
153 nsIBrowserProfileMigrator::COOKIES,
154 PR_FALSE } };
155 GetMigrateDataFromArray(data2, sizeof(data2)/sizeof(MigrationData),
156 aReplace, safariCookiesDir, aResult);
158 // Safari stores Preferences under ~/Library/Preferences/
159 nsCOMPtr<nsILocalFile> systemPrefsDir;
160 fileLocator->Get(NS_OSX_USER_PREFERENCES_DIR, NS_GET_IID(nsILocalFile),
161 getter_AddRefs(systemPrefsDir));
162 MigrationData data3[]= { { ToNewUnicode(SAFARI_PREFERENCES_FILE_NAME),
163 nsIBrowserProfileMigrator::SETTINGS,
164 PR_FALSE } };
165 GetMigrateDataFromArray(data3, sizeof(data3)/sizeof(MigrationData),
166 aReplace, systemPrefsDir, aResult);
168 // Don't offer to import the Safari user style sheet if the active profile
169 // already has a content style sheet (userContent.css)
170 PRBool hasContentStylesheet = PR_FALSE;
171 if (NS_SUCCEEDED(ProfileHasContentStyleSheet(&hasContentStylesheet)) &&
172 !hasContentStylesheet) {
173 nsCOMPtr<nsILocalFile> safariUserStylesheetFile;
174 if (NS_SUCCEEDED(GetSafariUserStyleSheet(getter_AddRefs(safariUserStylesheetFile))))
175 *aResult |= nsIBrowserProfileMigrator::OTHERDATA;
178 // Don't offer to import that Safari form data if there isn't any
179 if (HasFormDataToImport())
180 *aResult |= nsIBrowserProfileMigrator::FORMDATA;
182 return NS_OK;
185 NS_IMETHODIMP
186 nsSafariProfileMigrator::GetSourceExists(PRBool* aResult)
188 PRUint16 data;
189 GetMigrateData(nsnull, PR_FALSE, &data);
191 *aResult = data != 0;
193 return NS_OK;
196 NS_IMETHODIMP
197 nsSafariProfileMigrator::GetSourceHasMultipleProfiles(PRBool* aResult)
199 // Safari only has one profile per-user.
200 *aResult = PR_FALSE;
201 return NS_OK;
204 NS_IMETHODIMP
205 nsSafariProfileMigrator::GetSourceProfiles(nsISupportsArray** aResult)
207 *aResult = nsnull;
208 return NS_OK;
211 ///////////////////////////////////////////////////////////////////////////////
212 // nsSafariProfileMigrator
214 CFPropertyListRef CopyPListFromFile(nsILocalFile* aPListFile)
216 PRBool exists;
217 aPListFile->Exists(&exists);
218 nsCAutoString filePath;
219 aPListFile->GetNativePath(filePath);
220 if (!exists)
221 return nsnull;
223 nsCOMPtr<nsILocalFileMac> macFile(do_QueryInterface(aPListFile));
224 CFURLRef urlRef;
225 macFile->GetCFURL(&urlRef);
227 CFDataRef resourceData;
229 SInt32 errorCode;
230 Boolean status = ::CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault,
231 urlRef,
232 &resourceData,
233 NULL,
234 NULL,
235 &errorCode);
236 if (!status)
237 return nsnull;
239 CFPropertyListRef result = ::CFPropertyListCreateFromXMLData(kCFAllocatorDefault,
240 resourceData,
241 kCFPropertyListImmutable,
242 NULL);
243 ::CFRelease(resourceData);
244 ::CFRelease(urlRef);
246 return result;
249 CFDictionaryRef CopySafariPrefs()
251 nsCOMPtr<nsIProperties> fileLocator(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
252 nsCOMPtr<nsILocalFile> safariPrefsFile;
253 fileLocator->Get(NS_OSX_USER_PREFERENCES_DIR,
254 NS_GET_IID(nsILocalFile),
255 getter_AddRefs(safariPrefsFile));
257 safariPrefsFile->Append(SAFARI_PREFERENCES_FILE_NAME);
259 return (CFDictionaryRef)CopyPListFromFile(safariPrefsFile);
262 char*
263 GetNullTerminatedString(CFStringRef aStringRef)
265 CFIndex bufferSize = ::CFStringGetLength(aStringRef) + 1;
266 char* buffer = (char*)malloc(sizeof(char) * bufferSize);
267 if (!buffer)
268 return nsnull;
269 if (::CFStringGetCString(aStringRef, buffer, bufferSize,
270 kCFStringEncodingASCII))
271 buffer[bufferSize-1] = '\0';
272 return buffer;
275 void
276 FreeNullTerminatedString(char* aString)
278 free(aString);
279 aString = nsnull;
282 PRBool
283 GetDictionaryStringValue(CFDictionaryRef aDictionary, CFStringRef aKey,
284 nsAString& aResult)
286 CFStringRef value = (CFStringRef)::CFDictionaryGetValue(aDictionary, aKey);
287 if (value) {
288 nsAutoTArray<UniChar, 1024> buffer;
289 CFIndex valueLength = ::CFStringGetLength(value);
290 buffer.SetLength(valueLength);
292 ::CFStringGetCharacters(value, CFRangeMake(0, valueLength), buffer.Elements());
293 aResult.Assign(buffer.Elements(), valueLength);
294 return PR_TRUE;
296 return PR_FALSE;
299 PRBool
300 GetDictionaryCStringValue(CFDictionaryRef aDictionary, CFStringRef aKey,
301 nsACString& aResult, CFStringEncoding aEncoding)
303 CFStringRef value = (CFStringRef)::CFDictionaryGetValue(aDictionary, aKey);
304 if (value) {
305 nsAutoTArray<char, 1024> buffer;
306 CFIndex valueLength = ::CFStringGetLength(value);
307 buffer.SetLength(valueLength + 1);
309 if (::CFStringGetCString(value, buffer.Elements(), valueLength + 1, aEncoding)) {
310 aResult = buffer.Elements();
311 return PR_TRUE;
314 return PR_FALSE;
317 PRBool
318 GetArrayStringValue(CFArrayRef aArray, PRInt32 aIndex, nsAString& aResult)
320 CFStringRef value = (CFStringRef)::CFArrayGetValueAtIndex(aArray, aIndex);
321 if (value) {
322 nsAutoTArray<UniChar, 1024> buffer;
323 CFIndex valueLength = ::CFStringGetLength(value);
324 buffer.SetLength(valueLength);
326 ::CFStringGetCharacters(value, CFRangeMake(0, valueLength), buffer.Elements());
327 aResult.Assign(buffer.Elements(), valueLength);
328 return PR_TRUE;
330 return PR_FALSE;
333 #define _SPM(type) nsSafariProfileMigrator::type
335 static
336 nsSafariProfileMigrator::PrefTransform gTransforms[] = {
337 { CFSTR("AlwaysShowTabBar"), _SPM(BOOL), "browser.tabs.autoHide", _SPM(SetBoolInverted), PR_FALSE, -1 },
338 { CFSTR("AutoFillPasswords"), _SPM(BOOL), "signon.rememberSignons", _SPM(SetBool), PR_FALSE, -1 },
339 { CFSTR("OpenNewTabsInFront"), _SPM(BOOL), "browser.tabs.loadInBackground", _SPM(SetBoolInverted), PR_FALSE, -1 },
340 { CFSTR("NSDefaultOpenDir"), _SPM(STRING), "browser.download.dir", _SPM(SetDownloadFolder), PR_FALSE, -1 },
341 { CFSTR("AutoOpenSafeDownloads"), _SPM(BOOL), nsnull, _SPM(SetDownloadHandlers), PR_FALSE, -1 },
342 { CFSTR("DownloadsClearingPolicy"), _SPM(INT), "browser.download.manager.retention", _SPM(SetDownloadRetention), PR_FALSE, -1 },
343 { CFSTR("WebKitDefaultTextEncodingName"),_SPM(STRING), "intl.charset.default", _SPM(SetDefaultEncoding), PR_FALSE, -1 },
344 { CFSTR("WebKitStandardFont"), _SPM(STRING), "font.name.serif.", _SPM(SetFontName), PR_FALSE, -1 },
345 { CFSTR("WebKitDefaultFontSize"), _SPM(INT), "font.size.serif.", _SPM(SetFontSize), PR_FALSE, -1 },
346 { CFSTR("WebKitFixedFont"), _SPM(STRING), "font.name.fixed.", _SPM(SetFontName), PR_FALSE, -1 },
347 { CFSTR("WebKitDefaultFixedFontSize"), _SPM(INT), "font.size.fixed.", _SPM(SetFontSize), PR_FALSE, -1 },
348 { CFSTR("WebKitMinimumFontSize"), _SPM(INT), "font.minimum-size.", _SPM(SetFontSize), PR_FALSE, -1 },
349 { CFSTR("WebKitDisplayImagesKey"), _SPM(BOOL), "permissions.default.image", _SPM(SetDisplayImages), PR_FALSE, -1 },
350 { CFSTR("WebKitJavaEnabled"), _SPM(BOOL), "security.enable_java", _SPM(SetBool), PR_FALSE, -1 },
351 { CFSTR("WebKitJavaScriptEnabled"), _SPM(BOOL), "javascript.enabled", _SPM(SetBool), PR_FALSE, -1 },
352 { CFSTR("WebKitJavaScriptCanOpenWindowsAutomatically"),
353 _SPM(BOOL), "dom.disable_open_during_load", _SPM(SetBoolInverted), PR_FALSE, -1 }
356 nsresult
357 nsSafariProfileMigrator::SetBool(void* aTransform, nsIPrefBranch* aBranch)
359 PrefTransform* xform = (PrefTransform*)aTransform;
360 return aBranch->SetBoolPref(xform->targetPrefName, xform->boolValue);
363 nsresult
364 nsSafariProfileMigrator::SetBoolInverted(void* aTransform, nsIPrefBranch* aBranch)
366 PrefTransform* xform = (PrefTransform*)aTransform;
367 return aBranch->SetBoolPref(xform->targetPrefName, !xform->boolValue);
370 nsresult
371 nsSafariProfileMigrator::SetString(void* aTransform, nsIPrefBranch* aBranch)
373 PrefTransform* xform = (PrefTransform*)aTransform;
374 return aBranch->SetCharPref(xform->targetPrefName, xform->stringValue);
377 nsresult
378 nsSafariProfileMigrator::SetInt(void* aTransform, nsIPrefBranch* aBranch)
380 PrefTransform* xform = (PrefTransform*)aTransform;
381 return aBranch->SetIntPref(xform->targetPrefName, !xform->intValue);
384 struct charsetEntry {
385 const char *webkitLabel;
386 size_t webkitLabelLength;
387 const char *mozLabel;
388 const char *associatedLangGroup;
391 static const charsetEntry gCharsets[] = {
392 #define CHARSET_ENTRY(charsetLabel, associatedLangGroup) \
393 {#charsetLabel, sizeof(#charsetLabel) - 1, #charsetLabel, #associatedLangGroup}
394 #define CHARSET_ENTRY2(webkitLabel, mozLabel, associatedLangGroup) \
395 {#webkitLabel, sizeof(#webkitLabel) - 1, #mozLabel, #associatedLangGroup}
397 CHARSET_ENTRY(ISO-8859-1,x-western),
398 CHARSET_ENTRY2(MACINTOSH,x-mac-roman,x-western),
399 // Since "x-unicode" in the font dialog means "Other Languages" (that is,
400 // languages which don't have their own script), we're picking the default
401 // font group - "Western".
402 CHARSET_ENTRY(UTF-8,x-western),
403 CHARSET_ENTRY2(SHIFT_JIS,Shift_JIS,ja),
404 CHARSET_ENTRY(ISO-2022-JP,ja),
405 CHARSET_ENTRY(EUC-JP,ja),
406 CHARSET_ENTRY2(BIG5,Big5,zh-TW),
407 CHARSET_ENTRY(CP950,zh-TW),
408 CHARSET_ENTRY(Big5-HKSCS,zh-HK),
409 CHARSET_ENTRY(ISO-2022-KR,ko),
410 // XXX: fallback to the generic Korean encoding
411 CHARSET_ENTRY2(X-MAC-KOREAN,ISO-2022-KR,ko),
412 CHARSET_ENTRY(CP949,ko),
413 CHARSET_ENTRY(ISO-8859-6,ar),
414 CHARSET_ENTRY2(WINDOWS-1256,windows-1256,ar),
415 CHARSET_ENTRY(ISO-8859-8,he),
416 CHARSET_ENTRY2(WINDOWS-1255,windows-1255,he),
417 CHARSET_ENTRY(ISO-8859-7,el),
418 CHARSET_ENTRY2(WINDOWS-1253,windows-1253,el),
419 CHARSET_ENTRY(ISO-8859-5,x-cyrillic),
420 CHARSET_ENTRY2(X-MAC-CYRILLIC,x-mac-cyrillic,x-cyrillic),
421 CHARSET_ENTRY(KOI8-R,x-cyrillic),
422 CHARSET_ENTRY2(WINDOWS-1251,windows-1251,x-cyrillic),
423 CHARSET_ENTRY(CP874,th),
424 CHARSET_ENTRY2(GB_2312-80,GB2312,zh-CN),
425 CHARSET_ENTRY(HZ-GB-2312,zh-CN),
426 CHARSET_ENTRY2(GB18030,gb18030,zh-CN),
427 CHARSET_ENTRY(ISO-8859-2,x-central-euro),
428 CHARSET_ENTRY2(X-MAC-CENTRALEURROMAN,x-mac-ce,x-central-euro),
429 CHARSET_ENTRY2(WINDOWS-1250,windows-1250,x-central-euro),
430 CHARSET_ENTRY(ISO-8859-4,x-central-euro),
431 CHARSET_ENTRY(ISO-8859-9,tr),
432 CHARSET_ENTRY2(WINDOWS-125,windows-1254,tr),
433 CHARSET_ENTRY2(WINDOWS-1257,windows-1257,x-baltic)
435 #undef CHARSET_ENTRY
436 #undef CHARSET_ENTRY2
439 nsresult
440 nsSafariProfileMigrator::SetDefaultEncoding(void* aTransform, nsIPrefBranch* aBranch)
442 PrefTransform* xform = (PrefTransform*)aTransform;
444 nsCAutoString associatedLangGroup;
445 nsDependentCString encoding(xform->stringValue);
446 PRUint32 encodingLength = encoding.Length();
447 const char* encodingStr = encoding.get();
449 PRInt16 charsetIndex = -1;
450 for (PRUint16 i = 0; (charsetIndex == -1) &&
451 i < (sizeof(gCharsets) / sizeof(gCharsets[0])); ++i) {
452 if (gCharsets[i].webkitLabelLength == encodingLength &&
453 !strcmp(gCharsets[i].webkitLabel, encodingStr))
454 charsetIndex = (PRInt16)i;
456 if (charsetIndex == -1) // Default to "Western"
457 charsetIndex = 0;
459 aBranch->SetCharPref(xform->targetPrefName, gCharsets[charsetIndex].mozLabel);
461 // We also want to use the default encoding for picking the default language
462 // in the fonts preferences dialog, and its associated preferences.
464 aBranch->SetCharPref("font.language.group",
465 gCharsets[charsetIndex].associatedLangGroup);
466 aBranch->SetCharPref("migration.associatedLangGroup",
467 gCharsets[charsetIndex].associatedLangGroup);
469 return NS_OK;
472 nsresult
473 nsSafariProfileMigrator::SetDownloadFolder(void* aTransform, nsIPrefBranch* aBranch)
475 PrefTransform* xform = (PrefTransform*)aTransform;
477 nsCOMPtr<nsILocalFile> downloadFolder;
478 nsresult rv = NS_NewNativeLocalFile(nsDependentCString(xform->stringValue),
479 PR_TRUE, getter_AddRefs(downloadFolder));
480 NS_ENSURE_SUCCESS(rv, rv);
482 // If the Safari download folder is the desktop, set the folderList pref
483 // appropriately so that "Desktop" is selected in the list in our Preferences
484 // UI instead of just the raw path being shown.
485 nsCOMPtr<nsIProperties> fileLocator(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
486 nsCOMPtr<nsILocalFile> desktopFolder;
487 fileLocator->Get(NS_OSX_USER_DESKTOP_DIR, NS_GET_IID(nsILocalFile),
488 getter_AddRefs(desktopFolder));
490 PRBool equals;
491 downloadFolder->Equals(desktopFolder, &equals);
492 aBranch->SetIntPref("browser.download.folderList", equals ? 0 : 2);
493 aBranch->SetComplexValue("browser.download.dir",
494 NS_GET_IID(nsILocalFile), downloadFolder);
496 return NS_OK;
499 nsresult
500 nsSafariProfileMigrator::SetDownloadHandlers(void* aTransform, nsIPrefBranch* aBranch)
502 PrefTransform* xform = (PrefTransform*)aTransform;
503 if (!xform->boolValue) {
504 // If we're not set to auto-open safe downloads, we need to clear out the
505 // mime types list which contains default handlers.
507 nsCOMPtr<nsIProperties> fileLocator(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
508 nsCOMPtr<nsILocalFile> mimeRegistryFile;
509 fileLocator->Get(NS_APP_USER_MIMETYPES_50_FILE, NS_GET_IID(nsILocalFile),
510 getter_AddRefs(mimeRegistryFile));
512 nsCOMPtr<nsIIOService> ioService(do_GetService("@mozilla.org/network/io-service;1"));
513 nsCOMPtr<nsIProtocolHandler> ph;
514 ioService->GetProtocolHandler("file", getter_AddRefs(ph));
515 nsCOMPtr<nsIFileProtocolHandler> fph(do_QueryInterface(ph));
517 nsCOMPtr<nsIRDFService> rdfService(do_GetService("@mozilla.org/rdf/rdf-service;1"));
518 nsCOMPtr<nsIRDFDataSource> mimeTypes;
520 nsCAutoString dsURL;
521 fph->GetURLSpecFromFile(mimeRegistryFile, dsURL);
522 rdfService->GetDataSourceBlocking(dsURL.get(), getter_AddRefs(mimeTypes));
524 nsCOMPtr<nsIRDFResource> overridesListResource;
525 rdfService->GetResource(NS_LITERAL_CSTRING("urn:mimetypes:root"),
526 getter_AddRefs(overridesListResource));
528 nsCOMPtr<nsIRDFContainer> overridesList(do_CreateInstance("@mozilla.org/rdf/container;1"));
529 overridesList->Init(mimeTypes, overridesListResource);
531 nsCOMPtr<nsIRDFResource> handlerPropArc, externalApplicationArc;
532 rdfService->GetResource(NC_URI(handlerProp), getter_AddRefs(handlerPropArc));
533 rdfService->GetResource(NC_URI(externalApplication),
534 getter_AddRefs(externalApplicationArc));
536 PRInt32 count;
537 overridesList->GetCount(&count);
538 for (PRInt32 i = count; i >= 1; --i) {
539 nsCOMPtr<nsIRDFNode> currOverrideNode;
540 overridesList->RemoveElementAt(i, PR_FALSE, getter_AddRefs(currOverrideNode));
541 nsCOMPtr<nsIRDFResource> currOverride(do_QueryInterface(currOverrideNode));
543 nsCOMPtr<nsIRDFNode> handlerPropNode;
544 mimeTypes->GetTarget(currOverride, handlerPropArc, PR_TRUE,
545 getter_AddRefs(handlerPropNode));
546 nsCOMPtr<nsIRDFResource> handlerPropResource(do_QueryInterface(handlerPropNode));
548 if (handlerPropResource) {
549 nsCOMPtr<nsIRDFNode> externalApplicationNode;
550 mimeTypes->GetTarget(handlerPropResource, externalApplicationArc,
551 PR_TRUE, getter_AddRefs(externalApplicationNode));
552 nsCOMPtr<nsIRDFResource> externalApplicationResource(do_QueryInterface(externalApplicationNode));
554 // Strip the resources down so that the datasource is completely flushed.
555 if (externalApplicationResource)
556 CleanResource(mimeTypes, externalApplicationResource);
558 CleanResource(mimeTypes, handlerPropResource);
560 CleanResource(mimeTypes, currOverride);
563 nsCOMPtr<nsIRDFRemoteDataSource> rds(do_QueryInterface(mimeTypes));
564 if (rds)
565 rds->Flush();
567 return NS_OK;
570 void
571 nsSafariProfileMigrator::CleanResource(nsIRDFDataSource* aDataSource,
572 nsIRDFResource* aResource)
574 nsCOMPtr<nsISimpleEnumerator> arcLabels;
575 aDataSource->ArcLabelsOut(aResource, getter_AddRefs(arcLabels));
576 if (!arcLabels)
577 return;
579 do {
580 PRBool hasMore;
581 arcLabels->HasMoreElements(&hasMore);
583 if (!hasMore)
584 break;
586 nsCOMPtr<nsIRDFResource> currArc;
587 arcLabels->GetNext(getter_AddRefs(currArc));
589 if (currArc) {
590 nsCOMPtr<nsIRDFNode> currTarget;
591 aDataSource->GetTarget(aResource, currArc, PR_TRUE,
592 getter_AddRefs(currTarget));
594 aDataSource->Unassert(aResource, currArc, currTarget);
597 while (1);
600 nsresult
601 nsSafariProfileMigrator::SetDownloadRetention(void* aTransform,
602 nsIPrefBranch* aBranch)
604 // Safari stores Download Retention in the opposite order of Firefox, namely:
605 // Retention Mode: Safari Firefox
606 // Remove Manually 0 2
607 // Remove on Exit 1 1
608 // Remove on DL Complete 2 0
609 PrefTransform* xform = (PrefTransform*)aTransform;
610 aBranch->SetIntPref(xform->targetPrefName,
611 xform->intValue == 0 ? 2 : xform->intValue == 2 ? 0 : 1);
612 return NS_OK;
615 nsresult
616 nsSafariProfileMigrator::SetDisplayImages(void* aTransform, nsIPrefBranch* aBranch)
618 // Firefox has an elaborate set of Image preferences. The correlation is:
619 // Mode: Safari Firefox
620 // Blocked FALSE 2
621 // Allowed TRUE 1
622 // Allowed, originating site only -- 3
623 PrefTransform* xform = (PrefTransform*)aTransform;
624 aBranch->SetIntPref(xform->targetPrefName, xform->boolValue ? 1 : 2);
625 return NS_OK;
628 nsresult
629 nsSafariProfileMigrator::SetFontName(void* aTransform, nsIPrefBranch* aBranch)
631 nsCString associatedLangGroup;
632 nsresult rv = aBranch->GetCharPref("migration.associatedLangGroup",
633 getter_Copies(associatedLangGroup));
634 if (NS_FAILED(rv))
635 return NS_OK;
637 PrefTransform* xform = (PrefTransform*)aTransform;
638 nsCAutoString prefName(xform->targetPrefName);
639 prefName.Append(associatedLangGroup);
641 return aBranch->SetCharPref(prefName.get(), xform->stringValue);
644 nsresult
645 nsSafariProfileMigrator::SetFontSize(void* aTransform, nsIPrefBranch* aBranch)
647 nsCString associatedLangGroup;
648 nsresult rv = aBranch->GetCharPref("migration.associatedLangGroup",
649 getter_Copies(associatedLangGroup));
650 if (NS_FAILED(rv))
651 return NS_OK;
653 PrefTransform* xform = (PrefTransform*)aTransform;
654 nsCAutoString prefName(xform->targetPrefName);
655 prefName.Append(associatedLangGroup);
657 return aBranch->SetIntPref(prefName.get(), xform->intValue);
660 nsresult
661 nsSafariProfileMigrator::CopyPreferences(PRBool aReplace)
663 nsCOMPtr<nsIPrefBranch> branch(do_GetService(NS_PREFSERVICE_CONTRACTID));
665 CFDictionaryRef safariPrefs = CopySafariPrefs();
666 if (!safariPrefs)
667 return NS_ERROR_FAILURE;
669 // Traverse the standard transforms
670 PrefTransform* transform;
671 PrefTransform* end = gTransforms +
672 sizeof(gTransforms) / sizeof(PrefTransform);
674 for (transform = gTransforms; transform < end; ++transform) {
675 Boolean hasValue = ::CFDictionaryContainsKey(safariPrefs, transform->keyName);
676 if (!hasValue)
677 continue;
679 transform->prefHasValue = PR_FALSE;
680 switch (transform->type) {
681 case _SPM(STRING): {
682 CFStringRef stringValue = (CFStringRef)
683 ::CFDictionaryGetValue(safariPrefs,
684 transform->keyName);
685 char* value = GetNullTerminatedString(stringValue);
686 if (value) {
687 transform->stringValue = value;
688 transform->prefHasValue = PR_TRUE;
691 break;
692 case _SPM(INT): {
693 CFNumberRef intValue = (CFNumberRef)
694 ::CFDictionaryGetValue(safariPrefs,
695 transform->keyName);
696 PRInt32 value = 0;
697 if (::CFNumberGetValue(intValue, kCFNumberSInt32Type, &value)) {
698 transform->intValue = value;
699 transform->prefHasValue = PR_TRUE;
702 break;
703 case _SPM(BOOL): {
704 CFBooleanRef boolValue = (CFBooleanRef)
705 ::CFDictionaryGetValue(safariPrefs,
706 transform->keyName);
707 transform->boolValue = boolValue == kCFBooleanTrue;
708 transform->prefHasValue = PR_TRUE;
710 break;
711 default:
712 break;
715 if (transform->prefHasValue)
716 transform->prefSetterFunc(transform, branch);
718 if (transform->type == _SPM(STRING))
719 FreeNullTerminatedString(transform->stringValue);
722 ::CFRelease(safariPrefs);
724 // Safari stores the Cookie "Accept/Don't Accept/Don't Accept Foreign" cookie
725 // setting in a separate WebFoundation preferences PList.
726 nsCOMPtr<nsIProperties> fileLocator(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
727 nsCOMPtr<nsILocalFile> safariWebFoundationPrefsFile;
728 fileLocator->Get(NS_OSX_USER_PREFERENCES_DIR, NS_GET_IID(nsILocalFile),
729 getter_AddRefs(safariWebFoundationPrefsFile));
730 safariWebFoundationPrefsFile->Append(SAFARI_COOKIE_BEHAVIOR_FILE_NAME);
732 CFDictionaryRef safariWebFoundationPrefs =
733 (CFDictionaryRef)CopyPListFromFile(safariWebFoundationPrefsFile);
734 if (safariWebFoundationPrefs) {
735 // Mapping of Safari preference values to Firefox preference values:
737 // Setting Safari Firefox
738 // Always Accept always 0
739 // Accept from Originating current page 1
740 // Never Accept never 2
741 nsAutoString acceptCookies;
742 if (GetDictionaryStringValue(safariWebFoundationPrefs,
743 CFSTR("NSHTTPAcceptCookies"), acceptCookies)) {
744 PRInt32 cookieValue = 0;
745 if (acceptCookies.EqualsLiteral("never"))
746 cookieValue = 2;
747 else if (acceptCookies.EqualsLiteral("current page"))
748 cookieValue = 1;
750 branch->SetIntPref("network.cookie.cookieBehavior", cookieValue);
753 ::CFRelease(safariWebFoundationPrefs);
756 return NS_OK;
759 nsresult
760 nsSafariProfileMigrator::CopyCookies(PRBool aReplace)
762 nsCOMPtr<nsIProperties> fileLocator(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
763 nsCOMPtr<nsILocalFile> safariCookiesFile;
764 fileLocator->Get(NS_MAC_USER_LIB_DIR,
765 NS_GET_IID(nsILocalFile),
766 getter_AddRefs(safariCookiesFile));
767 safariCookiesFile->Append(NS_LITERAL_STRING("Cookies"));
768 safariCookiesFile->Append(SAFARI_COOKIES_FILE_NAME);
770 CFArrayRef safariCookies = (CFArrayRef)CopyPListFromFile(safariCookiesFile);
771 if (!safariCookies)
772 return NS_OK;
774 nsCOMPtr<nsICookieManager2> cookieManager(do_GetService(NS_COOKIEMANAGER_CONTRACTID));
775 CFIndex count = ::CFArrayGetCount(safariCookies);
776 for (PRInt32 i = 0; i < count; ++i) {
777 CFDictionaryRef entry = (CFDictionaryRef)::CFArrayGetValueAtIndex(safariCookies, i);
779 CFDateRef date = (CFDateRef)::CFDictionaryGetValue(entry, CFSTR("Expires"));
781 nsCAutoString domain, path, name, value;
782 if (date &&
783 GetDictionaryCStringValue(entry, CFSTR("Domain"), domain,
784 kCFStringEncodingUTF8) &&
785 GetDictionaryCStringValue(entry, CFSTR("Path"), path,
786 kCFStringEncodingUTF8) &&
787 GetDictionaryCStringValue(entry, CFSTR("Name"), name,
788 kCFStringEncodingASCII) &&
789 GetDictionaryCStringValue(entry, CFSTR("Value"), value,
790 kCFStringEncodingASCII)) {
791 PRInt64 expiryTime;
792 LL_D2L(expiryTime, (double)::CFDateGetAbsoluteTime(date));
794 expiryTime += SAFARI_DATE_OFFSET;
795 cookieManager->Add(domain, path, name, value,
796 PR_FALSE, // isSecure
797 PR_FALSE, // isHttpOnly
798 PR_FALSE, // isSession
799 expiryTime);
802 ::CFRelease(safariCookies);
804 return NS_OK;
807 nsresult
808 nsSafariProfileMigrator::CopyHistory(PRBool aReplace)
810 nsresult rv;
811 nsCOMPtr<nsINavHistoryService> history = do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID, &rv);
812 NS_ENSURE_SUCCESS(rv, rv);
814 return history->RunInBatchMode(this, nsnull);
817 NS_IMETHODIMP
818 nsSafariProfileMigrator::RunBatched(nsISupports* aUserData)
820 nsCOMPtr<nsIProperties> fileLocator(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
821 nsCOMPtr<nsILocalFile> safariHistoryFile;
822 fileLocator->Get(NS_MAC_USER_LIB_DIR, NS_GET_IID(nsILocalFile),
823 getter_AddRefs(safariHistoryFile));
824 safariHistoryFile->Append(NS_LITERAL_STRING("Safari"));
825 safariHistoryFile->Append(SAFARI_HISTORY_FILE_NAME);
827 CFDictionaryRef safariHistory = (CFDictionaryRef)CopyPListFromFile(safariHistoryFile);
828 if (!safariHistory)
829 return NS_OK;
831 if (!::CFDictionaryContainsKey(safariHistory, CFSTR("WebHistoryDates"))) {
832 ::CFRelease(safariHistory);
833 return NS_OK;
836 nsCOMPtr<nsIBrowserHistory> history(do_GetService(NS_GLOBALHISTORY2_CONTRACTID));
838 CFArrayRef children = (CFArrayRef)
839 ::CFDictionaryGetValue(safariHistory, CFSTR("WebHistoryDates"));
840 if (children) {
841 CFIndex count = ::CFArrayGetCount(children);
842 for (PRInt32 i = 0; i < count; ++i) {
843 CFDictionaryRef entry = (CFDictionaryRef)::CFArrayGetValueAtIndex(children, i);
845 CFStringRef lastVisitedDate = (CFStringRef)
846 ::CFDictionaryGetValue(entry, CFSTR("lastVisitedDate"));
847 nsAutoString url, title;
848 if (GetDictionaryStringValue(entry, CFSTR(""), url) &&
849 GetDictionaryStringValue(entry, CFSTR("title"), title) &&
850 lastVisitedDate) {
852 double lvd = ::CFStringGetDoubleValue(lastVisitedDate) + SAFARI_DATE_OFFSET;
853 PRTime lastVisitTime;
854 PRInt64 temp, million;
855 LL_D2L(temp, lvd);
856 LL_I2L(million, PR_USEC_PER_SEC);
857 LL_MUL(lastVisitTime, temp, million);
859 nsCOMPtr<nsIURI> uri;
860 NS_NewURI(getter_AddRefs(uri), url);
861 if (uri)
862 history->AddPageWithDetails(uri, title.get(), lastVisitTime);
867 ::CFRelease(safariHistory);
869 return NS_OK;
872 nsresult
873 nsSafariProfileMigrator::CopyBookmarks(PRBool aReplace)
875 // If "aReplace" is true, merge into the root level of bookmarks. Otherwise, create
876 // a folder called "Imported Safari Favorites" and place all the Bookmarks there.
877 nsresult rv;
879 nsCOMPtr<nsINavBookmarksService> bms(do_GetService(NS_NAVBOOKMARKSSERVICE_CONTRACTID, &rv));
880 NS_ENSURE_SUCCESS(rv, rv);
881 PRInt64 root;
882 rv = bms->GetBookmarksMenuFolder(&root);
883 NS_ENSURE_SUCCESS(rv, rv);
885 PRInt64 folder;
886 if (!aReplace) {
887 nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
888 if (NS_FAILED(rv)) return rv;
890 nsCOMPtr<nsIStringBundle> bundle;
891 bundleService->CreateBundle(MIGRATION_BUNDLE, getter_AddRefs(bundle));
893 nsString sourceNameSafari;
894 bundle->GetStringFromName(NS_LITERAL_STRING("sourceNameSafari").get(),
895 getter_Copies(sourceNameSafari));
897 const PRUnichar* sourceNameStrings[] = { sourceNameSafari.get() };
898 nsString importedSafariBookmarksTitle;
899 bundle->FormatStringFromName(NS_LITERAL_STRING("importedBookmarksFolder").get(),
900 sourceNameStrings, 1,
901 getter_Copies(importedSafariBookmarksTitle));
903 bms->CreateFolder(root, NS_ConvertUTF16toUTF8(importedSafariBookmarksTitle),
904 nsINavBookmarksService::DEFAULT_INDEX, &folder);
906 else {
907 nsCOMPtr<nsIFile> profile;
908 GetProfilePath(nsnull, profile);
909 rv = InitializeBookmarks(profile);
910 NS_ENSURE_SUCCESS(rv, rv);
911 // In replace mode we are merging at the top level.
912 folder = root;
915 nsCOMPtr<nsIProperties> fileLocator(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
916 nsCOMPtr<nsILocalFile> safariBookmarksFile;
917 fileLocator->Get(NS_MAC_USER_LIB_DIR, NS_GET_IID(nsILocalFile),
918 getter_AddRefs(safariBookmarksFile));
919 safariBookmarksFile->Append(NS_LITERAL_STRING("Safari"));
920 safariBookmarksFile->Append(SAFARI_BOOKMARKS_FILE_NAME);
922 CFDictionaryRef safariBookmarks = (CFDictionaryRef)CopyPListFromFile(safariBookmarksFile);
923 if (!safariBookmarks)
924 return NS_OK;
926 // The Safari Bookmarks file looks like this:
927 // At the top level are all the Folders, Special Folders and Proxies. Proxies
928 // are references to other data sources such as History, Rendezvous etc.
929 // We ignore these. Special folders exist for the Bookmarks Toolbar folder
930 // (called "BookmarksBar" and the Bookmarks Menu (called "BookmarksMenu").
931 // We put the contents of the "BookmarksBar" folder into our Personal Toolbar
932 // and merge the contents of the "BookmarksMenu" folder and the other toplevel
933 // non-special folders under our NC:BookmarksRoot.
934 if (::CFDictionaryContainsKey(safariBookmarks, CFSTR("Children")) &&
935 ::CFDictionaryContainsKey(safariBookmarks, CFSTR("WebBookmarkFileVersion")) ) {
936 CFNumberRef intValue =
937 (CFNumberRef)::CFDictionaryGetValue(safariBookmarks,
938 CFSTR("WebBookmarkFileVersion"));
939 PRInt32 value = 0;
940 if (::CFNumberGetValue(intValue, kCFNumberSInt32Type, &value) && value ==1) {
941 CFArrayRef children =
942 (CFArrayRef)::CFDictionaryGetValue(safariBookmarks, CFSTR("Children"));
943 if (children) {
944 rv = ParseBookmarksFolder(children, folder, bms, PR_TRUE);
945 if (NS_SUCCEEDED(rv)) {
946 // after importing the favorites,
947 // we need to set this pref so that on startup
948 // we don't blow away what we just imported
949 nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID));
950 NS_ENSURE_TRUE(pref, NS_ERROR_FAILURE);
951 rv = pref->SetBoolPref("browser.places.importBookmarksHTML", PR_FALSE);
952 NS_ENSURE_SUCCESS(rv, rv);
957 ::CFRelease(safariBookmarks);
958 return rv;
961 nsresult
962 nsSafariProfileMigrator::ParseBookmarksFolder(CFArrayRef aChildren,
963 PRInt64 aParentFolder,
964 nsINavBookmarksService * aBookmarksService,
965 PRBool aIsAtRootLevel)
967 nsresult rv = NS_OK;
969 CFIndex count = ::CFArrayGetCount(aChildren);
970 for (PRInt32 i = 0; i < count; ++i) {
971 CFDictionaryRef entry = (CFDictionaryRef)::CFArrayGetValueAtIndex(aChildren, i);
973 nsAutoString type;
974 if (!GetDictionaryStringValue(entry, CFSTR("WebBookmarkType"), type))
975 continue;
977 if (!type.EqualsLiteral("WebBookmarkTypeList") &&
978 !type.EqualsLiteral("WebBookmarkTypeLeaf"))
979 continue;
981 if (::CFDictionaryContainsKey(entry, CFSTR("Children")) &&
982 type.EqualsLiteral("WebBookmarkTypeList")) {
983 nsAutoString title;
984 if (!GetDictionaryStringValue(entry, CFSTR("Title"), title))
985 continue;
987 CFArrayRef children = (CFArrayRef)::CFDictionaryGetValue(entry,
988 CFSTR("Children"));
990 // Look for the BookmarksBar Bookmarks and add them into the appropriate
991 // Personal Toolbar Root
992 if (title.EqualsLiteral("BookmarksBar") && aIsAtRootLevel) {
993 PRInt64 toolbarFolder;
994 aBookmarksService->GetToolbarFolder(&toolbarFolder);
996 rv |= ParseBookmarksFolder(children,
997 toolbarFolder,
998 aBookmarksService,
999 PR_FALSE);
1001 // Look for the BookmarksMenu Bookmarks and flatten them into the top level
1002 else if (title.EqualsLiteral("BookmarksMenu") && aIsAtRootLevel) {
1003 rv |= ParseBookmarksFolder(children,
1004 aParentFolder,
1005 aBookmarksService,
1006 PR_TRUE);
1008 else {
1009 // Encountered a Folder, so create one in our Bookmarks DataSource and then
1010 // parse the contents of the Safari one into it...
1011 PRInt64 folder;
1012 rv |= aBookmarksService->CreateFolder(aParentFolder, NS_ConvertUTF16toUTF8(title),
1013 nsINavBookmarksService::DEFAULT_INDEX,
1014 &folder);
1015 rv |= ParseBookmarksFolder(children,
1016 folder,
1017 aBookmarksService,
1018 PR_FALSE);
1021 else if (type.EqualsLiteral("WebBookmarkTypeLeaf")) {
1022 // Encountered a Bookmark, so add it to the current folder...
1023 CFDictionaryRef URIDictionary = (CFDictionaryRef)
1024 ::CFDictionaryGetValue(entry, CFSTR("URIDictionary"));
1025 nsAutoString title;
1026 nsCAutoString url;
1027 if (GetDictionaryStringValue(URIDictionary, CFSTR("title"), title) &&
1028 GetDictionaryCStringValue(entry, CFSTR("URLString"), url, kCFStringEncodingUTF8)) {
1029 nsCOMPtr<nsIURI> uri;
1030 rv |= NS_NewURI(getter_AddRefs(uri), url);
1031 PRInt64 id;
1032 rv |= aBookmarksService->InsertBookmark(aParentFolder, uri,
1033 nsINavBookmarksService::DEFAULT_INDEX,
1034 NS_ConvertUTF16toUTF8(title), &id);
1038 return rv;
1041 // nsSafariProfileMigrator::HasFormDataToImport()
1042 // if we add support for "~/Library/Safari/Form Values",
1043 // keep in sync with CopyFormData()
1044 // see bug #344284
1045 PRBool
1046 nsSafariProfileMigrator::HasFormDataToImport()
1048 PRBool hasFormData = PR_FALSE;
1050 // Safari stores this data in an array under the "RecentSearchStrings" key
1051 // in its Preferences file.
1052 CFDictionaryRef safariPrefs = CopySafariPrefs();
1053 if (safariPrefs) {
1054 if (::CFDictionaryContainsKey(safariPrefs, CFSTR("RecentSearchStrings")))
1055 hasFormData = PR_TRUE;
1056 ::CFRelease(safariPrefs);
1058 return hasFormData;
1061 // nsSafariProfileMigrator::CopyFormData()
1062 // if we add support for "~/Library/Safari/Form Values",
1063 // keep in sync with HasFormDataToImport()
1064 // see bug #344284
1065 nsresult
1066 nsSafariProfileMigrator::CopyFormData(PRBool aReplace)
1068 nsresult rv = NS_ERROR_FAILURE;
1069 CFDictionaryRef safariPrefs = CopySafariPrefs();
1070 if (safariPrefs) {
1071 // We lump saved Searches in with Form Data since that's how we store it.
1072 // Safari stores this data in an array under the "RecentSearchStrings" key
1073 // in its Preferences file.
1074 Boolean hasSearchStrings = ::CFDictionaryContainsKey(safariPrefs,
1075 CFSTR("RecentSearchStrings"));
1076 if (hasSearchStrings) {
1077 nsCOMPtr<nsIFormHistory2> formHistory(do_GetService("@mozilla.org/satchel/form-history;1"));
1078 if (formHistory) {
1079 CFArrayRef strings = (CFArrayRef)::CFDictionaryGetValue(safariPrefs,
1080 CFSTR("RecentSearchStrings"));
1081 if (strings) {
1082 CFIndex count = ::CFArrayGetCount(strings);
1083 for (PRInt32 i = 0; i < count; ++i) {
1084 nsAutoString value;
1085 GetArrayStringValue(strings, i, value);
1086 formHistory->AddEntry(NS_LITERAL_STRING("searchbar-history"), value);
1089 rv = NS_OK;
1092 else
1093 rv = NS_OK;
1095 ::CFRelease(safariPrefs);
1098 return rv;
1101 // Returns whether or not the active profile has a content style sheet
1102 // (That is chrome/userContent.css)
1103 nsresult
1104 nsSafariProfileMigrator::ProfileHasContentStyleSheet(PRBool *outExists)
1106 NS_ENSURE_ARG(outExists);
1108 // Get the profile's chrome/ directory native path
1109 nsCOMPtr<nsIFile> userChromeDir;
1110 nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_CHROME_DIR,
1111 getter_AddRefs(userChromeDir));
1112 nsCAutoString userChromeDirPath;
1113 rv = userChromeDir->GetNativePath(userChromeDirPath);
1114 NS_ENSURE_SUCCESS(rv, rv);
1116 nsCAutoString path(userChromeDirPath);
1117 path.Append("/userContent.css");
1119 nsCOMPtr<nsILocalFile> file;
1120 rv = NS_NewNativeLocalFile(path, PR_FALSE,
1121 getter_AddRefs(file));
1122 NS_ENSURE_SUCCESS(rv, rv);
1124 file->Exists(outExists);
1125 return NS_OK;
1128 nsresult
1129 nsSafariProfileMigrator::GetSafariUserStyleSheet(nsILocalFile** aResult)
1131 *aResult = nsnull;
1133 CFDictionaryRef safariPrefs = CopySafariPrefs();
1134 if (!safariPrefs)
1135 return NS_ERROR_FAILURE;
1137 nsresult rv = NS_ERROR_FAILURE;
1138 // Check whether or not a user style sheet has been specified
1139 if (::CFDictionaryContainsKey
1140 (safariPrefs, CFSTR("WebKitUserStyleSheetEnabledPreferenceKey")) &&
1141 ::CFDictionaryContainsKey
1142 (safariPrefs, CFSTR("WebKitUserStyleSheetLocationPreferenceKey"))) {
1143 CFBooleanRef hasSheet = (CFBooleanRef)::CFDictionaryGetValue(safariPrefs,
1144 CFSTR("WebKitUserStyleSheetEnabledPreferenceKey"));
1145 if (hasSheet == kCFBooleanTrue) {
1146 nsAutoString path;
1147 // Get its path
1148 if (GetDictionaryStringValue(safariPrefs,
1149 CFSTR("WebKitUserStyleSheetLocation" \
1150 "PreferenceKey"), path)) {
1151 nsCOMPtr<nsILocalFile> file;
1152 rv = NS_NewLocalFile(path, PR_FALSE, getter_AddRefs(file));
1153 if (NS_SUCCEEDED(rv)) {
1154 PRBool exists = PR_FALSE;
1155 file->Exists(&exists);
1156 if (exists) {
1157 NS_ADDREF(*aResult = file);
1158 rv = NS_OK;
1160 else
1161 rv = NS_ERROR_FILE_NOT_FOUND;
1166 ::CFRelease(safariPrefs);
1168 return rv;
1171 nsresult
1172 nsSafariProfileMigrator::CopyOtherData(PRBool aReplace)
1174 // Get the Safari user style sheet and copy it into the active profile's
1175 // chrome folder
1176 nsCOMPtr<nsILocalFile> stylesheetFile;
1177 if (NS_SUCCEEDED(GetSafariUserStyleSheet(getter_AddRefs(stylesheetFile)))) {
1178 nsCOMPtr<nsIFile> userChromeDir;
1179 NS_GetSpecialDirectory(NS_APP_USER_CHROME_DIR,
1180 getter_AddRefs(userChromeDir));
1182 stylesheetFile->CopyTo(userChromeDir, NS_LITERAL_STRING("userContent.css"));
1184 return NS_OK;
1188 NS_IMETHODIMP
1189 nsSafariProfileMigrator::GetSourceHomePageURL(nsACString& aResult)
1191 aResult.Truncate();
1193 // Let's first check if there's a home page key in the com.apple.safari file...
1194 CFDictionaryRef safariPrefs = CopySafariPrefs();
1195 if (GetDictionaryCStringValue(safariPrefs,
1196 CFSTR(SAFARI_HOME_PAGE_PREF),
1197 aResult, kCFStringEncodingUTF8)) {
1198 ::CFRelease(safariPrefs);
1199 return NS_OK;
1202 ::CFRelease(safariPrefs);
1204 // Couldn't find the home page in com.apple.safai, time to check
1205 // com.apple.internetconfig for this key!
1206 ICInstance internetConfig;
1207 OSStatus error = ::ICStart(&internetConfig, 'FRFX');
1208 if (error != noErr)
1209 return NS_ERROR_FAILURE;
1211 ICAttr dummy;
1212 Str255 homePagePValue;
1213 long prefSize = sizeof(homePagePValue);
1214 error = ::ICGetPref(internetConfig, kICWWWHomePage, &dummy,
1215 homePagePValue, &prefSize);
1216 if (error != noErr)
1217 return NS_ERROR_FAILURE;
1219 char homePageValue[256] = "";
1220 CopyPascalStringToC((ConstStr255Param)homePagePValue, homePageValue);
1221 aResult.Assign(homePageValue);
1222 ::ICStop(internetConfig);
1224 return NS_OK;