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/utility/importer/external_process_importer_bridge.h" 6 7 #include "base/bind.h" 8 #include "base/logging.h" 9 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/utf_string_conversions.h" 11 #include "base/task_runner.h" 12 #include "base/values.h" 13 #include "chrome/common/importer/imported_bookmark_entry.h" 14 #include "chrome/common/importer/imported_favicon_usage.h" 15 #include "chrome/common/importer/importer_data_types.h" 16 #include "chrome/common/importer/profile_import_process_messages.h" 17 #include "components/autofill/core/common/password_form.h" 18 #include "ipc/ipc_sender.h" 19 20 namespace { 21 22 // Rather than sending all import items over IPC at once we chunk them into 23 // separate requests. This avoids the case of a large import causing 24 // oversized IPC messages. 25 const int kNumBookmarksToSend = 100; 26 const int kNumHistoryRowsToSend = 100; 27 const int kNumFaviconsToSend = 100; 28 const int kNumAutofillFormDataToSend = 100; 29 } 30 31 ExternalProcessImporterBridge::ExternalProcessImporterBridge( 32 const base::DictionaryValue& localized_strings, 33 IPC::Sender* sender, 34 base::TaskRunner* task_runner) 35 : sender_(sender), 36 task_runner_(task_runner) { 37 // Bridge needs to make its own copy because OS 10.6 autoreleases the 38 // localized_strings value that is passed in (see http://crbug.com/46003 ). 39 localized_strings_.reset(localized_strings.DeepCopy()); 40 } 41 42 void ExternalProcessImporterBridge::AddBookmarks( 43 const std::vector<ImportedBookmarkEntry>& bookmarks, 44 const base::string16& first_folder_name) { 45 Send(new ProfileImportProcessHostMsg_NotifyBookmarksImportStart( 46 first_folder_name, bookmarks.size())); 47 48 // |bookmarks_left| is required for the checks below as Windows has a 49 // Debug bounds-check which prevents pushing an iterator beyond its end() 50 // (i.e., |it + 2 < s.end()| crashes in debug mode if |i + 1 == s.end()|). 51 int bookmarks_left = bookmarks.end() - bookmarks.begin(); 52 for (std::vector<ImportedBookmarkEntry>::const_iterator it = 53 bookmarks.begin(); it < bookmarks.end();) { 54 std::vector<ImportedBookmarkEntry> bookmark_group; 55 std::vector<ImportedBookmarkEntry>::const_iterator end_group = 56 it + std::min(bookmarks_left, kNumBookmarksToSend); 57 bookmark_group.assign(it, end_group); 58 59 Send(new ProfileImportProcessHostMsg_NotifyBookmarksImportGroup( 60 bookmark_group)); 61 bookmarks_left -= end_group - it; 62 it = end_group; 63 } 64 DCHECK_EQ(0, bookmarks_left); 65 } 66 67 void ExternalProcessImporterBridge::AddHomePage(const GURL& home_page) { 68 Send(new ProfileImportProcessHostMsg_NotifyHomePageImportReady(home_page)); 69 } 70 71 #if defined(OS_WIN) 72 void ExternalProcessImporterBridge::AddIE7PasswordInfo( 73 const importer::ImporterIE7PasswordInfo& password_info) { 74 Send(new ProfileImportProcessHostMsg_NotifyIE7PasswordInfo(password_info)); 75 } 76 #endif 77 78 void ExternalProcessImporterBridge::SetFavicons( 79 const std::vector<ImportedFaviconUsage>& favicons) { 80 Send(new ProfileImportProcessHostMsg_NotifyFaviconsImportStart( 81 favicons.size())); 82 83 // |favicons_left| is required for the checks below as Windows has a 84 // Debug bounds-check which prevents pushing an iterator beyond its end() 85 // (i.e., |it + 2 < s.end()| crashes in debug mode if |i + 1 == s.end()|). 86 int favicons_left = favicons.end() - favicons.begin(); 87 for (std::vector<ImportedFaviconUsage>::const_iterator it = 88 favicons.begin(); it < favicons.end();) { 89 std::vector<ImportedFaviconUsage> favicons_group; 90 std::vector<ImportedFaviconUsage>::const_iterator end_group = 91 it + std::min(favicons_left, kNumFaviconsToSend); 92 favicons_group.assign(it, end_group); 93 94 Send(new ProfileImportProcessHostMsg_NotifyFaviconsImportGroup( 95 favicons_group)); 96 favicons_left -= end_group - it; 97 it = end_group; 98 } 99 DCHECK_EQ(0, favicons_left); 100 } 101 102 void ExternalProcessImporterBridge::SetHistoryItems( 103 const std::vector<ImporterURLRow>& rows, 104 importer::VisitSource visit_source) { 105 Send(new ProfileImportProcessHostMsg_NotifyHistoryImportStart(rows.size())); 106 107 // |rows_left| is required for the checks below as Windows has a 108 // Debug bounds-check which prevents pushing an iterator beyond its end() 109 // (i.e., |it + 2 < s.end()| crashes in debug mode if |i + 1 == s.end()|). 110 int rows_left = rows.end() - rows.begin(); 111 for (std::vector<ImporterURLRow>::const_iterator it = rows.begin(); 112 it < rows.end();) { 113 std::vector<ImporterURLRow> row_group; 114 std::vector<ImporterURLRow>::const_iterator end_group = 115 it + std::min(rows_left, kNumHistoryRowsToSend); 116 row_group.assign(it, end_group); 117 118 Send(new ProfileImportProcessHostMsg_NotifyHistoryImportGroup( 119 row_group, visit_source)); 120 rows_left -= end_group - it; 121 it = end_group; 122 } 123 DCHECK_EQ(0, rows_left); 124 } 125 126 void ExternalProcessImporterBridge::SetKeywords( 127 const std::vector<importer::URLKeywordInfo>& url_keywords, 128 bool unique_on_host_and_path) { 129 Send(new ProfileImportProcessHostMsg_NotifyKeywordsReady( 130 url_keywords, unique_on_host_and_path)); 131 } 132 133 void ExternalProcessImporterBridge::SetFirefoxSearchEnginesXMLData( 134 const std::vector<std::string>& search_engine_data) { 135 Send(new ProfileImportProcessHostMsg_NotifyFirefoxSearchEngData( 136 search_engine_data)); 137 } 138 139 void ExternalProcessImporterBridge::SetPasswordForm( 140 const autofill::PasswordForm& form) { 141 Send(new ProfileImportProcessHostMsg_NotifyPasswordFormReady(form)); 142 } 143 144 void ExternalProcessImporterBridge::SetAutofillFormData( 145 const std::vector<ImporterAutofillFormDataEntry>& entries) { 146 Send(new ProfileImportProcessHostMsg_AutofillFormDataImportStart( 147 entries.size())); 148 149 // |autofill_form_data_entries_left| is required for the checks below as 150 // Windows has a Debug bounds-check which prevents pushing an iterator beyond 151 // its end() (i.e., |it + 2 < s.end()| crashes in debug mode if |i + 1 == 152 // s.end()|). 153 int autofill_form_data_entries_left = entries.end() - entries.begin(); 154 for (std::vector<ImporterAutofillFormDataEntry>::const_iterator it = 155 entries.begin(); 156 it < entries.end();) { 157 std::vector<ImporterAutofillFormDataEntry> autofill_form_data_entry_group; 158 std::vector<ImporterAutofillFormDataEntry>::const_iterator end_group = 159 it + 160 std::min(autofill_form_data_entries_left, kNumAutofillFormDataToSend); 161 autofill_form_data_entry_group.assign(it, end_group); 162 163 Send(new ProfileImportProcessHostMsg_AutofillFormDataImportGroup( 164 autofill_form_data_entry_group)); 165 autofill_form_data_entries_left -= end_group - it; 166 it = end_group; 167 } 168 DCHECK_EQ(0, autofill_form_data_entries_left); 169 } 170 171 void ExternalProcessImporterBridge::NotifyStarted() { 172 Send(new ProfileImportProcessHostMsg_Import_Started()); 173 } 174 175 void ExternalProcessImporterBridge::NotifyItemStarted( 176 importer::ImportItem item) { 177 Send(new ProfileImportProcessHostMsg_ImportItem_Started(item)); 178 } 179 180 void ExternalProcessImporterBridge::NotifyItemEnded(importer::ImportItem item) { 181 Send(new ProfileImportProcessHostMsg_ImportItem_Finished(item)); 182 } 183 184 void ExternalProcessImporterBridge::NotifyEnded() { 185 // The internal process detects import end when all items have been received. 186 } 187 188 base::string16 ExternalProcessImporterBridge::GetLocalizedString( 189 int message_id) { 190 base::string16 message; 191 localized_strings_->GetString(base::IntToString(message_id), &message); 192 return message; 193 } 194 195 ExternalProcessImporterBridge::~ExternalProcessImporterBridge() {} 196 197 void ExternalProcessImporterBridge::Send(IPC::Message* message) { 198 task_runner_->PostTask( 199 FROM_HERE, 200 base::Bind(&ExternalProcessImporterBridge::SendInternal, 201 this, message)); 202 } 203 204 void ExternalProcessImporterBridge::SendInternal(IPC::Message* message) { 205 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 206 sender_->Send(message); 207 } 208