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_host.h"
6
7 #include "base/utf_string_conversions.h"
8 #include "chrome/browser/bookmarks/bookmark_model.h"
9 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/importer/firefox_profile_lock.h"
11 #include "chrome/browser/importer/importer.h"
12 #include "chrome/browser/importer/importer_lock_dialog.h"
13 #include "chrome/browser/importer/importer_progress_observer.h"
14 #include "chrome/browser/importer/importer_type.h"
15 #include "chrome/browser/importer/in_process_importer_bridge.h"
16 #include "chrome/browser/importer/toolbar_importer_utils.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/search_engines/template_url.h"
19 #include "chrome/browser/search_engines/template_url_model.h"
20 #include "chrome/browser/ui/browser_list.h"
21 #include "content/browser/browser_thread.h"
22 #include "content/common/notification_source.h"
23 #include "grit/generated_resources.h"
24 #include "ui/base/l10n/l10n_util.h"
25
26 #if defined(OS_WIN)
27 // TODO(port): Port this file.
28 #include "ui/base/message_box_win.h"
29 #endif
30
ImporterHost()31 ImporterHost::ImporterHost()
32 : profile_(NULL),
33 task_(NULL),
34 importer_(NULL),
35 waiting_for_bookmarkbar_model_(false),
36 installed_bookmark_observer_(false),
37 is_source_readable_(true),
38 headless_(false),
39 parent_window_(NULL),
40 observer_(NULL) {
41 }
42
ShowWarningDialog()43 void ImporterHost::ShowWarningDialog() {
44 if (headless_)
45 OnImportLockDialogEnd(false);
46 else
47 importer::ShowImportLockDialog(parent_window_, this);
48 }
49
OnImportLockDialogEnd(bool is_continue)50 void ImporterHost::OnImportLockDialogEnd(bool is_continue) {
51 if (is_continue) {
52 // User chose to continue, then we check the lock again to make
53 // sure that Firefox has been closed. Try to import the settings
54 // if successful. Otherwise, show a warning dialog.
55 firefox_lock_->Lock();
56 if (firefox_lock_->HasAcquired()) {
57 is_source_readable_ = true;
58 InvokeTaskIfDone();
59 } else {
60 ShowWarningDialog();
61 }
62 } else {
63 // User chose to skip the import process. We should delete
64 // the task and notify the ImporterHost to finish.
65 delete task_;
66 task_ = NULL;
67 importer_ = NULL;
68 NotifyImportEnded();
69 }
70 }
71
SetObserver(importer::ImporterProgressObserver * observer)72 void ImporterHost::SetObserver(importer::ImporterProgressObserver* observer) {
73 observer_ = observer;
74 }
75
NotifyImportStarted()76 void ImporterHost::NotifyImportStarted() {
77 if (observer_)
78 observer_->ImportStarted();
79 }
80
NotifyImportItemStarted(importer::ImportItem item)81 void ImporterHost::NotifyImportItemStarted(importer::ImportItem item) {
82 if (observer_)
83 observer_->ImportItemStarted(item);
84 }
85
NotifyImportItemEnded(importer::ImportItem item)86 void ImporterHost::NotifyImportItemEnded(importer::ImportItem item) {
87 if (observer_)
88 observer_->ImportItemEnded(item);
89 }
90
NotifyImportEnded()91 void ImporterHost::NotifyImportEnded() {
92 firefox_lock_.reset(); // Release the Firefox profile lock.
93 if (observer_)
94 observer_->ImportEnded();
95 Release();
96 }
97
StartImportSettings(const importer::SourceProfile & source_profile,Profile * target_profile,uint16 items,ProfileWriter * writer,bool first_run)98 void ImporterHost::StartImportSettings(
99 const importer::SourceProfile& source_profile,
100 Profile* target_profile,
101 uint16 items,
102 ProfileWriter* writer,
103 bool first_run) {
104 // We really only support importing from one host at a time.
105 DCHECK(!profile_);
106
107 profile_ = target_profile;
108 // Preserves the observer and creates a task, since we do async import so that
109 // it doesn't block the UI. When the import is complete, observer will be
110 // notified.
111 writer_ = writer;
112 importer_ = importer::CreateImporterByType(source_profile.importer_type);
113 // If we fail to create the Importer, exit, as we cannot do anything.
114 if (!importer_) {
115 NotifyImportEnded();
116 return;
117 }
118
119 importer_->AddRef();
120 importer_->set_import_to_bookmark_bar(ShouldImportToBookmarkBar(first_run));
121 importer_->set_bookmark_bar_disabled(first_run);
122
123 scoped_refptr<InProcessImporterBridge> bridge(
124 new InProcessImporterBridge(writer_.get(), this));
125 task_ = NewRunnableMethod(
126 importer_, &Importer::StartImport, source_profile, items, bridge);
127
128 CheckForFirefoxLock(source_profile, items, first_run);
129
130 #if defined(OS_WIN)
131 // For google toolbar import, we need the user to log in and store their GAIA
132 // credentials.
133 if (source_profile.importer_type == importer::GOOGLE_TOOLBAR5) {
134 if (!toolbar_importer_utils::IsGoogleGAIACookieInstalled()) {
135 ui::MessageBox(
136 NULL,
137 UTF16ToWide(l10n_util::GetStringUTF16(
138 IDS_IMPORTER_GOOGLE_LOGIN_TEXT)).c_str(),
139 L"",
140 MB_OK | MB_TOPMOST);
141
142 GURL url("https://www.google.com/accounts/ServiceLogin");
143 BrowserList::GetLastActive()->AddSelectedTabWithURL(
144 url, PageTransition::TYPED);
145
146 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
147 this, &ImporterHost::OnImportLockDialogEnd, false));
148
149 is_source_readable_ = false;
150 }
151 }
152 #endif
153
154 CheckForLoadedModels(items);
155 AddRef();
156 InvokeTaskIfDone();
157 }
158
Cancel()159 void ImporterHost::Cancel() {
160 if (importer_)
161 importer_->Cancel();
162 }
163
~ImporterHost()164 ImporterHost::~ImporterHost() {
165 if (NULL != importer_)
166 importer_->Release();
167
168 if (installed_bookmark_observer_) {
169 DCHECK(profile_); // Only way for waiting_for_bookmarkbar_model_ to be true
170 // is if we have a profile.
171 profile_->GetBookmarkModel()->RemoveObserver(this);
172 }
173 }
174
ShouldImportToBookmarkBar(bool first_run)175 bool ImporterHost::ShouldImportToBookmarkBar(bool first_run) {
176 bool import_to_bookmark_bar = first_run;
177 if (profile_ && profile_->GetBookmarkModel()->IsLoaded()) {
178 import_to_bookmark_bar = (!profile_->GetBookmarkModel()->HasBookmarks());
179 }
180 return import_to_bookmark_bar;
181 }
182
CheckForFirefoxLock(const importer::SourceProfile & source_profile,uint16 items,bool first_run)183 void ImporterHost::CheckForFirefoxLock(
184 const importer::SourceProfile& source_profile,
185 uint16 items,
186 bool first_run) {
187 if (source_profile.importer_type == importer::FIREFOX2 ||
188 source_profile.importer_type == importer::FIREFOX3) {
189 DCHECK(!firefox_lock_.get());
190 firefox_lock_.reset(new FirefoxProfileLock(source_profile.source_path));
191 if (!firefox_lock_->HasAcquired()) {
192 // If fail to acquire the lock, we set the source unreadable and
193 // show a warning dialog, unless running without UI.
194 is_source_readable_ = false;
195 ShowWarningDialog();
196 }
197 }
198 }
199
CheckForLoadedModels(uint16 items)200 void ImporterHost::CheckForLoadedModels(uint16 items) {
201 // BookmarkModel should be loaded before adding IE favorites. So we observe
202 // the BookmarkModel if needed, and start the task after it has been loaded.
203 if ((items & importer::FAVORITES) && !writer_->BookmarkModelIsLoaded()) {
204 profile_->GetBookmarkModel()->AddObserver(this);
205 waiting_for_bookmarkbar_model_ = true;
206 installed_bookmark_observer_ = true;
207 }
208
209 // Observes the TemplateURLModel if needed to import search engines from the
210 // other browser. We also check to see if we're importing bookmarks because
211 // we can import bookmark keywords from Firefox as search engines.
212 if ((items & importer::SEARCH_ENGINES) || (items & importer::FAVORITES)) {
213 if (!writer_->TemplateURLModelIsLoaded()) {
214 TemplateURLModel* model = profile_->GetTemplateURLModel();
215 registrar_.Add(this, NotificationType::TEMPLATE_URL_MODEL_LOADED,
216 Source<TemplateURLModel>(model));
217 model->Load();
218 }
219 }
220 }
221
InvokeTaskIfDone()222 void ImporterHost::InvokeTaskIfDone() {
223 if (waiting_for_bookmarkbar_model_ || !registrar_.IsEmpty() ||
224 !is_source_readable_)
225 return;
226 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, task_);
227 }
228
Loaded(BookmarkModel * model)229 void ImporterHost::Loaded(BookmarkModel* model) {
230 DCHECK(model->IsLoaded());
231 model->RemoveObserver(this);
232 waiting_for_bookmarkbar_model_ = false;
233 installed_bookmark_observer_ = false;
234
235 importer_->set_import_to_bookmark_bar(!model->HasBookmarks());
236 InvokeTaskIfDone();
237 }
238
BookmarkModelBeingDeleted(BookmarkModel * model)239 void ImporterHost::BookmarkModelBeingDeleted(BookmarkModel* model) {
240 installed_bookmark_observer_ = false;
241 }
242
BookmarkModelChanged()243 void ImporterHost::BookmarkModelChanged() {
244 }
245
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)246 void ImporterHost::Observe(NotificationType type,
247 const NotificationSource& source,
248 const NotificationDetails& details) {
249 DCHECK(type == NotificationType::TEMPLATE_URL_MODEL_LOADED);
250 registrar_.RemoveAll();
251 InvokeTaskIfDone();
252 }
253