nsSafariProfileMigrator.cpp
Go to the documentation of this file.
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
4  *
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/
9  *
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.
14  *
15  * The Original Code is The Browser Profile Migrator.
16  *
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.
20  *
21  * Contributor(s):
22  * Ben Goodger <ben@bengoodger.com>
23  * Asaf Romano <mozilla.mano@sent.com>
24  *
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.
36  *
37  * ***** END LICENSE BLOCK ***** */
38 
39 #include "nsAppDirectoryServiceDefs.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"
65 #include "nsToolkitCompsCID.h"
66 #include "nsNetUtil.h"
67 #include "nsTArray.h"
68 
69 #include <Carbon/Carbon.h>
70 
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"
79 
81 // nsSafariProfileMigrator
82 
84 
86 {
87  mObserverService = do_GetService("@mozilla.org/observer-service;1");
88 }
89 
91 {
92 }
93 
95 // nsIBrowserProfileMigrator
96 
97 NS_IMETHODIMP
98 nsSafariProfileMigrator::Migrate(PRUint16 aItems, nsIProfileStartup* aStartup,
99  const PRUnichar* aProfile)
100 {
101  nsresult rv = NS_OK;
102 
103  PRBool replace = PR_FALSE;
104 
105  if (aStartup) {
106  replace = PR_TRUE;
107  rv = aStartup->DoStartup();
108  NS_ENSURE_SUCCESS(rv, rv);
109  }
110 
112 
119 
121 
122  return rv;
123 }
124 
125 NS_IMETHODIMP
126 nsSafariProfileMigrator::GetMigrateData(const PRUnichar* aProfile,
127  PRBool aReplace,
128  PRUint16* aResult)
129 {
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"));
139 
140  // Safari stores most of its user settings under ~/Library/Safari/
141  MigrationData data[] = { { ToNewUnicode(SAFARI_HISTORY_FILE_NAME),
143  PR_FALSE },
144  { ToNewUnicode(SAFARI_BOOKMARKS_FILE_NAME),
146  PR_FALSE } };
147  // Frees file name strings allocated above.
148  GetMigrateDataFromArray(data, sizeof(data)/sizeof(MigrationData),
149  aReplace, safariSettingsDir, aResult);
150 
151  // Safari stores Cookies under ~/Library/Cookies/Cookies.plist
152  MigrationData data2[] = { { ToNewUnicode(SAFARI_COOKIES_FILE_NAME),
154  PR_FALSE } };
155  GetMigrateDataFromArray(data2, sizeof(data2)/sizeof(MigrationData),
156  aReplace, safariCookiesDir, aResult);
157 
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),
164  PR_FALSE } };
165  GetMigrateDataFromArray(data3, sizeof(data3)/sizeof(MigrationData),
166  aReplace, systemPrefsDir, aResult);
167 
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))))
176  }
177 
178  // Don't offer to import that Safari form data if there isn't any
179  if (HasFormDataToImport())
181 
182  return NS_OK;
183 }
184 
185 NS_IMETHODIMP
186 nsSafariProfileMigrator::GetSourceExists(PRBool* aResult)
187 {
188  PRUint16 data;
189  GetMigrateData(nsnull, PR_FALSE, &data);
190 
191  *aResult = data != 0;
192 
193  return NS_OK;
194 }
195 
196 NS_IMETHODIMP
197 nsSafariProfileMigrator::GetSourceHasMultipleProfiles(PRBool* aResult)
198 {
199  // Safari only has one profile per-user.
200  *aResult = PR_FALSE;
201  return NS_OK;
202 }
203 
204 NS_IMETHODIMP
205 nsSafariProfileMigrator::GetSourceProfiles(nsISupportsArray** aResult)
206 {
207  *aResult = nsnull;
208  return NS_OK;
209 }
210 
212 // nsSafariProfileMigrator
213 
214 CFPropertyListRef CopyPListFromFile(nsILocalFile* aPListFile)
215 {
216  PRBool exists;
217  aPListFile->Exists(&exists);
218  if (!exists)
219  return nsnull;
220 
221  nsCAutoString filePath;
222  aPListFile->GetNativePath(filePath);
223 
224  nsCOMPtr<nsILocalFileMac> macFile(do_QueryInterface(aPListFile));
225  CFURLRef urlRef;
226  macFile->GetCFURL(&urlRef);
227 
228  // It is possible for CFURLCreateDataAndPropertiesFromResource to allocate resource
229  // data and then return a failure so be careful to check both and clean up properly.
230  SInt32 errorCode;
231  CFDataRef resourceData = NULL;
232  Boolean dataSuccess = ::CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault,
233  urlRef,
234  &resourceData,
235  NULL,
236  NULL,
237  &errorCode);
238 
239  CFPropertyListRef propertyList = NULL;
240  if (resourceData) {
241  if (dataSuccess) {
242  propertyList = ::CFPropertyListCreateFromXMLData(kCFAllocatorDefault,
243  resourceData,
244  kCFPropertyListImmutable,
245  NULL);
246  }
247  ::CFRelease(resourceData);
248  }
249 
250  ::CFRelease(urlRef);
251 
252  return propertyList;
253 }
254 
255 CFDictionaryRef CopySafariPrefs()
256 {
257  nsCOMPtr<nsIProperties> fileLocator(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
258  nsCOMPtr<nsILocalFile> safariPrefsFile;
259  fileLocator->Get(NS_OSX_USER_PREFERENCES_DIR,
260  NS_GET_IID(nsILocalFile),
261  getter_AddRefs(safariPrefsFile));
262 
263  safariPrefsFile->Append(SAFARI_PREFERENCES_FILE_NAME);
264 
265  return static_cast<CFDictionaryRef>(CopyPListFromFile(safariPrefsFile));
266 }
267 
268 char*
269 GetNullTerminatedString(CFStringRef aStringRef)
270 {
271  CFIndex bufferSize = ::CFStringGetLength(aStringRef) + 1;
272  char* buffer = (char*)malloc(sizeof(char) * bufferSize);
273  if (!buffer)
274  return nsnull;
275  if (::CFStringGetCString(aStringRef, buffer, bufferSize,
276  kCFStringEncodingASCII))
277  buffer[bufferSize-1] = '\0';
278  return buffer;
279 }
280 
281 void
283 {
284  free(aString);
285  aString = nsnull;
286 }
287 
288 PRBool
289 GetDictionaryStringValue(CFDictionaryRef aDictionary, CFStringRef aKey,
290  nsAString& aResult)
291 {
292  CFStringRef value = (CFStringRef)::CFDictionaryGetValue(aDictionary, aKey);
293  if (value) {
294  nsAutoTArray<UniChar, 1024> buffer;
295  CFIndex valueLength = ::CFStringGetLength(value);
296  buffer.SetLength(valueLength);
297 
298  ::CFStringGetCharacters(value, CFRangeMake(0, valueLength), buffer.Elements());
299  aResult.Assign(buffer.Elements(), valueLength);
300  return PR_TRUE;
301  }
302  return PR_FALSE;
303 }
304 
305 PRBool
306 GetDictionaryCStringValue(CFDictionaryRef aDictionary, CFStringRef aKey,
307  nsACString& aResult, CFStringEncoding aEncoding)
308 {
309  CFStringRef value = (CFStringRef)::CFDictionaryGetValue(aDictionary, aKey);
310  if (value) {
311  nsAutoTArray<char, 1024> buffer;
312  CFIndex valueLength = ::CFStringGetLength(value);
313  buffer.SetLength(valueLength + 1);
314 
315  if (::CFStringGetCString(value, buffer.Elements(), valueLength + 1, aEncoding)) {
316  aResult = buffer.Elements();
317  return PR_TRUE;
318  }
319  }
320  return PR_FALSE;
321 }
322 
323 PRBool
324 GetArrayStringValue(CFArrayRef aArray, PRInt32 aIndex, nsAString& aResult)
325 {
326  CFStringRef value = (CFStringRef)::CFArrayGetValueAtIndex(aArray, aIndex);
327  if (value) {
328  nsAutoTArray<UniChar, 1024> buffer;
329  CFIndex valueLength = ::CFStringGetLength(value);
330  buffer.SetLength(valueLength);
331 
332  ::CFStringGetCharacters(value, CFRangeMake(0, valueLength), buffer.Elements());
333  aResult.Assign(buffer.Elements(), valueLength);
334  return PR_TRUE;
335  }
336  return PR_FALSE;
337 }
338 
339 #define _SPM(type) nsSafariProfileMigrator::type
340 
341 static
343  { CFSTR("AlwaysShowTabBar"), _SPM(BOOL), "browser.tabs.autoHide", _SPM(SetBoolInverted), PR_FALSE, -1 },
344  { CFSTR("AutoFillPasswords"), _SPM(BOOL), "signon.rememberSignons", _SPM(SetBool), PR_FALSE, -1 },
345  { CFSTR("OpenNewTabsInFront"), _SPM(BOOL), "browser.tabs.loadInBackground", _SPM(SetBoolInverted), PR_FALSE, -1 },
346  { CFSTR("NSDefaultOpenDir"), _SPM(STRING), "browser.download.dir", _SPM(SetDownloadFolder), PR_FALSE, -1 },
347  { CFSTR("AutoOpenSafeDownloads"), _SPM(BOOL), nsnull, _SPM(SetDownloadHandlers), PR_FALSE, -1 },
348  { CFSTR("DownloadsClearingPolicy"), _SPM(INT), "browser.download.manager.retention", _SPM(SetDownloadRetention), PR_FALSE, -1 },
349  { CFSTR("WebKitDefaultTextEncodingName"),_SPM(STRING), "intl.charset.default", _SPM(SetDefaultEncoding), PR_FALSE, -1 },
350  { CFSTR("WebKitStandardFont"), _SPM(STRING), "font.name.serif.", _SPM(SetFontName), PR_FALSE, -1 },
351  { CFSTR("WebKitDefaultFontSize"), _SPM(INT), "font.size.serif.", _SPM(SetFontSize), PR_FALSE, -1 },
352  { CFSTR("WebKitFixedFont"), _SPM(STRING), "font.name.fixed.", _SPM(SetFontName), PR_FALSE, -1 },
353  { CFSTR("WebKitDefaultFixedFontSize"), _SPM(INT), "font.size.fixed.", _SPM(SetFontSize), PR_FALSE, -1 },
354  { CFSTR("WebKitMinimumFontSize"), _SPM(INT), "font.minimum-size.", _SPM(SetFontSize), PR_FALSE, -1 },
355  { CFSTR("WebKitDisplayImagesKey"), _SPM(BOOL), "permissions.default.image", _SPM(SetDisplayImages), PR_FALSE, -1 },
356  { CFSTR("WebKitJavaScriptEnabled"), _SPM(BOOL), "javascript.enabled", _SPM(SetBool), PR_FALSE, -1 },
357  { CFSTR("WebKitJavaScriptCanOpenWindowsAutomatically"),
358  _SPM(BOOL), "dom.disable_open_during_load", _SPM(SetBoolInverted), PR_FALSE, -1 }
359 };
360 
361 nsresult
363 {
364  PrefTransform* xform = (PrefTransform*)aTransform;
365  return aBranch->SetBoolPref(xform->targetPrefName, xform->boolValue);
366 }
367 
368 nsresult
370 {
371  PrefTransform* xform = (PrefTransform*)aTransform;
372  return aBranch->SetBoolPref(xform->targetPrefName, !xform->boolValue);
373 }
374 
375 nsresult
377 {
378  PrefTransform* xform = (PrefTransform*)aTransform;
379  return aBranch->SetCharPref(xform->targetPrefName, xform->stringValue);
380 }
381 
382 nsresult
384 {
385  PrefTransform* xform = (PrefTransform*)aTransform;
386  return aBranch->SetIntPref(xform->targetPrefName, !xform->intValue);
387 }
388 
389 struct charsetEntry {
390  const char *webkitLabel;
392  const char *mozLabel;
393  const char *associatedLangGroup;
394 };
395 
396 static const charsetEntry gCharsets[] = {
397 #define CHARSET_ENTRY(charsetLabel, associatedLangGroup) \
398  {#charsetLabel, sizeof(#charsetLabel) - 1, #charsetLabel, #associatedLangGroup}
399 #define CHARSET_ENTRY2(webkitLabel, mozLabel, associatedLangGroup) \
400  {#webkitLabel, sizeof(#webkitLabel) - 1, #mozLabel, #associatedLangGroup}
401 
402  CHARSET_ENTRY(ISO-8859-1,x-western),
403  CHARSET_ENTRY2(MACINTOSH,x-mac-roman,x-western),
404  // Since "x-unicode" in the font dialog means "Other Languages" (that is,
405  // languages which don't have their own script), we're picking the default
406  // font group - "Western".
407  CHARSET_ENTRY(UTF-8,x-western),
408  CHARSET_ENTRY2(SHIFT_JIS,Shift_JIS,ja),
409  CHARSET_ENTRY(ISO-2022-JP,ja),
410  CHARSET_ENTRY(EUC-JP,ja),
411  CHARSET_ENTRY2(BIG5,Big5,zh-TW),
412  CHARSET_ENTRY(CP950,zh-TW),
413  CHARSET_ENTRY(Big5-HKSCS,zh-HK),
414  CHARSET_ENTRY(ISO-2022-KR,ko),
415  // XXX: fallback to the generic Korean encoding
416  CHARSET_ENTRY2(X-MAC-KOREAN,ISO-2022-KR,ko),
417  CHARSET_ENTRY(CP949,ko),
418  CHARSET_ENTRY(ISO-8859-6,ar),
419  CHARSET_ENTRY2(WINDOWS-1256,windows-1256,ar),
420  CHARSET_ENTRY(ISO-8859-8,he),
421  CHARSET_ENTRY2(WINDOWS-1255,windows-1255,he),
422  CHARSET_ENTRY(ISO-8859-7,el),
423  CHARSET_ENTRY2(WINDOWS-1253,windows-1253,el),
424  CHARSET_ENTRY(ISO-8859-5,x-cyrillic),
425  CHARSET_ENTRY2(X-MAC-CYRILLIC,x-mac-cyrillic,x-cyrillic),
426  CHARSET_ENTRY(KOI8-R,x-cyrillic),
427  CHARSET_ENTRY2(WINDOWS-1251,windows-1251,x-cyrillic),
428  CHARSET_ENTRY(CP874,th),
429  CHARSET_ENTRY2(GB_2312-80,GB2312,zh-CN),
430  CHARSET_ENTRY(HZ-GB-2312,zh-CN),
431  CHARSET_ENTRY2(GB18030,gb18030,zh-CN),
432  CHARSET_ENTRY(ISO-8859-2,x-central-euro),
433  CHARSET_ENTRY2(X-MAC-CENTRALEURROMAN,x-mac-ce,x-central-euro),
434  CHARSET_ENTRY2(WINDOWS-1250,windows-1250,x-central-euro),
435  CHARSET_ENTRY(ISO-8859-4,x-central-euro),
436  CHARSET_ENTRY(ISO-8859-9,tr),
437  CHARSET_ENTRY2(WINDOWS-125,windows-1254,tr),
438  CHARSET_ENTRY2(WINDOWS-1257,windows-1257,x-baltic)
439 
440 #undef CHARSET_ENTRY
441 #undef CHARSET_ENTRY2
442 };
443 
444 nsresult
446 {
447  PrefTransform* xform = (PrefTransform*)aTransform;
448 
449  nsCAutoString associatedLangGroup;
450  nsDependentCString encoding(xform->stringValue);
451  PRUint32 encodingLength = encoding.Length();
452  const char* encodingStr = encoding.get();
453 
454  PRInt16 charsetIndex = -1;
455  for (PRUint16 i = 0; (charsetIndex == -1) &&
456  i < (sizeof(gCharsets) / sizeof(gCharsets[0])); ++i) {
457  if (gCharsets[i].webkitLabelLength == encodingLength &&
458  !strcmp(gCharsets[i].webkitLabel, encodingStr))
459  charsetIndex = (PRInt16)i;
460  }
461  if (charsetIndex == -1) // Default to "Western"
462  charsetIndex = 0;
463 
464  aBranch->SetCharPref(xform->targetPrefName, gCharsets[charsetIndex].mozLabel);
465 
466  // We also want to use the default encoding for picking the default language
467  // in the fonts preferences dialog, and its associated preferences.
468 
469  aBranch->SetCharPref("font.language.group",
470  gCharsets[charsetIndex].associatedLangGroup);
471  aBranch->SetCharPref("migration.associatedLangGroup",
472  gCharsets[charsetIndex].associatedLangGroup);
473 
474  return NS_OK;
475 }
476 
477 nsresult
479 {
480  PrefTransform* xform = (PrefTransform*)aTransform;
481 
482  nsCOMPtr<nsILocalFile> downloadFolder;
483  nsresult rv = NS_NewNativeLocalFile(nsDependentCString(xform->stringValue),
484  PR_TRUE, getter_AddRefs(downloadFolder));
485  NS_ENSURE_SUCCESS(rv, rv);
486 
487  // If the Safari download folder is the desktop, set the folderList pref
488  // appropriately so that "Desktop" is selected in the list in our Preferences
489  // UI instead of just the raw path being shown.
490  nsCOMPtr<nsIProperties> fileLocator(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
491  nsCOMPtr<nsILocalFile> desktopFolder;
492  fileLocator->Get(NS_OSX_USER_DESKTOP_DIR, NS_GET_IID(nsILocalFile),
493  getter_AddRefs(desktopFolder));
494 
495  PRBool equals;
496  downloadFolder->Equals(desktopFolder, &equals);
497  aBranch->SetIntPref("browser.download.folderList", equals ? 0 : 2);
498  aBranch->SetComplexValue("browser.download.dir",
499  NS_GET_IID(nsILocalFile), downloadFolder);
500 
501  return NS_OK;
502 }
503 
504 nsresult
506 {
507  PrefTransform* xform = (PrefTransform*)aTransform;
508  if (!xform->boolValue) {
509  // If we're not set to auto-open safe downloads, we need to clear out the
510  // mime types list which contains default handlers.
511 
512  nsCOMPtr<nsIProperties> fileLocator(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
513  nsCOMPtr<nsILocalFile> mimeRegistryFile;
514  fileLocator->Get(NS_APP_USER_MIMETYPES_50_FILE, NS_GET_IID(nsILocalFile),
515  getter_AddRefs(mimeRegistryFile));
516 
517  nsCOMPtr<nsIIOService> ioService(do_GetService("@mozilla.org/network/io-service;1"));
518  nsCOMPtr<nsIProtocolHandler> ph;
519  ioService->GetProtocolHandler("file", getter_AddRefs(ph));
520  nsCOMPtr<nsIFileProtocolHandler> fph(do_QueryInterface(ph));
521 
522  nsCOMPtr<nsIRDFService> rdfService(do_GetService("@mozilla.org/rdf/rdf-service;1"));
523  nsCOMPtr<nsIRDFDataSource> mimeTypes;
524 
525  nsCAutoString dsURL;
526  fph->GetURLSpecFromFile(mimeRegistryFile, dsURL);
527  rdfService->GetDataSourceBlocking(dsURL.get(), getter_AddRefs(mimeTypes));
528 
529  nsCOMPtr<nsIRDFResource> overridesListResource;
530  rdfService->GetResource(NS_LITERAL_CSTRING("urn:mimetypes:root"),
531  getter_AddRefs(overridesListResource));
532 
533  nsCOMPtr<nsIRDFContainer> overridesList(do_CreateInstance("@mozilla.org/rdf/container;1"));
534  overridesList->Init(mimeTypes, overridesListResource);
535 
536  nsCOMPtr<nsIRDFResource> handlerPropArc, externalApplicationArc;
537  rdfService->GetResource(NC_URI(handlerProp), getter_AddRefs(handlerPropArc));
538  rdfService->GetResource(NC_URI(externalApplication),
539  getter_AddRefs(externalApplicationArc));
540 
541  PRInt32 count;
542  overridesList->GetCount(&count);
543  for (PRInt32 i = count; i >= 1; --i) {
544  nsCOMPtr<nsIRDFNode> currOverrideNode;
545  overridesList->RemoveElementAt(i, PR_FALSE, getter_AddRefs(currOverrideNode));
546  nsCOMPtr<nsIRDFResource> currOverride(do_QueryInterface(currOverrideNode));
547 
548  nsCOMPtr<nsIRDFNode> handlerPropNode;
549  mimeTypes->GetTarget(currOverride, handlerPropArc, PR_TRUE,
550  getter_AddRefs(handlerPropNode));
551  nsCOMPtr<nsIRDFResource> handlerPropResource(do_QueryInterface(handlerPropNode));
552 
553  if (handlerPropResource) {
554  nsCOMPtr<nsIRDFNode> externalApplicationNode;
555  mimeTypes->GetTarget(handlerPropResource, externalApplicationArc,
556  PR_TRUE, getter_AddRefs(externalApplicationNode));
557  nsCOMPtr<nsIRDFResource> externalApplicationResource(do_QueryInterface(externalApplicationNode));
558 
559  // Strip the resources down so that the datasource is completely flushed.
560  if (externalApplicationResource)
561  CleanResource(mimeTypes, externalApplicationResource);
562 
563  CleanResource(mimeTypes, handlerPropResource);
564  }
565  CleanResource(mimeTypes, currOverride);
566  }
567 
568  nsCOMPtr<nsIRDFRemoteDataSource> rds(do_QueryInterface(mimeTypes));
569  if (rds)
570  rds->Flush();
571  }
572  return NS_OK;
573 }
574 
575 void
576 nsSafariProfileMigrator::CleanResource(nsIRDFDataSource* aDataSource,
577  nsIRDFResource* aResource)
578 {
579  nsCOMPtr<nsISimpleEnumerator> arcLabels;
580  aDataSource->ArcLabelsOut(aResource, getter_AddRefs(arcLabels));
581  if (!arcLabels)
582  return;
583 
584  do {
585  PRBool hasMore;
586  arcLabels->HasMoreElements(&hasMore);
587 
588  if (!hasMore)
589  break;
590 
591  nsCOMPtr<nsIRDFResource> currArc;
592  arcLabels->GetNext(getter_AddRefs(currArc));
593 
594  if (currArc) {
595  nsCOMPtr<nsIRDFNode> currTarget;
596  aDataSource->GetTarget(aResource, currArc, PR_TRUE,
597  getter_AddRefs(currTarget));
598 
599  aDataSource->Unassert(aResource, currArc, currTarget);
600  }
601  }
602  while (1);
603 }
604 
605 nsresult
607  nsIPrefBranch* aBranch)
608 {
609  // Safari stores Download Retention in the opposite order of Firefox, namely:
610  // Retention Mode: Safari Firefox
611  // Remove Manually 0 2
612  // Remove on Exit 1 1
613  // Remove on DL Complete 2 0
614  PrefTransform* xform = (PrefTransform*)aTransform;
615  aBranch->SetIntPref(xform->targetPrefName,
616  xform->intValue == 0 ? 2 : xform->intValue == 2 ? 0 : 1);
617  return NS_OK;
618 }
619 
620 nsresult
622 {
623  // Firefox has an elaborate set of Image preferences. The correlation is:
624  // Mode: Safari Firefox
625  // Blocked FALSE 2
626  // Allowed TRUE 1
627  // Allowed, originating site only -- 3
628  PrefTransform* xform = (PrefTransform*)aTransform;
629  aBranch->SetIntPref(xform->targetPrefName, xform->boolValue ? 1 : 2);
630  return NS_OK;
631 }
632 
633 nsresult
635 {
636  nsCString associatedLangGroup;
637  nsresult rv = aBranch->GetCharPref("migration.associatedLangGroup",
638  getter_Copies(associatedLangGroup));
639  if (NS_FAILED(rv))
640  return NS_OK;
641 
642  PrefTransform* xform = (PrefTransform*)aTransform;
643  nsCAutoString prefName(xform->targetPrefName);
644  prefName.Append(associatedLangGroup);
645 
646  return aBranch->SetCharPref(prefName.get(), xform->stringValue);
647 }
648 
649 nsresult
651 {
652  nsCString associatedLangGroup;
653  nsresult rv = aBranch->GetCharPref("migration.associatedLangGroup",
654  getter_Copies(associatedLangGroup));
655  if (NS_FAILED(rv))
656  return NS_OK;
657 
658  PrefTransform* xform = (PrefTransform*)aTransform;
659  nsCAutoString prefName(xform->targetPrefName);
660  prefName.Append(associatedLangGroup);
661 
662  return aBranch->SetIntPref(prefName.get(), xform->intValue);
663 }
664 
665 nsresult
667 {
668  nsCOMPtr<nsIPrefBranch> branch(do_GetService(NS_PREFSERVICE_CONTRACTID));
669 
670  CFDictionaryRef safariPrefs = CopySafariPrefs();
671  if (!safariPrefs)
672  return NS_ERROR_FAILURE;
673 
674  // Traverse the standard transforms
675  PrefTransform* transform;
676  PrefTransform* end = gTransforms +
677  sizeof(gTransforms) / sizeof(PrefTransform);
678 
679  for (transform = gTransforms; transform < end; ++transform) {
680  Boolean hasValue = ::CFDictionaryContainsKey(safariPrefs, transform->keyName);
681  if (!hasValue)
682  continue;
683 
684  transform->prefHasValue = PR_FALSE;
685  switch (transform->type) {
686  case _SPM(STRING): {
687  CFStringRef stringValue = (CFStringRef)
688  ::CFDictionaryGetValue(safariPrefs,
689  transform->keyName);
690  char* value = GetNullTerminatedString(stringValue);
691  if (value) {
692  transform->stringValue = value;
693  transform->prefHasValue = PR_TRUE;
694  }
695  }
696  break;
697  case _SPM(INT): {
698  CFNumberRef intValue = (CFNumberRef)
699  ::CFDictionaryGetValue(safariPrefs,
700  transform->keyName);
701  PRInt32 value = 0;
702  if (::CFNumberGetValue(intValue, kCFNumberSInt32Type, &value)) {
703  transform->intValue = value;
704  transform->prefHasValue = PR_TRUE;
705  }
706  }
707  break;
708  case _SPM(BOOL): {
709  CFBooleanRef boolValue = (CFBooleanRef)
710  ::CFDictionaryGetValue(safariPrefs,
711  transform->keyName);
712  transform->boolValue = boolValue == kCFBooleanTrue;
713  transform->prefHasValue = PR_TRUE;
714  }
715  break;
716  default:
717  break;
718  }
719 
720  if (transform->prefHasValue)
721  transform->prefSetterFunc(transform, branch);
722 
723  if (transform->type == _SPM(STRING))
725  }
726 
727  ::CFRelease(safariPrefs);
728 
729  // Safari stores the Cookie "Accept/Don't Accept/Don't Accept Foreign" cookie
730  // setting in a separate WebFoundation preferences PList.
731  nsCOMPtr<nsIProperties> fileLocator(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
732  nsCOMPtr<nsILocalFile> safariWebFoundationPrefsFile;
733  fileLocator->Get(NS_OSX_USER_PREFERENCES_DIR, NS_GET_IID(nsILocalFile),
734  getter_AddRefs(safariWebFoundationPrefsFile));
735  safariWebFoundationPrefsFile->Append(SAFARI_COOKIE_BEHAVIOR_FILE_NAME);
736 
737  CFDictionaryRef safariWebFoundationPrefs =
738  static_cast<CFDictionaryRef>(CopyPListFromFile(safariWebFoundationPrefsFile));
739  if (safariWebFoundationPrefs) {
740  // Mapping of Safari preference values to Firefox preference values:
741  //
742  // Setting Safari Firefox
743  // Always Accept always 0
744  // Accept from Originating current page 1
745  // Never Accept never 2
746  nsAutoString acceptCookies;
747  if (GetDictionaryStringValue(safariWebFoundationPrefs,
748  CFSTR("NSHTTPAcceptCookies"), acceptCookies)) {
749  PRInt32 cookieValue = 0;
750  if (acceptCookies.EqualsLiteral("never"))
751  cookieValue = 2;
752  else if (acceptCookies.EqualsLiteral("current page"))
753  cookieValue = 1;
754 
755  branch->SetIntPref("network.cookie.cookieBehavior", cookieValue);
756  }
757 
758  ::CFRelease(safariWebFoundationPrefs);
759  }
760 
761  return NS_OK;
762 }
763 
764 nsresult
766 {
767  nsCOMPtr<nsIProperties> fileLocator(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
768  nsCOMPtr<nsILocalFile> safariCookiesFile;
769  fileLocator->Get(NS_MAC_USER_LIB_DIR,
770  NS_GET_IID(nsILocalFile),
771  getter_AddRefs(safariCookiesFile));
772  safariCookiesFile->Append(NS_LITERAL_STRING("Cookies"));
773  safariCookiesFile->Append(SAFARI_COOKIES_FILE_NAME);
774 
775  CFArrayRef safariCookies = (CFArrayRef)CopyPListFromFile(safariCookiesFile);
776  if (!safariCookies)
777  return NS_OK;
778 
779  nsCOMPtr<nsICookieManager2> cookieManager(do_GetService(NS_COOKIEMANAGER_CONTRACTID));
780  CFIndex count = ::CFArrayGetCount(safariCookies);
781  for (PRInt32 i = 0; i < count; ++i) {
782  CFDictionaryRef entry = (CFDictionaryRef)::CFArrayGetValueAtIndex(safariCookies, i);
783 
784  CFDateRef date = (CFDateRef)::CFDictionaryGetValue(entry, CFSTR("Expires"));
785 
786  nsCAutoString domain, path, name, value;
787  if (date &&
788  GetDictionaryCStringValue(entry, CFSTR("Domain"), domain,
789  kCFStringEncodingUTF8) &&
790  GetDictionaryCStringValue(entry, CFSTR("Path"), path,
791  kCFStringEncodingUTF8) &&
792  GetDictionaryCStringValue(entry, CFSTR("Name"), name,
793  kCFStringEncodingASCII) &&
794  GetDictionaryCStringValue(entry, CFSTR("Value"), value,
795  kCFStringEncodingASCII)) {
796  PRInt64 expiryTime;
797  LL_D2L(expiryTime, (double)::CFDateGetAbsoluteTime(date));
798 
799  expiryTime += SAFARI_DATE_OFFSET;
800  cookieManager->Add(domain, path, name, value,
801  PR_FALSE, // isSecure
802  PR_FALSE, // isHttpOnly
803  PR_FALSE, // isSession
804  expiryTime);
805  }
806  }
807  ::CFRelease(safariCookies);
808 
809  return NS_OK;
810 }
811 
812 NS_IMETHODIMP
813 nsSafariProfileMigrator::RunBatched(nsISupports* aUserData)
814 {
815  PRUint8 batchAction;
816  nsCOMPtr<nsISupportsPRUint8> strWrapper(do_QueryInterface(aUserData));
817  NS_ASSERTION(strWrapper, "Unable to create nsISupportsPRUint8 wrapper!");
818  nsresult rv = strWrapper->GetData(&batchAction);
819  NS_ENSURE_SUCCESS(rv, rv);
820 
821  switch (batchAction) {
823  rv = CopyHistoryBatched(PR_FALSE);
824  break;
826  rv = CopyHistoryBatched(PR_TRUE);
827  break;
829  rv = CopyBookmarksBatched(PR_FALSE);
830  break;
832  rv = CopyBookmarksBatched(PR_TRUE);
833  break;
834  }
835  NS_ENSURE_SUCCESS(rv, rv);
836 
837  return NS_OK;
838 }
839 
840 nsresult
842 {
843  nsresult rv;
844  nsCOMPtr<nsINavHistoryService> history =
845  do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID, &rv);
846  NS_ENSURE_SUCCESS(rv, rv);
847 
848  PRUint8 batchAction = aReplace ? BATCH_ACTION_HISTORY_REPLACE
850  nsCOMPtr<nsISupportsPRUint8> supports =
851  do_CreateInstance(NS_SUPPORTS_PRUINT8_CONTRACTID);
852  NS_ENSURE_TRUE(supports, NS_ERROR_OUT_OF_MEMORY);
853  rv = supports->SetData(batchAction);
854  NS_ENSURE_SUCCESS(rv, rv);
855 
856  rv = history->RunInBatchMode(this, supports);
857  NS_ENSURE_SUCCESS(rv, rv);
858 
859  return rv;
860 }
861 
862 nsresult
864 {
865  nsCOMPtr<nsIProperties> fileLocator(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
866  nsCOMPtr<nsILocalFile> safariHistoryFile;
867  fileLocator->Get(NS_MAC_USER_LIB_DIR, NS_GET_IID(nsILocalFile),
868  getter_AddRefs(safariHistoryFile));
869  safariHistoryFile->Append(NS_LITERAL_STRING("Safari"));
870  safariHistoryFile->Append(SAFARI_HISTORY_FILE_NAME);
871 
872  CFDictionaryRef safariHistory =
873  static_cast<CFDictionaryRef>(CopyPListFromFile(safariHistoryFile));
874  if (!safariHistory)
875  return NS_OK;
876 
877  if (!::CFDictionaryContainsKey(safariHistory, CFSTR("WebHistoryDates"))) {
878  ::CFRelease(safariHistory);
879  return NS_OK;
880  }
881 
882  nsCOMPtr<nsIBrowserHistory> history(do_GetService(NS_GLOBALHISTORY2_CONTRACTID));
883 
884  CFArrayRef children = (CFArrayRef)
885  ::CFDictionaryGetValue(safariHistory, CFSTR("WebHistoryDates"));
886  if (children) {
887  CFIndex count = ::CFArrayGetCount(children);
888  for (PRInt32 i = 0; i < count; ++i) {
889  CFDictionaryRef entry = (CFDictionaryRef)::CFArrayGetValueAtIndex(children, i);
890 
891  CFStringRef lastVisitedDate = (CFStringRef)
892  ::CFDictionaryGetValue(entry, CFSTR("lastVisitedDate"));
893  nsAutoString url, title;
894  if (GetDictionaryStringValue(entry, CFSTR(""), url) &&
895  GetDictionaryStringValue(entry, CFSTR("title"), title) &&
896  lastVisitedDate) {
897 
898  double lvd = ::CFStringGetDoubleValue(lastVisitedDate) + SAFARI_DATE_OFFSET;
899  PRTime lastVisitTime;
900  PRInt64 temp, million;
901  LL_D2L(temp, lvd);
902  LL_I2L(million, PR_USEC_PER_SEC);
903  LL_MUL(lastVisitTime, temp, million);
904 
905  nsCOMPtr<nsIURI> uri;
906  NS_NewURI(getter_AddRefs(uri), url);
907  if (uri)
908  history->AddPageWithDetails(uri, title.get(), lastVisitTime);
909  }
910  }
911  }
912 
913  ::CFRelease(safariHistory);
914 
915  return NS_OK;
916 }
917 
918 nsresult
920 {
921  nsresult rv;
922  nsCOMPtr<nsINavBookmarksService> bookmarks =
923  do_GetService(NS_NAVBOOKMARKSSERVICE_CONTRACTID, &rv);
924  NS_ENSURE_SUCCESS(rv, rv);
925 
926  PRUint8 batchAction = aReplace ? BATCH_ACTION_BOOKMARKS_REPLACE
928  nsCOMPtr<nsISupportsPRUint8> supports =
929  do_CreateInstance(NS_SUPPORTS_PRUINT8_CONTRACTID);
930  NS_ENSURE_TRUE(supports, NS_ERROR_OUT_OF_MEMORY);
931  rv = supports->SetData(batchAction);
932  NS_ENSURE_SUCCESS(rv, rv);
933 
934  rv = bookmarks->RunInBatchMode(this, supports);
935  NS_ENSURE_SUCCESS(rv, rv);
936 
937  return NS_OK;
938 }
939 
940 nsresult
942 {
943  // If "aReplace" is true, merge into the root level of bookmarks. Otherwise, create
944  // a folder called "Imported Safari Favorites" and place all the Bookmarks there.
945  nsresult rv;
946 
947  nsCOMPtr<nsINavBookmarksService> bms =
948  do_GetService(NS_NAVBOOKMARKSSERVICE_CONTRACTID, &rv);
949  NS_ENSURE_SUCCESS(rv, rv);
950  PRInt64 bookmarksMenuFolderId;
951  rv = bms->GetBookmarksMenuFolder(&bookmarksMenuFolderId);
952  NS_ENSURE_SUCCESS(rv, rv);
953 
954  PRInt64 folder;
955  if (!aReplace) {
956  nsCOMPtr<nsIStringBundleService> bundleService =
957  do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
958  NS_ENSURE_SUCCESS(rv, rv);
959  nsCOMPtr<nsIStringBundle> bundle;
960  rv = bundleService->CreateBundle(MIGRATION_BUNDLE, getter_AddRefs(bundle));
961  NS_ENSURE_SUCCESS(rv, rv);
962 
963  nsString sourceNameSafari;
964  rv = bundle->GetStringFromName(NS_LITERAL_STRING("sourceNameSafari").get(),
965  getter_Copies(sourceNameSafari));
966  NS_ENSURE_SUCCESS(rv, rv);
967 
968  const PRUnichar* sourceNameStrings[] = { sourceNameSafari.get() };
969  nsString importedSafariBookmarksTitle;
970  rv = bundle->FormatStringFromName(NS_LITERAL_STRING("importedBookmarksFolder").get(),
971  sourceNameStrings, 1,
972  getter_Copies(importedSafariBookmarksTitle));
973  NS_ENSURE_SUCCESS(rv, rv);
974 
975  rv = bms->CreateFolder(bookmarksMenuFolderId,
976  NS_ConvertUTF16toUTF8(importedSafariBookmarksTitle),
977  nsINavBookmarksService::DEFAULT_INDEX, &folder);
978  NS_ENSURE_SUCCESS(rv, rv);
979  }
980  else {
981  nsCOMPtr<nsIFile> profile;
982  GetProfilePath(nsnull, profile);
983  rv = InitializeBookmarks(profile);
984  NS_ENSURE_SUCCESS(rv, rv);
985  // In replace mode we are merging at the top level.
986  folder = bookmarksMenuFolderId;
987  }
988 
989  nsCOMPtr<nsIProperties> fileLocator(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
990  nsCOMPtr<nsILocalFile> safariBookmarksFile;
991  fileLocator->Get(NS_MAC_USER_LIB_DIR, NS_GET_IID(nsILocalFile),
992  getter_AddRefs(safariBookmarksFile));
993  safariBookmarksFile->Append(NS_LITERAL_STRING("Safari"));
994  safariBookmarksFile->Append(SAFARI_BOOKMARKS_FILE_NAME);
995 
996  CFDictionaryRef safariBookmarks =
997  static_cast<CFDictionaryRef>(CopyPListFromFile(safariBookmarksFile));
998  if (!safariBookmarks)
999  return NS_OK;
1000 
1001  // The Safari Bookmarks file looks like this:
1002  // At the top level are all the Folders, Special Folders and Proxies. Proxies
1003  // are references to other data sources such as History, Rendezvous etc.
1004  // We ignore these. Special folders exist for the Bookmarks Toolbar folder
1005  // (called "BookmarksBar" and the Bookmarks Menu (called "BookmarksMenu").
1006  // We put the contents of the "BookmarksBar" folder into our Personal Toolbar
1007  // and merge the contents of the "BookmarksMenu" folder and the other toplevel
1008  // non-special folders under our NC:BookmarksRoot.
1009  if (::CFDictionaryContainsKey(safariBookmarks, CFSTR("Children")) &&
1010  ::CFDictionaryContainsKey(safariBookmarks, CFSTR("WebBookmarkFileVersion")) ) {
1011  CFNumberRef intValue =
1012  (CFNumberRef)::CFDictionaryGetValue(safariBookmarks,
1013  CFSTR("WebBookmarkFileVersion"));
1014  PRInt32 value = 0;
1015  if (::CFNumberGetValue(intValue, kCFNumberSInt32Type, &value) && value ==1) {
1016  CFArrayRef children =
1017  (CFArrayRef)::CFDictionaryGetValue(safariBookmarks, CFSTR("Children"));
1018  if (children) {
1019  rv = ParseBookmarksFolder(children, folder, bms, PR_TRUE);
1020  }
1021  }
1022  }
1023  ::CFRelease(safariBookmarks);
1024  return rv;
1025 }
1026 
1027 nsresult
1029  PRInt64 aParentFolder,
1030  nsINavBookmarksService * aBookmarksService,
1031  PRBool aIsAtRootLevel)
1032 {
1033  nsresult rv = NS_OK;
1034 
1035  CFIndex count = ::CFArrayGetCount(aChildren);
1036  for (PRInt32 i = 0; i < count; ++i) {
1037  CFDictionaryRef entry = (CFDictionaryRef)::CFArrayGetValueAtIndex(aChildren, i);
1038 
1039  nsAutoString type;
1040  if (!GetDictionaryStringValue(entry, CFSTR("WebBookmarkType"), type))
1041  continue;
1042 
1043  if (!type.EqualsLiteral("WebBookmarkTypeList") &&
1044  !type.EqualsLiteral("WebBookmarkTypeLeaf"))
1045  continue;
1046 
1047  if (::CFDictionaryContainsKey(entry, CFSTR("Children")) &&
1048  type.EqualsLiteral("WebBookmarkTypeList")) {
1049  nsAutoString title;
1050  if (!GetDictionaryStringValue(entry, CFSTR("Title"), title))
1051  continue;
1052 
1053  CFArrayRef children = (CFArrayRef)::CFDictionaryGetValue(entry,
1054  CFSTR("Children"));
1055 
1056  // Look for the BookmarksBar Bookmarks and add them into the appropriate
1057  // Personal Toolbar Root
1058  if (title.EqualsLiteral("BookmarksBar") && aIsAtRootLevel) {
1059  PRInt64 toolbarFolder;
1060  aBookmarksService->GetToolbarFolder(&toolbarFolder);
1061 
1062  rv |= ParseBookmarksFolder(children,
1063  toolbarFolder,
1064  aBookmarksService,
1065  PR_FALSE);
1066  }
1067  // Look for the BookmarksMenu Bookmarks and flatten them into the top level
1068  else if (title.EqualsLiteral("BookmarksMenu") && aIsAtRootLevel) {
1069  rv |= ParseBookmarksFolder(children,
1070  aParentFolder,
1071  aBookmarksService,
1072  PR_TRUE);
1073  }
1074  else {
1075  // Encountered a Folder, so create one in our Bookmarks DataSource and then
1076  // parse the contents of the Safari one into it...
1077  PRInt64 folder;
1078  rv |= aBookmarksService->CreateFolder(aParentFolder, NS_ConvertUTF16toUTF8(title),
1079  nsINavBookmarksService::DEFAULT_INDEX,
1080  &folder);
1081  rv |= ParseBookmarksFolder(children,
1082  folder,
1083  aBookmarksService,
1084  PR_FALSE);
1085  }
1086  }
1087  else if (type.EqualsLiteral("WebBookmarkTypeLeaf")) {
1088  // Encountered a Bookmark, so add it to the current folder...
1089  CFDictionaryRef URIDictionary = (CFDictionaryRef)
1090  ::CFDictionaryGetValue(entry, CFSTR("URIDictionary"));
1091  nsAutoString title;
1092  nsCAutoString url;
1093  if (GetDictionaryStringValue(URIDictionary, CFSTR("title"), title) &&
1094  GetDictionaryCStringValue(entry, CFSTR("URLString"), url, kCFStringEncodingUTF8)) {
1095  nsCOMPtr<nsIURI> uri;
1096  rv = NS_NewURI(getter_AddRefs(uri), url);
1097  if (NS_SUCCEEDED(rv)) {
1098  PRInt64 id;
1099  rv = aBookmarksService->InsertBookmark(aParentFolder, uri,
1100  nsINavBookmarksService::DEFAULT_INDEX,
1101  NS_ConvertUTF16toUTF8(title), &id);
1102  }
1103  }
1104  }
1105  }
1106  return rv;
1107 }
1108 
1109 // nsSafariProfileMigrator::HasFormDataToImport()
1110 // if we add support for "~/Library/Safari/Form Values",
1111 // keep in sync with CopyFormData()
1112 // see bug #344284
1113 PRBool
1114 nsSafariProfileMigrator::HasFormDataToImport()
1115 {
1116  PRBool hasFormData = PR_FALSE;
1117 
1118  // Safari stores this data in an array under the "RecentSearchStrings" key
1119  // in its Preferences file.
1120  CFDictionaryRef safariPrefs = CopySafariPrefs();
1121  if (safariPrefs) {
1122  if (::CFDictionaryContainsKey(safariPrefs, CFSTR("RecentSearchStrings")))
1123  hasFormData = PR_TRUE;
1124  ::CFRelease(safariPrefs);
1125  }
1126  return hasFormData;
1127 }
1128 
1129 // nsSafariProfileMigrator::CopyFormData()
1130 // if we add support for "~/Library/Safari/Form Values",
1131 // keep in sync with HasFormDataToImport()
1132 // see bug #344284
1133 nsresult
1135 {
1136  nsresult rv = NS_ERROR_FAILURE;
1137  CFDictionaryRef safariPrefs = CopySafariPrefs();
1138  if (safariPrefs) {
1139  // We lump saved Searches in with Form Data since that's how we store it.
1140  // Safari stores this data in an array under the "RecentSearchStrings" key
1141  // in its Preferences file.
1142  Boolean hasSearchStrings = ::CFDictionaryContainsKey(safariPrefs,
1143  CFSTR("RecentSearchStrings"));
1144  if (hasSearchStrings) {
1145  nsCOMPtr<nsIFormHistory2> formHistory(do_GetService("@mozilla.org/satchel/form-history;1"));
1146  if (formHistory) {
1147  CFArrayRef strings = (CFArrayRef)::CFDictionaryGetValue(safariPrefs,
1148  CFSTR("RecentSearchStrings"));
1149  if (strings) {
1150  CFIndex count = ::CFArrayGetCount(strings);
1151  for (PRInt32 i = 0; i < count; ++i) {
1152  nsAutoString value;
1153  GetArrayStringValue(strings, i, value);
1154  formHistory->AddEntry(NS_LITERAL_STRING("searchbar-history"), value);
1155  }
1156  }
1157  rv = NS_OK;
1158  }
1159  }
1160  else
1161  rv = NS_OK;
1162 
1163  ::CFRelease(safariPrefs);
1164  }
1165 
1166  return rv;
1167 }
1168 
1169 // Returns whether or not the active profile has a content style sheet
1170 // (That is chrome/userContent.css)
1171 nsresult
1173 {
1174  NS_ENSURE_ARG(outExists);
1175 
1176  // Get the profile's chrome/ directory native path
1177  nsCOMPtr<nsIFile> userChromeDir;
1178  nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_CHROME_DIR,
1179  getter_AddRefs(userChromeDir));
1180  nsCAutoString userChromeDirPath;
1181  rv = userChromeDir->GetNativePath(userChromeDirPath);
1182  NS_ENSURE_SUCCESS(rv, rv);
1183 
1184  nsCAutoString path(userChromeDirPath);
1185  path.Append("/userContent.css");
1186 
1187  nsCOMPtr<nsILocalFile> file;
1188  rv = NS_NewNativeLocalFile(path, PR_FALSE,
1189  getter_AddRefs(file));
1190  NS_ENSURE_SUCCESS(rv, rv);
1191 
1192  file->Exists(outExists);
1193  return NS_OK;
1194 }
1195 
1196 nsresult
1198 {
1199  *aResult = nsnull;
1200 
1201  CFDictionaryRef safariPrefs = CopySafariPrefs();
1202  if (!safariPrefs)
1203  return NS_ERROR_FAILURE;
1204 
1205  nsresult rv = NS_ERROR_FAILURE;
1206  // Check whether or not a user style sheet has been specified
1207  if (::CFDictionaryContainsKey
1208  (safariPrefs, CFSTR("WebKitUserStyleSheetEnabledPreferenceKey")) &&
1209  ::CFDictionaryContainsKey
1210  (safariPrefs, CFSTR("WebKitUserStyleSheetLocationPreferenceKey"))) {
1211  CFBooleanRef hasSheet = (CFBooleanRef)::CFDictionaryGetValue(safariPrefs,
1212  CFSTR("WebKitUserStyleSheetEnabledPreferenceKey"));
1213  if (hasSheet == kCFBooleanTrue) {
1214  nsAutoString path;
1215  // Get its path
1216  if (GetDictionaryStringValue(safariPrefs,
1217  CFSTR("WebKitUserStyleSheetLocation" \
1218  "PreferenceKey"), path)) {
1219  nsCOMPtr<nsILocalFile> file;
1220  rv = NS_NewLocalFile(path, PR_FALSE, getter_AddRefs(file));
1221  if (NS_SUCCEEDED(rv)) {
1222  PRBool exists = PR_FALSE;
1223  file->Exists(&exists);
1224  if (exists) {
1225  NS_ADDREF(*aResult = file);
1226  rv = NS_OK;
1227  }
1228  else
1229  rv = NS_ERROR_FILE_NOT_FOUND;
1230  }
1231  }
1232  }
1233  }
1234  ::CFRelease(safariPrefs);
1235 
1236  return rv;
1237 }
1238 
1239 nsresult
1241 {
1242  // Get the Safari user style sheet and copy it into the active profile's
1243  // chrome folder
1244  nsCOMPtr<nsILocalFile> stylesheetFile;
1245  if (NS_SUCCEEDED(GetSafariUserStyleSheet(getter_AddRefs(stylesheetFile)))) {
1246  nsCOMPtr<nsIFile> userChromeDir;
1247  NS_GetSpecialDirectory(NS_APP_USER_CHROME_DIR,
1248  getter_AddRefs(userChromeDir));
1249 
1250  stylesheetFile->CopyTo(userChromeDir, NS_LITERAL_STRING("userContent.css"));
1251  }
1252  return NS_OK;
1253 }
1254 
1255 
1256 NS_IMETHODIMP
1257 nsSafariProfileMigrator::GetSourceHomePageURL(nsACString& aResult)
1258 {
1259  aResult.Truncate();
1260 
1261  // Let's first check if there's a home page key in the com.apple.safari file...
1262  CFDictionaryRef safariPrefs = CopySafariPrefs();
1263  if (safariPrefs) {
1264  PRBool foundPref = GetDictionaryCStringValue(safariPrefs,
1265  CFSTR(SAFARI_HOME_PAGE_PREF),
1266  aResult, kCFStringEncodingUTF8);
1267  ::CFRelease(safariPrefs);
1268  if (foundPref)
1269  return NS_OK;
1270  }
1271 
1272  // Couldn't find the home page in com.apple.safai, time to check
1273  // com.apple.internetconfig for this key!
1274  ICInstance internetConfig;
1275  OSStatus error = ::ICStart(&internetConfig, 'FRFX');
1276  if (error != noErr)
1277  return NS_ERROR_FAILURE;
1278 
1279  ICAttr dummy;
1280  Str255 homePagePValue;
1281  long prefSize = sizeof(homePagePValue);
1282  error = ::ICGetPref(internetConfig, kICWWWHomePage, &dummy,
1283  homePagePValue, &prefSize);
1284  if (error != noErr)
1285  return NS_ERROR_FAILURE;
1286 
1287  char homePageValue[256] = "";
1288  CopyPascalStringToC((ConstStr255Param)homePagePValue, homePageValue);
1289  aResult.Assign(homePageValue);
1290  ::ICStop(internetConfig);
1291 
1292  return NS_OK;
1293 }
PRBool GetDictionaryStringValue(CFDictionaryRef aDictionary, CFStringRef aKey, nsAString &aResult)
nsresult InitializeBookmarks(nsIFile *aTargetProfile)
static void CleanResource(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource)
PRBool GetDictionaryCStringValue(CFDictionaryRef aDictionary, CFStringRef aKey, nsACString &aResult, CFStringEncoding aEncoding)
classDescription entry
Definition: FeedWriter.js:1427
static const charsetEntry gCharsets[]
static nsresult SetDownloadFolder(void *aTransform, nsIPrefBranch *aBranch)
return NS_OK
nsresult CopyBookmarksBatched(PRBool aReplace)
void FreeNullTerminatedString(char *aString)
#define SAFARI_HISTORY_FILE_NAME
const char * associatedLangGroup
const char * mozLabel
_setDateDatepicker date
menuItem id
Definition: FeedWriter.js:971
NS_IMPL_ISUPPORTS1(sbDeviceCapabilitiesUtils, sbIDeviceCapabilitiesUtils) sbDeviceCapabilitiesUtils
var windows
static nsresult SetInt(void *aTransform, nsIPrefBranch *aBranch)
#define _SPM(type)
#define BATCH_ACTION_BOOKMARKS
var history
const NS_PREFSERVICE_CONTRACTID
static nsSafariProfileMigrator::PrefTransform gTransforms[]
static nsresult SetString(void *aTransform, nsIPrefBranch *aBranch)
#define SAFARI_PREFERENCES_FILE_NAME
static nsresult SetDownloadRetention(void *aTransform, nsIPrefBranch *aBranch)
char * GetNullTerminatedString(CFStringRef aStringRef)
size_t webkitLabelLength
PRBool GetArrayStringValue(CFArrayRef aArray, PRInt32 aIndex, nsAString &aResult)
static nsresult SetDisplayImages(void *aTransform, nsIPrefBranch *aBranch)
#define CHARSET_ENTRY2(webkitLabel, mozLabel, associatedLangGroup)
const nsIPrefBranch
var ioService
#define BATCH_ACTION_HISTORY_REPLACE
nsresult CopyBookmarks(PRBool aReplace)
foldersync central
Definition: central.js:16
#define NOTIFY_OBSERVERS(message, item)
#define SAFARI_DATE_OFFSET
#define SAFARI_HOME_PAGE_PREF
var strings
Definition: Info.js:46
nsresult CopyFormData(PRBool aReplace)
#define SAFARI_COOKIE_BEHAVIOR_FILE_NAME
nsresult CopyPreferences(PRBool aReplace)
var bundle
var count
Definition: test_bug7406.js:32
static nsresult SetFontName(void *aTransform, nsIPrefBranch *aBranch)
#define MIGRATION_BUNDLE
static nsresult SetDefaultEncoding(void *aTransform, nsIPrefBranch *aBranch)
#define MIGRATION_STARTED
nsresult CopyHistoryBatched(PRBool aReplace)
#define COPY_DATA(func, replace, itemIndex)
CFDictionaryRef CopySafariPrefs()
#define MIGRATION_ENDED
#define SAFARI_COOKIES_FILE_NAME
static nsresult SetFontSize(void *aTransform, nsIPrefBranch *aBranch)
#define CHARSET_ENTRY(charsetLabel, associatedLangGroup)
CFPropertyListRef CopyPListFromFile(nsILocalFile *aPListFile)
static nsresult SetDownloadHandlers(void *aTransform, nsIPrefBranch *aBranch)
nsresult CopyCookies(PRBool aReplace)
#define NC_URI(property)
const char * webkitLabel
nsresult GetSafariUserStyleSheet(nsILocalFile **aResult)
var uri
Definition: FeedWriter.js:1135
function url(spec)
StringArrayEnumerator prototype hasMore
countRef value
Definition: FeedWriter.js:1423
nsresult ProfileHasContentStyleSheet(PRBool *outExists)
#define SAFARI_BOOKMARKS_FILE_NAME
void GetProfilePath(nsIProfileStartup *aStartup, nsCOMPtr< nsIFile > &aProfileDir)
#define BATCH_ACTION_HISTORY
static nsresult SetBoolInverted(void *aTransform, nsIPrefBranch *aBranch)
#define BATCH_ACTION_BOOKMARKS_REPLACE
nsresult CopyHistory(PRBool aReplace)
observe data
Definition: FeedWriter.js:1329
static nsresult SetBool(void *aTransform, nsIPrefBranch *aBranch)
nsresult ParseBookmarksFolder(CFArrayRef aChildren, PRInt64 aParentFolder, nsINavBookmarksService *aBookmarksService, PRBool aIsAtRootLevel)
_getSelectedPageStyle s i
nsresult CopyOtherData(PRBool aReplace)
void GetMigrateDataFromArray(MigrationData *aDataArray, PRInt32 aDataArrayLength, PRBool aReplace, nsIFile *aSourceProfile, PRUint16 *aResult)
var file