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

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

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

Powered by Google App Engine
This is Rietveld 408576698