OLD | NEW |
| (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/webdata/autofill/autofill_table.h" | |
6 | |
7 #include <algorithm> | |
8 #include <limits> | |
9 #include <map> | |
10 #include <set> | |
11 #include <string> | |
12 #include <vector> | |
13 | |
14 #include "base/guid.h" | |
15 #include "base/i18n/case_conversion.h" | |
16 #include "base/logging.h" | |
17 #include "base/strings/string_number_conversions.h" | |
18 #include "base/time.h" | |
19 #include "base/tuple.h" | |
20 #include "components/autofill/browser/autofill_country.h" | |
21 #include "components/autofill/browser/autofill_profile.h" | |
22 #include "components/autofill/browser/autofill_type.h" | |
23 #include "components/autofill/browser/credit_card.h" | |
24 #include "components/autofill/browser/personal_data_manager.h" | |
25 #include "components/autofill/common/form_field_data.h" | |
26 #include "components/webdata/autofill/autofill_change.h" | |
27 #include "components/webdata/autofill/autofill_entry.h" | |
28 #include "components/webdata/common/web_database.h" | |
29 #include "components/webdata/encryptor/encryptor.h" | |
30 #include "sql/statement.h" | |
31 #include "ui/base/l10n/l10n_util.h" | |
32 | |
33 using base::Time; | |
34 | |
35 namespace { | |
36 | |
37 typedef std::vector<Tuple3<int64, string16, string16> > AutofillElementList; | |
38 | |
39 // TODO(dhollowa): Find a common place for this. It is duplicated in | |
40 // personal_data_manager.cc. | |
41 template<typename T> | |
42 T* address_of(T& v) { | |
43 return &v; | |
44 } | |
45 | |
46 string16 LimitDataSize(const string16& data) { | |
47 if (data.size() > AutofillTable::kMaxDataLength) | |
48 return data.substr(0, AutofillTable::kMaxDataLength); | |
49 | |
50 return data; | |
51 } | |
52 | |
53 void BindAutofillProfileToStatement(const AutofillProfile& profile, | |
54 sql::Statement* s, | |
55 const std::string& app_locale) { | |
56 DCHECK(base::IsValidGUID(profile.guid())); | |
57 s->BindString(0, profile.guid()); | |
58 | |
59 string16 text = profile.GetRawInfo(COMPANY_NAME); | |
60 s->BindString16(1, LimitDataSize(text)); | |
61 text = profile.GetRawInfo(ADDRESS_HOME_LINE1); | |
62 s->BindString16(2, LimitDataSize(text)); | |
63 text = profile.GetRawInfo(ADDRESS_HOME_LINE2); | |
64 s->BindString16(3, LimitDataSize(text)); | |
65 text = profile.GetRawInfo(ADDRESS_HOME_CITY); | |
66 s->BindString16(4, LimitDataSize(text)); | |
67 text = profile.GetRawInfo(ADDRESS_HOME_STATE); | |
68 s->BindString16(5, LimitDataSize(text)); | |
69 text = profile.GetRawInfo(ADDRESS_HOME_ZIP); | |
70 s->BindString16(6, LimitDataSize(text)); | |
71 text = profile.GetInfo(ADDRESS_HOME_COUNTRY, app_locale); | |
72 s->BindString16(7, LimitDataSize(text)); | |
73 text = profile.GetRawInfo(ADDRESS_HOME_COUNTRY); | |
74 s->BindString16(8, LimitDataSize(text)); | |
75 s->BindInt64(9, Time::Now().ToTimeT()); | |
76 } | |
77 | |
78 AutofillProfile* AutofillProfileFromStatement(const sql::Statement& s, | |
79 const std::string& app_locale) { | |
80 AutofillProfile* profile = new AutofillProfile; | |
81 profile->set_guid(s.ColumnString(0)); | |
82 DCHECK(base::IsValidGUID(profile->guid())); | |
83 | |
84 profile->SetRawInfo(COMPANY_NAME, s.ColumnString16(1)); | |
85 profile->SetRawInfo(ADDRESS_HOME_LINE1, s.ColumnString16(2)); | |
86 profile->SetRawInfo(ADDRESS_HOME_LINE2, s.ColumnString16(3)); | |
87 profile->SetRawInfo(ADDRESS_HOME_CITY, s.ColumnString16(4)); | |
88 profile->SetRawInfo(ADDRESS_HOME_STATE, s.ColumnString16(5)); | |
89 profile->SetRawInfo(ADDRESS_HOME_ZIP, s.ColumnString16(6)); | |
90 // Intentionally skip column 7, which stores the localized country name. | |
91 profile->SetRawInfo(ADDRESS_HOME_COUNTRY, s.ColumnString16(8)); | |
92 // Intentionally skip column 9, which stores the profile's modification date. | |
93 | |
94 return profile; | |
95 } | |
96 | |
97 void BindCreditCardToStatement(const CreditCard& credit_card, | |
98 sql::Statement* s) { | |
99 DCHECK(base::IsValidGUID(credit_card.guid())); | |
100 s->BindString(0, credit_card.guid()); | |
101 | |
102 string16 text = credit_card.GetRawInfo(CREDIT_CARD_NAME); | |
103 s->BindString16(1, LimitDataSize(text)); | |
104 text = credit_card.GetRawInfo(CREDIT_CARD_EXP_MONTH); | |
105 s->BindString16(2, LimitDataSize(text)); | |
106 text = credit_card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR); | |
107 s->BindString16(3, LimitDataSize(text)); | |
108 text = credit_card.GetRawInfo(CREDIT_CARD_NUMBER); | |
109 std::string encrypted_data; | |
110 Encryptor::EncryptString16(text, &encrypted_data); | |
111 s->BindBlob(4, encrypted_data.data(), | |
112 static_cast<int>(encrypted_data.length())); | |
113 s->BindInt64(5, Time::Now().ToTimeT()); | |
114 } | |
115 | |
116 CreditCard* CreditCardFromStatement(const sql::Statement& s) { | |
117 CreditCard* credit_card = new CreditCard; | |
118 | |
119 credit_card->set_guid(s.ColumnString(0)); | |
120 DCHECK(base::IsValidGUID(credit_card->guid())); | |
121 | |
122 credit_card->SetRawInfo(CREDIT_CARD_NAME, s.ColumnString16(1)); | |
123 credit_card->SetRawInfo(CREDIT_CARD_EXP_MONTH, s.ColumnString16(2)); | |
124 credit_card->SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, s.ColumnString16(3)); | |
125 int encrypted_number_len = s.ColumnByteLength(4); | |
126 string16 credit_card_number; | |
127 if (encrypted_number_len) { | |
128 std::string encrypted_number; | |
129 encrypted_number.resize(encrypted_number_len); | |
130 memcpy(&encrypted_number[0], s.ColumnBlob(4), encrypted_number_len); | |
131 Encryptor::DecryptString16(encrypted_number, &credit_card_number); | |
132 } | |
133 credit_card->SetRawInfo(CREDIT_CARD_NUMBER, credit_card_number); | |
134 // Intentionally skip column 5, which stores the modification date. | |
135 | |
136 return credit_card; | |
137 } | |
138 | |
139 bool AddAutofillProfileNamesToProfile(sql::Connection* db, | |
140 AutofillProfile* profile) { | |
141 sql::Statement s(db->GetUniqueStatement( | |
142 "SELECT guid, first_name, middle_name, last_name " | |
143 "FROM autofill_profile_names " | |
144 "WHERE guid=?")); | |
145 s.BindString(0, profile->guid()); | |
146 | |
147 if (!s.is_valid()) | |
148 return false; | |
149 | |
150 std::vector<string16> first_names; | |
151 std::vector<string16> middle_names; | |
152 std::vector<string16> last_names; | |
153 while (s.Step()) { | |
154 DCHECK_EQ(profile->guid(), s.ColumnString(0)); | |
155 first_names.push_back(s.ColumnString16(1)); | |
156 middle_names.push_back(s.ColumnString16(2)); | |
157 last_names.push_back(s.ColumnString16(3)); | |
158 } | |
159 if (!s.Succeeded()) | |
160 return false; | |
161 | |
162 profile->SetRawMultiInfo(NAME_FIRST, first_names); | |
163 profile->SetRawMultiInfo(NAME_MIDDLE, middle_names); | |
164 profile->SetRawMultiInfo(NAME_LAST, last_names); | |
165 return true; | |
166 } | |
167 | |
168 bool AddAutofillProfileEmailsToProfile(sql::Connection* db, | |
169 AutofillProfile* profile) { | |
170 sql::Statement s(db->GetUniqueStatement( | |
171 "SELECT guid, email " | |
172 "FROM autofill_profile_emails " | |
173 "WHERE guid=?")); | |
174 s.BindString(0, profile->guid()); | |
175 | |
176 if (!s.is_valid()) | |
177 return false; | |
178 | |
179 std::vector<string16> emails; | |
180 while (s.Step()) { | |
181 DCHECK_EQ(profile->guid(), s.ColumnString(0)); | |
182 emails.push_back(s.ColumnString16(1)); | |
183 } | |
184 if (!s.Succeeded()) | |
185 return false; | |
186 | |
187 profile->SetRawMultiInfo(EMAIL_ADDRESS, emails); | |
188 return true; | |
189 } | |
190 | |
191 bool AddAutofillProfilePhonesToProfile(sql::Connection* db, | |
192 AutofillProfile* profile) { | |
193 sql::Statement s(db->GetUniqueStatement( | |
194 "SELECT guid, type, number " | |
195 "FROM autofill_profile_phones " | |
196 "WHERE guid=? AND type=?")); | |
197 | |
198 // Value used to be either [(0, phone), (1, fax)] but fax has been removed. | |
199 s.BindString(0, profile->guid()); | |
200 s.BindInt(1, 0); | |
201 | |
202 if (!s.is_valid()) | |
203 return false; | |
204 | |
205 std::vector<string16> numbers; | |
206 while (s.Step()) { | |
207 DCHECK_EQ(profile->guid(), s.ColumnString(0)); | |
208 numbers.push_back(s.ColumnString16(2)); | |
209 } | |
210 if (!s.Succeeded()) | |
211 return false; | |
212 | |
213 profile->SetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, numbers); | |
214 return true; | |
215 } | |
216 | |
217 bool AddAutofillProfileNames(const AutofillProfile& profile, | |
218 sql::Connection* db) { | |
219 std::vector<string16> first_names; | |
220 profile.GetRawMultiInfo(NAME_FIRST, &first_names); | |
221 std::vector<string16> middle_names; | |
222 profile.GetRawMultiInfo(NAME_MIDDLE, &middle_names); | |
223 std::vector<string16> last_names; | |
224 profile.GetRawMultiInfo(NAME_LAST, &last_names); | |
225 DCHECK_EQ(first_names.size(), middle_names.size()); | |
226 DCHECK_EQ(middle_names.size(), last_names.size()); | |
227 | |
228 for (size_t i = 0; i < first_names.size(); ++i) { | |
229 // Add the new name. | |
230 sql::Statement s(db->GetUniqueStatement( | |
231 "INSERT INTO autofill_profile_names" | |
232 " (guid, first_name, middle_name, last_name) " | |
233 "VALUES (?,?,?,?)")); | |
234 s.BindString(0, profile.guid()); | |
235 s.BindString16(1, first_names[i]); | |
236 s.BindString16(2, middle_names[i]); | |
237 s.BindString16(3, last_names[i]); | |
238 | |
239 if (!s.Run()) | |
240 return false; | |
241 } | |
242 return true; | |
243 } | |
244 | |
245 bool AddAutofillProfileEmails(const AutofillProfile& profile, | |
246 sql::Connection* db) { | |
247 std::vector<string16> emails; | |
248 profile.GetRawMultiInfo(EMAIL_ADDRESS, &emails); | |
249 | |
250 for (size_t i = 0; i < emails.size(); ++i) { | |
251 // Add the new email. | |
252 sql::Statement s(db->GetUniqueStatement( | |
253 "INSERT INTO autofill_profile_emails" | |
254 " (guid, email) " | |
255 "VALUES (?,?)")); | |
256 s.BindString(0, profile.guid()); | |
257 s.BindString16(1, emails[i]); | |
258 | |
259 if (!s.Run()) | |
260 return false; | |
261 } | |
262 | |
263 return true; | |
264 } | |
265 | |
266 bool AddAutofillProfilePhones(const AutofillProfile& profile, | |
267 sql::Connection* db) { | |
268 std::vector<string16> numbers; | |
269 profile.GetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, &numbers); | |
270 | |
271 for (size_t i = 0; i < numbers.size(); ++i) { | |
272 // Add the new number. | |
273 sql::Statement s(db->GetUniqueStatement( | |
274 "INSERT INTO autofill_profile_phones" | |
275 " (guid, type, number) " | |
276 "VALUES (?,?,?)")); | |
277 s.BindString(0, profile.guid()); | |
278 // Value used to be either [(0, phone), (1, fax)] but fax has been removed. | |
279 s.BindInt(1, 0); | |
280 s.BindString16(2, numbers[i]); | |
281 | |
282 if (!s.Run()) | |
283 return false; | |
284 } | |
285 | |
286 return true; | |
287 } | |
288 | |
289 bool AddAutofillProfilePieces(const AutofillProfile& profile, | |
290 sql::Connection* db) { | |
291 if (!AddAutofillProfileNames(profile, db)) | |
292 return false; | |
293 | |
294 if (!AddAutofillProfileEmails(profile, db)) | |
295 return false; | |
296 | |
297 if (!AddAutofillProfilePhones(profile, db)) | |
298 return false; | |
299 | |
300 return true; | |
301 } | |
302 | |
303 bool RemoveAutofillProfilePieces(const std::string& guid, sql::Connection* db) { | |
304 sql::Statement s1(db->GetUniqueStatement( | |
305 "DELETE FROM autofill_profile_names WHERE guid = ?")); | |
306 s1.BindString(0, guid); | |
307 | |
308 if (!s1.Run()) | |
309 return false; | |
310 | |
311 sql::Statement s2(db->GetUniqueStatement( | |
312 "DELETE FROM autofill_profile_emails WHERE guid = ?")); | |
313 s2.BindString(0, guid); | |
314 | |
315 if (!s2.Run()) | |
316 return false; | |
317 | |
318 sql::Statement s3(db->GetUniqueStatement( | |
319 "DELETE FROM autofill_profile_phones WHERE guid = ?")); | |
320 s3.BindString(0, guid); | |
321 | |
322 return s3.Run(); | |
323 } | |
324 | |
325 int table_key = 0; | |
326 | |
327 WebDatabaseTable::TypeKey GetKey() { | |
328 return reinterpret_cast<void*>(&table_key); | |
329 } | |
330 | |
331 } // namespace | |
332 | |
333 // The maximum length allowed for form data. | |
334 const size_t AutofillTable::kMaxDataLength = 1024; | |
335 | |
336 AutofillTable::AutofillTable(const std::string& app_locale) | |
337 : app_locale_(app_locale) { | |
338 } | |
339 | |
340 AutofillTable::~AutofillTable() { | |
341 } | |
342 | |
343 AutofillTable* AutofillTable::FromWebDatabase(WebDatabase* db) { | |
344 return static_cast<AutofillTable*>(db->GetTable(GetKey())); | |
345 } | |
346 | |
347 WebDatabaseTable::TypeKey AutofillTable::GetTypeKey() const { | |
348 return GetKey(); | |
349 } | |
350 | |
351 bool AutofillTable::Init(sql::Connection* db, sql::MetaTable* meta_table) { | |
352 WebDatabaseTable::Init(db, meta_table); | |
353 return (InitMainTable() && InitCreditCardsTable() && InitDatesTable() && | |
354 InitProfilesTable() && InitProfileNamesTable() && | |
355 InitProfileEmailsTable() && InitProfilePhonesTable() && | |
356 InitProfileTrashTable()); | |
357 } | |
358 | |
359 bool AutofillTable::IsSyncable() { | |
360 return true; | |
361 } | |
362 | |
363 bool AutofillTable::MigrateToVersion(int version, | |
364 bool* update_compatible_version) { | |
365 // Migrate if necessary. | |
366 switch (version) { | |
367 case 22: | |
368 return ClearAutofillEmptyValueElements(); | |
369 case 23: | |
370 return MigrateToVersion23AddCardNumberEncryptedColumn(); | |
371 case 24: | |
372 return MigrateToVersion24CleanupOversizedStringFields(); | |
373 case 27: | |
374 *update_compatible_version = true; | |
375 return MigrateToVersion27UpdateLegacyCreditCards(); | |
376 case 30: | |
377 *update_compatible_version = true; | |
378 return MigrateToVersion30AddDateModifed(); | |
379 case 31: | |
380 *update_compatible_version = true; | |
381 return MigrateToVersion31AddGUIDToCreditCardsAndProfiles(); | |
382 case 32: | |
383 *update_compatible_version = true; | |
384 return MigrateToVersion32UpdateProfilesAndCreditCards(); | |
385 case 33: | |
386 *update_compatible_version = true; | |
387 return MigrateToVersion33ProfilesBasedOnFirstName(); | |
388 case 34: | |
389 *update_compatible_version = true; | |
390 return MigrateToVersion34ProfilesBasedOnCountryCode(); | |
391 case 35: | |
392 *update_compatible_version = true; | |
393 return MigrateToVersion35GreatBritainCountryCodes(); | |
394 // Combine migrations 36 and 37. This is due to enhancements to the merge | |
395 // step when migrating profiles. The original migration from 35 to 36 did | |
396 // not merge profiles with identical addresses, but the migration from 36 to | |
397 // 37 does. The step from 35 to 36 should only happen on the Chrome 12 dev | |
398 // channel. Chrome 12 beta and release users will jump from 35 to 37 | |
399 // directly getting the full benefits of the multi-valued merge as well as | |
400 // the culling of bad data. | |
401 case 37: | |
402 *update_compatible_version = true; | |
403 return MigrateToVersion37MergeAndCullOlderProfiles(); | |
404 } | |
405 return true; | |
406 } | |
407 | |
408 bool AutofillTable::AddFormFieldValues( | |
409 const std::vector<FormFieldData>& elements, | |
410 std::vector<AutofillChange>* changes) { | |
411 return AddFormFieldValuesTime(elements, changes, Time::Now()); | |
412 } | |
413 | |
414 bool AutofillTable::AddFormFieldValue(const FormFieldData& element, | |
415 std::vector<AutofillChange>* changes) { | |
416 return AddFormFieldValueTime(element, changes, Time::Now()); | |
417 } | |
418 | |
419 bool AutofillTable::GetFormValuesForElementName(const string16& name, | |
420 const string16& prefix, | |
421 std::vector<string16>* values, | |
422 int limit) { | |
423 DCHECK(values); | |
424 sql::Statement s; | |
425 | |
426 if (prefix.empty()) { | |
427 s.Assign(db_->GetUniqueStatement( | |
428 "SELECT value FROM autofill " | |
429 "WHERE name = ? " | |
430 "ORDER BY count DESC " | |
431 "LIMIT ?")); | |
432 s.BindString16(0, name); | |
433 s.BindInt(1, limit); | |
434 } else { | |
435 string16 prefix_lower = base::i18n::ToLower(prefix); | |
436 string16 next_prefix = prefix_lower; | |
437 next_prefix[next_prefix.length() - 1]++; | |
438 | |
439 s.Assign(db_->GetUniqueStatement( | |
440 "SELECT value FROM autofill " | |
441 "WHERE name = ? AND " | |
442 "value_lower >= ? AND " | |
443 "value_lower < ? " | |
444 "ORDER BY count DESC " | |
445 "LIMIT ?")); | |
446 s.BindString16(0, name); | |
447 s.BindString16(1, prefix_lower); | |
448 s.BindString16(2, next_prefix); | |
449 s.BindInt(3, limit); | |
450 } | |
451 | |
452 values->clear(); | |
453 while (s.Step()) | |
454 values->push_back(s.ColumnString16(0)); | |
455 return s.Succeeded(); | |
456 } | |
457 | |
458 bool AutofillTable::RemoveFormElementsAddedBetween( | |
459 const Time& delete_begin, | |
460 const Time& delete_end, | |
461 std::vector<AutofillChange>* changes) { | |
462 DCHECK(changes); | |
463 // Query for the pair_id, name, and value of all form elements that | |
464 // were used between the given times. | |
465 sql::Statement s(db_->GetUniqueStatement( | |
466 "SELECT DISTINCT a.pair_id, a.name, a.value " | |
467 "FROM autofill_dates ad JOIN autofill a ON ad.pair_id = a.pair_id " | |
468 "WHERE ad.date_created >= ? AND ad.date_created < ?")); | |
469 s.BindInt64(0, delete_begin.ToTimeT()); | |
470 s.BindInt64(1, | |
471 (delete_end.is_null() || delete_end == base::Time::Max()) ? | |
472 std::numeric_limits<int64>::max() : | |
473 delete_end.ToTimeT()); | |
474 | |
475 AutofillElementList elements; | |
476 while (s.Step()) { | |
477 elements.push_back(MakeTuple(s.ColumnInt64(0), | |
478 s.ColumnString16(1), | |
479 s.ColumnString16(2))); | |
480 } | |
481 if (!s.Succeeded()) | |
482 return false; | |
483 | |
484 for (AutofillElementList::iterator itr = elements.begin(); | |
485 itr != elements.end(); ++itr) { | |
486 int how_many = 0; | |
487 if (!RemoveFormElementForTimeRange(itr->a, delete_begin, delete_end, | |
488 &how_many)) { | |
489 return false; | |
490 } | |
491 // We store at most 2 time stamps. If we remove both of them we should | |
492 // delete the corresponding data. If we delete only one it could still be | |
493 // the last timestamp for the data, so check how many timestamps do remain. | |
494 bool should_remove = (CountTimestampsData(itr->a) == 0); | |
495 if (should_remove) { | |
496 if (!RemoveFormElementForID(itr->a)) | |
497 return false; | |
498 } else { | |
499 if (!AddToCountOfFormElement(itr->a, -how_many)) | |
500 return false; | |
501 } | |
502 AutofillChange::Type change_type = | |
503 should_remove ? AutofillChange::REMOVE : AutofillChange::UPDATE; | |
504 changes->push_back(AutofillChange(change_type, | |
505 AutofillKey(itr->b, itr->c))); | |
506 } | |
507 | |
508 return true; | |
509 } | |
510 | |
511 bool AutofillTable::RemoveExpiredFormElements( | |
512 std::vector<AutofillChange>* changes) { | |
513 DCHECK(changes); | |
514 | |
515 base::Time delete_end = AutofillEntry::ExpirationTime(); | |
516 // Query for the pair_id, name, and value of all form elements that | |
517 // were last used before the |delete_end|. | |
518 sql::Statement select_for_delete(db_->GetUniqueStatement( | |
519 "SELECT DISTINCT pair_id, name, value " | |
520 "FROM autofill WHERE pair_id NOT IN " | |
521 "(SELECT DISTINCT pair_id " | |
522 "FROM autofill_dates WHERE date_created >= ?)")); | |
523 select_for_delete.BindInt64(0, delete_end.ToTimeT()); | |
524 AutofillElementList entries_to_delete; | |
525 while (select_for_delete.Step()) { | |
526 entries_to_delete.push_back(MakeTuple(select_for_delete.ColumnInt64(0), | |
527 select_for_delete.ColumnString16(1), | |
528 select_for_delete.ColumnString16(2))); | |
529 } | |
530 | |
531 if (!select_for_delete.Succeeded()) | |
532 return false; | |
533 | |
534 sql::Statement delete_data_statement(db_->GetUniqueStatement( | |
535 "DELETE FROM autofill WHERE pair_id NOT IN (" | |
536 "SELECT pair_id FROM autofill_dates WHERE date_created >= ?)")); | |
537 delete_data_statement.BindInt64(0, delete_end.ToTimeT()); | |
538 if (!delete_data_statement.Run()) | |
539 return false; | |
540 | |
541 sql::Statement delete_times_statement(db_->GetUniqueStatement( | |
542 "DELETE FROM autofill_dates WHERE pair_id NOT IN (" | |
543 "SELECT pair_id FROM autofill_dates WHERE date_created >= ?)")); | |
544 delete_times_statement.BindInt64(0, delete_end.ToTimeT()); | |
545 if (!delete_times_statement.Run()) | |
546 return false; | |
547 | |
548 // Cull remaining entries' timestamps. | |
549 std::vector<AutofillEntry> entries; | |
550 if (!GetAllAutofillEntries(&entries)) | |
551 return false; | |
552 sql::Statement cull_date_entry(db_->GetUniqueStatement( | |
553 "DELETE FROM autofill_dates " | |
554 "WHERE pair_id == (SELECT pair_id FROM autofill " | |
555 "WHERE name = ? and value = ?)" | |
556 "AND date_created != ? AND date_created != ?")); | |
557 for (size_t i = 0; i < entries.size(); ++i) { | |
558 cull_date_entry.BindString16(0, entries[i].key().name()); | |
559 cull_date_entry.BindString16(1, entries[i].key().value()); | |
560 cull_date_entry.BindInt64(2, | |
561 entries[i].timestamps().empty() ? 0 : | |
562 entries[i].timestamps().front().ToTimeT()); | |
563 cull_date_entry.BindInt64(3, | |
564 entries[i].timestamps().empty() ? 0 : | |
565 entries[i].timestamps().back().ToTimeT()); | |
566 if (!cull_date_entry.Run()) | |
567 return false; | |
568 cull_date_entry.Reset(true); | |
569 } | |
570 | |
571 changes->clear(); | |
572 changes->reserve(entries_to_delete.size()); | |
573 | |
574 for (AutofillElementList::iterator it = entries_to_delete.begin(); | |
575 it != entries_to_delete.end(); ++it) { | |
576 changes->push_back(AutofillChange( | |
577 AutofillChange::REMOVE, AutofillKey(it->b, it->c))); | |
578 } | |
579 return true; | |
580 } | |
581 | |
582 bool AutofillTable::RemoveFormElementForTimeRange(int64 pair_id, | |
583 const Time& delete_begin, | |
584 const Time& delete_end, | |
585 int* how_many) { | |
586 sql::Statement s(db_->GetUniqueStatement( | |
587 "DELETE FROM autofill_dates WHERE pair_id = ? AND " | |
588 "date_created >= ? AND date_created < ?")); | |
589 s.BindInt64(0, pair_id); | |
590 s.BindInt64(1, delete_begin.is_null() ? 0 : delete_begin.ToTimeT()); | |
591 s.BindInt64(2, delete_end.is_null() ? std::numeric_limits<int64>::max() : | |
592 delete_end.ToTimeT()); | |
593 | |
594 bool result = s.Run(); | |
595 if (how_many) | |
596 *how_many = db_->GetLastChangeCount(); | |
597 | |
598 return result; | |
599 } | |
600 | |
601 int AutofillTable::CountTimestampsData(int64 pair_id) { | |
602 sql::Statement s(db_->GetUniqueStatement( | |
603 "SELECT COUNT(*) FROM autofill_dates WHERE pair_id = ?")); | |
604 s.BindInt64(0, pair_id); | |
605 if (!s.Step()) { | |
606 NOTREACHED(); | |
607 return 0; | |
608 } else { | |
609 return s.ColumnInt(0); | |
610 } | |
611 } | |
612 | |
613 bool AutofillTable::AddToCountOfFormElement(int64 pair_id, | |
614 int delta) { | |
615 int count = 0; | |
616 | |
617 if (!GetCountOfFormElement(pair_id, &count)) | |
618 return false; | |
619 | |
620 if (count + delta == 0) { | |
621 // Should remove the element earlier in the code. | |
622 NOTREACHED(); | |
623 return false; | |
624 } else { | |
625 if (!SetCountOfFormElement(pair_id, count + delta)) | |
626 return false; | |
627 } | |
628 return true; | |
629 } | |
630 | |
631 bool AutofillTable::GetIDAndCountOfFormElement( | |
632 const FormFieldData& element, | |
633 int64* pair_id, | |
634 int* count) { | |
635 DCHECK(pair_id); | |
636 DCHECK(count); | |
637 | |
638 sql::Statement s(db_->GetUniqueStatement( | |
639 "SELECT pair_id, count FROM autofill " | |
640 "WHERE name = ? AND value = ?")); | |
641 s.BindString16(0, element.name); | |
642 s.BindString16(1, element.value); | |
643 | |
644 if (!s.is_valid()) | |
645 return false; | |
646 | |
647 *pair_id = 0; | |
648 *count = 0; | |
649 | |
650 if (s.Step()) { | |
651 *pair_id = s.ColumnInt64(0); | |
652 *count = s.ColumnInt(1); | |
653 } | |
654 | |
655 return true; | |
656 } | |
657 | |
658 bool AutofillTable::GetCountOfFormElement(int64 pair_id, int* count) { | |
659 DCHECK(count); | |
660 sql::Statement s(db_->GetUniqueStatement( | |
661 "SELECT count FROM autofill WHERE pair_id = ?")); | |
662 s.BindInt64(0, pair_id); | |
663 | |
664 if (s.Step()) { | |
665 *count = s.ColumnInt(0); | |
666 return true; | |
667 } | |
668 return false; | |
669 } | |
670 | |
671 bool AutofillTable::SetCountOfFormElement(int64 pair_id, int count) { | |
672 sql::Statement s(db_->GetUniqueStatement( | |
673 "UPDATE autofill SET count = ? WHERE pair_id = ?")); | |
674 s.BindInt(0, count); | |
675 s.BindInt64(1, pair_id); | |
676 | |
677 return s.Run(); | |
678 } | |
679 | |
680 bool AutofillTable::InsertFormElement(const FormFieldData& element, | |
681 int64* pair_id) { | |
682 DCHECK(pair_id); | |
683 sql::Statement s(db_->GetUniqueStatement( | |
684 "INSERT INTO autofill (name, value, value_lower) VALUES (?,?,?)")); | |
685 s.BindString16(0, element.name); | |
686 s.BindString16(1, element.value); | |
687 s.BindString16(2, base::i18n::ToLower(element.value)); | |
688 | |
689 if (!s.Run()) | |
690 return false; | |
691 | |
692 *pair_id = db_->GetLastInsertRowId(); | |
693 return true; | |
694 } | |
695 | |
696 bool AutofillTable::InsertPairIDAndDate(int64 pair_id, | |
697 const Time& date_created) { | |
698 sql::Statement s(db_->GetUniqueStatement( | |
699 "INSERT INTO autofill_dates " | |
700 "(pair_id, date_created) VALUES (?, ?)")); | |
701 s.BindInt64(0, pair_id); | |
702 s.BindInt64(1, date_created.ToTimeT()); | |
703 | |
704 return s.Run(); | |
705 } | |
706 | |
707 bool AutofillTable::DeleteLastAccess(int64 pair_id) { | |
708 // Inner SELECT selects the newest |date_created| for a given |pair_id|. | |
709 // DELETE deletes only that entry. | |
710 sql::Statement s(db_->GetUniqueStatement( | |
711 "DELETE FROM autofill_dates WHERE pair_id = ? and date_created IN " | |
712 "(SELECT date_created FROM autofill_dates WHERE pair_id = ? " | |
713 "ORDER BY date_created DESC LIMIT 1)")); | |
714 s.BindInt64(0, pair_id); | |
715 s.BindInt64(1, pair_id); | |
716 | |
717 return s.Run(); | |
718 } | |
719 | |
720 bool AutofillTable::AddFormFieldValuesTime( | |
721 const std::vector<FormFieldData>& elements, | |
722 std::vector<AutofillChange>* changes, | |
723 Time time) { | |
724 // Only add one new entry for each unique element name. Use |seen_names| to | |
725 // track this. Add up to |kMaximumUniqueNames| unique entries per form. | |
726 const size_t kMaximumUniqueNames = 256; | |
727 std::set<string16> seen_names; | |
728 bool result = true; | |
729 for (std::vector<FormFieldData>::const_iterator itr = elements.begin(); | |
730 itr != elements.end(); ++itr) { | |
731 if (seen_names.size() >= kMaximumUniqueNames) | |
732 break; | |
733 if (seen_names.find(itr->name) != seen_names.end()) | |
734 continue; | |
735 result = result && AddFormFieldValueTime(*itr, changes, time); | |
736 seen_names.insert(itr->name); | |
737 } | |
738 return result; | |
739 } | |
740 | |
741 bool AutofillTable::ClearAutofillEmptyValueElements() { | |
742 sql::Statement s(db_->GetUniqueStatement( | |
743 "SELECT pair_id FROM autofill WHERE TRIM(value)= \"\"")); | |
744 if (!s.is_valid()) | |
745 return false; | |
746 | |
747 std::set<int64> ids; | |
748 while (s.Step()) | |
749 ids.insert(s.ColumnInt64(0)); | |
750 if (!s.Succeeded()) | |
751 return false; | |
752 | |
753 bool success = true; | |
754 for (std::set<int64>::const_iterator iter = ids.begin(); iter != ids.end(); | |
755 ++iter) { | |
756 if (!RemoveFormElementForID(*iter)) | |
757 success = false; | |
758 } | |
759 | |
760 return success; | |
761 } | |
762 | |
763 bool AutofillTable::GetAllAutofillEntries(std::vector<AutofillEntry>* entries) { | |
764 DCHECK(entries); | |
765 sql::Statement s(db_->GetUniqueStatement( | |
766 "SELECT name, value, date_created FROM autofill a JOIN " | |
767 "autofill_dates ad ON a.pair_id=ad.pair_id")); | |
768 | |
769 bool first_entry = true; | |
770 AutofillKey* current_key_ptr = NULL; | |
771 std::vector<Time>* timestamps_ptr = NULL; | |
772 string16 name, value; | |
773 Time time; | |
774 while (s.Step()) { | |
775 name = s.ColumnString16(0); | |
776 value = s.ColumnString16(1); | |
777 time = Time::FromTimeT(s.ColumnInt64(2)); | |
778 | |
779 if (first_entry) { | |
780 current_key_ptr = new AutofillKey(name, value); | |
781 | |
782 timestamps_ptr = new std::vector<Time>; | |
783 timestamps_ptr->push_back(time); | |
784 | |
785 first_entry = false; | |
786 } else { | |
787 // we've encountered the next entry | |
788 if (current_key_ptr->name().compare(name) != 0 || | |
789 current_key_ptr->value().compare(value) != 0) { | |
790 AutofillEntry entry(*current_key_ptr, *timestamps_ptr); | |
791 entries->push_back(entry); | |
792 | |
793 delete current_key_ptr; | |
794 delete timestamps_ptr; | |
795 | |
796 current_key_ptr = new AutofillKey(name, value); | |
797 timestamps_ptr = new std::vector<Time>; | |
798 } | |
799 timestamps_ptr->push_back(time); | |
800 } | |
801 } | |
802 | |
803 // If there is at least one result returned, first_entry will be false. | |
804 // For this case we need to do a final cleanup step. | |
805 if (!first_entry) { | |
806 AutofillEntry entry(*current_key_ptr, *timestamps_ptr); | |
807 entries->push_back(entry); | |
808 delete current_key_ptr; | |
809 delete timestamps_ptr; | |
810 } | |
811 | |
812 return s.Succeeded(); | |
813 } | |
814 | |
815 bool AutofillTable::GetAutofillTimestamps(const string16& name, | |
816 const string16& value, | |
817 std::vector<Time>* timestamps) { | |
818 DCHECK(timestamps); | |
819 sql::Statement s(db_->GetUniqueStatement( | |
820 "SELECT date_created FROM autofill a JOIN " | |
821 "autofill_dates ad ON a.pair_id=ad.pair_id " | |
822 "WHERE a.name = ? AND a.value = ?")); | |
823 s.BindString16(0, name); | |
824 s.BindString16(1, value); | |
825 | |
826 while (s.Step()) | |
827 timestamps->push_back(Time::FromTimeT(s.ColumnInt64(0))); | |
828 | |
829 return s.Succeeded(); | |
830 } | |
831 | |
832 bool AutofillTable::UpdateAutofillEntries( | |
833 const std::vector<AutofillEntry>& entries) { | |
834 if (!entries.size()) | |
835 return true; | |
836 | |
837 // Remove all existing entries. | |
838 for (size_t i = 0; i < entries.size(); i++) { | |
839 std::string sql = "SELECT pair_id FROM autofill " | |
840 "WHERE name = ? AND value = ?"; | |
841 sql::Statement s(db_->GetUniqueStatement(sql.c_str())); | |
842 s.BindString16(0, entries[i].key().name()); | |
843 s.BindString16(1, entries[i].key().value()); | |
844 | |
845 if (!s.is_valid()) | |
846 return false; | |
847 | |
848 if (s.Step()) { | |
849 if (!RemoveFormElementForID(s.ColumnInt64(0))) | |
850 return false; | |
851 } | |
852 } | |
853 | |
854 // Insert all the supplied autofill entries. | |
855 for (size_t i = 0; i < entries.size(); i++) { | |
856 if (!InsertAutofillEntry(entries[i])) | |
857 return false; | |
858 } | |
859 | |
860 return true; | |
861 } | |
862 | |
863 bool AutofillTable::InsertAutofillEntry(const AutofillEntry& entry) { | |
864 std::string sql = "INSERT INTO autofill (name, value, value_lower, count) " | |
865 "VALUES (?, ?, ?, ?)"; | |
866 sql::Statement s(db_->GetUniqueStatement(sql.c_str())); | |
867 s.BindString16(0, entry.key().name()); | |
868 s.BindString16(1, entry.key().value()); | |
869 s.BindString16(2, base::i18n::ToLower(entry.key().value())); | |
870 s.BindInt(3, entry.timestamps().size()); | |
871 | |
872 if (!s.Run()) | |
873 return false; | |
874 | |
875 int64 pair_id = db_->GetLastInsertRowId(); | |
876 for (size_t i = 0; i < entry.timestamps().size(); i++) { | |
877 if (!InsertPairIDAndDate(pair_id, entry.timestamps()[i])) | |
878 return false; | |
879 } | |
880 | |
881 return true; | |
882 } | |
883 | |
884 bool AutofillTable::AddFormFieldValueTime(const FormFieldData& element, | |
885 std::vector<AutofillChange>* changes, | |
886 Time time) { | |
887 int count = 0; | |
888 int64 pair_id; | |
889 | |
890 if (!GetIDAndCountOfFormElement(element, &pair_id, &count)) | |
891 return false; | |
892 | |
893 if (count == 0 && !InsertFormElement(element, &pair_id)) | |
894 return false; | |
895 | |
896 if (!SetCountOfFormElement(pair_id, count + 1)) | |
897 return false; | |
898 | |
899 // If we already have more than 2 times delete last one, before adding new | |
900 // one. | |
901 if (count >= 2 && !DeleteLastAccess(pair_id)) | |
902 return false; | |
903 | |
904 if (!InsertPairIDAndDate(pair_id, time)) | |
905 return false; | |
906 | |
907 AutofillChange::Type change_type = | |
908 count == 0 ? AutofillChange::ADD : AutofillChange::UPDATE; | |
909 changes->push_back( | |
910 AutofillChange(change_type, | |
911 AutofillKey(element.name, element.value))); | |
912 return true; | |
913 } | |
914 | |
915 | |
916 bool AutofillTable::RemoveFormElement(const string16& name, | |
917 const string16& value) { | |
918 // Find the id for that pair. | |
919 sql::Statement s(db_->GetUniqueStatement( | |
920 "SELECT pair_id FROM autofill WHERE name = ? AND value= ?")); | |
921 s.BindString16(0, name); | |
922 s.BindString16(1, value); | |
923 | |
924 if (s.Step()) | |
925 return RemoveFormElementForID(s.ColumnInt64(0)); | |
926 return false; | |
927 } | |
928 | |
929 bool AutofillTable::AddAutofillProfile(const AutofillProfile& profile) { | |
930 if (IsAutofillGUIDInTrash(profile.guid())) | |
931 return true; | |
932 | |
933 sql::Statement s(db_->GetUniqueStatement( | |
934 "INSERT INTO autofill_profiles" | |
935 "(guid, company_name, address_line_1, address_line_2, city, state," | |
936 " zipcode, country, country_code, date_modified)" | |
937 "VALUES (?,?,?,?,?,?,?,?,?,?)")); | |
938 BindAutofillProfileToStatement(profile, &s, app_locale_); | |
939 | |
940 if (!s.Run()) | |
941 return false; | |
942 | |
943 return AddAutofillProfilePieces(profile, db_); | |
944 } | |
945 | |
946 bool AutofillTable::GetAutofillProfile(const std::string& guid, | |
947 AutofillProfile** profile) { | |
948 DCHECK(base::IsValidGUID(guid)); | |
949 DCHECK(profile); | |
950 sql::Statement s(db_->GetUniqueStatement( | |
951 "SELECT guid, company_name, address_line_1, address_line_2, city, state," | |
952 " zipcode, country, country_code, date_modified " | |
953 "FROM autofill_profiles " | |
954 "WHERE guid=?")); | |
955 s.BindString(0, guid); | |
956 | |
957 if (!s.Step()) | |
958 return false; | |
959 | |
960 scoped_ptr<AutofillProfile> p(AutofillProfileFromStatement(s, app_locale_)); | |
961 | |
962 // Get associated name info. | |
963 AddAutofillProfileNamesToProfile(db_, p.get()); | |
964 | |
965 // Get associated email info. | |
966 AddAutofillProfileEmailsToProfile(db_, p.get()); | |
967 | |
968 // Get associated phone info. | |
969 AddAutofillProfilePhonesToProfile(db_, p.get()); | |
970 | |
971 *profile = p.release(); | |
972 return true; | |
973 } | |
974 | |
975 bool AutofillTable::GetAutofillProfiles( | |
976 std::vector<AutofillProfile*>* profiles) { | |
977 DCHECK(profiles); | |
978 profiles->clear(); | |
979 | |
980 sql::Statement s(db_->GetUniqueStatement( | |
981 "SELECT guid " | |
982 "FROM autofill_profiles")); | |
983 | |
984 while (s.Step()) { | |
985 std::string guid = s.ColumnString(0); | |
986 AutofillProfile* profile = NULL; | |
987 if (!GetAutofillProfile(guid, &profile)) | |
988 return false; | |
989 profiles->push_back(profile); | |
990 } | |
991 | |
992 return s.Succeeded(); | |
993 } | |
994 | |
995 bool AutofillTable::UpdateAutofillProfile(const AutofillProfile& profile) { | |
996 DCHECK(base::IsValidGUID(profile.guid())); | |
997 | |
998 // Don't update anything until the trash has been emptied. There may be | |
999 // pending modifications to process. | |
1000 if (!IsAutofillProfilesTrashEmpty()) | |
1001 return true; | |
1002 | |
1003 AutofillProfile* tmp_profile = NULL; | |
1004 if (!GetAutofillProfile(profile.guid(), &tmp_profile)) | |
1005 return false; | |
1006 | |
1007 // Preserve appropriate modification dates by not updating unchanged profiles. | |
1008 scoped_ptr<AutofillProfile> old_profile(tmp_profile); | |
1009 if (old_profile->Compare(profile) == 0) | |
1010 return true; | |
1011 | |
1012 AutofillProfile new_profile(profile); | |
1013 std::vector<string16> values; | |
1014 | |
1015 old_profile->GetRawMultiInfo(NAME_FULL, &values); | |
1016 values[0] = new_profile.GetRawInfo(NAME_FULL); | |
1017 new_profile.SetRawMultiInfo(NAME_FULL, values); | |
1018 | |
1019 old_profile->GetRawMultiInfo(EMAIL_ADDRESS, &values); | |
1020 values[0] = new_profile.GetRawInfo(EMAIL_ADDRESS); | |
1021 new_profile.SetRawMultiInfo(EMAIL_ADDRESS, values); | |
1022 | |
1023 old_profile->GetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, &values); | |
1024 values[0] = new_profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER); | |
1025 new_profile.SetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, values); | |
1026 | |
1027 return UpdateAutofillProfileMulti(new_profile); | |
1028 } | |
1029 | |
1030 bool AutofillTable::UpdateAutofillProfileMulti(const AutofillProfile& profile) { | |
1031 DCHECK(base::IsValidGUID(profile.guid())); | |
1032 | |
1033 // Don't update anything until the trash has been emptied. There may be | |
1034 // pending modifications to process. | |
1035 if (!IsAutofillProfilesTrashEmpty()) | |
1036 return true; | |
1037 | |
1038 AutofillProfile* tmp_profile = NULL; | |
1039 if (!GetAutofillProfile(profile.guid(), &tmp_profile)) | |
1040 return false; | |
1041 | |
1042 // Preserve appropriate modification dates by not updating unchanged profiles. | |
1043 scoped_ptr<AutofillProfile> old_profile(tmp_profile); | |
1044 if (old_profile->Compare(profile) == 0) | |
1045 return true; | |
1046 | |
1047 sql::Statement s(db_->GetUniqueStatement( | |
1048 "UPDATE autofill_profiles " | |
1049 "SET guid=?, company_name=?, address_line_1=?, address_line_2=?, " | |
1050 " city=?, state=?, zipcode=?, country=?, country_code=?, " | |
1051 " date_modified=? " | |
1052 "WHERE guid=?")); | |
1053 BindAutofillProfileToStatement(profile, &s, app_locale_); | |
1054 s.BindString(10, profile.guid()); | |
1055 | |
1056 bool result = s.Run(); | |
1057 DCHECK_GT(db_->GetLastChangeCount(), 0); | |
1058 if (!result) | |
1059 return result; | |
1060 | |
1061 // Remove the old names, emails, and phone numbers. | |
1062 if (!RemoveAutofillProfilePieces(profile.guid(), db_)) | |
1063 return false; | |
1064 | |
1065 return AddAutofillProfilePieces(profile, db_); | |
1066 } | |
1067 | |
1068 bool AutofillTable::RemoveAutofillProfile(const std::string& guid) { | |
1069 DCHECK(base::IsValidGUID(guid)); | |
1070 | |
1071 if (IsAutofillGUIDInTrash(guid)) { | |
1072 sql::Statement s_trash(db_->GetUniqueStatement( | |
1073 "DELETE FROM autofill_profiles_trash WHERE guid = ?")); | |
1074 s_trash.BindString(0, guid); | |
1075 | |
1076 bool success = s_trash.Run(); | |
1077 DCHECK_GT(db_->GetLastChangeCount(), 0) << "Expected item in trash"; | |
1078 return success; | |
1079 } | |
1080 | |
1081 sql::Statement s(db_->GetUniqueStatement( | |
1082 "DELETE FROM autofill_profiles WHERE guid = ?")); | |
1083 s.BindString(0, guid); | |
1084 | |
1085 if (!s.Run()) | |
1086 return false; | |
1087 | |
1088 return RemoveAutofillProfilePieces(guid, db_); | |
1089 } | |
1090 | |
1091 bool AutofillTable::ClearAutofillProfiles() { | |
1092 sql::Statement s1(db_->GetUniqueStatement( | |
1093 "DELETE FROM autofill_profiles")); | |
1094 | |
1095 if (!s1.Run()) | |
1096 return false; | |
1097 | |
1098 sql::Statement s2(db_->GetUniqueStatement( | |
1099 "DELETE FROM autofill_profile_names")); | |
1100 | |
1101 if (!s2.Run()) | |
1102 return false; | |
1103 | |
1104 sql::Statement s3(db_->GetUniqueStatement( | |
1105 "DELETE FROM autofill_profile_emails")); | |
1106 | |
1107 if (!s3.Run()) | |
1108 return false; | |
1109 | |
1110 sql::Statement s4(db_->GetUniqueStatement( | |
1111 "DELETE FROM autofill_profile_phones")); | |
1112 | |
1113 return s4.Run(); | |
1114 } | |
1115 | |
1116 bool AutofillTable::AddCreditCard(const CreditCard& credit_card) { | |
1117 sql::Statement s(db_->GetUniqueStatement( | |
1118 "INSERT INTO credit_cards" | |
1119 "(guid, name_on_card, expiration_month, expiration_year, " | |
1120 "card_number_encrypted, date_modified)" | |
1121 "VALUES (?,?,?,?,?,?)")); | |
1122 BindCreditCardToStatement(credit_card, &s); | |
1123 | |
1124 if (!s.Run()) | |
1125 return false; | |
1126 | |
1127 DCHECK_GT(db_->GetLastChangeCount(), 0); | |
1128 return true; | |
1129 } | |
1130 | |
1131 bool AutofillTable::GetCreditCard(const std::string& guid, | |
1132 CreditCard** credit_card) { | |
1133 DCHECK(base::IsValidGUID(guid)); | |
1134 sql::Statement s(db_->GetUniqueStatement( | |
1135 "SELECT guid, name_on_card, expiration_month, expiration_year, " | |
1136 "card_number_encrypted, date_modified " | |
1137 "FROM credit_cards " | |
1138 "WHERE guid = ?")); | |
1139 s.BindString(0, guid); | |
1140 | |
1141 if (!s.Step()) | |
1142 return false; | |
1143 | |
1144 *credit_card = CreditCardFromStatement(s); | |
1145 return true; | |
1146 } | |
1147 | |
1148 bool AutofillTable::GetCreditCards( | |
1149 std::vector<CreditCard*>* credit_cards) { | |
1150 DCHECK(credit_cards); | |
1151 credit_cards->clear(); | |
1152 | |
1153 sql::Statement s(db_->GetUniqueStatement( | |
1154 "SELECT guid " | |
1155 "FROM credit_cards")); | |
1156 | |
1157 while (s.Step()) { | |
1158 std::string guid = s.ColumnString(0); | |
1159 CreditCard* credit_card = NULL; | |
1160 if (!GetCreditCard(guid, &credit_card)) | |
1161 return false; | |
1162 credit_cards->push_back(credit_card); | |
1163 } | |
1164 | |
1165 return s.Succeeded(); | |
1166 } | |
1167 | |
1168 bool AutofillTable::UpdateCreditCard(const CreditCard& credit_card) { | |
1169 DCHECK(base::IsValidGUID(credit_card.guid())); | |
1170 | |
1171 CreditCard* tmp_credit_card = NULL; | |
1172 if (!GetCreditCard(credit_card.guid(), &tmp_credit_card)) | |
1173 return false; | |
1174 | |
1175 // Preserve appropriate modification dates by not updating unchanged cards. | |
1176 scoped_ptr<CreditCard> old_credit_card(tmp_credit_card); | |
1177 if (*old_credit_card == credit_card) | |
1178 return true; | |
1179 | |
1180 sql::Statement s(db_->GetUniqueStatement( | |
1181 "UPDATE credit_cards " | |
1182 "SET guid=?, name_on_card=?, expiration_month=?, " | |
1183 " expiration_year=?, card_number_encrypted=?, date_modified=? " | |
1184 "WHERE guid=?")); | |
1185 BindCreditCardToStatement(credit_card, &s); | |
1186 s.BindString(6, credit_card.guid()); | |
1187 | |
1188 bool result = s.Run(); | |
1189 DCHECK_GT(db_->GetLastChangeCount(), 0); | |
1190 return result; | |
1191 } | |
1192 | |
1193 bool AutofillTable::RemoveCreditCard(const std::string& guid) { | |
1194 DCHECK(base::IsValidGUID(guid)); | |
1195 sql::Statement s(db_->GetUniqueStatement( | |
1196 "DELETE FROM credit_cards WHERE guid = ?")); | |
1197 s.BindString(0, guid); | |
1198 | |
1199 return s.Run(); | |
1200 } | |
1201 | |
1202 bool AutofillTable::RemoveAutofillDataModifiedBetween( | |
1203 const Time& delete_begin, | |
1204 const Time& delete_end, | |
1205 std::vector<std::string>* profile_guids, | |
1206 std::vector<std::string>* credit_card_guids) { | |
1207 DCHECK(delete_end.is_null() || delete_begin < delete_end); | |
1208 | |
1209 time_t delete_begin_t = delete_begin.ToTimeT(); | |
1210 time_t delete_end_t = | |
1211 (delete_end.is_null() || delete_end == base::Time::Max()) ? | |
1212 std::numeric_limits<time_t>::max() : delete_end.ToTimeT(); | |
1213 | |
1214 // Remember Autofill profiles in the time range. | |
1215 sql::Statement s_profiles_get(db_->GetUniqueStatement( | |
1216 "SELECT guid FROM autofill_profiles " | |
1217 "WHERE date_modified >= ? AND date_modified < ?")); | |
1218 s_profiles_get.BindInt64(0, delete_begin_t); | |
1219 s_profiles_get.BindInt64(1, delete_end_t); | |
1220 | |
1221 profile_guids->clear(); | |
1222 while (s_profiles_get.Step()) { | |
1223 std::string guid = s_profiles_get.ColumnString(0); | |
1224 profile_guids->push_back(guid); | |
1225 } | |
1226 if (!s_profiles_get.Succeeded()) | |
1227 return false; | |
1228 | |
1229 // Remove Autofill profiles in the time range. | |
1230 sql::Statement s_profiles(db_->GetUniqueStatement( | |
1231 "DELETE FROM autofill_profiles " | |
1232 "WHERE date_modified >= ? AND date_modified < ?")); | |
1233 s_profiles.BindInt64(0, delete_begin_t); | |
1234 s_profiles.BindInt64(1, delete_end_t); | |
1235 | |
1236 if (!s_profiles.Run()) | |
1237 return false; | |
1238 | |
1239 // Remember Autofill credit cards in the time range. | |
1240 sql::Statement s_credit_cards_get(db_->GetUniqueStatement( | |
1241 "SELECT guid FROM credit_cards " | |
1242 "WHERE date_modified >= ? AND date_modified < ?")); | |
1243 s_credit_cards_get.BindInt64(0, delete_begin_t); | |
1244 s_credit_cards_get.BindInt64(1, delete_end_t); | |
1245 | |
1246 credit_card_guids->clear(); | |
1247 while (s_credit_cards_get.Step()) { | |
1248 std::string guid = s_credit_cards_get.ColumnString(0); | |
1249 credit_card_guids->push_back(guid); | |
1250 } | |
1251 if (!s_credit_cards_get.Succeeded()) | |
1252 return false; | |
1253 | |
1254 // Remove Autofill credit cards in the time range. | |
1255 sql::Statement s_credit_cards(db_->GetUniqueStatement( | |
1256 "DELETE FROM credit_cards " | |
1257 "WHERE date_modified >= ? AND date_modified < ?")); | |
1258 s_credit_cards.BindInt64(0, delete_begin_t); | |
1259 s_credit_cards.BindInt64(1, delete_end_t); | |
1260 | |
1261 return s_credit_cards.Run(); | |
1262 } | |
1263 | |
1264 bool AutofillTable::GetAutofillProfilesInTrash( | |
1265 std::vector<std::string>* guids) { | |
1266 guids->clear(); | |
1267 | |
1268 sql::Statement s(db_->GetUniqueStatement( | |
1269 "SELECT guid " | |
1270 "FROM autofill_profiles_trash")); | |
1271 | |
1272 while (s.Step()) { | |
1273 std::string guid = s.ColumnString(0); | |
1274 guids->push_back(guid); | |
1275 } | |
1276 | |
1277 return s.Succeeded(); | |
1278 } | |
1279 | |
1280 bool AutofillTable::EmptyAutofillProfilesTrash() { | |
1281 sql::Statement s(db_->GetUniqueStatement( | |
1282 "DELETE FROM autofill_profiles_trash")); | |
1283 | |
1284 return s.Run(); | |
1285 } | |
1286 | |
1287 | |
1288 bool AutofillTable::RemoveFormElementForID(int64 pair_id) { | |
1289 sql::Statement s(db_->GetUniqueStatement( | |
1290 "DELETE FROM autofill WHERE pair_id = ?")); | |
1291 s.BindInt64(0, pair_id); | |
1292 | |
1293 if (s.Run()) | |
1294 return RemoveFormElementForTimeRange(pair_id, Time(), Time(), NULL); | |
1295 | |
1296 return false; | |
1297 } | |
1298 | |
1299 bool AutofillTable::AddAutofillGUIDToTrash(const std::string& guid) { | |
1300 sql::Statement s(db_->GetUniqueStatement( | |
1301 "INSERT INTO autofill_profiles_trash" | |
1302 " (guid) " | |
1303 "VALUES (?)")); | |
1304 s.BindString(0, guid); | |
1305 | |
1306 return s.Run(); | |
1307 } | |
1308 | |
1309 bool AutofillTable::IsAutofillProfilesTrashEmpty() { | |
1310 sql::Statement s(db_->GetUniqueStatement( | |
1311 "SELECT guid " | |
1312 "FROM autofill_profiles_trash")); | |
1313 | |
1314 return !s.Step(); | |
1315 } | |
1316 | |
1317 bool AutofillTable::IsAutofillGUIDInTrash(const std::string& guid) { | |
1318 sql::Statement s(db_->GetUniqueStatement( | |
1319 "SELECT guid " | |
1320 "FROM autofill_profiles_trash " | |
1321 "WHERE guid = ?")); | |
1322 s.BindString(0, guid); | |
1323 | |
1324 return s.Step(); | |
1325 } | |
1326 | |
1327 bool AutofillTable::InitMainTable() { | |
1328 if (!db_->DoesTableExist("autofill")) { | |
1329 if (!db_->Execute("CREATE TABLE autofill (" | |
1330 "name VARCHAR, " | |
1331 "value VARCHAR, " | |
1332 "value_lower VARCHAR, " | |
1333 "pair_id INTEGER PRIMARY KEY, " | |
1334 "count INTEGER DEFAULT 1)")) { | |
1335 NOTREACHED(); | |
1336 return false; | |
1337 } | |
1338 if (!db_->Execute("CREATE INDEX autofill_name ON autofill (name)")) { | |
1339 NOTREACHED(); | |
1340 return false; | |
1341 } | |
1342 if (!db_->Execute("CREATE INDEX autofill_name_value_lower ON " | |
1343 "autofill (name, value_lower)")) { | |
1344 NOTREACHED(); | |
1345 return false; | |
1346 } | |
1347 } | |
1348 return true; | |
1349 } | |
1350 | |
1351 bool AutofillTable::InitCreditCardsTable() { | |
1352 if (!db_->DoesTableExist("credit_cards")) { | |
1353 if (!db_->Execute("CREATE TABLE credit_cards ( " | |
1354 "guid VARCHAR PRIMARY KEY, " | |
1355 "name_on_card VARCHAR, " | |
1356 "expiration_month INTEGER, " | |
1357 "expiration_year INTEGER, " | |
1358 "card_number_encrypted BLOB, " | |
1359 "date_modified INTEGER NOT NULL DEFAULT 0)")) { | |
1360 NOTREACHED(); | |
1361 return false; | |
1362 } | |
1363 } | |
1364 | |
1365 return true; | |
1366 } | |
1367 | |
1368 bool AutofillTable::InitDatesTable() { | |
1369 if (!db_->DoesTableExist("autofill_dates")) { | |
1370 if (!db_->Execute("CREATE TABLE autofill_dates ( " | |
1371 "pair_id INTEGER DEFAULT 0, " | |
1372 "date_created INTEGER DEFAULT 0)")) { | |
1373 NOTREACHED(); | |
1374 return false; | |
1375 } | |
1376 if (!db_->Execute("CREATE INDEX autofill_dates_pair_id ON " | |
1377 "autofill_dates (pair_id)")) { | |
1378 NOTREACHED(); | |
1379 return false; | |
1380 } | |
1381 } | |
1382 return true; | |
1383 } | |
1384 | |
1385 bool AutofillTable::InitProfilesTable() { | |
1386 if (!db_->DoesTableExist("autofill_profiles")) { | |
1387 if (!db_->Execute("CREATE TABLE autofill_profiles ( " | |
1388 "guid VARCHAR PRIMARY KEY, " | |
1389 "company_name VARCHAR, " | |
1390 "address_line_1 VARCHAR, " | |
1391 "address_line_2 VARCHAR, " | |
1392 "city VARCHAR, " | |
1393 "state VARCHAR, " | |
1394 "zipcode VARCHAR, " | |
1395 "country VARCHAR, " | |
1396 "country_code VARCHAR, " | |
1397 "date_modified INTEGER NOT NULL DEFAULT 0)")) { | |
1398 NOTREACHED(); | |
1399 return false; | |
1400 } | |
1401 } | |
1402 return true; | |
1403 } | |
1404 | |
1405 bool AutofillTable::InitProfileNamesTable() { | |
1406 if (!db_->DoesTableExist("autofill_profile_names")) { | |
1407 if (!db_->Execute("CREATE TABLE autofill_profile_names ( " | |
1408 "guid VARCHAR, " | |
1409 "first_name VARCHAR, " | |
1410 "middle_name VARCHAR, " | |
1411 "last_name VARCHAR)")) { | |
1412 NOTREACHED(); | |
1413 return false; | |
1414 } | |
1415 } | |
1416 return true; | |
1417 } | |
1418 | |
1419 bool AutofillTable::InitProfileEmailsTable() { | |
1420 if (!db_->DoesTableExist("autofill_profile_emails")) { | |
1421 if (!db_->Execute("CREATE TABLE autofill_profile_emails ( " | |
1422 "guid VARCHAR, " | |
1423 "email VARCHAR)")) { | |
1424 NOTREACHED(); | |
1425 return false; | |
1426 } | |
1427 } | |
1428 return true; | |
1429 } | |
1430 | |
1431 bool AutofillTable::InitProfilePhonesTable() { | |
1432 if (!db_->DoesTableExist("autofill_profile_phones")) { | |
1433 if (!db_->Execute("CREATE TABLE autofill_profile_phones ( " | |
1434 "guid VARCHAR, " | |
1435 "type INTEGER DEFAULT 0, " | |
1436 "number VARCHAR)")) { | |
1437 NOTREACHED(); | |
1438 return false; | |
1439 } | |
1440 } | |
1441 return true; | |
1442 } | |
1443 | |
1444 bool AutofillTable::InitProfileTrashTable() { | |
1445 if (!db_->DoesTableExist("autofill_profiles_trash")) { | |
1446 if (!db_->Execute("CREATE TABLE autofill_profiles_trash ( " | |
1447 "guid VARCHAR)")) { | |
1448 NOTREACHED(); | |
1449 return false; | |
1450 } | |
1451 } | |
1452 return true; | |
1453 } | |
1454 | |
1455 // Add the card_number_encrypted column if credit card table was not | |
1456 // created in this build (otherwise the column already exists). | |
1457 // WARNING: Do not change the order of the execution of the SQL | |
1458 // statements in this case! Profile corruption and data migration | |
1459 // issues WILL OCCUR. See http://crbug.com/10913 | |
1460 // | |
1461 // The problem is that if a user has a profile which was created before | |
1462 // r37036, when the credit_cards table was added, and then failed to | |
1463 // update this profile between the credit card addition and the addition | |
1464 // of the "encrypted" columns (44963), the next data migration will put | |
1465 // the user's profile in an incoherent state: The user will update from | |
1466 // a data profile set to be earlier than 22, and therefore pass through | |
1467 // this update case. But because the user did not have a credit_cards | |
1468 // table before starting Chrome, it will have just been initialized | |
1469 // above, and so already have these columns -- and thus this data | |
1470 // update step will have failed. | |
1471 // | |
1472 // The false assumption in this case is that at this step in the | |
1473 // migration, the user has a credit card table, and that this | |
1474 // table does not include encrypted columns! | |
1475 // Because this case does not roll back the complete set of SQL | |
1476 // transactions properly in case of failure (that is, it does not | |
1477 // roll back the table initialization done above), the incoherent | |
1478 // profile will now see itself as being at version 22 -- but include a | |
1479 // fully initialized credit_cards table. Every time Chrome runs, it | |
1480 // will try to update the web database and fail at this step, unless | |
1481 // we allow for the faulty assumption described above by checking for | |
1482 // the existence of the columns only AFTER we've executed the commands | |
1483 // to add them. | |
1484 bool AutofillTable::MigrateToVersion23AddCardNumberEncryptedColumn() { | |
1485 if (!db_->DoesColumnExist("credit_cards", "card_number_encrypted")) { | |
1486 if (!db_->Execute("ALTER TABLE credit_cards ADD COLUMN " | |
1487 "card_number_encrypted BLOB DEFAULT NULL")) { | |
1488 LOG(WARNING) << "Could not add card_number_encrypted to " | |
1489 "credit_cards table."; | |
1490 return false; | |
1491 } | |
1492 } | |
1493 | |
1494 if (!db_->DoesColumnExist("credit_cards", "verification_code_encrypted")) { | |
1495 if (!db_->Execute("ALTER TABLE credit_cards ADD COLUMN " | |
1496 "verification_code_encrypted BLOB DEFAULT NULL")) { | |
1497 LOG(WARNING) << "Could not add verification_code_encrypted to " | |
1498 "credit_cards table."; | |
1499 return false; | |
1500 } | |
1501 } | |
1502 | |
1503 return true; | |
1504 } | |
1505 | |
1506 // One-time cleanup for http://crbug.com/38364 - In the presence of | |
1507 // multi-byte UTF-8 characters, that bug could cause Autofill strings | |
1508 // to grow larger and more corrupt with each save. The cleanup removes | |
1509 // any row with a string field larger than a reasonable size. The string | |
1510 // fields examined here are precisely the ones that were subject to | |
1511 // corruption by the original bug. | |
1512 bool AutofillTable::MigrateToVersion24CleanupOversizedStringFields() { | |
1513 const std::string autofill_is_too_big = | |
1514 "max(length(name), length(value)) > 500"; | |
1515 | |
1516 const std::string credit_cards_is_too_big = | |
1517 "max(length(label), length(name_on_card), length(type), " | |
1518 " length(expiration_month), length(expiration_year), " | |
1519 " length(billing_address), length(shipping_address) " | |
1520 ") > 500"; | |
1521 | |
1522 const std::string autofill_profiles_is_too_big = | |
1523 "max(length(label), length(first_name), " | |
1524 " length(middle_name), length(last_name), length(email), " | |
1525 " length(company_name), length(address_line_1), " | |
1526 " length(address_line_2), length(city), length(state), " | |
1527 " length(zipcode), length(country), length(phone)) > 500"; | |
1528 | |
1529 std::string query = "DELETE FROM autofill_dates WHERE pair_id IN (" | |
1530 "SELECT pair_id FROM autofill WHERE " + autofill_is_too_big + ")"; | |
1531 | |
1532 if (!db_->Execute(query.c_str())) | |
1533 return false; | |
1534 | |
1535 query = "DELETE FROM autofill WHERE " + autofill_is_too_big; | |
1536 | |
1537 if (!db_->Execute(query.c_str())) | |
1538 return false; | |
1539 | |
1540 // Only delete from legacy credit card tables where specific columns exist. | |
1541 if (db_->DoesColumnExist("credit_cards", "label") && | |
1542 db_->DoesColumnExist("credit_cards", "name_on_card") && | |
1543 db_->DoesColumnExist("credit_cards", "type") && | |
1544 db_->DoesColumnExist("credit_cards", "expiration_month") && | |
1545 db_->DoesColumnExist("credit_cards", "expiration_year") && | |
1546 db_->DoesColumnExist("credit_cards", "billing_address") && | |
1547 db_->DoesColumnExist("credit_cards", "shipping_address") && | |
1548 db_->DoesColumnExist("autofill_profiles", "label")) { | |
1549 query = "DELETE FROM credit_cards WHERE (" + credit_cards_is_too_big + | |
1550 ") OR label IN (SELECT label FROM autofill_profiles WHERE " + | |
1551 autofill_profiles_is_too_big + ")"; | |
1552 | |
1553 if (!db_->Execute(query.c_str())) | |
1554 return false; | |
1555 } | |
1556 | |
1557 if (db_->DoesColumnExist("autofill_profiles", "label")) { | |
1558 query = "DELETE FROM autofill_profiles WHERE " + | |
1559 autofill_profiles_is_too_big; | |
1560 | |
1561 if (!db_->Execute(query.c_str())) | |
1562 return false; | |
1563 } | |
1564 | |
1565 return true; | |
1566 } | |
1567 | |
1568 // Change the credit_cards.billing_address column from a string to an | |
1569 // int. The stored string is the label of an address, so we have to | |
1570 // select the unique ID of this address using the label as a foreign | |
1571 // key into the |autofill_profiles| table. | |
1572 bool AutofillTable::MigrateToVersion27UpdateLegacyCreditCards() { | |
1573 // Only migrate from legacy credit card tables where specific columns | |
1574 // exist. | |
1575 if (!(db_->DoesColumnExist("credit_cards", "unique_id") && | |
1576 db_->DoesColumnExist("credit_cards", "billing_address") && | |
1577 db_->DoesColumnExist("autofill_profiles", "unique_id"))) { | |
1578 return true; | |
1579 } | |
1580 | |
1581 std::string stmt = | |
1582 "SELECT credit_cards.unique_id, autofill_profiles.unique_id " | |
1583 "FROM autofill_profiles, credit_cards " | |
1584 "WHERE credit_cards.billing_address = autofill_profiles.label"; | |
1585 sql::Statement s(db_->GetUniqueStatement(stmt.c_str())); | |
1586 | |
1587 std::map<int, int> cc_billing_map; | |
1588 while (s.Step()) | |
1589 cc_billing_map[s.ColumnInt(0)] = s.ColumnInt(1); | |
1590 if (!s.Succeeded()) | |
1591 return false; | |
1592 | |
1593 // Windows already stores the IDs as strings in |billing_address|. Try | |
1594 // to convert those. | |
1595 if (cc_billing_map.empty()) { | |
1596 std::string stmt = "SELECT unique_id,billing_address FROM credit_cards"; | |
1597 sql::Statement s(db_->GetUniqueStatement(stmt.c_str())); | |
1598 | |
1599 while (s.Step()) { | |
1600 int id = 0; | |
1601 if (base::StringToInt(s.ColumnString(1), &id)) | |
1602 cc_billing_map[s.ColumnInt(0)] = id; | |
1603 } | |
1604 if (!s.Succeeded()) | |
1605 return false; | |
1606 } | |
1607 | |
1608 if (!db_->Execute("CREATE TABLE credit_cards_temp ( " | |
1609 "label VARCHAR, " | |
1610 "unique_id INTEGER PRIMARY KEY, " | |
1611 "name_on_card VARCHAR, " | |
1612 "type VARCHAR, " | |
1613 "card_number VARCHAR, " | |
1614 "expiration_month INTEGER, " | |
1615 "expiration_year INTEGER, " | |
1616 "verification_code VARCHAR, " | |
1617 "billing_address INTEGER, " | |
1618 "shipping_address VARCHAR, " | |
1619 "card_number_encrypted BLOB, " | |
1620 "verification_code_encrypted BLOB)")) { | |
1621 return false; | |
1622 } | |
1623 | |
1624 if (!db_->Execute( | |
1625 "INSERT INTO credit_cards_temp " | |
1626 "SELECT label,unique_id,name_on_card,type,card_number," | |
1627 "expiration_month,expiration_year,verification_code,0," | |
1628 "shipping_address,card_number_encrypted," | |
1629 "verification_code_encrypted FROM credit_cards")) { | |
1630 return false; | |
1631 } | |
1632 | |
1633 if (!db_->Execute("DROP TABLE credit_cards")) | |
1634 return false; | |
1635 | |
1636 if (!db_->Execute("ALTER TABLE credit_cards_temp RENAME TO credit_cards")) | |
1637 return false; | |
1638 | |
1639 for (std::map<int, int>::const_iterator iter = cc_billing_map.begin(); | |
1640 iter != cc_billing_map.end(); ++iter) { | |
1641 sql::Statement s(db_->GetCachedStatement( | |
1642 SQL_FROM_HERE, | |
1643 "UPDATE credit_cards SET billing_address=? WHERE unique_id=?")); | |
1644 s.BindInt(0, (*iter).second); | |
1645 s.BindInt(1, (*iter).first); | |
1646 | |
1647 if (!s.Run()) | |
1648 return false; | |
1649 } | |
1650 | |
1651 return true; | |
1652 } | |
1653 | |
1654 bool AutofillTable::MigrateToVersion30AddDateModifed() { | |
1655 // Add date_modified to autofill_profiles. | |
1656 if (!db_->DoesColumnExist("autofill_profiles", "date_modified")) { | |
1657 if (!db_->Execute("ALTER TABLE autofill_profiles ADD COLUMN " | |
1658 "date_modified INTEGER NON NULL DEFAULT 0")) { | |
1659 return false; | |
1660 } | |
1661 | |
1662 sql::Statement s(db_->GetUniqueStatement( | |
1663 "UPDATE autofill_profiles SET date_modified=?")); | |
1664 s.BindInt64(0, Time::Now().ToTimeT()); | |
1665 | |
1666 if (!s.Run()) | |
1667 return false; | |
1668 } | |
1669 | |
1670 // Add date_modified to credit_cards. | |
1671 if (!db_->DoesColumnExist("credit_cards", "date_modified")) { | |
1672 if (!db_->Execute("ALTER TABLE credit_cards ADD COLUMN " | |
1673 "date_modified INTEGER NON NULL DEFAULT 0")) { | |
1674 return false; | |
1675 } | |
1676 | |
1677 sql::Statement s(db_->GetUniqueStatement( | |
1678 "UPDATE credit_cards SET date_modified=?")); | |
1679 s.BindInt64(0, Time::Now().ToTimeT()); | |
1680 | |
1681 if (!s.Run()) | |
1682 return false; | |
1683 } | |
1684 | |
1685 return true; | |
1686 } | |
1687 | |
1688 bool AutofillTable::MigrateToVersion31AddGUIDToCreditCardsAndProfiles() { | |
1689 // Note that we need to check for the guid column's existence due to the | |
1690 // fact that for a version 22 database the |autofill_profiles| table | |
1691 // gets created fresh with |InitAutofillProfilesTable|. | |
1692 if (!db_->DoesColumnExist("autofill_profiles", "guid")) { | |
1693 if (!db_->Execute("ALTER TABLE autofill_profiles ADD COLUMN " | |
1694 "guid VARCHAR NOT NULL DEFAULT \"\"")) { | |
1695 return false; | |
1696 } | |
1697 | |
1698 // Set all the |guid| fields to valid values. | |
1699 | |
1700 sql::Statement s(db_->GetUniqueStatement("SELECT unique_id " | |
1701 "FROM autofill_profiles")); | |
1702 | |
1703 while (s.Step()) { | |
1704 sql::Statement update_s( | |
1705 db_->GetUniqueStatement("UPDATE autofill_profiles " | |
1706 "SET guid=? WHERE unique_id=?")); | |
1707 update_s.BindString(0, base::GenerateGUID()); | |
1708 update_s.BindInt(1, s.ColumnInt(0)); | |
1709 | |
1710 if (!update_s.Run()) | |
1711 return false; | |
1712 } | |
1713 if (!s.Succeeded()) | |
1714 return false; | |
1715 } | |
1716 | |
1717 // Note that we need to check for the guid column's existence due to the | |
1718 // fact that for a version 22 database the |autofill_profiles| table | |
1719 // gets created fresh with |InitAutofillProfilesTable|. | |
1720 if (!db_->DoesColumnExist("credit_cards", "guid")) { | |
1721 if (!db_->Execute("ALTER TABLE credit_cards ADD COLUMN " | |
1722 "guid VARCHAR NOT NULL DEFAULT \"\"")) { | |
1723 return false; | |
1724 } | |
1725 | |
1726 // Set all the |guid| fields to valid values. | |
1727 | |
1728 sql::Statement s(db_->GetUniqueStatement("SELECT unique_id " | |
1729 "FROM credit_cards")); | |
1730 | |
1731 while (s.Step()) { | |
1732 sql::Statement update_s( | |
1733 db_->GetUniqueStatement("UPDATE credit_cards " | |
1734 "set guid=? WHERE unique_id=?")); | |
1735 update_s.BindString(0, base::GenerateGUID()); | |
1736 update_s.BindInt(1, s.ColumnInt(0)); | |
1737 | |
1738 if (!update_s.Run()) | |
1739 return false; | |
1740 } | |
1741 if (!s.Succeeded()) | |
1742 return false; | |
1743 } | |
1744 | |
1745 return true; | |
1746 } | |
1747 | |
1748 bool AutofillTable::MigrateToVersion32UpdateProfilesAndCreditCards() { | |
1749 if (db_->DoesColumnExist("autofill_profiles", "unique_id")) { | |
1750 if (!db_->Execute("CREATE TABLE autofill_profiles_temp ( " | |
1751 "guid VARCHAR PRIMARY KEY, " | |
1752 "label VARCHAR, " | |
1753 "first_name VARCHAR, " | |
1754 "middle_name VARCHAR, " | |
1755 "last_name VARCHAR, " | |
1756 "email VARCHAR, " | |
1757 "company_name VARCHAR, " | |
1758 "address_line_1 VARCHAR, " | |
1759 "address_line_2 VARCHAR, " | |
1760 "city VARCHAR, " | |
1761 "state VARCHAR, " | |
1762 "zipcode VARCHAR, " | |
1763 "country VARCHAR, " | |
1764 "phone VARCHAR, " | |
1765 "date_modified INTEGER NOT NULL DEFAULT 0)")) { | |
1766 return false; | |
1767 } | |
1768 | |
1769 if (!db_->Execute( | |
1770 "INSERT INTO autofill_profiles_temp " | |
1771 "SELECT guid, label, first_name, middle_name, last_name, email, " | |
1772 "company_name, address_line_1, address_line_2, city, state, " | |
1773 "zipcode, country, phone, date_modified " | |
1774 "FROM autofill_profiles")) { | |
1775 return false; | |
1776 } | |
1777 | |
1778 if (!db_->Execute("DROP TABLE autofill_profiles")) | |
1779 return false; | |
1780 | |
1781 if (!db_->Execute( | |
1782 "ALTER TABLE autofill_profiles_temp RENAME TO autofill_profiles")) { | |
1783 return false; | |
1784 } | |
1785 } | |
1786 | |
1787 if (db_->DoesColumnExist("credit_cards", "unique_id")) { | |
1788 if (!db_->Execute("CREATE TABLE credit_cards_temp ( " | |
1789 "guid VARCHAR PRIMARY KEY, " | |
1790 "label VARCHAR, " | |
1791 "name_on_card VARCHAR, " | |
1792 "expiration_month INTEGER, " | |
1793 "expiration_year INTEGER, " | |
1794 "card_number_encrypted BLOB, " | |
1795 "date_modified INTEGER NOT NULL DEFAULT 0)")) { | |
1796 return false; | |
1797 } | |
1798 | |
1799 if (!db_->Execute( | |
1800 "INSERT INTO credit_cards_temp " | |
1801 "SELECT guid, label, name_on_card, expiration_month, " | |
1802 "expiration_year, card_number_encrypted, date_modified " | |
1803 "FROM credit_cards")) { | |
1804 return false; | |
1805 } | |
1806 | |
1807 if (!db_->Execute("DROP TABLE credit_cards")) | |
1808 return false; | |
1809 | |
1810 if (!db_->Execute("ALTER TABLE credit_cards_temp RENAME TO credit_cards")) | |
1811 return false; | |
1812 } | |
1813 | |
1814 return true; | |
1815 } | |
1816 | |
1817 // Test the existence of the |first_name| column as an indication that | |
1818 // we need a migration. It is possible that the new |autofill_profiles| | |
1819 // schema is in place because the table was newly created when migrating | |
1820 // from a pre-version-22 database. | |
1821 bool AutofillTable::MigrateToVersion33ProfilesBasedOnFirstName() { | |
1822 if (db_->DoesColumnExist("autofill_profiles", "first_name")) { | |
1823 // Create autofill_profiles_temp table that will receive the data. | |
1824 if (!db_->DoesTableExist("autofill_profiles_temp")) { | |
1825 if (!db_->Execute("CREATE TABLE autofill_profiles_temp ( " | |
1826 "guid VARCHAR PRIMARY KEY, " | |
1827 "company_name VARCHAR, " | |
1828 "address_line_1 VARCHAR, " | |
1829 "address_line_2 VARCHAR, " | |
1830 "city VARCHAR, " | |
1831 "state VARCHAR, " | |
1832 "zipcode VARCHAR, " | |
1833 "country VARCHAR, " | |
1834 "date_modified INTEGER NOT NULL DEFAULT 0)")) { | |
1835 return false; | |
1836 } | |
1837 } | |
1838 | |
1839 sql::Statement s(db_->GetUniqueStatement( | |
1840 "SELECT guid, first_name, middle_name, last_name, email, " | |
1841 "company_name, address_line_1, address_line_2, city, state, " | |
1842 "zipcode, country, phone, date_modified " | |
1843 "FROM autofill_profiles")); | |
1844 | |
1845 while (s.Step()) { | |
1846 AutofillProfile profile; | |
1847 profile.set_guid(s.ColumnString(0)); | |
1848 DCHECK(base::IsValidGUID(profile.guid())); | |
1849 | |
1850 profile.SetRawInfo(NAME_FIRST, s.ColumnString16(1)); | |
1851 profile.SetRawInfo(NAME_MIDDLE, s.ColumnString16(2)); | |
1852 profile.SetRawInfo(NAME_LAST, s.ColumnString16(3)); | |
1853 profile.SetRawInfo(EMAIL_ADDRESS, s.ColumnString16(4)); | |
1854 profile.SetRawInfo(COMPANY_NAME, s.ColumnString16(5)); | |
1855 profile.SetRawInfo(ADDRESS_HOME_LINE1, s.ColumnString16(6)); | |
1856 profile.SetRawInfo(ADDRESS_HOME_LINE2, s.ColumnString16(7)); | |
1857 profile.SetRawInfo(ADDRESS_HOME_CITY, s.ColumnString16(8)); | |
1858 profile.SetRawInfo(ADDRESS_HOME_STATE, s.ColumnString16(9)); | |
1859 profile.SetRawInfo(ADDRESS_HOME_ZIP, s.ColumnString16(10)); | |
1860 profile.SetInfo(ADDRESS_HOME_COUNTRY, s.ColumnString16(11), app_locale_); | |
1861 profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, s.ColumnString16(12)); | |
1862 int64 date_modified = s.ColumnInt64(13); | |
1863 | |
1864 sql::Statement s_insert(db_->GetUniqueStatement( | |
1865 "INSERT INTO autofill_profiles_temp" | |
1866 "(guid, company_name, address_line_1, address_line_2, city," | |
1867 " state, zipcode, country, date_modified)" | |
1868 "VALUES (?,?,?,?,?,?,?,?,?)")); | |
1869 s_insert.BindString(0, profile.guid()); | |
1870 s_insert.BindString16(1, profile.GetRawInfo(COMPANY_NAME)); | |
1871 s_insert.BindString16(2, profile.GetRawInfo(ADDRESS_HOME_LINE1)); | |
1872 s_insert.BindString16(3, profile.GetRawInfo(ADDRESS_HOME_LINE2)); | |
1873 s_insert.BindString16(4, profile.GetRawInfo(ADDRESS_HOME_CITY)); | |
1874 s_insert.BindString16(5, profile.GetRawInfo(ADDRESS_HOME_STATE)); | |
1875 s_insert.BindString16(6, profile.GetRawInfo(ADDRESS_HOME_ZIP)); | |
1876 s_insert.BindString16(7, profile.GetRawInfo(ADDRESS_HOME_COUNTRY)); | |
1877 s_insert.BindInt64(8, date_modified); | |
1878 | |
1879 if (!s_insert.Run()) | |
1880 return false; | |
1881 | |
1882 // Add the other bits: names, emails, and phone numbers. | |
1883 if (!AddAutofillProfilePieces(profile, db_)) | |
1884 return false; | |
1885 } // endwhile | |
1886 if (!s.Succeeded()) | |
1887 return false; | |
1888 | |
1889 if (!db_->Execute("DROP TABLE autofill_profiles")) | |
1890 return false; | |
1891 | |
1892 if (!db_->Execute( | |
1893 "ALTER TABLE autofill_profiles_temp RENAME TO autofill_profiles")) { | |
1894 return false; | |
1895 } | |
1896 } | |
1897 | |
1898 // Remove the labels column from the credit_cards table. | |
1899 if (db_->DoesColumnExist("credit_cards", "label")) { | |
1900 if (!db_->Execute("CREATE TABLE credit_cards_temp ( " | |
1901 "guid VARCHAR PRIMARY KEY, " | |
1902 "name_on_card VARCHAR, " | |
1903 "expiration_month INTEGER, " | |
1904 "expiration_year INTEGER, " | |
1905 "card_number_encrypted BLOB, " | |
1906 "date_modified INTEGER NOT NULL DEFAULT 0)")) { | |
1907 return false; | |
1908 } | |
1909 | |
1910 if (!db_->Execute( | |
1911 "INSERT INTO credit_cards_temp " | |
1912 "SELECT guid, name_on_card, expiration_month, " | |
1913 "expiration_year, card_number_encrypted, date_modified " | |
1914 "FROM credit_cards")) { | |
1915 return false; | |
1916 } | |
1917 | |
1918 if (!db_->Execute("DROP TABLE credit_cards")) | |
1919 return false; | |
1920 | |
1921 if (!db_->Execute("ALTER TABLE credit_cards_temp RENAME TO credit_cards")) | |
1922 return false; | |
1923 } | |
1924 | |
1925 return true; | |
1926 } | |
1927 | |
1928 // Test the existence of the |country_code| column as an indication that | |
1929 // we need a migration. It is possible that the new |autofill_profiles| | |
1930 // schema is in place because the table was newly created when migrating | |
1931 // from a pre-version-22 database. | |
1932 bool AutofillTable::MigrateToVersion34ProfilesBasedOnCountryCode() { | |
1933 if (!db_->DoesColumnExist("autofill_profiles", "country_code")) { | |
1934 if (!db_->Execute("ALTER TABLE autofill_profiles ADD COLUMN " | |
1935 "country_code VARCHAR")) { | |
1936 return false; | |
1937 } | |
1938 | |
1939 // Set all the |country_code| fields to match existing |country| values. | |
1940 sql::Statement s(db_->GetUniqueStatement("SELECT guid, country " | |
1941 "FROM autofill_profiles")); | |
1942 | |
1943 while (s.Step()) { | |
1944 sql::Statement update_s( | |
1945 db_->GetUniqueStatement("UPDATE autofill_profiles " | |
1946 "SET country_code=? WHERE guid=?")); | |
1947 | |
1948 string16 country = s.ColumnString16(1); | |
1949 update_s.BindString(0, AutofillCountry::GetCountryCode(country, | |
1950 app_locale_)); | |
1951 update_s.BindString(1, s.ColumnString(0)); | |
1952 | |
1953 if (!update_s.Run()) | |
1954 return false; | |
1955 } | |
1956 if (!s.Succeeded()) | |
1957 return false; | |
1958 } | |
1959 | |
1960 return true; | |
1961 } | |
1962 | |
1963 // Correct all country codes with value "UK" to be "GB". This data | |
1964 // was mistakenly introduced in build 686.0. This migration is to clean | |
1965 // it up. See http://crbug.com/74511 for details. | |
1966 bool AutofillTable::MigrateToVersion35GreatBritainCountryCodes() { | |
1967 sql::Statement s(db_->GetUniqueStatement( | |
1968 "UPDATE autofill_profiles SET country_code=\"GB\" " | |
1969 "WHERE country_code=\"UK\"")); | |
1970 | |
1971 return s.Run(); | |
1972 } | |
1973 | |
1974 // Merge and cull older profiles where possible. | |
1975 bool AutofillTable::MigrateToVersion37MergeAndCullOlderProfiles() { | |
1976 sql::Statement s(db_->GetUniqueStatement( | |
1977 "SELECT guid, date_modified FROM autofill_profiles")); | |
1978 | |
1979 // Accumulate the good profiles. | |
1980 std::vector<AutofillProfile> accumulated_profiles; | |
1981 std::vector<AutofillProfile*> accumulated_profiles_p; | |
1982 std::map<std::string, int64> modification_map; | |
1983 while (s.Step()) { | |
1984 std::string guid = s.ColumnString(0); | |
1985 int64 date_modified = s.ColumnInt64(1); | |
1986 modification_map.insert( | |
1987 std::pair<std::string, int64>(guid, date_modified)); | |
1988 AutofillProfile* profile = NULL; | |
1989 if (!GetAutofillProfile(guid, &profile)) | |
1990 return false; | |
1991 | |
1992 scoped_ptr<AutofillProfile> p(profile); | |
1993 | |
1994 if (PersonalDataManager::IsValidLearnableProfile(*p, app_locale_)) { | |
1995 std::vector<AutofillProfile> merged_profiles; | |
1996 bool merged = PersonalDataManager::MergeProfile( | |
1997 *p, accumulated_profiles_p, app_locale_, &merged_profiles); | |
1998 | |
1999 std::swap(accumulated_profiles, merged_profiles); | |
2000 | |
2001 accumulated_profiles_p.clear(); | |
2002 accumulated_profiles_p.resize(accumulated_profiles.size()); | |
2003 std::transform(accumulated_profiles.begin(), | |
2004 accumulated_profiles.end(), | |
2005 accumulated_profiles_p.begin(), | |
2006 address_of<AutofillProfile>); | |
2007 | |
2008 // If the profile got merged trash the original. | |
2009 if (merged) | |
2010 AddAutofillGUIDToTrash(p->guid()); | |
2011 | |
2012 } else { | |
2013 // An invalid profile, so trash it. | |
2014 AddAutofillGUIDToTrash(p->guid()); | |
2015 } | |
2016 } // endwhile | |
2017 if (!s.Succeeded()) | |
2018 return false; | |
2019 | |
2020 // Drop the current profiles. | |
2021 if (!ClearAutofillProfiles()) | |
2022 return false; | |
2023 | |
2024 // Add the newly merged profiles back in. | |
2025 for (std::vector<AutofillProfile>::const_iterator | |
2026 iter = accumulated_profiles.begin(); | |
2027 iter != accumulated_profiles.end(); | |
2028 ++iter) { | |
2029 if (!AddAutofillProfile(*iter)) | |
2030 return false; | |
2031 | |
2032 // Fix up the original modification date. | |
2033 std::map<std::string, int64>::const_iterator date_item = | |
2034 modification_map.find(iter->guid()); | |
2035 if (date_item == modification_map.end()) | |
2036 return false; | |
2037 | |
2038 sql::Statement s_date(db_->GetUniqueStatement( | |
2039 "UPDATE autofill_profiles SET date_modified=? " | |
2040 "WHERE guid=?")); | |
2041 s_date.BindInt64(0, date_item->second); | |
2042 s_date.BindString(1, iter->guid()); | |
2043 | |
2044 if (!s_date.Run()) | |
2045 return false; | |
2046 } | |
2047 | |
2048 return true; | |
2049 } | |
OLD | NEW |