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 "content/public/browser/browser_thread.h"
13#include "grit/generated_resources.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  firefox->locale = locale;
98  profiles->push_back(firefox);
99}
100
101std::vector<importer::SourceProfile*> DetectSourceProfilesWorker(
102    const std::string& locale,
103    bool include_interactive_profiles) {
104  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
105
106  std::vector<importer::SourceProfile*> profiles;
107
108  // The first run import will automatically take settings from the first
109  // profile detected, which should be the user's current default.
110#if defined(OS_WIN)
111  if (ShellIntegration::IsFirefoxDefaultBrowser()) {
112    DetectFirefoxProfiles(locale, &profiles);
113    DetectIEProfiles(&profiles);
114  } else {
115    DetectIEProfiles(&profiles);
116    DetectFirefoxProfiles(locale, &profiles);
117  }
118#elif defined(OS_MACOSX)
119  if (ShellIntegration::IsFirefoxDefaultBrowser()) {
120    DetectFirefoxProfiles(locale, &profiles);
121    DetectSafariProfiles(&profiles);
122  } else {
123    DetectSafariProfiles(&profiles);
124    DetectFirefoxProfiles(locale, &profiles);
125  }
126#else
127  DetectFirefoxProfiles(locale, &profiles);
128#endif
129  if (include_interactive_profiles) {
130    importer::SourceProfile* bookmarks_profile = new importer::SourceProfile;
131    bookmarks_profile->importer_name =
132        l10n_util::GetStringUTF16(IDS_IMPORT_FROM_BOOKMARKS_HTML_FILE);
133    bookmarks_profile->importer_type = importer::TYPE_BOOKMARKS_FILE;
134    bookmarks_profile->services_supported = importer::FAVORITES;
135    profiles.push_back(bookmarks_profile);
136  }
137
138  return profiles;
139}
140
141}  // namespace
142
143ImporterList::ImporterList()
144    : weak_ptr_factory_(this) {
145  DCHECK_CURRENTLY_ON(BrowserThread::UI);
146}
147
148ImporterList::~ImporterList() {
149  DCHECK_CURRENTLY_ON(BrowserThread::UI);
150}
151
152void ImporterList::DetectSourceProfiles(
153    const std::string& locale,
154    bool include_interactive_profiles,
155    const base::Closure& profiles_loaded_callback) {
156  DCHECK_CURRENTLY_ON(BrowserThread::UI);
157  BrowserThread::PostTaskAndReplyWithResult(
158      BrowserThread::FILE,
159      FROM_HERE,
160      base::Bind(&DetectSourceProfilesWorker,
161                 locale,
162                 include_interactive_profiles),
163      base::Bind(&ImporterList::SourceProfilesLoaded,
164                 weak_ptr_factory_.GetWeakPtr(),
165                 profiles_loaded_callback));
166}
167
168const importer::SourceProfile& ImporterList::GetSourceProfileAt(
169    size_t index) const {
170  DCHECK_LT(index, count());
171  return *source_profiles_[index];
172}
173
174void ImporterList::SourceProfilesLoaded(
175    const base::Closure& profiles_loaded_callback,
176    const std::vector<importer::SourceProfile*>& profiles) {
177  DCHECK_CURRENTLY_ON(BrowserThread::UI);
178
179  source_profiles_.assign(profiles.begin(), profiles.end());
180  profiles_loaded_callback.Run();
181}
182