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