OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/autofill/autofill_ie_toolbar_import_win.h" | 5 #include "chrome/browser/autofill/autofill_ie_toolbar_import_win.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <map> | 8 #include <map> |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
13 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/string16.h" | 15 #include "base/string16.h" |
16 #include "base/win/registry.h" | 16 #include "base/win/registry.h" |
| 17 #include "chrome/browser/autofill/autofill_country.h" |
17 #include "chrome/browser/autofill/autofill_profile.h" | 18 #include "chrome/browser/autofill/autofill_profile.h" |
18 #include "chrome/browser/autofill/credit_card.h" | 19 #include "chrome/browser/autofill/credit_card.h" |
19 #include "chrome/browser/autofill/crypto/rc4_decryptor.h" | 20 #include "chrome/browser/autofill/crypto/rc4_decryptor.h" |
20 #include "chrome/browser/autofill/field_types.h" | 21 #include "chrome/browser/autofill/field_types.h" |
21 #include "chrome/browser/autofill/form_group.h" | 22 #include "chrome/browser/autofill/form_group.h" |
22 #include "chrome/browser/autofill/personal_data_manager.h" | 23 #include "chrome/browser/autofill/personal_data_manager.h" |
23 #include "chrome/browser/autofill/personal_data_manager_observer.h" | 24 #include "chrome/browser/autofill/personal_data_manager_observer.h" |
24 #include "chrome/browser/autofill/phone_number.h" | 25 #include "chrome/browser/autofill/phone_number.h" |
25 #include "chrome/browser/autofill/phone_number_i18n.h" | 26 #include "chrome/browser/autofill/phone_number_i18n.h" |
26 #include "sync/util/data_encryption_win.h" | 27 #include "sync/util/data_encryption_win.h" |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 // Empty salt in IE Toolbar is \x1\x2...\x14 | 59 // Empty salt in IE Toolbar is \x1\x2...\x14 |
59 if (salt.length() != 20) | 60 if (salt.length() != 20) |
60 return false; | 61 return false; |
61 for (size_t i = 0; i < salt.length(); ++i) { | 62 for (size_t i = 0; i < salt.length(); ++i) { |
62 if (salt[i] != i + 1) | 63 if (salt[i] != i + 1) |
63 return false; | 64 return false; |
64 } | 65 } |
65 return true; | 66 return true; |
66 } | 67 } |
67 | 68 |
68 string16 ReadAndDecryptValue(RegKey* key, const wchar_t* value_name) { | 69 string16 ReadAndDecryptValue(const RegKey& key, const wchar_t* value_name) { |
69 DWORD data_type = REG_BINARY; | 70 DWORD data_type = REG_BINARY; |
70 DWORD data_size = 0; | 71 DWORD data_size = 0; |
71 LONG result = key->ReadValue(value_name, NULL, &data_size, &data_type); | 72 LONG result = key.ReadValue(value_name, NULL, &data_size, &data_type); |
72 if ((result != ERROR_SUCCESS) || !data_size || data_type != REG_BINARY) | 73 if ((result != ERROR_SUCCESS) || !data_size || data_type != REG_BINARY) |
73 return string16(); | 74 return string16(); |
74 std::vector<uint8> data; | 75 std::vector<uint8> data; |
75 data.resize(data_size); | 76 data.resize(data_size); |
76 result = key->ReadValue(value_name, &(data[0]), &data_size, &data_type); | 77 result = key.ReadValue(value_name, &(data[0]), &data_size, &data_type); |
77 if (result == ERROR_SUCCESS) { | 78 if (result == ERROR_SUCCESS) { |
78 std::string out_data; | 79 std::string out_data; |
79 if (syncer::DecryptData(data, &out_data)) { | 80 if (syncer::DecryptData(data, &out_data)) { |
80 // The actual data is in UTF16 already. | 81 // The actual data is in UTF16 already. |
81 if (!(out_data.size() & 1) && (out_data.size() > 2) && | 82 if (!(out_data.size() & 1) && (out_data.size() > 2) && |
82 !out_data[out_data.size() - 1] && !out_data[out_data.size() - 2]) { | 83 !out_data[out_data.size() - 1] && !out_data[out_data.size() - 2]) { |
83 return string16( | 84 return string16( |
84 reinterpret_cast<const wchar_t *>(out_data.c_str())); | 85 reinterpret_cast<const wchar_t *>(out_data.c_str())); |
85 } | 86 } |
86 } | 87 } |
(...skipping 29 matching lines...) Expand all Loading... |
116 { CREDIT_CARD_NAME, L"credit_card_name" }, | 117 { CREDIT_CARD_NAME, L"credit_card_name" }, |
117 { CREDIT_CARD_NUMBER, L"credit_card_number" }, | 118 { CREDIT_CARD_NUMBER, L"credit_card_number" }, |
118 { CREDIT_CARD_EXP_MONTH, L"credit_card_exp_month" }, | 119 { CREDIT_CARD_EXP_MONTH, L"credit_card_exp_month" }, |
119 { CREDIT_CARD_EXP_4_DIGIT_YEAR, L"credit_card_exp_4_digit_year" }, | 120 { CREDIT_CARD_EXP_4_DIGIT_YEAR, L"credit_card_exp_4_digit_year" }, |
120 { CREDIT_CARD_TYPE, L"credit_card_type" }, | 121 { CREDIT_CARD_TYPE, L"credit_card_type" }, |
121 // We do not import verification code. | 122 // We do not import verification code. |
122 }; | 123 }; |
123 | 124 |
124 typedef std::map<std::wstring, AutofillFieldType> RegToFieldMap; | 125 typedef std::map<std::wstring, AutofillFieldType> RegToFieldMap; |
125 | 126 |
126 bool ImportSingleProfile(FormGroup* profile, | 127 // Imports address or credit card data from the given registry |key| into the |
127 RegKey* key, | 128 // given |form_group|, with the help of |reg_to_field|. When importing address |
128 const RegToFieldMap& reg_to_field ) { | 129 // data, writes the phone data into |phone|; otherwise, |phone| should be null. |
129 DCHECK(profile != NULL); | 130 // Returns true if any fields were set, false otherwise. |
130 if (!key->Valid()) | 131 bool ImportSingleFormGroup(const RegKey& key, |
| 132 const RegToFieldMap& reg_to_field, |
| 133 FormGroup* form_group, |
| 134 PhoneNumber::PhoneCombineHelper* phone) { |
| 135 if (!key.Valid()) |
131 return false; | 136 return false; |
132 | 137 |
133 bool has_non_empty_fields = false; | 138 bool has_non_empty_fields = false; |
134 | 139 |
135 // Phones need to be rebuilt. | 140 for (uint32 i = 0; i < key.GetValueCount(); ++i) { |
136 PhoneNumber::PhoneCombineHelper phone; | 141 std::wstring value_name; |
| 142 if (key.GetValueNameAt(i, &value_name) != ERROR_SUCCESS) |
| 143 continue; |
137 | 144 |
138 for (uint32 i = 0; i < key->GetValueCount(); ++i) { | |
139 std::wstring value_name; | |
140 if (key->GetValueNameAt(i, &value_name) != ERROR_SUCCESS) | |
141 continue; | |
142 RegToFieldMap::const_iterator it = reg_to_field.find(value_name); | 145 RegToFieldMap::const_iterator it = reg_to_field.find(value_name); |
143 if (it == reg_to_field.end()) | 146 if (it == reg_to_field.end()) |
144 continue; // This field is not imported. | 147 continue; // This field is not imported. |
| 148 |
145 string16 field_value = ReadAndDecryptValue(key, value_name.c_str()); | 149 string16 field_value = ReadAndDecryptValue(key, value_name.c_str()); |
146 if (!field_value.empty()) { | 150 if (!field_value.empty()) { |
147 has_non_empty_fields = true; | |
148 if (it->second == CREDIT_CARD_NUMBER) | 151 if (it->second == CREDIT_CARD_NUMBER) |
149 field_value = DecryptCCNumber(field_value); | 152 field_value = DecryptCCNumber(field_value); |
150 | 153 |
151 // We need to store phone data in |phone| before building the whole number | 154 // Phone numbers are stored piece-by-piece, and then reconstructed from |
152 // at the end. The rest of the fields are set "as is". | 155 // the pieces. The rest of the fields are set "as is". |
153 // TODO(isherman): Call SetInfo(), rather than SetRawInfo(). | 156 // TODO(isherman): Call SetInfo(), rather than SetRawInfo(). |
154 if (!phone.SetInfo(it->second, field_value)) | 157 if (!phone || !phone->SetInfo(it->second, field_value)) { |
155 profile->SetRawInfo(it->second, field_value); | 158 has_non_empty_fields = true; |
| 159 form_group->SetRawInfo(it->second, field_value); |
| 160 } |
156 } | 161 } |
157 } | 162 } |
| 163 |
| 164 return has_non_empty_fields; |
| 165 } |
| 166 |
| 167 // Imports address data from the given registry |key| into the given |profile|, |
| 168 // with the help of |reg_to_field|. Returns true if any fields were set, false |
| 169 // otherwise. |
| 170 bool ImportSingleProfile(const RegKey& key, |
| 171 const RegToFieldMap& reg_to_field, |
| 172 AutofillProfile* profile) { |
| 173 PhoneNumber::PhoneCombineHelper phone; |
| 174 bool has_non_empty_fields = |
| 175 ImportSingleFormGroup(key, reg_to_field, profile, &phone); |
| 176 |
158 // Now re-construct the phones if needed. | 177 // Now re-construct the phones if needed. |
159 string16 constructed_number; | 178 string16 constructed_number; |
160 if (!phone.IsEmpty() && | 179 const std::string app_locale = AutofillCountry::ApplicationLocale(); |
161 phone.ParseNumber(std::string("US"), &constructed_number)) { | 180 if (phone.ParseNumber(*profile, app_locale, &constructed_number)) { |
| 181 has_non_empty_fields = true; |
162 profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, constructed_number); | 182 profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, constructed_number); |
163 } | 183 } |
164 | 184 |
165 return has_non_empty_fields; | 185 return has_non_empty_fields; |
166 } | 186 } |
167 | 187 |
168 // Imports profiles from the IE toolbar and stores them. Asynchronous | 188 // Imports profiles from the IE toolbar and stores them. Asynchronous |
169 // if PersonalDataManager has not been loaded yet. Deletes itself on completion. | 189 // if PersonalDataManager has not been loaded yet. Deletes itself on completion. |
170 class AutofillImporter : public PersonalDataManagerObserver { | 190 class AutofillImporter : public PersonalDataManagerObserver { |
171 public: | 191 public: |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 } | 245 } |
226 | 246 |
227 base::win::RegistryKeyIterator iterator_profiles(HKEY_CURRENT_USER, | 247 base::win::RegistryKeyIterator iterator_profiles(HKEY_CURRENT_USER, |
228 kProfileKey); | 248 kProfileKey); |
229 for (; iterator_profiles.Valid(); ++iterator_profiles) { | 249 for (; iterator_profiles.Valid(); ++iterator_profiles) { |
230 std::wstring key_name(kProfileKey); | 250 std::wstring key_name(kProfileKey); |
231 key_name.append(L"\\"); | 251 key_name.append(L"\\"); |
232 key_name.append(iterator_profiles.Name()); | 252 key_name.append(iterator_profiles.Name()); |
233 RegKey key(HKEY_CURRENT_USER, key_name.c_str(), KEY_READ); | 253 RegKey key(HKEY_CURRENT_USER, key_name.c_str(), KEY_READ); |
234 AutofillProfile profile; | 254 AutofillProfile profile; |
235 if (ImportSingleProfile(&profile, &key, reg_to_field)) { | 255 if (ImportSingleProfile(key, reg_to_field, &profile)) { |
236 // Combine phones into whole phone #. | 256 // Combine phones into whole phone #. |
237 profiles->push_back(profile); | 257 profiles->push_back(profile); |
238 } | 258 } |
239 } | 259 } |
240 string16 password_hash; | 260 string16 password_hash; |
241 string16 salt; | 261 string16 salt; |
242 RegKey cc_key(HKEY_CURRENT_USER, kCreditCardKey, KEY_READ); | 262 RegKey cc_key(HKEY_CURRENT_USER, kCreditCardKey, KEY_READ); |
243 if (cc_key.Valid()) { | 263 if (cc_key.Valid()) { |
244 password_hash = ReadAndDecryptValue(&cc_key, kPasswordHashValue); | 264 password_hash = ReadAndDecryptValue(cc_key, kPasswordHashValue); |
245 salt = ReadAndDecryptValue(&cc_key, kSaltValue); | 265 salt = ReadAndDecryptValue(cc_key, kSaltValue); |
246 } | 266 } |
247 | 267 |
248 // We import CC profiles only if they are not password protected. | 268 // We import CC profiles only if they are not password protected. |
249 if (password_hash.empty() && IsEmptySalt(salt)) { | 269 if (password_hash.empty() && IsEmptySalt(salt)) { |
250 base::win::RegistryKeyIterator iterator_cc(HKEY_CURRENT_USER, | 270 base::win::RegistryKeyIterator iterator_cc(HKEY_CURRENT_USER, |
251 kCreditCardKey); | 271 kCreditCardKey); |
252 for (; iterator_cc.Valid(); ++iterator_cc) { | 272 for (; iterator_cc.Valid(); ++iterator_cc) { |
253 std::wstring key_name(kCreditCardKey); | 273 std::wstring key_name(kCreditCardKey); |
254 key_name.append(L"\\"); | 274 key_name.append(L"\\"); |
255 key_name.append(iterator_cc.Name()); | 275 key_name.append(iterator_cc.Name()); |
256 RegKey key(HKEY_CURRENT_USER, key_name.c_str(), KEY_READ); | 276 RegKey key(HKEY_CURRENT_USER, key_name.c_str(), KEY_READ); |
257 CreditCard credit_card; | 277 CreditCard credit_card; |
258 if (ImportSingleProfile(&credit_card, &key, reg_to_field)) { | 278 if (ImportSingleFormGroup(key, reg_to_field, &credit_card, NULL)) { |
259 // TODO(isherman): Call into GetInfo() below, rather than GetRawInfo(). | 279 // TODO(isherman): Call into GetInfo() below, rather than GetRawInfo(). |
260 string16 cc_number = credit_card.GetRawInfo(CREDIT_CARD_NUMBER); | 280 string16 cc_number = credit_card.GetRawInfo(CREDIT_CARD_NUMBER); |
261 if (!cc_number.empty()) | 281 if (!cc_number.empty()) |
262 credit_cards->push_back(credit_card); | 282 credit_cards->push_back(credit_card); |
263 } | 283 } |
264 } | 284 } |
265 } | 285 } |
266 return (profiles->size() + credit_cards->size()) > 0; | 286 return (profiles->size() + credit_cards->size()) > 0; |
267 } | 287 } |
268 | 288 |
269 bool ImportAutofillDataWin(PersonalDataManager* pdm) { | 289 bool ImportAutofillDataWin(PersonalDataManager* pdm) { |
270 // In incognito mode we do not have PDM - and we should not import anything. | 290 // In incognito mode we do not have PDM - and we should not import anything. |
271 if (!pdm) | 291 if (!pdm) |
272 return false; | 292 return false; |
273 AutofillImporter *importer = new AutofillImporter(pdm); | 293 AutofillImporter *importer = new AutofillImporter(pdm); |
274 // importer will self delete. | 294 // importer will self delete. |
275 return importer->ImportProfiles(); | 295 return importer->ImportProfiles(); |
276 } | 296 } |
OLD | NEW |