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