OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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/webdata/autofill_util.h" | |
6 | |
7 #include "app/sql/statement.h" | |
8 #include "base/logging.h" | |
9 #include "base/time.h" | |
10 #include "chrome/browser/autofill/autofill_profile.h" | |
11 #include "chrome/browser/autofill/autofill_type.h" | |
12 #include "chrome/browser/autofill/credit_card.h" | |
13 #include "chrome/browser/password_manager/encryptor.h" | |
14 #include "chrome/common/guid.h" | |
15 | |
16 using base::Time; | |
17 | |
18 namespace autofill_util { | |
19 | |
20 // The maximum length allowed for form data. | |
21 const size_t kMaxDataLength = 1024; | |
22 | |
23 string16 LimitDataSize(const string16& data) { | |
24 if (data.size() > kMaxDataLength) | |
25 return data.substr(0, kMaxDataLength); | |
26 | |
27 return data; | |
28 } | |
29 | |
30 void BindAutofillProfileToStatement(const AutofillProfile& profile, | |
31 sql::Statement* s) { | |
32 DCHECK(guid::IsValidGUID(profile.guid())); | |
33 s->BindString(0, profile.guid()); | |
34 | |
35 string16 text = profile.GetInfo(COMPANY_NAME); | |
36 s->BindString16(1, LimitDataSize(text)); | |
37 text = profile.GetInfo(ADDRESS_HOME_LINE1); | |
38 s->BindString16(2, LimitDataSize(text)); | |
39 text = profile.GetInfo(ADDRESS_HOME_LINE2); | |
40 s->BindString16(3, LimitDataSize(text)); | |
41 text = profile.GetInfo(ADDRESS_HOME_CITY); | |
42 s->BindString16(4, LimitDataSize(text)); | |
43 text = profile.GetInfo(ADDRESS_HOME_STATE); | |
44 s->BindString16(5, LimitDataSize(text)); | |
45 text = profile.GetInfo(ADDRESS_HOME_ZIP); | |
46 s->BindString16(6, LimitDataSize(text)); | |
47 text = profile.GetInfo(ADDRESS_HOME_COUNTRY); | |
48 s->BindString16(7, LimitDataSize(text)); | |
49 std::string country_code = profile.CountryCode(); | |
50 s->BindString(8, country_code); | |
51 s->BindInt64(9, Time::Now().ToTimeT()); | |
52 } | |
53 | |
54 AutofillProfile* AutofillProfileFromStatement(const sql::Statement& s) { | |
55 AutofillProfile* profile = new AutofillProfile; | |
56 profile->set_guid(s.ColumnString(0)); | |
57 DCHECK(guid::IsValidGUID(profile->guid())); | |
58 | |
59 profile->SetInfo(COMPANY_NAME, s.ColumnString16(1)); | |
60 profile->SetInfo(ADDRESS_HOME_LINE1, s.ColumnString16(2)); | |
61 profile->SetInfo(ADDRESS_HOME_LINE2, s.ColumnString16(3)); | |
62 profile->SetInfo(ADDRESS_HOME_CITY, s.ColumnString16(4)); | |
63 profile->SetInfo(ADDRESS_HOME_STATE, s.ColumnString16(5)); | |
64 profile->SetInfo(ADDRESS_HOME_ZIP, s.ColumnString16(6)); | |
65 // Intentionally skip column 7, which stores the localized country name. | |
66 profile->SetCountryCode(s.ColumnString(8)); | |
67 // Intentionally skip column 9, which stores the profile's modification date. | |
68 | |
69 return profile; | |
70 } | |
71 | |
72 void BindCreditCardToStatement(const CreditCard& credit_card, | |
73 sql::Statement* s) { | |
74 DCHECK(guid::IsValidGUID(credit_card.guid())); | |
75 s->BindString(0, credit_card.guid()); | |
76 | |
77 string16 text = credit_card.GetInfo(CREDIT_CARD_NAME); | |
78 s->BindString16(1, LimitDataSize(text)); | |
79 text = credit_card.GetInfo(CREDIT_CARD_EXP_MONTH); | |
80 s->BindString16(2, LimitDataSize(text)); | |
81 text = credit_card.GetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR); | |
82 s->BindString16(3, LimitDataSize(text)); | |
83 text = credit_card.GetInfo(CREDIT_CARD_NUMBER); | |
84 std::string encrypted_data; | |
85 Encryptor::EncryptString16(text, &encrypted_data); | |
86 s->BindBlob(4, encrypted_data.data(), | |
87 static_cast<int>(encrypted_data.length())); | |
88 s->BindInt64(5, Time::Now().ToTimeT()); | |
89 } | |
90 | |
91 CreditCard* CreditCardFromStatement(const sql::Statement& s) { | |
92 CreditCard* credit_card = new CreditCard; | |
93 | |
94 credit_card->set_guid(s.ColumnString(0)); | |
95 DCHECK(guid::IsValidGUID(credit_card->guid())); | |
96 | |
97 credit_card->SetInfo(CREDIT_CARD_NAME, s.ColumnString16(1)); | |
98 credit_card->SetInfo(CREDIT_CARD_EXP_MONTH, | |
99 s.ColumnString16(2)); | |
100 credit_card->SetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, | |
101 s.ColumnString16(3)); | |
102 int encrypted_number_len = s.ColumnByteLength(4); | |
103 string16 credit_card_number; | |
104 if (encrypted_number_len) { | |
105 std::string encrypted_number; | |
106 encrypted_number.resize(encrypted_number_len); | |
107 memcpy(&encrypted_number[0], s.ColumnBlob(4), encrypted_number_len); | |
108 Encryptor::DecryptString16(encrypted_number, &credit_card_number); | |
109 } | |
110 credit_card->SetInfo(CREDIT_CARD_NUMBER, credit_card_number); | |
111 // Intentionally skip column 5, which stores the modification date. | |
112 | |
113 return credit_card; | |
114 } | |
115 | |
116 bool AddAutofillProfileNamesToProfile(sql::Connection* db, | |
117 AutofillProfile* profile) { | |
118 sql::Statement s(db->GetUniqueStatement( | |
119 "SELECT guid, first_name, middle_name, last_name " | |
120 "FROM autofill_profile_names " | |
121 "WHERE guid=?")); | |
122 if (!s) { | |
123 NOTREACHED() << "Statement prepare failed"; | |
124 return false; | |
125 } | |
126 s.BindString(0, profile->guid()); | |
127 | |
128 std::vector<string16> first_names; | |
129 std::vector<string16> middle_names; | |
130 std::vector<string16> last_names; | |
131 while (s.Step()) { | |
132 DCHECK_EQ(profile->guid(), s.ColumnString(0)); | |
133 first_names.push_back(s.ColumnString16(1)); | |
134 middle_names.push_back(s.ColumnString16(2)); | |
135 last_names.push_back(s.ColumnString16(3)); | |
136 } | |
137 profile->SetMultiInfo(NAME_FIRST, first_names); | |
138 profile->SetMultiInfo(NAME_MIDDLE, middle_names); | |
139 profile->SetMultiInfo(NAME_LAST, last_names); | |
140 return true; | |
141 } | |
142 | |
143 bool AddAutofillProfileEmailsToProfile(sql::Connection* db, | |
144 AutofillProfile* profile) { | |
145 sql::Statement s(db->GetUniqueStatement( | |
146 "SELECT guid, email " | |
147 "FROM autofill_profile_emails " | |
148 "WHERE guid=?")); | |
149 if (!s) { | |
150 NOTREACHED() << "Statement prepare failed"; | |
151 return false; | |
152 } | |
153 s.BindString(0, profile->guid()); | |
154 | |
155 std::vector<string16> emails; | |
156 while (s.Step()) { | |
157 DCHECK_EQ(profile->guid(), s.ColumnString(0)); | |
158 emails.push_back(s.ColumnString16(1)); | |
159 } | |
160 profile->SetMultiInfo(EMAIL_ADDRESS, emails); | |
161 return true; | |
162 } | |
163 | |
164 bool AddAutofillProfilePhonesToProfile(sql::Connection* db, | |
165 AutofillProfile* profile) { | |
166 sql::Statement s(db->GetUniqueStatement( | |
167 "SELECT guid, type, number " | |
168 "FROM autofill_profile_phones " | |
169 "WHERE guid=? AND type=?")); | |
170 if (!s) { | |
171 NOTREACHED() << "Statement prepare failed"; | |
172 return false; | |
173 } | |
174 s.BindString(0, profile->guid()); | |
175 s.BindInt(1, kAutofillPhoneNumber); | |
176 | |
177 std::vector<string16> numbers; | |
178 while (s.Step()) { | |
179 DCHECK_EQ(profile->guid(), s.ColumnString(0)); | |
180 numbers.push_back(s.ColumnString16(2)); | |
181 } | |
182 profile->SetMultiInfo(PHONE_HOME_WHOLE_NUMBER, numbers); | |
183 return true; | |
184 } | |
185 | |
186 bool AddAutofillProfileFaxesToProfile(sql::Connection* db, | |
187 AutofillProfile* profile) { | |
188 sql::Statement s(db->GetUniqueStatement( | |
189 "SELECT guid, type, number " | |
190 "FROM autofill_profile_phones " | |
191 "WHERE guid=? AND type=?")); | |
192 if (!s) { | |
193 NOTREACHED() << "Statement prepare failed"; | |
194 return false; | |
195 } | |
196 s.BindString(0, profile->guid()); | |
197 s.BindInt(1, kAutofillFaxNumber); | |
198 | |
199 std::vector<string16> numbers; | |
200 while (s.Step()) { | |
201 DCHECK_EQ(profile->guid(), s.ColumnString(0)); | |
202 numbers.push_back(s.ColumnString16(2)); | |
203 } | |
204 profile->SetMultiInfo(PHONE_FAX_WHOLE_NUMBER, numbers); | |
205 return true; | |
206 } | |
207 | |
208 | |
209 bool AddAutofillProfileNames(const AutofillProfile& profile, | |
210 sql::Connection* db) { | |
211 std::vector<string16> first_names; | |
212 profile.GetMultiInfo(NAME_FIRST, &first_names); | |
213 std::vector<string16> middle_names; | |
214 profile.GetMultiInfo(NAME_MIDDLE, &middle_names); | |
215 std::vector<string16> last_names; | |
216 profile.GetMultiInfo(NAME_LAST, &last_names); | |
217 DCHECK_EQ(first_names.size(), middle_names.size()); | |
218 DCHECK_EQ(middle_names.size(), last_names.size()); | |
219 | |
220 for (size_t i = 0; i < first_names.size(); ++i) { | |
221 // Add the new name. | |
222 sql::Statement s(db->GetUniqueStatement( | |
223 "INSERT INTO autofill_profile_names" | |
224 " (guid, first_name, middle_name, last_name) " | |
225 "VALUES (?,?,?,?)")); | |
226 if (!s) { | |
227 NOTREACHED(); | |
228 return false; | |
229 } | |
230 s.BindString(0, profile.guid()); | |
231 s.BindString16(1, first_names[i]); | |
232 s.BindString16(2, middle_names[i]); | |
233 s.BindString16(3, last_names[i]); | |
234 | |
235 if (!s.Run()) { | |
236 NOTREACHED(); | |
237 return false; | |
238 } | |
239 } | |
240 return true; | |
241 } | |
242 | |
243 bool AddAutofillProfileEmails(const AutofillProfile& profile, | |
244 sql::Connection* db) { | |
245 std::vector<string16> emails; | |
246 profile.GetMultiInfo(EMAIL_ADDRESS, &emails); | |
247 | |
248 for (size_t i = 0; i < emails.size(); ++i) { | |
249 // Add the new email. | |
250 sql::Statement s(db->GetUniqueStatement( | |
251 "INSERT INTO autofill_profile_emails" | |
252 " (guid, email) " | |
253 "VALUES (?,?)")); | |
254 if (!s) { | |
255 NOTREACHED(); | |
256 return false; | |
257 } | |
258 s.BindString(0, profile.guid()); | |
259 s.BindString16(1, emails[i]); | |
260 | |
261 if (!s.Run()) { | |
262 NOTREACHED(); | |
263 return false; | |
264 } | |
265 } | |
266 return true; | |
267 } | |
268 | |
269 bool AddAutofillProfilePhones(const AutofillProfile& profile, | |
270 AutofillPhoneType phone_type, | |
271 sql::Connection* db) { | |
272 AutofillFieldType field_type; | |
273 if (phone_type == kAutofillPhoneNumber) { | |
274 field_type = PHONE_HOME_WHOLE_NUMBER; | |
275 } else if (phone_type == kAutofillFaxNumber) { | |
276 field_type = PHONE_FAX_WHOLE_NUMBER; | |
277 } else { | |
278 NOTREACHED(); | |
279 return false; | |
280 } | |
281 | |
282 std::vector<string16> numbers; | |
283 profile.GetMultiInfo(field_type, &numbers); | |
284 | |
285 for (size_t i = 0; i < numbers.size(); ++i) { | |
286 // Add the new number. | |
287 sql::Statement s(db->GetUniqueStatement( | |
288 "INSERT INTO autofill_profile_phones" | |
289 " (guid, type, number) " | |
290 "VALUES (?,?,?)")); | |
291 if (!s) { | |
292 NOTREACHED(); | |
293 return false; | |
294 } | |
295 s.BindString(0, profile.guid()); | |
296 s.BindInt(1, phone_type); | |
297 s.BindString16(2, numbers[i]); | |
298 | |
299 if (!s.Run()) { | |
300 NOTREACHED(); | |
301 return false; | |
302 } | |
303 } | |
304 return true; | |
305 } | |
306 | |
307 bool AddAutofillProfilePieces(const AutofillProfile& profile, | |
308 sql::Connection* db) { | |
309 if (!AddAutofillProfileNames(profile, db)) | |
310 return false; | |
311 | |
312 if (!AddAutofillProfileEmails(profile, db)) | |
313 return false; | |
314 | |
315 if (!AddAutofillProfilePhones(profile, kAutofillPhoneNumber, db)) | |
316 return false; | |
317 | |
318 if (!AddAutofillProfilePhones(profile, kAutofillFaxNumber, db)) | |
319 return false; | |
320 | |
321 return true; | |
322 } | |
323 | |
324 bool RemoveAutofillProfilePieces(const std::string& guid, sql::Connection* db) { | |
325 sql::Statement s1(db->GetUniqueStatement( | |
326 "DELETE FROM autofill_profile_names WHERE guid = ?")); | |
327 if (!s1) { | |
328 NOTREACHED() << "Statement prepare failed"; | |
329 return false; | |
330 } | |
331 | |
332 s1.BindString(0, guid); | |
333 if (!s1.Run()) | |
334 return false; | |
335 | |
336 sql::Statement s2(db->GetUniqueStatement( | |
337 "DELETE FROM autofill_profile_emails WHERE guid = ?")); | |
338 if (!s2) { | |
339 NOTREACHED() << "Statement prepare failed"; | |
340 return false; | |
341 } | |
342 | |
343 s2.BindString(0, guid); | |
344 if (!s2.Run()) | |
345 return false; | |
346 | |
347 sql::Statement s3(db->GetUniqueStatement( | |
348 "DELETE FROM autofill_profile_phones WHERE guid = ?")); | |
349 if (!s3) { | |
350 NOTREACHED() << "Statement prepare failed"; | |
351 return false; | |
352 } | |
353 | |
354 s3.BindString(0, guid); | |
355 return s3.Run(); | |
356 } | |
357 | |
358 } // namespace autofill_util | |
OLD | NEW |