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

Side by Side Diff: components/webdata/autofill/autofill_table.cc

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

Powered by Google App Engine
This is Rietveld 408576698