// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/importer/external_process_importer_client.h" #include "base/bind.h" #include "base/string_number_conversions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/importer/external_process_importer_host.h" #include "chrome/browser/importer/firefox_importer_utils.h" #include "chrome/browser/importer/importer_host.h" #include "chrome/browser/importer/in_process_importer_bridge.h" #include "chrome/browser/importer/profile_import_process_messages.h" #include "chrome/browser/search_engines/template_url.h" #include "chrome/browser/search_engines/template_url_service.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/utility_process_host.h" #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" using content::BrowserThread; using content::UtilityProcessHost; ExternalProcessImporterClient::ExternalProcessImporterClient( ExternalProcessImporterHost* importer_host, const importer::SourceProfile& source_profile, uint16 items, InProcessImporterBridge* bridge) : total_bookmarks_count_(0), total_history_rows_count_(0), total_favicons_count_(0), process_importer_host_(importer_host), source_profile_(source_profile), items_(items), bridge_(bridge), cancelled_(false) { process_importer_host_->NotifyImportStarted(); } void ExternalProcessImporterClient::Start() { AddRef(); // balanced in Cleanup. BrowserThread::ID thread_id; CHECK(BrowserThread::GetCurrentThreadIdentifier(&thread_id)); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind(&ExternalProcessImporterClient::StartProcessOnIOThread, this, thread_id)); } void ExternalProcessImporterClient::Cancel() { if (cancelled_) return; cancelled_ = true; BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind( &ExternalProcessImporterClient::CancelImportProcessOnIOThread, this)); Release(); } void ExternalProcessImporterClient::OnProcessCrashed(int exit_code) { if (cancelled_) return; process_importer_host_->Cancel(); } bool ExternalProcessImporterClient::OnMessageReceived( const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(ExternalProcessImporterClient, message) // Notification messages about the state of the import process. IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_Import_Started, OnImportStart) IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_Import_Finished, OnImportFinished) IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_ImportItem_Started, OnImportItemStart) IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_ImportItem_Finished, OnImportItemFinished) // Data messages containing items to be written to the user profile. IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyHistoryImportStart, OnHistoryImportStart) IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyHistoryImportGroup, OnHistoryImportGroup) IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyHomePageImportReady, OnHomePageImportReady) IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyBookmarksImportStart, OnBookmarksImportStart) IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyBookmarksImportGroup, OnBookmarksImportGroup) IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyFaviconsImportStart, OnFaviconsImportStart) IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyFaviconsImportGroup, OnFaviconsImportGroup) IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyPasswordFormReady, OnPasswordFormImportReady) IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyKeywordsReady, OnKeywordsImportReady) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; } void ExternalProcessImporterClient::OnImportStart() { if (cancelled_) return; bridge_->NotifyStarted(); } void ExternalProcessImporterClient::OnImportFinished( bool succeeded, const std::string& error_msg) { if (cancelled_) return; if (!succeeded) LOG(WARNING) << "Import failed. Error: " << error_msg; Cleanup(); } void ExternalProcessImporterClient::OnImportItemStart(int item_data) { if (cancelled_) return; bridge_->NotifyItemStarted(static_cast(item_data)); } void ExternalProcessImporterClient::OnImportItemFinished(int item_data) { if (cancelled_) return; importer::ImportItem import_item = static_cast(item_data); bridge_->NotifyItemEnded(import_item); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind(&ExternalProcessImporterClient::NotifyItemFinishedOnIOThread, this, import_item)); } void ExternalProcessImporterClient::OnHistoryImportStart( size_t total_history_rows_count) { if (cancelled_) return; total_history_rows_count_ = total_history_rows_count; history_rows_.reserve(total_history_rows_count); } void ExternalProcessImporterClient::OnHistoryImportGroup( const history::URLRows& history_rows_group, int visit_source) { if (cancelled_) return; history_rows_.insert(history_rows_.end(), history_rows_group.begin(), history_rows_group.end()); if (history_rows_.size() == total_history_rows_count_) bridge_->SetHistoryItems(history_rows_, static_cast(visit_source)); } void ExternalProcessImporterClient::OnHomePageImportReady( const GURL& home_page) { if (cancelled_) return; bridge_->AddHomePage(home_page); } void ExternalProcessImporterClient::OnBookmarksImportStart( const string16& first_folder_name, size_t total_bookmarks_count) { if (cancelled_) return; bookmarks_first_folder_name_ = first_folder_name; total_bookmarks_count_ = total_bookmarks_count; bookmarks_.reserve(total_bookmarks_count); } void ExternalProcessImporterClient::OnBookmarksImportGroup( const std::vector& bookmarks_group) { if (cancelled_) return; // Collect sets of bookmarks from importer process until we have reached // total_bookmarks_count_: bookmarks_.insert(bookmarks_.end(), bookmarks_group.begin(), bookmarks_group.end()); if (bookmarks_.size() == total_bookmarks_count_) bridge_->AddBookmarks(bookmarks_, bookmarks_first_folder_name_); } void ExternalProcessImporterClient::OnFaviconsImportStart( size_t total_favicons_count) { if (cancelled_) return; total_favicons_count_ = total_favicons_count; favicons_.reserve(total_favicons_count); } void ExternalProcessImporterClient::OnFaviconsImportGroup( const std::vector& favicons_group) { if (cancelled_) return; favicons_.insert(favicons_.end(), favicons_group.begin(), favicons_group.end()); if (favicons_.size() == total_favicons_count_) bridge_->SetFavicons(favicons_); } void ExternalProcessImporterClient::OnPasswordFormImportReady( const webkit::forms::PasswordForm& form) { if (cancelled_) return; bridge_->SetPasswordForm(form); } void ExternalProcessImporterClient::OnKeywordsImportReady( const std::vector& template_urls, bool unique_on_host_and_path) { if (cancelled_) return; bridge_->SetKeywords(template_urls, unique_on_host_and_path); // The pointers in |template_urls| have now been deleted. } ExternalProcessImporterClient::~ExternalProcessImporterClient() {} void ExternalProcessImporterClient::Cleanup() { if (cancelled_) return; if (process_importer_host_) process_importer_host_->NotifyImportEnded(); Release(); } void ExternalProcessImporterClient::CancelImportProcessOnIOThread() { if (utility_process_host_) utility_process_host_->Send(new ProfileImportProcessMsg_CancelImport()); } void ExternalProcessImporterClient::NotifyItemFinishedOnIOThread( importer::ImportItem import_item) { utility_process_host_->Send( new ProfileImportProcessMsg_ReportImportItemFinished(import_item)); } void ExternalProcessImporterClient::StartProcessOnIOThread( BrowserThread::ID thread_id) { utility_process_host_ = UtilityProcessHost::Create(this, thread_id)->AsWeakPtr(); utility_process_host_->DisableSandbox(); #if defined(OS_MACOSX) base::EnvironmentVector env; std::string dylib_path = GetFirefoxDylibPath().value(); if (!dylib_path.empty()) env.push_back(std::make_pair("DYLD_FALLBACK_LIBRARY_PATH", dylib_path)); utility_process_host_->SetEnv(env); #endif // Dictionary of all localized strings that could be needed by the importer // in the external process. DictionaryValue localized_strings; localized_strings.SetString( base::IntToString(IDS_BOOKMARK_GROUP_FROM_FIREFOX), l10n_util::GetStringUTF8(IDS_BOOKMARK_GROUP_FROM_FIREFOX)); localized_strings.SetString( base::IntToString(IDS_BOOKMARK_GROUP_FROM_SAFARI), l10n_util::GetStringUTF8(IDS_BOOKMARK_GROUP_FROM_SAFARI)); localized_strings.SetString( base::IntToString(IDS_IMPORT_FROM_FIREFOX), l10n_util::GetStringUTF8(IDS_IMPORT_FROM_FIREFOX)); localized_strings.SetString( base::IntToString(IDS_IMPORT_FROM_GOOGLE_TOOLBAR), l10n_util::GetStringUTF8(IDS_IMPORT_FROM_GOOGLE_TOOLBAR)); localized_strings.SetString( base::IntToString(IDS_IMPORT_FROM_SAFARI), l10n_util::GetStringUTF8(IDS_IMPORT_FROM_SAFARI)); localized_strings.SetString( base::IntToString(IDS_BOOKMARK_BAR_FOLDER_NAME), l10n_util::GetStringUTF8(IDS_BOOKMARK_BAR_FOLDER_NAME)); utility_process_host_->Send(new ProfileImportProcessMsg_StartImport( source_profile_, items_, localized_strings)); }