external_process_importer_client.cc revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
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/external_process_importer_client.h"
6
7#include "base/bind.h"
8#include "base/strings/string_number_conversions.h"
9#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
10#include "chrome/browser/browser_process.h"
11#include "chrome/browser/importer/external_process_importer_host.h"
12#include "chrome/browser/importer/firefox_importer_utils.h"
13#include "chrome/browser/importer/importer_host.h"
14#include "chrome/browser/importer/in_process_importer_bridge.h"
15#include "chrome/browser/importer/profile_import_process_messages.h"
16#include "chrome/browser/search_engines/template_url.h"
17#include "chrome/browser/search_engines/template_url_service.h"
18#include "content/public/browser/browser_thread.h"
19#include "content/public/browser/utility_process_host.h"
20#include "grit/generated_resources.h"
21#include "ui/base/l10n/l10n_util.h"
22
23using content::BrowserThread;
24using content::UtilityProcessHost;
25
26ExternalProcessImporterClient::ExternalProcessImporterClient(
27    ExternalProcessImporterHost* importer_host,
28    const importer::SourceProfile& source_profile,
29    uint16 items,
30    InProcessImporterBridge* bridge)
31    : total_bookmarks_count_(0),
32      total_history_rows_count_(0),
33      total_favicons_count_(0),
34      process_importer_host_(importer_host),
35      source_profile_(source_profile),
36      items_(items),
37      bridge_(bridge),
38      cancelled_(false) {
39  process_importer_host_->NotifyImportStarted();
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      base::Bind(&ExternalProcessImporterClient::StartProcessOnIOThread,
49                 this,
50                 thread_id));
51}
52
53void ExternalProcessImporterClient::Cancel() {
54  if (cancelled_)
55    return;
56
57  cancelled_ = true;
58  BrowserThread::PostTask(
59      BrowserThread::IO, FROM_HERE,
60      base::Bind(
61          &ExternalProcessImporterClient::CancelImportProcessOnIOThread,
62          this));
63  Release();
64}
65
66void ExternalProcessImporterClient::OnProcessCrashed(int exit_code) {
67  if (cancelled_)
68    return;
69
70  process_importer_host_->Cancel();
71}
72
73bool ExternalProcessImporterClient::OnMessageReceived(
74    const IPC::Message& message) {
75  bool handled = true;
76  IPC_BEGIN_MESSAGE_MAP(ExternalProcessImporterClient, message)
77    // Notification messages about the state of the import process.
78    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_Import_Started,
79                        OnImportStart)
80    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_Import_Finished,
81                        OnImportFinished)
82    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_ImportItem_Started,
83                        OnImportItemStart)
84    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_ImportItem_Finished,
85                        OnImportItemFinished)
86    // Data messages containing items to be written to the user profile.
87    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyHistoryImportStart,
88                        OnHistoryImportStart)
89    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyHistoryImportGroup,
90                        OnHistoryImportGroup)
91    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyHomePageImportReady,
92                        OnHomePageImportReady)
93    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyBookmarksImportStart,
94                        OnBookmarksImportStart)
95    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyBookmarksImportGroup,
96                        OnBookmarksImportGroup)
97    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyFaviconsImportStart,
98                        OnFaviconsImportStart)
99    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyFaviconsImportGroup,
100                        OnFaviconsImportGroup)
101    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyPasswordFormReady,
102                        OnPasswordFormImportReady)
103    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyKeywordsReady,
104                        OnKeywordsImportReady)
105    IPC_MESSAGE_UNHANDLED(handled = false)
106  IPC_END_MESSAGE_MAP()
107  return handled;
108}
109
110void ExternalProcessImporterClient::OnImportStart() {
111  if (cancelled_)
112    return;
113
114  bridge_->NotifyStarted();
115}
116
117void ExternalProcessImporterClient::OnImportFinished(
118    bool succeeded, const std::string& error_msg) {
119  if (cancelled_)
120    return;
121
122  if (!succeeded)
123    LOG(WARNING) << "Import failed.  Error: " << error_msg;
124  Cleanup();
125}
126
127void ExternalProcessImporterClient::OnImportItemStart(int item_data) {
128  if (cancelled_)
129    return;
130
131  bridge_->NotifyItemStarted(static_cast<importer::ImportItem>(item_data));
132}
133
134void ExternalProcessImporterClient::OnImportItemFinished(int item_data) {
135  if (cancelled_)
136    return;
137
138  importer::ImportItem import_item =
139      static_cast<importer::ImportItem>(item_data);
140  bridge_->NotifyItemEnded(import_item);
141  BrowserThread::PostTask(
142      BrowserThread::IO, FROM_HERE,
143      base::Bind(&ExternalProcessImporterClient::NotifyItemFinishedOnIOThread,
144                 this,
145                 import_item));
146}
147
148void ExternalProcessImporterClient::OnHistoryImportStart(
149    size_t total_history_rows_count) {
150  if (cancelled_)
151    return;
152
153  total_history_rows_count_ = total_history_rows_count;
154  history_rows_.reserve(total_history_rows_count);
155}
156
157void ExternalProcessImporterClient::OnHistoryImportGroup(
158    const history::URLRows& history_rows_group,
159    int visit_source) {
160  if (cancelled_)
161    return;
162
163  history_rows_.insert(history_rows_.end(), history_rows_group.begin(),
164                       history_rows_group.end());
165  if (history_rows_.size() == total_history_rows_count_)
166    bridge_->SetHistoryItems(history_rows_,
167                             static_cast<history::VisitSource>(visit_source));
168}
169
170void ExternalProcessImporterClient::OnHomePageImportReady(
171    const GURL& home_page) {
172  if (cancelled_)
173    return;
174
175  bridge_->AddHomePage(home_page);
176}
177
178void ExternalProcessImporterClient::OnBookmarksImportStart(
179    const string16& first_folder_name,
180    size_t total_bookmarks_count) {
181  if (cancelled_)
182    return;
183
184  bookmarks_first_folder_name_ = first_folder_name;
185  total_bookmarks_count_ = total_bookmarks_count;
186  bookmarks_.reserve(total_bookmarks_count);
187}
188
189void ExternalProcessImporterClient::OnBookmarksImportGroup(
190    const std::vector<ImportedBookmarkEntry>& bookmarks_group) {
191  if (cancelled_)
192    return;
193
194  // Collect sets of bookmarks from importer process until we have reached
195  // total_bookmarks_count_:
196  bookmarks_.insert(bookmarks_.end(), bookmarks_group.begin(),
197                    bookmarks_group.end());
198  if (bookmarks_.size() == total_bookmarks_count_)
199    bridge_->AddBookmarks(bookmarks_, bookmarks_first_folder_name_);
200}
201
202void ExternalProcessImporterClient::OnFaviconsImportStart(
203    size_t total_favicons_count) {
204  if (cancelled_)
205    return;
206
207  total_favicons_count_ = total_favicons_count;
208  favicons_.reserve(total_favicons_count);
209}
210
211void ExternalProcessImporterClient::OnFaviconsImportGroup(
212    const std::vector<ImportedFaviconUsage>& favicons_group) {
213  if (cancelled_)
214    return;
215
216  favicons_.insert(favicons_.end(), favicons_group.begin(),
217                    favicons_group.end());
218  if (favicons_.size() == total_favicons_count_)
219    bridge_->SetFavicons(favicons_);
220}
221
222void ExternalProcessImporterClient::OnPasswordFormImportReady(
223    const content::PasswordForm& form) {
224  if (cancelled_)
225    return;
226
227  bridge_->SetPasswordForm(form);
228}
229
230void ExternalProcessImporterClient::OnKeywordsImportReady(
231    const std::vector<TemplateURL*>& template_urls,
232    bool unique_on_host_and_path) {
233  if (cancelled_)
234    return;
235
236  bridge_->SetKeywords(template_urls, unique_on_host_and_path);
237  // The pointers in |template_urls| have now been deleted.
238}
239
240ExternalProcessImporterClient::~ExternalProcessImporterClient() {}
241
242void ExternalProcessImporterClient::Cleanup() {
243  if (cancelled_)
244    return;
245
246  if (process_importer_host_)
247    process_importer_host_->NotifyImportEnded();
248  Release();
249}
250
251void ExternalProcessImporterClient::CancelImportProcessOnIOThread() {
252  if (utility_process_host_)
253    utility_process_host_->Send(new ProfileImportProcessMsg_CancelImport());
254}
255
256void ExternalProcessImporterClient::NotifyItemFinishedOnIOThread(
257    importer::ImportItem import_item) {
258  utility_process_host_->Send(
259      new ProfileImportProcessMsg_ReportImportItemFinished(import_item));
260}
261
262void ExternalProcessImporterClient::StartProcessOnIOThread(
263    BrowserThread::ID thread_id) {
264  utility_process_host_ =
265      UtilityProcessHost::Create(
266          this,
267          BrowserThread::GetMessageLoopProxyForThread(thread_id))->AsWeakPtr();
268  utility_process_host_->DisableSandbox();
269
270#if defined(OS_MACOSX)
271  base::EnvironmentVector env;
272  std::string dylib_path = GetFirefoxDylibPath().value();
273  if (!dylib_path.empty())
274    env.push_back(std::make_pair("DYLD_FALLBACK_LIBRARY_PATH", dylib_path));
275  utility_process_host_->SetEnv(env);
276#endif
277
278  // Dictionary of all localized strings that could be needed by the importer
279  // in the external process.
280  DictionaryValue localized_strings;
281  localized_strings.SetString(
282      base::IntToString(IDS_BOOKMARK_GROUP_FROM_FIREFOX),
283      l10n_util::GetStringUTF8(IDS_BOOKMARK_GROUP_FROM_FIREFOX));
284  localized_strings.SetString(
285      base::IntToString(IDS_BOOKMARK_GROUP_FROM_SAFARI),
286      l10n_util::GetStringUTF8(IDS_BOOKMARK_GROUP_FROM_SAFARI));
287  localized_strings.SetString(
288      base::IntToString(IDS_IMPORT_FROM_FIREFOX),
289      l10n_util::GetStringUTF8(IDS_IMPORT_FROM_FIREFOX));
290  localized_strings.SetString(
291      base::IntToString(IDS_IMPORT_FROM_GOOGLE_TOOLBAR),
292      l10n_util::GetStringUTF8(IDS_IMPORT_FROM_GOOGLE_TOOLBAR));
293  localized_strings.SetString(
294      base::IntToString(IDS_IMPORT_FROM_SAFARI),
295      l10n_util::GetStringUTF8(IDS_IMPORT_FROM_SAFARI));
296  localized_strings.SetString(
297      base::IntToString(IDS_BOOKMARK_BAR_FOLDER_NAME),
298      l10n_util::GetStringUTF8(IDS_BOOKMARK_BAR_FOLDER_NAME));
299
300  utility_process_host_->Send(new ProfileImportProcessMsg_StartImport(
301      source_profile_, items_, localized_strings));
302}
303