This source file includes following definitions.
- DecryptCCNumber
 
- IsEmptySalt
 
- ReadAndDecryptValue
 
- ImportSingleFormGroup
 
- ImportSingleProfile
 
- ImportProfiles
 
- OnPersonalDataChanged
 
- ImportCurrentUserProfiles
 
- ImportAutofillDataWin
 
#include "components/autofill/core/browser/autofill_ie_toolbar_import_win.h"
#include <stddef.h>
#include <map>
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/strings/string16.h"
#include "base/win/registry.h"
#include "components/autofill/core/browser/autofill_country.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/crypto/rc4_decryptor.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/form_group.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/personal_data_manager_observer.h"
#include "components/autofill/core/browser/phone_number.h"
#include "components/autofill/core/browser/phone_number_i18n.h"
#include "components/os_crypt/os_crypt.h"
using base::win::RegKey;
namespace autofill {
bool ImportCurrentUserProfiles(const std::string& app_locale,
                               std::vector<AutofillProfile>* profiles,
                               std::vector<CreditCard>* credit_cards);
namespace {
const wchar_t* const kProfileKey =
    L"Software\\Google\\Google Toolbar\\4.0\\Autofill\\Profiles";
const wchar_t* const kCreditCardKey =
    L"Software\\Google\\Google Toolbar\\4.0\\Autofill\\Credit Cards";
const wchar_t* const kPasswordHashValue = L"password_hash";
const wchar_t* const kSaltValue = L"salt";
const char kIEToolbarImportOrigin[] = "Imported from Internet Explorer";
std::wstring DecryptCCNumber(const std::wstring& data) {
  const wchar_t* kEmptyKey =
    L"\x3605\xCEE5\xCE49\x44F7\xCF4E\xF6CC\x604B\xFCBE\xC70A\x08FD";
  const size_t kMacLen = 10;
  if (data.length() <= kMacLen)
    return std::wstring();
  RC4Decryptor rc4_algorithm(kEmptyKey);
  return rc4_algorithm.Run(data.substr(kMacLen));
}
bool IsEmptySalt(std::wstring const& salt) {
  
  if (salt.length() != 20)
    return false;
  for (size_t i = 0; i < salt.length(); ++i) {
    if (salt[i] != i + 1)
      return false;
  }
  return true;
}
base::string16 ReadAndDecryptValue(const RegKey& key,
                                   const wchar_t* value_name) {
  DWORD data_type = REG_BINARY;
  DWORD data_size = 0;
  LONG result = key.ReadValue(value_name, NULL, &data_size, &data_type);
  if ((result != ERROR_SUCCESS) || !data_size || data_type != REG_BINARY)
    return base::string16();
  std::string data;
  data.resize(data_size);
  result = key.ReadValue(value_name, &(data[0]), &data_size, &data_type);
  if (result == ERROR_SUCCESS) {
    std::string out_data;
    if (OSCrypt::DecryptString(data, &out_data)) {
      
      if (!(out_data.size() & 1) && (out_data.size() > 2) &&
          !out_data[out_data.size() - 1] && !out_data[out_data.size() - 2]) {
        return base::string16(
            reinterpret_cast<const wchar_t *>(out_data.c_str()));
      }
    }
  }
  return base::string16();
}
struct {
  ServerFieldType field_type;
  const wchar_t *reg_value_name;
} profile_reg_values[] = {
  { NAME_FIRST,                    L"name_first" },
  { NAME_MIDDLE,                   L"name_middle" },
  { NAME_LAST,                     L"name_last" },
  { NAME_SUFFIX,                   L"name_suffix" },
  { EMAIL_ADDRESS,                 L"email" },
  { COMPANY_NAME,                  L"company_name" },
  { PHONE_HOME_NUMBER,             L"phone_home_number" },
  { PHONE_HOME_CITY_CODE,          L"phone_home_city_code" },
  { PHONE_HOME_COUNTRY_CODE,       L"phone_home_country_code" },
  { ADDRESS_HOME_LINE1,            L"address_home_line1" },
  { ADDRESS_HOME_LINE2,            L"address_home_line2" },
  { ADDRESS_HOME_CITY,             L"address_home_city" },
  { ADDRESS_HOME_STATE,            L"address_home_state" },
  { ADDRESS_HOME_ZIP,              L"address_home_zip" },
  { ADDRESS_HOME_COUNTRY,          L"address_home_country" },
  { ADDRESS_BILLING_LINE1,         L"address_billing_line1" },
  { ADDRESS_BILLING_LINE2,         L"address_billing_line2" },
  { ADDRESS_BILLING_CITY,          L"address_billing_city" },
  { ADDRESS_BILLING_STATE,         L"address_billing_state" },
  { ADDRESS_BILLING_ZIP,           L"address_billing_zip" },
  { ADDRESS_BILLING_COUNTRY,       L"address_billing_country" },
  { CREDIT_CARD_NAME,              L"credit_card_name" },
  { CREDIT_CARD_NUMBER,            L"credit_card_number" },
  { CREDIT_CARD_EXP_MONTH,         L"credit_card_exp_month" },
  { CREDIT_CARD_EXP_4_DIGIT_YEAR,  L"credit_card_exp_4_digit_year" },
  { CREDIT_CARD_TYPE,              L"credit_card_type" },
  
};
typedef std::map<std::wstring, ServerFieldType> RegToFieldMap;
bool ImportSingleFormGroup(const RegKey& key,
                           const RegToFieldMap& reg_to_field,
                           const std::string& app_locale,
                           FormGroup* form_group,
                           PhoneNumber::PhoneCombineHelper* phone) {
  if (!key.Valid())
    return false;
  bool has_non_empty_fields = false;
  for (uint32 i = 0; i < key.GetValueCount(); ++i) {
    std::wstring value_name;
    if (key.GetValueNameAt(i, &value_name) != ERROR_SUCCESS)
      continue;
    RegToFieldMap::const_iterator it = reg_to_field.find(value_name);
    if (it == reg_to_field.end())
      continue;  
    base::string16 field_value = ReadAndDecryptValue(key, value_name.c_str());
    if (!field_value.empty()) {
      if (it->second == CREDIT_CARD_NUMBER)
        field_value = DecryptCCNumber(field_value);
      
      
      if (!phone || !phone->SetInfo(AutofillType(it->second), field_value)) {
        has_non_empty_fields = true;
        form_group->SetInfo(AutofillType(it->second), field_value, app_locale);
      }
    }
  }
  return has_non_empty_fields;
}
bool ImportSingleProfile(const std::string& app_locale,
                         const RegKey& key,
                         const RegToFieldMap& reg_to_field,
                         AutofillProfile* profile) {
  PhoneNumber::PhoneCombineHelper phone;
  bool has_non_empty_fields =
      ImportSingleFormGroup(key, reg_to_field, app_locale, profile, &phone);
  
  base::string16 constructed_number;
  if (phone.ParseNumber(*profile, app_locale, &constructed_number)) {
    has_non_empty_fields = true;
    profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, constructed_number);
  }
  return has_non_empty_fields;
}
class AutofillImporter : public PersonalDataManagerObserver {
 public:
  explicit AutofillImporter(PersonalDataManager* personal_data_manager)
    : personal_data_manager_(personal_data_manager) {
      personal_data_manager_->AddObserver(this);
  }
  bool ImportProfiles() {
    if (!ImportCurrentUserProfiles(personal_data_manager_->app_locale(),
                                   &profiles_,
                                   &credit_cards_)) {
      delete this;
      return false;
    }
    if (personal_data_manager_->IsDataLoaded())
      OnPersonalDataChanged();
    return true;
  }
  
