Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(195)

Side by Side Diff: components/autofill/browser/autofill_ie_toolbar_import_win.cc

Issue 17392006: In components/autofill, move browser/ to core/browser/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase to fix conflicts Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 "components/autofill/browser/autofill_ie_toolbar_import_win.h"
6
7 #include <stddef.h>
8 #include <map>
9 #include <string>
10 #include <vector>
11
12 #include "base/basictypes.h"
13 #include "base/compiler_specific.h"
14 #include "base/logging.h"
15 #include "base/strings/string16.h"
16 #include "base/win/registry.h"
17 #include "components/autofill/browser/autofill_country.h"
18 #include "components/autofill/browser/autofill_profile.h"
19 #include "components/autofill/browser/credit_card.h"
20 #include "components/autofill/browser/crypto/rc4_decryptor.h"
21 #include "components/autofill/browser/field_types.h"
22 #include "components/autofill/browser/form_group.h"
23 #include "components/autofill/browser/personal_data_manager.h"
24 #include "components/autofill/browser/personal_data_manager_observer.h"
25 #include "components/autofill/browser/phone_number.h"
26 #include "components/autofill/browser/phone_number_i18n.h"
27 #include "sync/util/data_encryption_win.h"
28
29 using base::win::RegKey;
30
31 namespace autofill {
32
33 // Forward declaration. This function is not in unnamed namespace as it
34 // is referenced in the unittest.
35 bool ImportCurrentUserProfiles(const std::string& app_locale,
36 std::vector<AutofillProfile>* profiles,
37 std::vector<CreditCard>* credit_cards);
38 namespace {
39
40 const wchar_t* const kProfileKey =
41 L"Software\\Google\\Google Toolbar\\4.0\\Autofill\\Profiles";
42 const wchar_t* const kCreditCardKey =
43 L"Software\\Google\\Google Toolbar\\4.0\\Autofill\\Credit Cards";
44 const wchar_t* const kPasswordHashValue = L"password_hash";
45 const wchar_t* const kSaltValue = L"salt";
46
47 // This string is stored along with saved addresses and credit cards in the
48 // WebDB, and hence should not be modified, so that it remains consistent over
49 // time.
50 const char kIEToolbarImportOrigin[] = "Imported from Internet Explorer";
51
52 // This is RC4 decryption for Toolbar credit card data. This is necessary
53 // because it is not standard, so Crypto API cannot be used.
54 std::wstring DecryptCCNumber(const std::wstring& data) {
55 const wchar_t* kEmptyKey =
56 L"\x3605\xCEE5\xCE49\x44F7\xCF4E\xF6CC\x604B\xFCBE\xC70A\x08FD";
57 const size_t kMacLen = 10;
58
59 if (data.length() <= kMacLen)
60 return std::wstring();
61
62 RC4Decryptor rc4_algorithm(kEmptyKey);
63 return rc4_algorithm.Run(data.substr(kMacLen));
64 }
65
66 bool IsEmptySalt(std::wstring const& salt) {
67 // Empty salt in IE Toolbar is \x1\x2...\x14
68 if (salt.length() != 20)
69 return false;
70 for (size_t i = 0; i < salt.length(); ++i) {
71 if (salt[i] != i + 1)
72 return false;
73 }
74 return true;
75 }
76
77 base::string16 ReadAndDecryptValue(const RegKey& key,
78 const wchar_t* value_name) {
79 DWORD data_type = REG_BINARY;
80 DWORD data_size = 0;
81 LONG result = key.ReadValue(value_name, NULL, &data_size, &data_type);
82 if ((result != ERROR_SUCCESS) || !data_size || data_type != REG_BINARY)
83 return base::string16();
84 std::vector<uint8> data;
85 data.resize(data_size);
86 result = key.ReadValue(value_name, &(data[0]), &data_size, &data_type);
87 if (result == ERROR_SUCCESS) {
88 std::string out_data;
89 if (syncer::DecryptData(data, &out_data)) {
90 // The actual data is in UTF16 already.
91 if (!(out_data.size() & 1) && (out_data.size() > 2) &&
92 !out_data[out_data.size() - 1] && !out_data[out_data.size() - 2]) {
93 return base::string16(
94 reinterpret_cast<const wchar_t *>(out_data.c_str()));
95 }
96 }
97 }
98 return base::string16();
99 }
100
101 struct {
102 AutofillFieldType field_type;
103 const wchar_t *reg_value_name;
104 } profile_reg_values[] = {
105 { NAME_FIRST, L"name_first" },
106 { NAME_MIDDLE, L"name_middle" },
107 { NAME_LAST, L"name_last" },
108 { NAME_SUFFIX, L"name_suffix" },
109 { EMAIL_ADDRESS, L"email" },
110 { COMPANY_NAME, L"company_name" },
111 { PHONE_HOME_NUMBER, L"phone_home_number" },
112 { PHONE_HOME_CITY_CODE, L"phone_home_city_code" },
113 { PHONE_HOME_COUNTRY_CODE, L"phone_home_country_code" },
114 { ADDRESS_HOME_LINE1, L"address_home_line1" },
115 { ADDRESS_HOME_LINE2, L"address_home_line2" },
116 { ADDRESS_HOME_CITY, L"address_home_city" },
117 { ADDRESS_HOME_STATE, L"address_home_state" },
118 { ADDRESS_HOME_ZIP, L"address_home_zip" },
119 { ADDRESS_HOME_COUNTRY, L"address_home_country" },
120 { ADDRESS_BILLING_LINE1, L"address_billing_line1" },
121 { ADDRESS_BILLING_LINE2, L"address_billing_line2" },
122 { ADDRESS_BILLING_CITY, L"address_billing_city" },
123 { ADDRESS_BILLING_STATE, L"address_billing_state" },
124 { ADDRESS_BILLING_ZIP, L"address_billing_zip" },
125 { ADDRESS_BILLING_COUNTRY, L"address_billing_country" },
126 { CREDIT_CARD_NAME, L"credit_card_name" },
127 { CREDIT_CARD_NUMBER, L"credit_card_number" },
128 { CREDIT_CARD_EXP_MONTH, L"credit_card_exp_month" },
129 { CREDIT_CARD_EXP_4_DIGIT_YEAR, L"credit_card_exp_4_digit_year" },
130 { CREDIT_CARD_TYPE, L"credit_card_type" },
131 // We do not import verification code.
132 };
133
134 typedef std::map<std::wstring, AutofillFieldType> RegToFieldMap;
135
136 // Imports address or credit card data from the given registry |key| into the
137 // given |form_group|, with the help of |reg_to_field|. When importing address
138 // data, writes the phone data into |phone|; otherwise, |phone| should be null.
139 // Returns true if any fields were set, false otherwise.
140 bool ImportSingleFormGroup(const RegKey& key,
141 const RegToFieldMap& reg_to_field,
142 const std::string& app_locale,
143 FormGroup* form_group,
144 PhoneNumber::PhoneCombineHelper* phone) {
145 if (!key.Valid())
146 return false;
147
148 bool has_non_empty_fields = false;
149
150 for (uint32 i = 0; i < key.GetValueCount(); ++i) {
151 std::wstring value_name;
152 if (key.GetValueNameAt(i, &value_name) != ERROR_SUCCESS)
153 continue;
154
155 RegToFieldMap::const_iterator it = reg_to_field.find(value_name);
156 if (it == reg_to_field.end())
157 continue; // This field is not imported.
158
159 base::string16 field_value = ReadAndDecryptValue(key, value_name.c_str());
160 if (!field_value.empty()) {
161 if (it->second == CREDIT_CARD_NUMBER)
162 field_value = DecryptCCNumber(field_value);
163
164 // Phone numbers are stored piece-by-piece, and then reconstructed from
165 // the pieces. The rest of the fields are set "as is".
166 if (!phone || !phone->SetInfo(it->second, field_value)) {
167 has_non_empty_fields = true;
168 form_group->SetInfo(it->second, field_value, app_locale);
169 }
170 }
171 }
172
173 return has_non_empty_fields;
174 }
175
176 // Imports address data from the given registry |key| into the given |profile|,
177 // with the help of |reg_to_field|. Returns true if any fields were set, false
178 // otherwise.
179 bool ImportSingleProfile(const std::string& app_locale,
180 const RegKey& key,
181 const RegToFieldMap& reg_to_field,
182 AutofillProfile* profile) {
183 PhoneNumber::PhoneCombineHelper phone;
184 bool has_non_empty_fields =
185 ImportSingleFormGroup(key, reg_to_field, app_locale, profile, &phone);
186
187 // Now re-construct the phones if needed.
188 base::string16 constructed_number;
189 if (phone.ParseNumber(*profile, app_locale, &constructed_number)) {
190 has_non_empty_fields = true;
191 profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, constructed_number);
192 }
193
194 return has_non_empty_fields;
195 }
196
197 // Imports profiles from the IE toolbar and stores them. Asynchronous
198 // if PersonalDataManager has not been loaded yet. Deletes itself on completion.
199 class AutofillImporter : public PersonalDataManagerObserver {
200 public:
201 explicit AutofillImporter(PersonalDataManager* personal_data_manager)
202 : personal_data_manager_(personal_data_manager) {
203 personal_data_manager_->AddObserver(this);
204 }
205
206 bool ImportProfiles() {
207 if (!ImportCurrentUserProfiles(personal_data_manager_->app_locale(),
208 &profiles_,
209 &credit_cards_)) {
210 delete this;
211 return false;
212 }
213 if (personal_data_manager_->IsDataLoaded())
214 OnPersonalDataChanged();
215 return true;
216 }
217
218 // PersonalDataManagerObserver:
219 virtual void OnPersonalDataChanged() OVERRIDE {
220 for (std::vector<AutofillProfile>::const_iterator iter = profiles_.begin();
221 iter != profiles_.end(); ++iter) {
222 personal_data_manager_->AddProfile(*iter);
223 }
224 for (std::vector<CreditCard>::const_iterator iter = credit_cards_.begin();
225 iter != credit_cards_.end(); ++iter) {
226 personal_data_manager_->AddCreditCard(*iter);
227 }
228 delete this;
229 }
230
231 private:
232 ~AutofillImporter() {
233 personal_data_manager_->RemoveObserver(this);
234 }
235
236 PersonalDataManager* personal_data_manager_;
237 std::vector<AutofillProfile> profiles_;
238 std::vector<CreditCard> credit_cards_;
239 };
240
241 } // namespace
242
243 // Imports Autofill profiles and credit cards from IE Toolbar if present and not
244 // password protected. Returns true if data is successfully retrieved. False if
245 // there is no data, data is password protected or error occurred.
246 bool ImportCurrentUserProfiles(const std::string& app_locale,
247 std::vector<AutofillProfile>* profiles,
248 std::vector<CreditCard>* credit_cards) {
249 DCHECK(profiles);
250 DCHECK(credit_cards);
251
252 // Create a map of possible fields for a quick access.
253 RegToFieldMap reg_to_field;
254 for (size_t i = 0; i < arraysize(profile_reg_values); ++i) {
255 reg_to_field[std::wstring(profile_reg_values[i].reg_value_name)] =
256 profile_reg_values[i].field_type;
257 }
258
259 base::win::RegistryKeyIterator iterator_profiles(HKEY_CURRENT_USER,
260 kProfileKey);
261 for (; iterator_profiles.Valid(); ++iterator_profiles) {
262 std::wstring key_name(kProfileKey);
263 key_name.append(L"\\");
264 key_name.append(iterator_profiles.Name());
265 RegKey key(HKEY_CURRENT_USER, key_name.c_str(), KEY_READ);
266 AutofillProfile profile;
267 profile.set_origin(kIEToolbarImportOrigin);
268 if (ImportSingleProfile(app_locale, key, reg_to_field, &profile)) {
269 // Combine phones into whole phone #.
270 profiles->push_back(profile);
271 }
272 }
273 base::string16 password_hash;
274 base::string16 salt;
275 RegKey cc_key(HKEY_CURRENT_USER, kCreditCardKey, KEY_READ);
276 if (cc_key.Valid()) {
277 password_hash = ReadAndDecryptValue(cc_key, kPasswordHashValue);
278 salt = ReadAndDecryptValue(cc_key, kSaltValue);
279 }
280
281 // We import CC profiles only if they are not password protected.
282 if (password_hash.empty() && IsEmptySalt(salt)) {
283 base::win::RegistryKeyIterator iterator_cc(HKEY_CURRENT_USER,
284 kCreditCardKey);
285 for (; iterator_cc.Valid(); ++iterator_cc) {
286 std::wstring key_name(kCreditCardKey);
287 key_name.append(L"\\");
288 key_name.append(iterator_cc.Name());
289 RegKey key(HKEY_CURRENT_USER, key_name.c_str(), KEY_READ);
290 CreditCard credit_card;
291 credit_card.set_origin(kIEToolbarImportOrigin);
292 if (ImportSingleFormGroup(
293 key, reg_to_field, app_locale, &credit_card, NULL)) {
294 base::string16 cc_number = credit_card.GetRawInfo(CREDIT_CARD_NUMBER);
295 if (!cc_number.empty())
296 credit_cards->push_back(credit_card);
297 }
298 }
299 }
300 return (profiles->size() + credit_cards->size()) > 0;
301 }
302
303 bool ImportAutofillDataWin(PersonalDataManager* pdm) {
304 // In incognito mode we do not have PDM - and we should not import anything.
305 if (!pdm)
306 return false;
307 AutofillImporter *importer = new AutofillImporter(pdm);
308 // importer will self delete.
309 return importer->ImportProfiles();
310 }
311
312 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698