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

Side by Side Diff: chrome/browser/webdata/autofill_table.cc

Issue 13392014: Move c/b/webdata/ code to components/webdata/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Pure merge Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698