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