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