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