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/external_process_importer_client.h"
6
7#include "chrome/browser/browser_process.h"
8#include "chrome/browser/importer/external_process_importer_host.h"
9#include "chrome/browser/importer/importer_host.h"
10#include "chrome/browser/importer/in_process_importer_bridge.h"
11#include "chrome/browser/importer/profile_import_process_host.h"
12#include "chrome/browser/search_engines/template_url.h"
13#include "chrome/browser/search_engines/template_url_model.h"
14#include "content/browser/browser_thread.h"
15#include "content/browser/renderer_host/resource_dispatcher_host.h"
16
17ExternalProcessImporterClient::ExternalProcessImporterClient(
18    ExternalProcessImporterHost* importer_host,
19    const importer::SourceProfile& source_profile,
20    uint16 items,
21    InProcessImporterBridge* bridge,
22    bool import_to_bookmark_bar)
23    : bookmarks_options_(0),
24      total_bookmarks_count_(0),
25      total_history_rows_count_(0),
26      total_favicons_count_(0),
27      process_importer_host_(importer_host),
28      profile_import_process_host_(NULL),
29      source_profile_(source_profile),
30      items_(items),
31      import_to_bookmark_bar_(import_to_bookmark_bar),
32      bridge_(bridge),
33      cancelled_(false) {
34  bridge_->AddRef();
35  process_importer_host_->NotifyImportStarted();
36}
37
38ExternalProcessImporterClient::~ExternalProcessImporterClient() {
39  bridge_->Release();
40}
41
42void ExternalProcessImporterClient::Start() {
43  AddRef();  // balanced in Cleanup.
44  BrowserThread::ID thread_id;
45  CHECK(BrowserThread::GetCurrentThreadIdentifier(&thread_id));
46  BrowserThread::PostTask(
47      BrowserThread::IO, FROM_HERE,
48      NewRunnableMethod(
49          this,
50          &ExternalProcessImporterClient::StartImportProcessOnIOThread,
51          thread_id));
52}
53
54void ExternalProcessImporterClient::Cancel() {
55  if (cancelled_)
56    return;
57
58  cancelled_ = true;
59  if (profile_import_process_host_) {
60    BrowserThread::PostTask(
61        BrowserThread::IO, FROM_HERE,
62        NewRunnableMethod(this,
63            &ExternalProcessImporterClient::CancelImportProcessOnIOThread));
64  }
65  Release();
66}
67
68void ExternalProcessImporterClient::Cleanup() {
69  if (cancelled_)
70    return;
71
72  if (process_importer_host_)
73    process_importer_host_->NotifyImportEnded();
74  Release();
75}
76
77void ExternalProcessImporterClient::StartImportProcessOnIOThread(
78    BrowserThread::ID thread_id) {
79  profile_import_process_host_ =
80      new ProfileImportProcessHost(this, thread_id);
81  profile_import_process_host_->StartProfileImportProcess(
82      source_profile_, items_, import_to_bookmark_bar_);
83}
84
85void ExternalProcessImporterClient::CancelImportProcessOnIOThread() {
86  profile_import_process_host_->CancelProfileImportProcess();
87}
88
89void ExternalProcessImporterClient::NotifyItemFinishedOnIOThread(
90    importer::ImportItem import_item) {
91  profile_import_process_host_->ReportImportItemFinished(import_item);
92}
93
94void ExternalProcessImporterClient::OnProcessCrashed(int exit_code) {
95  if (cancelled_)
96    return;
97
98  process_importer_host_->Cancel();
99}
100
101void ExternalProcessImporterClient::OnImportStart() {
102  if (cancelled_)
103    return;
104
105  bridge_->NotifyStarted();
106}
107
108void ExternalProcessImporterClient::OnImportFinished(
109    bool succeeded, const std::string& error_msg) {
110  if (cancelled_)
111    return;
112
113  if (!succeeded)
114    LOG(WARNING) << "Import failed.  Error: " << error_msg;
115  Cleanup();
116}
117
118void ExternalProcessImporterClient::OnImportItemStart(int item_data) {
119  if (cancelled_)
120    return;
121
122  bridge_->NotifyItemStarted(static_cast<importer::ImportItem>(item_data));
123}
124
125void ExternalProcessImporterClient::OnImportItemFinished(int item_data) {
126  if (cancelled_)
127    return;
128
129  importer::ImportItem import_item =
130      static_cast<importer::ImportItem>(item_data);
131  bridge_->NotifyItemEnded(import_item);
132  BrowserThread::PostTask(
133      BrowserThread::IO, FROM_HERE,
134      NewRunnableMethod(this,
135          &ExternalProcessImporterClient::NotifyItemFinishedOnIOThread,
136          import_item));
137}
138
139void ExternalProcessImporterClient::OnHistoryImportStart(
140    size_t total_history_rows_count) {
141  if (cancelled_)
142    return;
143
144  total_history_rows_count_ = total_history_rows_count;
145  history_rows_.reserve(total_history_rows_count);
146}
147
148void ExternalProcessImporterClient::OnHistoryImportGroup(
149    const std::vector<history::URLRow>& history_rows_group,
150    int visit_source) {
151  if (cancelled_)
152    return;
153
154  history_rows_.insert(history_rows_.end(), history_rows_group.begin(),
155                       history_rows_group.end());
156  if (history_rows_.size() == total_history_rows_count_)
157    bridge_->SetHistoryItems(history_rows_,
158                             static_cast<history::VisitSource>(visit_source));
159}
160
161void ExternalProcessImporterClient::OnHomePageImportReady(
162    const GURL& home_page) {
163  if (cancelled_)
164    return;
165
166  bridge_->AddHomePage(home_page);
167}
168
169void ExternalProcessImporterClient::OnBookmarksImportStart(
170    const string16& first_folder_name,
171    int options,
172    size_t total_bookmarks_count) {
173  if (cancelled_)
174    return;
175
176  bookmarks_first_folder_name_ = first_folder_name;
177  bookmarks_options_ = options;
178  total_bookmarks_count_ = total_bookmarks_count;
179  bookmarks_.reserve(total_bookmarks_count);
180}
181
182void ExternalProcessImporterClient::OnBookmarksImportGroup(
183    const std::vector<ProfileWriter::BookmarkEntry>& bookmarks_group) {
184  if (cancelled_)
185    return;
186
187  // Collect sets of bookmarks from importer process until we have reached
188  // total_bookmarks_count_:
189  bookmarks_.insert(bookmarks_.end(), bookmarks_group.begin(),
190                    bookmarks_group.end());
191  if (bookmarks_.size() == total_bookmarks_count_) {
192    bridge_->AddBookmarkEntries(bookmarks_, bookmarks_first_folder_name_,
193                                bookmarks_options_);
194  }
195}
196
197void ExternalProcessImporterClient::OnFaviconsImportStart(
198    size_t total_favicons_count) {
199  if (cancelled_)
200    return;
201
202  total_favicons_count_ = total_favicons_count;
203  favicons_.reserve(total_favicons_count);
204}
205
206void ExternalProcessImporterClient::OnFaviconsImportGroup(
207    const std::vector<history::ImportedFaviconUsage>& favicons_group) {
208  if (cancelled_)
209    return;
210
211  favicons_.insert(favicons_.end(), favicons_group.begin(),
212                    favicons_group.end());
213  if (favicons_.size() == total_favicons_count_)
214    bridge_->SetFavicons(favicons_);
215}
216
217void ExternalProcessImporterClient::OnPasswordFormImportReady(
218    const webkit_glue::PasswordForm& form) {
219  if (cancelled_)
220    return;
221
222  bridge_->SetPasswordForm(form);
223}
224
225void ExternalProcessImporterClient::OnKeywordsImportReady(
226    const std::vector<TemplateURL>& template_urls,
227        int default_keyword_index, bool unique_on_host_and_path) {
228  if (cancelled_)
229    return;
230
231  std::vector<TemplateURL*> template_url_vec;
232  template_url_vec.reserve(template_urls.size());
233  std::vector<TemplateURL>::const_iterator iter;
234  for (iter = template_urls.begin();
235       iter != template_urls.end();
236       ++iter) {
237    template_url_vec.push_back(new TemplateURL(*iter));
238  }
239  bridge_->SetKeywords(template_url_vec, default_keyword_index,
240                       unique_on_host_and_path);
241}
242