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/in_process_importer_bridge.h" 6 7 #include "base/bind.h" 8 #include "base/file_util.h" 9 #include "base/strings/utf_string_conversions.h" 10 #include "chrome/browser/importer/external_process_importer_host.h" 11 #include "chrome/browser/search_engines/template_url.h" 12 #include "chrome/browser/search_engines/template_url_parser.h" 13 #include "chrome/browser/search_engines/template_url_prepopulate_data.h" 14 #include "chrome/browser/search_engines/template_url_service.h" 15 #include "chrome/common/importer/imported_bookmark_entry.h" 16 #include "chrome/common/importer/imported_favicon_usage.h" 17 #include "content/public/browser/browser_thread.h" 18 #include "content/public/common/password_form.h" 19 #include "ui/base/l10n/l10n_util.h" 20 21 #if defined(OS_WIN) 22 #include "components/webdata/encryptor/ie7_password.h" 23 #endif 24 25 #include <iterator> 26 27 namespace { 28 29 history::URLRows ConvertImporterURLRowsToHistoryURLRows( 30 const std::vector<ImporterURLRow>& rows) { 31 history::URLRows converted; 32 converted.reserve(rows.size()); 33 for (std::vector<ImporterURLRow>::const_iterator it = rows.begin(); 34 it != rows.end(); ++it) { 35 history::URLRow row(it->url); 36 row.set_title(it->title); 37 row.set_visit_count(it->visit_count); 38 row.set_typed_count(it->typed_count); 39 row.set_last_visit(it->last_visit); 40 row.set_hidden(it->hidden); 41 converted.push_back(row); 42 } 43 return converted; 44 } 45 46 history::VisitSource ConvertImporterVisitSourceToHistoryVisitSource( 47 importer::VisitSource visit_source) { 48 switch (visit_source) { 49 case importer::VISIT_SOURCE_BROWSED: 50 return history::SOURCE_BROWSED; 51 case importer::VISIT_SOURCE_FIREFOX_IMPORTED: 52 return history::SOURCE_FIREFOX_IMPORTED; 53 case importer::VISIT_SOURCE_IE_IMPORTED: 54 return history::SOURCE_IE_IMPORTED; 55 case importer::VISIT_SOURCE_SAFARI_IMPORTED: 56 return history::SOURCE_SAFARI_IMPORTED; 57 } 58 NOTREACHED(); 59 return history::SOURCE_SYNCED; 60 } 61 62 } // namespace 63 64 using content::BrowserThread; 65 66 namespace { 67 68 // FirefoxURLParameterFilter is used to remove parameter mentioning Firefox from 69 // the search URL when importing search engines. 70 class FirefoxURLParameterFilter : public TemplateURLParser::ParameterFilter { 71 public: 72 FirefoxURLParameterFilter() {} 73 virtual ~FirefoxURLParameterFilter() {} 74 75 // TemplateURLParser::ParameterFilter method. 76 virtual bool KeepParameter(const std::string& key, 77 const std::string& value) OVERRIDE { 78 std::string low_value = StringToLowerASCII(value); 79 if (low_value.find("mozilla") != std::string::npos || 80 low_value.find("firefox") != std::string::npos || 81 low_value.find("moz:") != std::string::npos) { 82 return false; 83 } 84 return true; 85 } 86 87 private: 88 DISALLOW_COPY_AND_ASSIGN(FirefoxURLParameterFilter); 89 }; 90 91 // Creates a TemplateURL with the |keyword| and |url|. |title| may be empty. 92 // This function transfers ownership of the created TemplateURL to the caller. 93 TemplateURL* CreateTemplateURL(const string16& title, 94 const string16& keyword, 95 const GURL& url) { 96 // Skip if the url is invalid. 97 if (!url.is_valid()) 98 return NULL; 99 100 TemplateURLData data; 101 if (keyword.empty()) 102 data.SetKeyword(TemplateURLService::GenerateKeyword(url)); 103 else 104 data.SetKeyword(keyword); 105 // We set short name by using the title if it exists. 106 // Otherwise, we use the shortcut. 107 data.short_name = title.empty() ? keyword : title; 108 data.SetURL(TemplateURLRef::DisplayURLToURLRef(UTF8ToUTF16(url.spec()))); 109 return new TemplateURL(NULL, data); 110 } 111 112 // Parses the OpenSearch XML files in |xml_files| and populates |search_engines| 113 // with the resulting TemplateURLs. 114 void ParseSearchEnginesFromFirefoxXMLData( 115 const std::vector<std::string>& xml_data, 116 std::vector<TemplateURL*>* search_engines) { 117 DCHECK(search_engines); 118 119 typedef std::map<std::string, TemplateURL*> SearchEnginesMap; 120 SearchEnginesMap search_engine_for_url; 121 FirefoxURLParameterFilter param_filter; 122 // The first XML file represents the default search engine in Firefox 3, so we 123 // need to keep it on top of the list. 124 SearchEnginesMap::const_iterator default_turl = search_engine_for_url.end(); 125 for (std::vector<std::string>::const_iterator xml_iter = 126 xml_data.begin(); xml_iter != xml_data.end(); ++xml_iter) { 127 TemplateURL* template_url = TemplateURLParser::Parse(NULL, true, 128 xml_iter->data(), xml_iter->length(), ¶m_filter); 129 if (template_url) { 130 SearchEnginesMap::iterator iter = 131 search_engine_for_url.find(template_url->url()); 132 if (iter == search_engine_for_url.end()) { 133 iter = search_engine_for_url.insert( 134 std::make_pair(template_url->url(), template_url)).first; 135 } else { 136 // We have already found a search engine with the same URL. We give 137 // priority to the latest one found, as GetSearchEnginesXMLFiles() 138 // returns a vector with first Firefox default search engines and then 139 // the user's ones. We want to give priority to the user ones. 140 delete iter->second; 141 iter->second = template_url; 142 } 143 if (default_turl == search_engine_for_url.end()) 144 default_turl = iter; 145 } 146 } 147 148 // Put the results in the |search_engines| vector. 149 for (SearchEnginesMap::iterator t_iter = search_engine_for_url.begin(); 150 t_iter != search_engine_for_url.end(); ++t_iter) { 151 if (t_iter == default_turl) 152 search_engines->insert(search_engines->begin(), default_turl->second); 153 else 154 search_engines->push_back(t_iter->second); 155 } 156 } 157 158 } // namespace 159 160 InProcessImporterBridge::InProcessImporterBridge( 161 ProfileWriter* writer, 162 base::WeakPtr<ExternalProcessImporterHost> host) : writer_(writer), 163 host_(host) { 164 } 165 166 void InProcessImporterBridge::AddBookmarks( 167 const std::vector<ImportedBookmarkEntry>& bookmarks, 168 const string16& first_folder_name) { 169 BrowserThread::PostTask( 170 BrowserThread::UI, FROM_HERE, 171 base::Bind(&ProfileWriter::AddBookmarks, writer_, bookmarks, 172 first_folder_name)); 173 } 174 175 void InProcessImporterBridge::AddHomePage(const GURL& home_page) { 176 BrowserThread::PostTask( 177 BrowserThread::UI, FROM_HERE, 178 base::Bind(&ProfileWriter::AddHomepage, writer_, home_page)); 179 } 180 181 #if defined(OS_WIN) 182 void InProcessImporterBridge::AddIE7PasswordInfo( 183 const importer::ImporterIE7PasswordInfo& password_info) { 184 IE7PasswordInfo ie7_password_info; 185 ie7_password_info.url_hash = password_info.url_hash; 186 ie7_password_info.encrypted_data = password_info.encrypted_data; 187 ie7_password_info.date_created = password_info.date_created; 188 189 BrowserThread::PostTask( 190 BrowserThread::UI, FROM_HERE, 191 base::Bind(&ProfileWriter::AddIE7PasswordInfo, writer_, 192 ie7_password_info)); 193 } 194 #endif // OS_WIN 195 196 void InProcessImporterBridge::SetFavicons( 197 const std::vector<ImportedFaviconUsage>& favicons) { 198 BrowserThread::PostTask( 199 BrowserThread::UI, FROM_HERE, 200 base::Bind(&ProfileWriter::AddFavicons, writer_, favicons)); 201 } 202 203 void InProcessImporterBridge::SetHistoryItems( 204 const std::vector<ImporterURLRow>& rows, 205 importer::VisitSource visit_source) { 206 history::URLRows converted_rows = 207 ConvertImporterURLRowsToHistoryURLRows(rows); 208 history::VisitSource converted_visit_source = 209 ConvertImporterVisitSourceToHistoryVisitSource(visit_source); 210 BrowserThread::PostTask(BrowserThread::UI, 211 FROM_HERE, 212 base::Bind(&ProfileWriter::AddHistoryPage, 213 writer_, 214 converted_rows, 215 converted_visit_source)); 216 } 217 218 void InProcessImporterBridge::SetKeywords( 219 const std::vector<importer::URLKeywordInfo>& url_keywords, 220 bool unique_on_host_and_path) { 221 ScopedVector<TemplateURL> owned_template_urls; 222 for (size_t i = 0; i < url_keywords.size(); ++i) { 223 owned_template_urls.push_back( 224 CreateTemplateURL(url_keywords[i].display_name, 225 url_keywords[i].keyword, 226 url_keywords[i].url)); 227 } 228 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 229 base::Bind(&ProfileWriter::AddKeywords, writer_, 230 base::Passed(&owned_template_urls), unique_on_host_and_path)); 231 } 232 233 void InProcessImporterBridge::SetFirefoxSearchEnginesXMLData( 234 const std::vector<std::string>& search_engine_data) { 235 std::vector<TemplateURL*> search_engines; 236 ParseSearchEnginesFromFirefoxXMLData(search_engine_data, &search_engines); 237 238 ScopedVector<TemplateURL> owned_template_urls; 239 std::copy(search_engines.begin(), search_engines.end(), 240 std::back_inserter(owned_template_urls)); 241 242 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 243 base::Bind(&ProfileWriter::AddKeywords, writer_, 244 base::Passed(&owned_template_urls), true)); 245 } 246 247 void InProcessImporterBridge::SetPasswordForm( 248 const content::PasswordForm& form) { 249 BrowserThread::PostTask( 250 BrowserThread::UI, FROM_HERE, 251 base::Bind(&ProfileWriter::AddPasswordForm, writer_, form)); 252 } 253 254 void InProcessImporterBridge::NotifyStarted() { 255 BrowserThread::PostTask( 256 BrowserThread::UI, FROM_HERE, 257 base::Bind(&ExternalProcessImporterHost::NotifyImportStarted, host_)); 258 } 259 260 void InProcessImporterBridge::NotifyItemStarted(importer::ImportItem item) { 261 BrowserThread::PostTask( 262 BrowserThread::UI, FROM_HERE, 263 base::Bind(&ExternalProcessImporterHost::NotifyImportItemStarted, 264 host_, item)); 265 } 266 267 void InProcessImporterBridge::NotifyItemEnded(importer::ImportItem item) { 268 BrowserThread::PostTask( 269 BrowserThread::UI, FROM_HERE, 270 base::Bind(&ExternalProcessImporterHost::NotifyImportItemEnded, 271 host_, item)); 272 } 273 274 void InProcessImporterBridge::NotifyEnded() { 275 BrowserThread::PostTask( 276 BrowserThread::UI, FROM_HERE, 277 base::Bind(&ExternalProcessImporterHost::NotifyImportEnded, host_)); 278 } 279 280 string16 InProcessImporterBridge::GetLocalizedString(int message_id) { 281 return l10n_util::GetStringUTF16(message_id); 282 } 283 284 InProcessImporterBridge::~InProcessImporterBridge() {} 285