1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/importer/importer_list.h"
6
7#include "base/bind.h"
8#include "chrome/browser/shell_integration.h"
9#include "chrome/common/importer/firefox_importer_utils.h"
10#include "chrome/common/importer/importer_bridge.h"
11#include "chrome/common/importer/importer_data_types.h"
12#include "chrome/grit/generated_resources.h"
13#include "content/public/browser/browser_thread.h"
14#include "ui/base/l10n/l10n_util.h"
15
16#if defined(OS_MACOSX)
17#include <CoreFoundation/CoreFoundation.h>
18
19#include "base/mac/foundation_util.h"
20#include "chrome/common/importer/safari_importer_utils.h"
21#endif
22
23using content::BrowserThread;
24
25namespace {
26
27#if defined(OS_WIN)
28void DetectIEProfiles(std::vector<importer::SourceProfile*>* profiles) {
29  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
30  // IE always exists and doesn't have multiple profiles.
31  importer::SourceProfile* ie = new importer::SourceProfile;
32  ie->importer_name = l10n_util::GetStringUTF16(IDS_IMPORT_FROM_IE);
33  ie->importer_type = importer::TYPE_IE;
34  ie->source_path.clear();
35  ie->app_path.clear();
36  ie->services_supported = importer::HISTORY | importer::FAVORITES |
37      importer::COOKIES | importer::PASSWORDS | importer::SEARCH_ENGINES;
38  profiles->push_back(ie);
39}
40#endif  // defined(OS_WIN)
41
42#if defined(OS_MACOSX)
43void DetectSafariProfiles(std::vector<importer::SourceProfile*>* profiles) {
44  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
45  uint16 items = importer::NONE;
46  if (!SafariImporterCanImport(base::mac::GetUserLibraryPath(), &items))
47    return;
48
49  importer::SourceProfile* safari = new importer::SourceProfile;
50  safari->importer_name = l10n_util::GetStringUTF16(IDS_IMPORT_FROM_SAFARI);
51  safari->importer_type = importer::TYPE_SAFARI;
52  safari->source_path.clear();
53  safari->app_path.clear();
54  safari->services_supported = items;
55  profiles->push_back(safari);
56}
57#endif  // defined(OS_MACOSX)
58
59// |locale|: The application locale used for lookups in Firefox's
60// locale-specific search engines feature (see firefox_importer.cc for
61// details).
62void DetectFirefoxProfiles(const std::string locale,
63                           std::vector<importer::SourceProfile*>* profiles) {
64  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
65  base::FilePath profile_path = GetFirefoxProfilePath();
66  if (profile_path.empty())
67    return;
68
69  // Detects which version of Firefox is installed.
70  importer::ImporterType firefox_type;
71  base::FilePath app_path;
72  int version = 0;
73#if defined(OS_WIN)
74  version = GetCurrentFirefoxMajorVersionFromRegistry();
75#endif
76  if (version < 2)
77    GetFirefoxVersionAndPathFromProfile(profile_path, &version, &app_path);
78
79  if (version >= 3) {
80    firefox_type = importer::TYPE_FIREFOX;
81  } else {
82    // Ignores old versions of firefox.
83    return;
84  }
85
86  importer::SourceProfile* firefox = new importer::SourceProfile;
87  firefox->importer_name = GetFirefoxImporterName(app_path);
88  firefox->importer_type = firefox_type;
89  firefox->source_path = profile_path;
90#if defined(OS_WIN)
91  firefox->app_path = GetFirefoxInstallPathFromRegistry();
92#endif
93  if (firefox->app_path.empty())
94    firefox->app_path = app_path;
95  firefox->services_supported = importer::HISTORY | importer::FAVORITES |
96                                importer::PASSWORDS | importer::SEARCH_ENGINES |
97                                importer::AUTOFILL_FORM_DATA;
98  firefox->locale = locale;
99  profiles->push_back(firefox);
100}
101
102std::vector<importer::SourceProfile*> DetectSourceProfilesWorker(
103    const std::string& locale,
104    bool include_interactive_profiles) {
105  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
106
107  std::vector<importer::SourceProfile*> profiles;
108
109  // The first run import will automatically take settings from the first
110  // profile detected, which should be the user's current default.
111#if defined(OS_WIN)
112  if (ShellIntegration::IsFirefoxDefaultBrowser()) {
113    DetectFirefoxProfiles(locale, &profiles);
114    DetectIEProfiles(&profiles);
115  } else {
116    DetectIEProfiles(&profiles);
117    DetectFirefoxProfiles(locale, &profiles);
118  }
119#elif defined(OS_MACOSX)
120  if (ShellIntegration::IsFirefoxDefaultBrowser()) {
121    DetectFirefoxProfiles(locale, &profiles);
122    DetectSafariProfiles(&profiles);
123  } else {
124    DetectSafariProfiles(&profiles);
125    DetectFirefoxProfiles(locale, &profiles);
126  }
127#else
128  DetectFirefoxProfiles(locale, &profiles);
129#endif
130  if (include_interactive_profiles) {
131    importer::SourceProfile* bookmarks_profile = new importer::SourceProfile;
132    bookmarks_profile->importer_name =
133        l10n_util::GetStringUTF16(IDS_IMPORT_FROM_BOOKMARKS_HTML_FILE);
134    bookmarks_profile->importer_type = importer::TYPE_BOOKMARKS_FILE;
135    bookmarks_profile->services_supported = importer::FAVORITES;
136    profiles.push_back(bookmarks_profile);
137  }
138
139  return profiles;
140}
141
142}  // namespace
143
144ImporterList::ImporterList()
145    : weak_ptr_factory_(this) {
146  DCHECK_CURRENTLY_ON(BrowserThread::UI);
147}
148
149ImporterList::~ImporterList() {
150  DCHECK_CURRENTLY_ON(BrowserThread::UI);
151}
152
153void ImporterList::DetectSourceProfiles(
154    const std::string& locale,
155    bool include_interactive_profiles,
156    const base::Closure& profiles_loaded_callback) {
157  DCHECK_CURRENTLY_ON(BrowserThread::UI);
158  BrowserThread::PostTaskAndReplyWithResult(
159      BrowserThread::FILE,
160      FROM_HERE,
161      base::Bind(&DetectSourceProfilesWorker,
162                 locale,
163                 include_interactive_profiles),
164      base::Bind(&ImporterList::SourceProfilesLoaded,
165                 weak_ptr_factory_.GetWeakPtr(),
166                 profiles_loaded_callback));
167}
168
169const importer::SourceProfile& ImporterList::GetSourceProfileAt(
170    size_t index) const {
171  DCHECK_LT(index, count());
172  return *source_profiles_[index];
173}
174
175void ImporterList::SourceProfilesLoaded(
176    const base::Closure& profiles_loaded_callback,
177    const std::vector<importer::SourceProfile*>& profiles) {
178  DCHECK_CURRENTLY_ON(BrowserThread::UI);
179
180  source_profiles_.assign(profiles.begin(), profiles.end());
181  profiles_loaded_callback.Run();
182}
183