importer_list.cc revision dc0f95d653279beabeb9817299e2902918ba123e
1// Copyright (c) 2011 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/file_util.h"
8#include "base/stl_util-inl.h"
9#include "base/values.h"
10#include "base/utf_string_conversions.h"
11#include "chrome/browser/first_run/first_run.h"
12#include "chrome/browser/importer/firefox2_importer.h"
13#include "chrome/browser/importer/firefox3_importer.h"
14#include "chrome/browser/importer/firefox_importer_utils.h"
15#include "chrome/browser/importer/importer_bridge.h"
16#include "chrome/browser/importer/toolbar_importer.h"
17#include "chrome/browser/shell_integration.h"
18#include "grit/generated_resources.h"
19#include "ui/base/l10n/l10n_util.h"
20
21#if defined(OS_WIN)
22#include "chrome/browser/importer/ie_importer.h"
23#include "chrome/browser/password_manager/ie7_password.h"
24#endif
25#if defined(OS_MACOSX)
26#include "base/mac/mac_util.h"
27#include "chrome/browser/importer/safari_importer.h"
28#endif
29
30namespace {
31
32#if defined(OS_WIN)
33void DetectIEProfiles(std::vector<importer::ProfileInfo*>* profiles) {
34    // IE always exists and doesn't have multiple profiles.
35  importer::ProfileInfo* ie = new importer::ProfileInfo();
36  ie->description = UTF16ToWide(l10n_util::GetStringUTF16(IDS_IMPORT_FROM_IE));
37  ie->browser_type = importer::MS_IE;
38  ie->source_path.clear();
39  ie->app_path.clear();
40  ie->services_supported = importer::HISTORY | importer::FAVORITES |
41      importer::COOKIES | importer::PASSWORDS | importer::SEARCH_ENGINES;
42  profiles->push_back(ie);
43}
44#endif  // defined(OS_WIN)
45
46#if defined(OS_MACOSX)
47void DetectSafariProfiles(std::vector<importer::ProfileInfo*>* profiles) {
48  uint16 items = importer::NONE;
49  if (!SafariImporter::CanImport(base::mac::GetUserLibraryPath(), &items))
50    return;
51
52  importer::ProfileInfo* safari = new importer::ProfileInfo();
53  safari->browser_type = importer::SAFARI;
54  safari->description =
55      UTF16ToWideHack(l10n_util::GetStringUTF16(IDS_IMPORT_FROM_SAFARI));
56  safari->source_path.clear();
57  safari->app_path.clear();
58  safari->services_supported = items;
59  profiles->push_back(safari);
60}
61#endif  // defined(OS_MACOSX)
62
63void DetectFirefoxProfiles(std::vector<importer::ProfileInfo*>* profiles) {
64  FilePath profile_path = GetFirefoxProfilePath();
65  if (profile_path.empty())
66    return;
67
68  // Detects which version of Firefox is installed.
69  importer::ProfileType firefox_type;
70  FilePath app_path;
71  int version = 0;
72#if defined(OS_WIN)
73  version = GetCurrentFirefoxMajorVersionFromRegistry();
74#endif
75  if (version < 2)
76    GetFirefoxVersionAndPathFromProfile(profile_path, &version, &app_path);
77
78  if (version == 2) {
79    firefox_type = importer::FIREFOX2;
80  } else if (version >= 3) {
81    firefox_type = importer::FIREFOX3;
82  } else {
83    // Ignores other versions of firefox.
84    return;
85  }
86
87  importer::ProfileInfo* firefox = new importer::ProfileInfo();
88  firefox->description =
89      UTF16ToWideHack(l10n_util::GetStringUTF16(IDS_IMPORT_FROM_FIREFOX));
90  firefox->browser_type = firefox_type;
91  firefox->source_path = profile_path;
92#if defined(OS_WIN)
93  firefox->app_path = FilePath::FromWStringHack(
94      GetFirefoxInstallPathFromRegistry());
95#endif
96  if (firefox->app_path.empty())
97    firefox->app_path = app_path;
98  firefox->services_supported = importer::HISTORY | importer::FAVORITES |
99      importer::PASSWORDS | importer::SEARCH_ENGINES;
100  profiles->push_back(firefox);
101}
102
103void DetectGoogleToolbarProfiles(
104    std::vector<importer::ProfileInfo*>* profiles) {
105  if (FirstRun::IsChromeFirstRun())
106    return;
107
108  importer::ProfileInfo* google_toolbar = new importer::ProfileInfo();
109  google_toolbar->browser_type = importer::GOOGLE_TOOLBAR5;
110  google_toolbar->description = UTF16ToWideHack(l10n_util::GetStringUTF16(
111      IDS_IMPORT_FROM_GOOGLE_TOOLBAR));
112  google_toolbar->source_path.clear();
113  google_toolbar->app_path.clear();
114  google_toolbar->services_supported = importer::FAVORITES;
115  profiles->push_back(google_toolbar);
116}
117
118}  // namespace
119
120// static
121Importer* ImporterList::CreateImporterByType(importer::ProfileType type) {
122  switch (type) {
123#if defined(OS_WIN)
124    case importer::MS_IE:
125      return new IEImporter();
126#endif
127    case importer::BOOKMARKS_HTML:
128    case importer::FIREFOX2:
129      return new Firefox2Importer();
130    case importer::FIREFOX3:
131      return new Firefox3Importer();
132    case importer::GOOGLE_TOOLBAR5:
133      return new Toolbar5Importer();
134#if defined(OS_MACOSX)
135    case importer::SAFARI:
136      return new SafariImporter(base::mac::GetUserLibraryPath());
137#endif  // OS_MACOSX
138    case importer::NO_PROFILE_TYPE:
139      NOTREACHED();
140      return NULL;
141  }
142  NOTREACHED();
143  return NULL;
144}
145
146ImporterList::ImporterList()
147    : source_thread_id_(BrowserThread::UI),
148      observer_(NULL),
149      is_observed_(false),
150      source_profiles_loaded_(false) {
151}
152
153ImporterList::~ImporterList() {
154}
155
156void ImporterList::DetectSourceProfiles(Observer* observer) {
157  DCHECK(observer);
158  observer_ = observer;
159  is_observed_ = true;
160
161  BrowserThread::GetCurrentThreadIdentifier(&source_thread_id_);
162
163  BrowserThread::PostTask(
164      BrowserThread::FILE,
165      FROM_HERE,
166      NewRunnableMethod(this, &ImporterList::DetectSourceProfilesWorker));
167}
168
169void ImporterList::SetObserver(Observer* observer) {
170  observer_ = observer;
171}
172
173void ImporterList::DetectSourceProfilesHack() {
174  DetectSourceProfilesWorker();
175}
176
177int ImporterList::GetAvailableProfileCount() const {
178  DCHECK(source_profiles_loaded_);
179  return static_cast<int>(source_profiles_.size());
180}
181
182std::wstring ImporterList::GetSourceProfileNameAt(int index) const {
183  DCHECK(source_profiles_loaded_);
184  DCHECK(index >=0 && index < GetAvailableProfileCount());
185  return source_profiles_[index]->description;
186}
187
188const importer::ProfileInfo& ImporterList::GetSourceProfileInfoAt(
189    int index) const {
190  DCHECK(source_profiles_loaded_);
191  DCHECK(index >=0 && index < GetAvailableProfileCount());
192  return *source_profiles_[index];
193}
194
195const importer::ProfileInfo& ImporterList::GetSourceProfileInfoForBrowserType(
196    int browser_type) const {
197  DCHECK(source_profiles_loaded_);
198
199  int count = GetAvailableProfileCount();
200  for (int i = 0; i < count; ++i) {
201    if (source_profiles_[i]->browser_type == browser_type)
202      return *source_profiles_[i];
203  }
204  NOTREACHED();
205  return *(new importer::ProfileInfo());
206}
207
208bool ImporterList::source_profiles_loaded() const {
209  return source_profiles_loaded_;
210}
211
212void ImporterList::DetectSourceProfilesWorker() {
213  // TODO(jhawkins): Remove this condition once DetectSourceProfileHack is
214  // removed.
215  if (is_observed_)
216    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
217
218  std::vector<importer::ProfileInfo*> profiles;
219
220// The first run import will automatically take settings from the first
221// profile detected, which should be the user's current default.
222#if defined(OS_WIN)
223  if (ShellIntegration::IsFirefoxDefaultBrowser()) {
224    DetectFirefoxProfiles(&profiles);
225    DetectIEProfiles(&profiles);
226  } else {
227    DetectIEProfiles(&profiles);
228    DetectFirefoxProfiles(&profiles);
229  }
230  // TODO(brg) : Current UI requires win_util.
231  DetectGoogleToolbarProfiles(&profiles);
232#elif defined(OS_MACOSX)
233  if (ShellIntegration::IsFirefoxDefaultBrowser()) {
234    DetectFirefoxProfiles(&profiles);
235    DetectSafariProfiles(&profiles);
236  } else {
237    DetectSafariProfiles(&profiles);
238    DetectFirefoxProfiles(&profiles);
239  }
240#else
241  DetectFirefoxProfiles(&profiles);
242#endif
243
244  // TODO(jhawkins): Remove this condition once DetectSourceProfileHack is
245  // removed.
246  if (is_observed_) {
247    BrowserThread::PostTask(
248        source_thread_id_,
249        FROM_HERE,
250        NewRunnableMethod(this, &ImporterList::SourceProfilesLoaded, profiles));
251  } else {
252    source_profiles_->assign(profiles.begin(), profiles.end());
253    source_profiles_loaded_ = true;
254  }
255}
256
257void ImporterList::SourceProfilesLoaded(
258    const std::vector<importer::ProfileInfo*>& profiles) {
259  // |observer_| may be NULL if it removed itself before being notified.
260  if (!observer_)
261    return;
262
263  BrowserThread::ID current_thread_id;
264  BrowserThread::GetCurrentThreadIdentifier(&current_thread_id);
265  DCHECK_EQ(current_thread_id, source_thread_id_);
266
267  source_profiles_->assign(profiles.begin(), profiles.end());
268  source_profiles_loaded_ = true;
269  source_thread_id_ = BrowserThread::UI;
270
271  observer_->SourceProfilesLoaded();
272  observer_ = NULL;
273
274  // TODO(jhawkins): Remove once DetectSourceProfileHack is removed.
275  is_observed_ = false;
276}
277