  virtual void OnPersonalDataChanged() OVERRIDE {
    for (std::vector<AutofillProfile>::const_iterator iter = profiles_.begin();
         iter != profiles_.end(); ++iter) {
      personal_data_manager_->AddProfile(*iter);
    }
    for (std::vector<CreditCard>::const_iterator iter = credit_cards_.begin();
         iter != credit_cards_.end(); ++iter) {
      personal_data_manager_->AddCreditCard(*iter);
    }
    delete this;
  }
 private:
  ~AutofillImporter() {
    personal_data_manager_->RemoveObserver(this);
  }
  PersonalDataManager* personal_data_manager_;
  std::vector<AutofillProfile> profiles_;
  std::vector<CreditCard> credit_cards_;
};
}  
bool ImportCurrentUserProfiles(const std::string& app_locale,
                               std::vector<AutofillProfile>* profiles,
                               std::vector<CreditCard>* credit_cards) {
  DCHECK(profiles);
  DCHECK(credit_cards);
  
  RegToFieldMap reg_to_field;
  for (size_t i = 0; i < arraysize(profile_reg_values); ++i) {
    reg_to_field[std::wstring(profile_reg_values[i].reg_value_name)] =
        profile_reg_values[i].field_type;
  }
  base::win::RegistryKeyIterator iterator_profiles(HKEY_CURRENT_USER,
                                                   kProfileKey);
  for (; iterator_profiles.Valid(); ++iterator_profiles) {
    std::wstring key_name(kProfileKey);
    key_name.append(L"\\");
    key_name.append(iterator_profiles.Name());
    RegKey key(HKEY_CURRENT_USER, key_name.c_str(), KEY_READ);
    AutofillProfile profile;
    profile.set_origin(kIEToolbarImportOrigin);
    if (ImportSingleProfile(app_locale, key, reg_to_field, &profile)) {
      
      profiles->push_back(profile);
    }
  }
  base::string16 password_hash;
  base::string16 salt;
  RegKey cc_key(HKEY_CURRENT_USER, kCreditCardKey, KEY_READ);
  if (cc_key.Valid()) {
    password_hash = ReadAndDecryptValue(cc_key, kPasswordHashValue);
    salt = ReadAndDecryptValue(cc_key, kSaltValue);
  }
  
  if (password_hash.empty() && IsEmptySalt(salt)) {
    base::win::RegistryKeyIterator iterator_cc(HKEY_CURRENT_USER,
                                               kCreditCardKey);
    for (; iterator_cc.Valid(); ++iterator_cc) {
      std::wstring key_name(kCreditCardKey);
      key_name.append(L"\\");
      key_name.append(iterator_cc.Name());
      RegKey key(HKEY_CURRENT_USER, key_name.c_str(), KEY_READ);
      CreditCard credit_card;
      credit_card.set_origin(kIEToolbarImportOrigin);
      if (ImportSingleFormGroup(
              key, reg_to_field, app_locale, &credit_card, NULL)) {
        base::string16 cc_number = credit_card.GetRawInfo(CREDIT_CARD_NUMBER);
        if (!cc_number.empty())
          credit_cards->push_back(credit_card);
      }
    }
  }
  return (profiles->size() + credit_cards->size()) > 0;
}
bool ImportAutofillDataWin(PersonalDataManager* pdm) {
  
  if (!pdm)
    return false;
  AutofillImporter *importer = new AutofillImporter(pdm);
  
  return importer->ImportProfiles();
}
}