blob: 254132fce868ac4a26b5ae0fa15030ba77158376 [file] [log] [blame]
// 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/strings/string_number_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/importer/external_process_importer_host.h"
#include "chrome/browser/importer/in_process_importer_bridge.h"
#include "chrome/common/importer/firefox_importer_utils.h"
#include "chrome/common/importer/imported_bookmark_entry.h"
#include "chrome/common/importer/profile_import_process_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/utility_process_host.h"
#include "grit/components_strings.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
using content::BrowserThread;
using content::UtilityProcessHost;
ExternalProcessImporterClient::ExternalProcessImporterClient(
base::WeakPtr<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) {
DLOG(ERROR) << __FUNCTION__;
if (cancelled_)
return;
// If the host is still around, cancel the import; otherwise it means the
// import was already cancelled or completed and this message can be dropped.
if (process_importer_host_.get())
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_HANDLER(ProfileImportProcessHostMsg_NotifyFirefoxSearchEngData,
OnFirefoxSearchEngineDataReceived)
#if defined(OS_WIN)
IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyIE7PasswordInfo,
OnIE7PasswordReceived)
#endif
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<importer::ImportItem>(item_data));
}
void ExternalProcessImporterClient::OnImportItemFinished(int item_data) {
if (cancelled_)
return;
importer::ImportItem import_item =
static_cast<importer::ImportItem>(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 std::vector<ImporterURLRow>& 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<importer::VisitSource>(visit_source));
}
void ExternalProcessImporterClient::OnHomePageImportReady(
const GURL& home_page) {
if (cancelled_)
return;
bridge_->AddHomePage(home_page);
}
void ExternalProcessImporterClient::OnBookmarksImportStart(
const base::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<ImportedBookmarkEntry>& 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<ImportedFaviconUsage>& 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 autofill::PasswordForm& form) {
if (cancelled_)
return;
bridge_->SetPasswordForm(form);
}
void ExternalProcessImporterClient::OnKeywordsImportReady(
const std::vector<importer::URLKeywordInfo>& url_keywords,
bool unique_on_host_and_path) {
if (cancelled_)
return;
bridge_->SetKeywords(url_keywords, unique_on_host_and_path);
}
void ExternalProcessImporterClient::OnFirefoxSearchEngineDataReceived(
const std::vector<std::string> search_engine_data) {
if (cancelled_)
return;
bridge_->SetFirefoxSearchEnginesXMLData(search_engine_data);
}
#if defined(OS_WIN)
void ExternalProcessImporterClient::OnIE7PasswordReceived(
const importer::ImporterIE7PasswordInfo& importer_password_info) {
if (cancelled_)
return;
bridge_->AddIE7PasswordInfo(importer_password_info);
}
#endif
ExternalProcessImporterClient::~ExternalProcessImporterClient() {}
void ExternalProcessImporterClient::Cleanup() {
if (cancelled_)
return;
if (process_importer_host_.get())
process_importer_host_->NotifyImportEnded();
Release();
}
void ExternalProcessImporterClient::CancelImportProcessOnIOThread() {
if (utility_process_host_.get())
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, BrowserThread::GetMessageLoopProxyForThread(thread_id).get())
->AsWeakPtr();
utility_process_host_->DisableSandbox();
#if defined(OS_MACOSX)
base::EnvironmentMap env;
std::string dylib_path = GetFirefoxDylibPath().value();
if (!dylib_path.empty())
env["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.
base::DictionaryValue localized_strings;
localized_strings.SetString(
base::IntToString(IDS_BOOKMARK_GROUP),
l10n_util::GetStringUTF8(IDS_BOOKMARK_GROUP));
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_ICEWEASEL),
l10n_util::GetStringUTF8(IDS_IMPORT_FROM_ICEWEASEL));
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));
}