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

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

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

Powered by Google App Engine
This is Rietveld 408576698