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

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

Issue 6677124: Move migration code out of WebDatabase and into table-specific classes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Nits from dhollowa Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/webdata/autofill_table.h ('k') | chrome/browser/webdata/autofill_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/webdata/autofill_table.h" 5 #include "chrome/browser/webdata/autofill_table.h"
6 6
7 #include <algorithm>
8 #include <limits>
9 #include <map>
10 #include <set>
11 #include <string>
12 #include <vector>
13
7 #include "app/sql/statement.h" 14 #include "app/sql/statement.h"
15 #include "base/logging.h"
16 #include "base/string_number_conversions.h"
8 #include "base/time.h" 17 #include "base/time.h"
9 #include "base/tuple.h" 18 #include "base/tuple.h"
10 #include "chrome/browser/autofill/autofill_country.h" 19 #include "chrome/browser/autofill/autofill_country.h"
11 #include "chrome/browser/autofill/autofill_profile.h" 20 #include "chrome/browser/autofill/autofill_profile.h"
12 #include "chrome/browser/autofill/autofill_type.h" 21 #include "chrome/browser/autofill/autofill_type.h"
13 #include "chrome/browser/autofill/credit_card.h" 22 #include "chrome/browser/autofill/credit_card.h"
14 #include "chrome/browser/autofill/personal_data_manager.h" 23 #include "chrome/browser/autofill/personal_data_manager.h"
24 #include "chrome/browser/password_manager/encryptor.h"
15 #include "chrome/browser/webdata/autofill_change.h" 25 #include "chrome/browser/webdata/autofill_change.h"
16 #include "chrome/browser/webdata/autofill_util.h"
17 #include "chrome/common/guid.h" 26 #include "chrome/common/guid.h"
18 #include "ui/base/l10n/l10n_util.h" 27 #include "ui/base/l10n/l10n_util.h"
19 #include "webkit/glue/form_field.h" 28 #include "webkit/glue/form_field.h"
20 29
21 using base::Time; 30 using base::Time;
22 using webkit_glue::FormField; 31 using webkit_glue::FormField;
23 32
24 namespace { 33 namespace {
34
35 // Constants for the |autofill_profile_phones| |type| column.
36 enum AutofillPhoneType {
37 kAutofillPhoneNumber = 0,
38 kAutofillFaxNumber = 1
39 };
40
25 typedef std::vector<Tuple3<int64, string16, string16> > AutofillElementList; 41 typedef std::vector<Tuple3<int64, string16, string16> > AutofillElementList;
26 } // anonymous namespace 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 // The maximum length allowed for form data.
51 const size_t kMaxDataLength = 1024;
52
53 string16 LimitDataSize(const string16& data) {
54 if (data.size() > kMaxDataLength)
55 return data.substr(0, kMaxDataLength);
56
57 return data;
58 }
59
60 void BindAutofillProfileToStatement(const AutofillProfile& profile,
61 sql::Statement* s) {
62 DCHECK(guid::IsValidGUID(profile.guid()));
63 s->BindString(0, profile.guid());
64
65 string16 text = profile.GetInfo(COMPANY_NAME);
66 s->BindString16(1, LimitDataSize(text));
67 text = profile.GetInfo(ADDRESS_HOME_LINE1);
68 s->BindString16(2, LimitDataSize(text));
69 text = profile.GetInfo(ADDRESS_HOME_LINE2);
70 s->BindString16(3, LimitDataSize(text));
71 text = profile.GetInfo(ADDRESS_HOME_CITY);
72 s->BindString16(4, LimitDataSize(text));
73 text = profile.GetInfo(ADDRESS_HOME_STATE);
74 s->BindString16(5, LimitDataSize(text));
75 text = profile.GetInfo(ADDRESS_HOME_ZIP);
76 s->BindString16(6, LimitDataSize(text));
77 text = profile.GetInfo(ADDRESS_HOME_COUNTRY);
78 s->BindString16(7, LimitDataSize(text));
79 std::string country_code = profile.CountryCode();
80 s->BindString(8, country_code);
81 s->BindInt64(9, Time::Now().ToTimeT());
82 }
83
84 AutofillProfile* AutofillProfileFromStatement(const sql::Statement& s) {
85 AutofillProfile* profile = new AutofillProfile;
86 profile->set_guid(s.ColumnString(0));
87 DCHECK(guid::IsValidGUID(profile->guid()));
88
89 profile->SetInfo(COMPANY_NAME, s.ColumnString16(1));
90 profile->SetInfo(ADDRESS_HOME_LINE1, s.ColumnString16(2));
91 profile->SetInfo(ADDRESS_HOME_LINE2, s.ColumnString16(3));
92 profile->SetInfo(ADDRESS_HOME_CITY, s.ColumnString16(4));
93 profile->SetInfo(ADDRESS_HOME_STATE, s.ColumnString16(5));
94 profile->SetInfo(ADDRESS_HOME_ZIP, s.ColumnString16(6));
95 // Intentionally skip column 7, which stores the localized country name.
96 profile->SetCountryCode(s.ColumnString(8));
97 // Intentionally skip column 9, which stores the profile's modification date.
98
99 return profile;
100 }
101
102 void BindCreditCardToStatement(const CreditCard& credit_card,
103 sql::Statement* s) {
104 DCHECK(guid::IsValidGUID(credit_card.guid()));
105 s->BindString(0, credit_card.guid());
106
107 string16 text = credit_card.GetInfo(CREDIT_CARD_NAME);
108 s->BindString16(1, LimitDataSize(text));
109 text = credit_card.GetInfo(CREDIT_CARD_EXP_MONTH);
110 s->BindString16(2, LimitDataSize(text));
111 text = credit_card.GetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR);
112 s->BindString16(3, LimitDataSize(text));
113 text = credit_card.GetInfo(CREDIT_CARD_NUMBER);
114 std::string encrypted_data;
115 Encryptor::EncryptString16(text, &encrypted_data);
116 s->BindBlob(4, encrypted_data.data(),
117 static_cast<int>(encrypted_data.length()));
118 s->BindInt64(5, Time::Now().ToTimeT());
119 }
120
121 CreditCard* CreditCardFromStatement(const sql::Statement& s) {
122 CreditCard* credit_card = new CreditCard;
123
124 credit_card->set_guid(s.ColumnString(0));
125 DCHECK(guid::IsValidGUID(credit_card->guid()));
126
127 credit_card->SetInfo(CREDIT_CARD_NAME, s.ColumnString16(1));
128 credit_card->SetInfo(CREDIT_CARD_EXP_MONTH,
129 s.ColumnString16(2));
130 credit_card->SetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR,
131 s.ColumnString16(3));
132 int encrypted_number_len = s.ColumnByteLength(4);
133 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->SetInfo(CREDIT_CARD_NUMBER, credit_card_number);
141 // Intentionally skip column 5, which stores the modification date.
142
143 return credit_card;
144 }
145
146 bool AddAutofillProfileNamesToProfile(sql::Connection* db,
147 AutofillProfile* profile) {
148 sql::Statement s(db->GetUniqueStatement(
149 "SELECT guid, first_name, middle_name, last_name "
150 "FROM autofill_profile_names "
151 "WHERE guid=?"));
152 if (!s) {
153 NOTREACHED() << "Statement prepare failed";
154 return false;
155 }
156 s.BindString(0, profile->guid());
157
158 std::vector<string16> first_names;
159 std::vector<string16> middle_names;
160 std::vector<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 profile->SetMultiInfo(NAME_FIRST, first_names);
168 profile->SetMultiInfo(NAME_MIDDLE, middle_names);
169 profile->SetMultiInfo(NAME_LAST, last_names);
170 return true;
171 }
172
173 bool AddAutofillProfileEmailsToProfile(sql::Connection* db,
174 AutofillProfile* profile) {
175 sql::Statement s(db->GetUniqueStatement(
176 "SELECT guid, email "
177 "FROM autofill_profile_emails "
178 "WHERE guid=?"));
179 if (!s) {
180 NOTREACHED() << "Statement prepare failed";
181 return false;
182 }
183 s.BindString(0, profile->guid());
184
185 std::vector<string16> emails;
186 while (s.Step()) {
187 DCHECK_EQ(profile->guid(), s.ColumnString(0));
188 emails.push_back(s.ColumnString16(1));
189 }
190 profile->SetMultiInfo(EMAIL_ADDRESS, emails);
191 return true;
192 }
193
194 bool AddAutofillProfilePhonesToProfile(sql::Connection* db,
195 AutofillProfile* profile) {
196 sql::Statement s(db->GetUniqueStatement(
197 "SELECT guid, type, number "
198 "FROM autofill_profile_phones "
199 "WHERE guid=? AND type=?"));
200 if (!s) {
201 NOTREACHED() << "Statement prepare failed";
202 return false;
203 }
204 s.BindString(0, profile->guid());
205 s.BindInt(1, kAutofillPhoneNumber);
206
207 std::vector<string16> numbers;
208 while (s.Step()) {
209 DCHECK_EQ(profile->guid(), s.ColumnString(0));
210 numbers.push_back(s.ColumnString16(2));
211 }
212 profile->SetMultiInfo(PHONE_HOME_WHOLE_NUMBER, numbers);
213 return true;
214 }
215
216 bool AddAutofillProfileFaxesToProfile(sql::Connection* db,
217 AutofillProfile* profile) {
218 sql::Statement s(db->GetUniqueStatement(
219 "SELECT guid, type, number "
220 "FROM autofill_profile_phones "
221 "WHERE guid=? AND type=?"));
222 if (!s) {
223 NOTREACHED() << "Statement prepare failed";
224 return false;
225 }
226 s.BindString(0, profile->guid());
227 s.BindInt(1, kAutofillFaxNumber);
228
229 std::vector<string16> numbers;
230 while (s.Step()) {
231 DCHECK_EQ(profile->guid(), s.ColumnString(0));
232 numbers.push_back(s.ColumnString16(2));
233 }
234 profile->SetMultiInfo(PHONE_FAX_WHOLE_NUMBER, numbers);
235 return true;
236 }
237
238
239 bool AddAutofillProfileNames(const AutofillProfile& profile,
240 sql::Connection* db) {
241 std::vector<string16> first_names;
242 profile.GetMultiInfo(NAME_FIRST, &first_names);
243 std::vector<string16> middle_names;
244 profile.GetMultiInfo(NAME_MIDDLE, &middle_names);
245 std::vector<string16> last_names;
246 profile.GetMultiInfo(NAME_LAST, &last_names);
247 DCHECK_EQ(first_names.size(), middle_names.size());
248 DCHECK_EQ(middle_names.size(), last_names.size());
249
250 for (size_t i = 0; i < first_names.size(); ++i) {
251 // Add the new name.
252 sql::Statement s(db->GetUniqueStatement(
253 "INSERT INTO autofill_profile_names"
254 " (guid, first_name, middle_name, last_name) "
255 "VALUES (?,?,?,?)"));
256 if (!s) {
257 NOTREACHED();
258 return false;
259 }
260 s.BindString(0, profile.guid());
261 s.BindString16(1, first_names[i]);
262 s.BindString16(2, middle_names[i]);
263 s.BindString16(3, last_names[i]);
264
265 if (!s.Run()) {
266 NOTREACHED();
267 return false;
268 }
269 }
270 return true;
271 }
272
273 bool AddAutofillProfileEmails(const AutofillProfile& profile,
274 sql::Connection* db) {
275 std::vector<string16> emails;
276 profile.GetMultiInfo(EMAIL_ADDRESS, &emails);
277
278 for (size_t i = 0; i < emails.size(); ++i) {
279 // Add the new email.
280 sql::Statement s(db->GetUniqueStatement(
281 "INSERT INTO autofill_profile_emails"
282 " (guid, email) "
283 "VALUES (?,?)"));
284 if (!s) {
285 NOTREACHED();
286 return false;
287 }
288 s.BindString(0, profile.guid());
289 s.BindString16(1, emails[i]);
290
291 if (!s.Run()) {
292 NOTREACHED();
293 return false;
294 }
295 }
296 return true;
297 }
298
299 bool AddAutofillProfilePhones(const AutofillProfile& profile,
300 AutofillPhoneType phone_type,
301 sql::Connection* db) {
302 AutofillFieldType field_type;
303 if (phone_type == kAutofillPhoneNumber) {
304 field_type = PHONE_HOME_WHOLE_NUMBER;
305 } else if (phone_type == kAutofillFaxNumber) {
306 field_type = PHONE_FAX_WHOLE_NUMBER;
307 } else {
308 NOTREACHED();
309 return false;
310 }
311
312 std::vector<string16> numbers;
313 profile.GetMultiInfo(field_type, &numbers);
314
315 for (size_t i = 0; i < numbers.size(); ++i) {
316 // Add the new number.
317 sql::Statement s(db->GetUniqueStatement(
318 "INSERT INTO autofill_profile_phones"
319 " (guid, type, number) "
320 "VALUES (?,?,?)"));
321 if (!s) {
322 NOTREACHED();
323 return false;
324 }
325 s.BindString(0, profile.guid());
326 s.BindInt(1, phone_type);
327 s.BindString16(2, numbers[i]);
328
329 if (!s.Run()) {
330 NOTREACHED();
331 return false;
332 }
333 }
334 return true;
335 }
336
337 bool AddAutofillProfilePieces(const AutofillProfile& profile,
338 sql::Connection* db) {
339 if (!AddAutofillProfileNames(profile, db))
340 return false;
341
342 if (!AddAutofillProfileEmails(profile, db))
343 return false;
344
345 if (!AddAutofillProfilePhones(profile, kAutofillPhoneNumber, db))
346 return false;
347
348 if (!AddAutofillProfilePhones(profile, kAutofillFaxNumber, db))
349 return false;
350
351 return true;
352 }
353
354 bool RemoveAutofillProfilePieces(const std::string& guid, sql::Connection* db) {
355 sql::Statement s1(db->GetUniqueStatement(
356 "DELETE FROM autofill_profile_names WHERE guid = ?"));
357 if (!s1) {
358 NOTREACHED() << "Statement prepare failed";
359 return false;
360 }
361
362 s1.BindString(0, guid);
363 if (!s1.Run())
364 return false;
365
366 sql::Statement s2(db->GetUniqueStatement(
367 "DELETE FROM autofill_profile_emails WHERE guid = ?"));
368 if (!s2) {
369 NOTREACHED() << "Statement prepare failed";
370 return false;
371 }
372
373 s2.BindString(0, guid);
374 if (!s2.Run())
375 return false;
376
377 sql::Statement s3(db->GetUniqueStatement(
378 "DELETE FROM autofill_profile_phones WHERE guid = ?"));
379 if (!s3) {
380 NOTREACHED() << "Statement prepare failed";
381 return false;
382 }
383
384 s3.BindString(0, guid);
385 return s3.Run();
386 }
387
388 } // namespace
27 389
28 bool AutofillTable::Init() { 390 bool AutofillTable::Init() {
29 return (InitMainTable() && InitCreditCardsTable() && InitDatesTable() && 391 return (InitMainTable() && InitCreditCardsTable() && InitDatesTable() &&
30 InitProfilesTable() && InitProfileNamesTable() && 392 InitProfilesTable() && InitProfileNamesTable() &&
31 InitProfileEmailsTable() && InitProfilePhonesTable() && 393 InitProfileEmailsTable() && InitProfilePhonesTable() &&
32 InitProfileTrashTable()); 394 InitProfileTrashTable());
33 } 395 }
34 396
35 bool AutofillTable::IsSyncable() { 397 bool AutofillTable::IsSyncable() {
36 return true; 398 return true;
(...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 sql::Statement s(db_->GetUniqueStatement( 892 sql::Statement s(db_->GetUniqueStatement(
531 "INSERT INTO autofill_profiles" 893 "INSERT INTO autofill_profiles"
532 "(guid, company_name, address_line_1, address_line_2, city, state," 894 "(guid, company_name, address_line_1, address_line_2, city, state,"
533 " zipcode, country, country_code, date_modified)" 895 " zipcode, country, country_code, date_modified)"
534 "VALUES (?,?,?,?,?,?,?,?,?,?)")); 896 "VALUES (?,?,?,?,?,?,?,?,?,?)"));
535 if (!s) { 897 if (!s) {
536 NOTREACHED() << "Statement prepare failed"; 898 NOTREACHED() << "Statement prepare failed";
537 return false; 899 return false;
538 } 900 }
539 901
540 autofill_util::BindAutofillProfileToStatement(profile, &s); 902 BindAutofillProfileToStatement(profile, &s);
541 903
542 if (!s.Run()) { 904 if (!s.Run()) {
543 NOTREACHED(); 905 NOTREACHED();
544 return false; 906 return false;
545 } 907 }
546 908
547 if (!s.Succeeded()) 909 if (!s.Succeeded())
548 return false; 910 return false;
549 911
550 return autofill_util::AddAutofillProfilePieces(profile, db_); 912 return AddAutofillProfilePieces(profile, db_);
551 } 913 }
552 914
553 bool AutofillTable::GetAutofillProfile(const std::string& guid, 915 bool AutofillTable::GetAutofillProfile(const std::string& guid,
554 AutofillProfile** profile) { 916 AutofillProfile** profile) {
555 DCHECK(guid::IsValidGUID(guid)); 917 DCHECK(guid::IsValidGUID(guid));
556 DCHECK(profile); 918 DCHECK(profile);
557 sql::Statement s(db_->GetUniqueStatement( 919 sql::Statement s(db_->GetUniqueStatement(
558 "SELECT guid, company_name, address_line_1, address_line_2, city, state," 920 "SELECT guid, company_name, address_line_1, address_line_2, city, state,"
559 " zipcode, country, country_code, date_modified " 921 " zipcode, country, country_code, date_modified "
560 "FROM autofill_profiles " 922 "FROM autofill_profiles "
561 "WHERE guid=?")); 923 "WHERE guid=?"));
562 if (!s) { 924 if (!s) {
563 NOTREACHED() << "Statement prepare failed"; 925 NOTREACHED() << "Statement prepare failed";
564 return false; 926 return false;
565 } 927 }
566 928
567 s.BindString(0, guid); 929 s.BindString(0, guid);
568 if (!s.Step()) 930 if (!s.Step())
569 return false; 931 return false;
570 932
571 if (!s.Succeeded()) 933 if (!s.Succeeded())
572 return false; 934 return false;
573 935
574 scoped_ptr<AutofillProfile> p(autofill_util::AutofillProfileFromStatement(s)); 936 scoped_ptr<AutofillProfile> p(AutofillProfileFromStatement(s));
575 937
576 // Get associated name info. 938 // Get associated name info.
577 autofill_util::AddAutofillProfileNamesToProfile(db_, p.get()); 939 AddAutofillProfileNamesToProfile(db_, p.get());
578 940
579 // Get associated email info. 941 // Get associated email info.
580 autofill_util::AddAutofillProfileEmailsToProfile(db_, p.get()); 942 AddAutofillProfileEmailsToProfile(db_, p.get());
581 943
582 // Get associated phone info. 944 // Get associated phone info.
583 autofill_util::AddAutofillProfilePhonesToProfile(db_, p.get()); 945 AddAutofillProfilePhonesToProfile(db_, p.get());
584 946
585 // Get associated fax info. 947 // Get associated fax info.
586 autofill_util::AddAutofillProfileFaxesToProfile(db_, p.get()); 948 AddAutofillProfileFaxesToProfile(db_, p.get());
587 949
588 *profile = p.release(); 950 *profile = p.release();
589 return true; 951 return true;
590 } 952 }
591 953
592 bool AutofillTable::GetAutofillProfiles( 954 bool AutofillTable::GetAutofillProfiles(
593 std::vector<AutofillProfile*>* profiles) { 955 std::vector<AutofillProfile*>* profiles) {
594 DCHECK(profiles); 956 DCHECK(profiles);
595 profiles->clear(); 957 profiles->clear();
596 958
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
673 "UPDATE autofill_profiles " 1035 "UPDATE autofill_profiles "
674 "SET guid=?, company_name=?, address_line_1=?, address_line_2=?, " 1036 "SET guid=?, company_name=?, address_line_1=?, address_line_2=?, "
675 " city=?, state=?, zipcode=?, country=?, country_code=?, " 1037 " city=?, state=?, zipcode=?, country=?, country_code=?, "
676 " date_modified=? " 1038 " date_modified=? "
677 "WHERE guid=?")); 1039 "WHERE guid=?"));
678 if (!s) { 1040 if (!s) {
679 NOTREACHED() << "Statement prepare failed"; 1041 NOTREACHED() << "Statement prepare failed";
680 return false; 1042 return false;
681 } 1043 }
682 1044
683 autofill_util::BindAutofillProfileToStatement(profile, &s); 1045 BindAutofillProfileToStatement(profile, &s);
684 s.BindString(10, profile.guid()); 1046 s.BindString(10, profile.guid());
685 bool result = s.Run(); 1047 bool result = s.Run();
686 DCHECK_GT(db_->GetLastChangeCount(), 0); 1048 DCHECK_GT(db_->GetLastChangeCount(), 0);
687 if (!result) 1049 if (!result)
688 return result; 1050 return result;
689 1051
690 // Remove the old names, emails, and phone/fax numbers. 1052 // Remove the old names, emails, and phone/fax numbers.
691 if (!autofill_util::RemoveAutofillProfilePieces(profile.guid(), db_)) 1053 if (!RemoveAutofillProfilePieces(profile.guid(), db_))
692 return false; 1054 return false;
693 1055
694 return autofill_util::AddAutofillProfilePieces(profile, db_); 1056 return AddAutofillProfilePieces(profile, db_);
695 } 1057 }
696 1058
697 bool AutofillTable::RemoveAutofillProfile(const std::string& guid) { 1059 bool AutofillTable::RemoveAutofillProfile(const std::string& guid) {
698 DCHECK(guid::IsValidGUID(guid)); 1060 DCHECK(guid::IsValidGUID(guid));
699 1061
700 if (IsAutofillGUIDInTrash(guid)) { 1062 if (IsAutofillGUIDInTrash(guid)) {
701 sql::Statement s_trash(db_->GetUniqueStatement( 1063 sql::Statement s_trash(db_->GetUniqueStatement(
702 "DELETE FROM autofill_profiles_trash WHERE guid = ?")); 1064 "DELETE FROM autofill_profiles_trash WHERE guid = ?"));
703 if (!s_trash) { 1065 if (!s_trash) {
704 NOTREACHED() << "Statement prepare failed"; 1066 NOTREACHED() << "Statement prepare failed";
(...skipping 12 matching lines...) Expand all
717 "DELETE FROM autofill_profiles WHERE guid = ?")); 1079 "DELETE FROM autofill_profiles WHERE guid = ?"));
718 if (!s) { 1080 if (!s) {
719 NOTREACHED() << "Statement prepare failed"; 1081 NOTREACHED() << "Statement prepare failed";
720 return false; 1082 return false;
721 } 1083 }
722 1084
723 s.BindString(0, guid); 1085 s.BindString(0, guid);
724 if (!s.Run()) 1086 if (!s.Run())
725 return false; 1087 return false;
726 1088
727 return autofill_util::RemoveAutofillProfilePieces(guid, db_); 1089 return RemoveAutofillProfilePieces(guid, db_);
728 } 1090 }
729 1091
730 bool AutofillTable::ClearAutofillProfiles() { 1092 bool AutofillTable::ClearAutofillProfiles() {
731 sql::Statement s1(db_->GetUniqueStatement( 1093 sql::Statement s1(db_->GetUniqueStatement(
732 "DELETE FROM autofill_profiles")); 1094 "DELETE FROM autofill_profiles"));
733 if (!s1) { 1095 if (!s1) {
734 NOTREACHED() << "Statement prepare failed"; 1096 NOTREACHED() << "Statement prepare failed";
735 return false; 1097 return false;
736 } 1098 }
737 1099
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
775 sql::Statement s(db_->GetUniqueStatement( 1137 sql::Statement s(db_->GetUniqueStatement(
776 "INSERT INTO credit_cards" 1138 "INSERT INTO credit_cards"
777 "(guid, name_on_card, expiration_month, expiration_year, " 1139 "(guid, name_on_card, expiration_month, expiration_year, "
778 "card_number_encrypted, date_modified)" 1140 "card_number_encrypted, date_modified)"
779 "VALUES (?,?,?,?,?,?)")); 1141 "VALUES (?,?,?,?,?,?)"));
780 if (!s) { 1142 if (!s) {
781 NOTREACHED() << "Statement prepare failed"; 1143 NOTREACHED() << "Statement prepare failed";
782 return false; 1144 return false;
783 } 1145 }
784 1146
785 autofill_util::BindCreditCardToStatement(credit_card, &s); 1147 BindCreditCardToStatement(credit_card, &s);
786 1148
787 if (!s.Run()) { 1149 if (!s.Run()) {
788 NOTREACHED(); 1150 NOTREACHED();
789 return false; 1151 return false;
790 } 1152 }
791 1153
792 DCHECK_GT(db_->GetLastChangeCount(), 0); 1154 DCHECK_GT(db_->GetLastChangeCount(), 0);
793 return s.Succeeded(); 1155 return s.Succeeded();
794 } 1156 }
795 1157
796 bool AutofillTable::GetCreditCard(const std::string& guid, 1158 bool AutofillTable::GetCreditCard(const std::string& guid,
797 CreditCard** credit_card) { 1159 CreditCard** credit_card) {
798 DCHECK(guid::IsValidGUID(guid)); 1160 DCHECK(guid::IsValidGUID(guid));
799 sql::Statement s(db_->GetUniqueStatement( 1161 sql::Statement s(db_->GetUniqueStatement(
800 "SELECT guid, name_on_card, expiration_month, expiration_year, " 1162 "SELECT guid, name_on_card, expiration_month, expiration_year, "
801 "card_number_encrypted, date_modified " 1163 "card_number_encrypted, date_modified "
802 "FROM credit_cards " 1164 "FROM credit_cards "
803 "WHERE guid = ?")); 1165 "WHERE guid = ?"));
804 if (!s) { 1166 if (!s) {
805 NOTREACHED() << "Statement prepare failed"; 1167 NOTREACHED() << "Statement prepare failed";
806 return false; 1168 return false;
807 } 1169 }
808 1170
809 s.BindString(0, guid); 1171 s.BindString(0, guid);
810 if (!s.Step()) 1172 if (!s.Step())
811 return false; 1173 return false;
812 1174
813 *credit_card = autofill_util::CreditCardFromStatement(s); 1175 *credit_card = CreditCardFromStatement(s);
814 1176
815 return s.Succeeded(); 1177 return s.Succeeded();
816 } 1178 }
817 1179
818 bool AutofillTable::GetCreditCards( 1180 bool AutofillTable::GetCreditCards(
819 std::vector<CreditCard*>* credit_cards) { 1181 std::vector<CreditCard*>* credit_cards) {
820 DCHECK(credit_cards); 1182 DCHECK(credit_cards);
821 credit_cards->clear(); 1183 credit_cards->clear();
822 1184
823 sql::Statement s(db_->GetUniqueStatement( 1185 sql::Statement s(db_->GetUniqueStatement(
(...skipping 30 matching lines...) Expand all
854 sql::Statement s(db_->GetUniqueStatement( 1216 sql::Statement s(db_->GetUniqueStatement(
855 "UPDATE credit_cards " 1217 "UPDATE credit_cards "
856 "SET guid=?, name_on_card=?, expiration_month=?, " 1218 "SET guid=?, name_on_card=?, expiration_month=?, "
857 " expiration_year=?, card_number_encrypted=?, date_modified=? " 1219 " expiration_year=?, card_number_encrypted=?, date_modified=? "
858 "WHERE guid=?")); 1220 "WHERE guid=?"));
859 if (!s) { 1221 if (!s) {
860 NOTREACHED() << "Statement prepare failed"; 1222 NOTREACHED() << "Statement prepare failed";
861 return false; 1223 return false;
862 } 1224 }
863 1225
864 autofill_util::BindCreditCardToStatement(credit_card, &s); 1226 BindCreditCardToStatement(credit_card, &s);
865 s.BindString(6, credit_card.guid()); 1227 s.BindString(6, credit_card.guid());
866 bool result = s.Run(); 1228 bool result = s.Run();
867 DCHECK_GT(db_->GetLastChangeCount(), 0); 1229 DCHECK_GT(db_->GetLastChangeCount(), 0);
868 return result; 1230 return result;
869 } 1231 }
870 1232
871 bool AutofillTable::RemoveCreditCard(const std::string& guid) { 1233 bool AutofillTable::RemoveCreditCard(const std::string& guid) {
872 DCHECK(guid::IsValidGUID(guid)); 1234 DCHECK(guid::IsValidGUID(guid));
873 sql::Statement s(db_->GetUniqueStatement( 1235 sql::Statement s(db_->GetUniqueStatement(
874 "DELETE FROM credit_cards WHERE guid = ?")); 1236 "DELETE FROM credit_cards WHERE guid = ?"));
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
1141 bool AutofillTable::InitProfileTrashTable() { 1503 bool AutofillTable::InitProfileTrashTable() {
1142 if (!db_->DoesTableExist("autofill_profiles_trash")) { 1504 if (!db_->DoesTableExist("autofill_profiles_trash")) {
1143 if (!db_->Execute("CREATE TABLE autofill_profiles_trash ( " 1505 if (!db_->Execute("CREATE TABLE autofill_profiles_trash ( "
1144 "guid VARCHAR)")) { 1506 "guid VARCHAR)")) {
1145 NOTREACHED(); 1507 NOTREACHED();
1146 return false; 1508 return false;
1147 } 1509 }
1148 } 1510 }
1149 return true; 1511 return true;
1150 } 1512 }
1513
1514 // Add the card_number_encrypted column if credit card table was not
1515 // created in this build (otherwise the column already exists).
1516 // WARNING: Do not change the order of the execution of the SQL
1517 // statements in this case! Profile corruption and data migration
1518 // issues WILL OCCUR. See http://crbug.com/10913
1519 //
1520 // The problem is that if a user has a profile which was created before
1521 // r37036, when the credit_cards table was added, and then failed to
1522 // update this profile between the credit card addition and the addition
1523 // of the "encrypted" columns (44963), the next data migration will put
1524 // the user's profile in an incoherent state: The user will update from
1525 // a data profile set to be earlier than 22, and therefore pass through
1526 // this update case. But because the user did not have a credit_cards
1527 // table before starting Chrome, it will have just been initialized
1528 // above, and so already have these columns -- and thus this data
1529 // update step will have failed.
1530 //
1531 // The false assumption in this case is that at this step in the
1532 // migration, the user has a credit card table, and that this
1533 // table does not include encrypted columns!
1534 // Because this case does not roll back the complete set of SQL
1535 // transactions properly in case of failure (that is, it does not
1536 // roll back the table initialization done above), the incoherent
1537 // profile will now see itself as being at version 22 -- but include a
1538 // fully initialized credit_cards table. Every time Chrome runs, it
1539 // will try to update the web database and fail at this step, unless
1540 // we allow for the faulty assumption described above by checking for
1541 // the existence of the columns only AFTER we've executed the commands
1542 // to add them.
1543 bool AutofillTable::MigrateToVersion23AddCardNumberEncryptedColumn() {
1544 if (!db_->DoesColumnExist("credit_cards", "card_number_encrypted")) {
1545 if (!db_->Execute("ALTER TABLE credit_cards ADD COLUMN "
1546 "card_number_encrypted BLOB DEFAULT NULL")) {
1547 LOG(WARNING) << "Could not add card_number_encrypted to "
1548 "credit_cards table.";
1549 return false;
1550 }
1551 }
1552
1553 if (!db_->DoesColumnExist("credit_cards", "verification_code_encrypted")) {
1554 if (!db_->Execute("ALTER TABLE credit_cards ADD COLUMN "
1555 "verification_code_encrypted BLOB DEFAULT NULL")) {
1556 LOG(WARNING) << "Could not add verification_code_encrypted to "
1557 "credit_cards table.";
1558 return false;
1559 }
1560 }
1561
1562 return true;
1563 }
1564
1565 // One-time cleanup for http://crbug.com/38364 - In the presence of
1566 // multi-byte UTF-8 characters, that bug could cause Autofill strings
1567 // to grow larger and more corrupt with each save. The cleanup removes
1568 // any row with a string field larger than a reasonable size. The string
1569 // fields examined here are precisely the ones that were subject to
1570 // corruption by the original bug.
1571 bool AutofillTable::MigrateToVersion24CleanupOversizedStringFields() {
1572 const std::string autofill_is_too_big =
1573 "max(length(name), length(value)) > 500";
1574
1575 const std::string credit_cards_is_too_big =
1576 "max(length(label), length(name_on_card), length(type), "
1577 " length(expiration_month), length(expiration_year), "
1578 " length(billing_address), length(shipping_address) "
1579 ") > 500";
1580
1581 const std::string autofill_profiles_is_too_big =
1582 "max(length(label), length(first_name), "
1583 " length(middle_name), length(last_name), length(email), "
1584 " length(company_name), length(address_line_1), "
1585 " length(address_line_2), length(city), length(state), "
1586 " length(zipcode), length(country), length(phone), "
1587 " length(fax)) > 500";
1588
1589 std::string query = "DELETE FROM autofill_dates WHERE pair_id IN ("
1590 "SELECT pair_id FROM autofill WHERE " + autofill_is_too_big + ")";
1591
1592 if (!db_->Execute(query.c_str()))
1593 return false;
1594
1595 query = "DELETE FROM autofill WHERE " + autofill_is_too_big;
1596
1597 if (!db_->Execute(query.c_str()))
1598 return false;
1599
1600 // Only delete from legacy credit card tables where specific columns exist.
1601 if (db_->DoesColumnExist("credit_cards", "label") &&
1602 db_->DoesColumnExist("credit_cards", "name_on_card") &&
1603 db_->DoesColumnExist("credit_cards", "type") &&
1604 db_->DoesColumnExist("credit_cards", "expiration_month") &&
1605 db_->DoesColumnExist("credit_cards", "expiration_year") &&
1606 db_->DoesColumnExist("credit_cards", "billing_address") &&
1607 db_->DoesColumnExist("credit_cards", "shipping_address") &&
1608 db_->DoesColumnExist("autofill_profiles", "label")) {
1609 query = "DELETE FROM credit_cards WHERE (" + credit_cards_is_too_big +
1610 ") OR label IN (SELECT label FROM autofill_profiles WHERE " +
1611 autofill_profiles_is_too_big + ")";
1612
1613 if (!db_->Execute(query.c_str()))
1614 return false;
1615 }
1616
1617 if (db_->DoesColumnExist("autofill_profiles", "label")) {
1618 query = "DELETE FROM autofill_profiles WHERE " +
1619 autofill_profiles_is_too_big;
1620
1621 if (!db_->Execute(query.c_str()))
1622 return false;
1623 }
1624
1625 return true;
1626 }
1627
1628 // Change the credit_cards.billing_address column from a string to an
1629 // int. The stored string is the label of an address, so we have to
1630 // select the unique ID of this address using the label as a foreign
1631 // key into the |autofill_profiles| table.
1632 bool AutofillTable::MigrateToVersion27UpdateLegacyCreditCards() {
1633 // Only migrate from legacy credit card tables where specific columns
1634 // exist.
1635 if (!(db_->DoesColumnExist("credit_cards", "unique_id") &&
1636 db_->DoesColumnExist("credit_cards", "billing_address") &&
1637 db_->DoesColumnExist("autofill_profiles", "unique_id"))) {
1638 return true;
1639 }
1640
1641 std::string stmt =
1642 "SELECT credit_cards.unique_id, autofill_profiles.unique_id "
1643 "FROM autofill_profiles, credit_cards "
1644 "WHERE credit_cards.billing_address = autofill_profiles.label";
1645 sql::Statement s(db_->GetUniqueStatement(stmt.c_str()));
1646 if (!s)
1647 return false;
1648
1649 std::map<int, int> cc_billing_map;
1650 while (s.Step())
1651 cc_billing_map[s.ColumnInt(0)] = s.ColumnInt(1);
1652
1653 // Windows already stores the IDs as strings in |billing_address|. Try
1654 // to convert those.
1655 if (cc_billing_map.empty()) {
1656 std::string stmt = "SELECT unique_id,billing_address FROM credit_cards";
1657 sql::Statement s(db_->GetUniqueStatement(stmt.c_str()));
1658 if (!s)
1659 return false;
1660
1661 while (s.Step()) {
1662 int id = 0;
1663 if (base::StringToInt(s.ColumnString(1), &id))
1664 cc_billing_map[s.ColumnInt(0)] = id;
1665 }
1666 }
1667
1668 if (!db_->Execute("CREATE TABLE credit_cards_temp ( "
1669 "label VARCHAR, "
1670 "unique_id INTEGER PRIMARY KEY, "
1671 "name_on_card VARCHAR, "
1672 "type VARCHAR, "
1673 "card_number VARCHAR, "
1674 "expiration_month INTEGER, "
1675 "expiration_year INTEGER, "
1676 "verification_code VARCHAR, "
1677 "billing_address INTEGER, "
1678 "shipping_address VARCHAR, "
1679 "card_number_encrypted BLOB, "
1680 "verification_code_encrypted BLOB)")) {
1681 return false;
1682 }
1683
1684 if (!db_->Execute(
1685 "INSERT INTO credit_cards_temp "
1686 "SELECT label,unique_id,name_on_card,type,card_number,"
1687 "expiration_month,expiration_year,verification_code,0,"
1688 "shipping_address,card_number_encrypted,"
1689 "verification_code_encrypted FROM credit_cards")) {
1690 return false;
1691 }
1692
1693 if (!db_->Execute("DROP TABLE credit_cards"))
1694 return false;
1695
1696 if (!db_->Execute("ALTER TABLE credit_cards_temp RENAME TO credit_cards"))
1697 return false;
1698
1699 for (std::map<int, int>::const_iterator iter = cc_billing_map.begin();
1700 iter != cc_billing_map.end(); ++iter) {
1701 sql::Statement s(db_->GetCachedStatement(
1702 SQL_FROM_HERE,
1703 "UPDATE credit_cards SET billing_address=? WHERE unique_id=?"));
1704 if (!s)
1705 return false;
1706
1707 s.BindInt(0, (*iter).second);
1708 s.BindInt(1, (*iter).first);
1709
1710 if (!s.Run())
1711 return false;
1712 }
1713
1714 return true;
1715 }
1716
1717 bool AutofillTable::MigrateToVersion30AddDateModifed() {
1718 // Add date_modified to autofill_profiles.
1719 if (!db_->DoesColumnExist("autofill_profiles", "date_modified")) {
1720 if (!db_->Execute("ALTER TABLE autofill_profiles ADD COLUMN "
1721 "date_modified INTEGER NON NULL DEFAULT 0")) {
1722 return false;
1723 }
1724
1725 sql::Statement s(db_->GetUniqueStatement(
1726 "UPDATE autofill_profiles SET date_modified=?"));
1727 if (!s)
1728 return false;
1729
1730 s.BindInt64(0, Time::Now().ToTimeT());
1731
1732 if (!s.Run())
1733 return false;
1734 }
1735
1736 // Add date_modified to credit_cards.
1737 if (!db_->DoesColumnExist("credit_cards", "date_modified")) {
1738 if (!db_->Execute("ALTER TABLE credit_cards ADD COLUMN "
1739 "date_modified INTEGER NON NULL DEFAULT 0")) {
1740 return false;
1741 }
1742
1743 sql::Statement s(db_->GetUniqueStatement(
1744 "UPDATE credit_cards SET date_modified=?"));
1745 if (!s)
1746 return false;
1747
1748 s.BindInt64(0, Time::Now().ToTimeT());
1749
1750 if (!s.Run())
1751 return false;
1752 }
1753
1754 return true;
1755 }
1756
1757 bool AutofillTable::MigrateToVersion31AddGUIDToCreditCardsAndProfiles() {
1758 // Note that we need to check for the guid column's existence due to the
1759 // fact that for a version 22 database the |autofill_profiles| table
1760 // gets created fresh with |InitAutofillProfilesTable|.
1761 if (!db_->DoesColumnExist("autofill_profiles", "guid")) {
1762 if (!db_->Execute("ALTER TABLE autofill_profiles ADD COLUMN "
1763 "guid VARCHAR NOT NULL DEFAULT \"\"")) {
1764 return false;
1765 }
1766
1767 // Set all the |guid| fields to valid values.
1768
1769 sql::Statement s(db_->GetUniqueStatement("SELECT unique_id "
1770 "FROM autofill_profiles"));
1771 if (!s)
1772 return false;
1773
1774 while (s.Step()) {
1775 sql::Statement update_s(
1776 db_->GetUniqueStatement("UPDATE autofill_profiles "
1777 "SET guid=? WHERE unique_id=?"));
1778 if (!update_s)
1779 return false;
1780 update_s.BindString(0, guid::GenerateGUID());
1781 update_s.BindInt(1, s.ColumnInt(0));
1782
1783 if (!update_s.Run())
1784 return false;
1785 }
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 if (!s)
1802 return false;
1803
1804 while (s.Step()) {
1805 sql::Statement update_s(
1806 db_->GetUniqueStatement("UPDATE credit_cards "
1807 "set guid=? WHERE unique_id=?"));
1808 if (!update_s)
1809 return false;
1810 update_s.BindString(0, guid::GenerateGUID());
1811 update_s.BindInt(1, s.ColumnInt(0));
1812
1813 if (!update_s.Run())
1814 return false;
1815 }
1816 }
1817
1818 return true;
1819 }
1820
1821 bool AutofillTable::MigrateToVersion32UpdateProfilesAndCreditCards() {
1822 if (db_->DoesColumnExist("autofill_profiles", "unique_id")) {
1823 if (!db_->Execute("CREATE TABLE autofill_profiles_temp ( "
1824 "guid VARCHAR PRIMARY KEY, "
1825 "label VARCHAR, "
1826 "first_name VARCHAR, "
1827 "middle_name VARCHAR, "
1828 "last_name VARCHAR, "
1829 "email VARCHAR, "
1830 "company_name VARCHAR, "
1831 "address_line_1 VARCHAR, "
1832 "address_line_2 VARCHAR, "
1833 "city VARCHAR, "
1834 "state VARCHAR, "
1835 "zipcode VARCHAR, "
1836 "country VARCHAR, "
1837 "phone VARCHAR, "
1838 "fax VARCHAR, "
1839 "date_modified INTEGER NOT NULL DEFAULT 0)")) {
1840 return false;
1841 }
1842
1843 if (!db_->Execute(
1844 "INSERT INTO autofill_profiles_temp "
1845 "SELECT guid, label, first_name, middle_name, last_name, email, "
1846 "company_name, address_line_1, address_line_2, city, state, "
1847 "zipcode, country, phone, fax, date_modified "
1848 "FROM autofill_profiles")) {
1849 return false;
1850 }
1851
1852 if (!db_->Execute("DROP TABLE autofill_profiles"))
1853 return false;
1854
1855 if (!db_->Execute(
1856 "ALTER TABLE autofill_profiles_temp RENAME TO autofill_profiles")) {
1857 return false;
1858 }
1859 }
1860
1861 if (db_->DoesColumnExist("credit_cards", "unique_id")) {
1862 if (!db_->Execute("CREATE TABLE credit_cards_temp ( "
1863 "guid VARCHAR PRIMARY KEY, "
1864 "label VARCHAR, "
1865 "name_on_card VARCHAR, "
1866 "expiration_month INTEGER, "
1867 "expiration_year INTEGER, "
1868 "card_number_encrypted BLOB, "
1869 "date_modified INTEGER NOT NULL DEFAULT 0)")) {
1870 return false;
1871 }
1872
1873 if (!db_->Execute(
1874 "INSERT INTO credit_cards_temp "
1875 "SELECT guid, label, name_on_card, expiration_month, "
1876 "expiration_year, card_number_encrypted, date_modified "
1877 "FROM credit_cards")) {
1878 return false;
1879 }
1880
1881 if (!db_->Execute("DROP TABLE credit_cards"))
1882 return false;
1883
1884 if (!db_->Execute("ALTER TABLE credit_cards_temp RENAME TO credit_cards"))
1885 return false;
1886 }
1887
1888 return true;
1889 }
1890
1891 // Test the existence of the |first_name| column as an indication that
1892 // we need a migration. It is possible that the new |autofill_profiles|
1893 // schema is in place because the table was newly created when migrating
1894 // from a pre-version-22 database.
1895 bool AutofillTable::MigrateToVersion33ProfilesBasedOnFirstName() {
1896 if (db_->DoesColumnExist("autofill_profiles", "first_name")) {
1897 // Create autofill_profiles_temp table that will receive the data.
1898 if (!db_->DoesTableExist("autofill_profiles_temp")) {
1899 if (!db_->Execute("CREATE TABLE autofill_profiles_temp ( "
1900 "guid VARCHAR PRIMARY KEY, "
1901 "company_name VARCHAR, "
1902 "address_line_1 VARCHAR, "
1903 "address_line_2 VARCHAR, "
1904 "city VARCHAR, "
1905 "state VARCHAR, "
1906 "zipcode VARCHAR, "
1907 "country VARCHAR, "
1908 "date_modified INTEGER NOT NULL DEFAULT 0)")) {
1909 return false;
1910 }
1911 }
1912
1913 sql::Statement s(db_->GetUniqueStatement(
1914 "SELECT guid, first_name, middle_name, last_name, email, "
1915 "company_name, address_line_1, address_line_2, city, state, "
1916 "zipcode, country, phone, fax, date_modified "
1917 "FROM autofill_profiles"));
1918 while (s.Step()) {
1919 AutofillProfile profile;
1920 profile.set_guid(s.ColumnString(0));
1921 DCHECK(guid::IsValidGUID(profile.guid()));
1922
1923 profile.SetInfo(NAME_FIRST, s.ColumnString16(1));
1924 profile.SetInfo(NAME_MIDDLE, s.ColumnString16(2));
1925 profile.SetInfo(NAME_LAST, s.ColumnString16(3));
1926 profile.SetInfo(EMAIL_ADDRESS, s.ColumnString16(4));
1927 profile.SetInfo(COMPANY_NAME, s.ColumnString16(5));
1928 profile.SetInfo(ADDRESS_HOME_LINE1, s.ColumnString16(6));
1929 profile.SetInfo(ADDRESS_HOME_LINE2, s.ColumnString16(7));
1930 profile.SetInfo(ADDRESS_HOME_CITY, s.ColumnString16(8));
1931 profile.SetInfo(ADDRESS_HOME_STATE, s.ColumnString16(9));
1932 profile.SetInfo(ADDRESS_HOME_ZIP, s.ColumnString16(10));
1933 profile.SetInfo(ADDRESS_HOME_COUNTRY, s.ColumnString16(11));
1934 profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, s.ColumnString16(12));
1935 profile.SetInfo(PHONE_FAX_WHOLE_NUMBER, s.ColumnString16(13));
1936 int64 date_modified = s.ColumnInt64(14);
1937
1938 sql::Statement s_insert(db_->GetUniqueStatement(
1939 "INSERT INTO autofill_profiles_temp"
1940 "(guid, company_name, address_line_1, address_line_2, city,"
1941 " state, zipcode, country, date_modified)"
1942 "VALUES (?,?,?,?,?,?,?,?,?)"));
1943 if (!s)
1944 return false;
1945
1946 s_insert.BindString(0, profile.guid());
1947 s_insert.BindString16(1, profile.GetInfo(COMPANY_NAME));
1948 s_insert.BindString16(2, profile.GetInfo(ADDRESS_HOME_LINE1));
1949 s_insert.BindString16(3, profile.GetInfo(ADDRESS_HOME_LINE2));
1950 s_insert.BindString16(4, profile.GetInfo(ADDRESS_HOME_CITY));
1951 s_insert.BindString16(5, profile.GetInfo(ADDRESS_HOME_STATE));
1952 s_insert.BindString16(6, profile.GetInfo(ADDRESS_HOME_ZIP));
1953 s_insert.BindString16(7, profile.GetInfo(ADDRESS_HOME_COUNTRY));
1954 s_insert.BindInt64(8, date_modified);
1955
1956 if (!s_insert.Run())
1957 return false;
1958
1959 // Add the other bits: names, emails, and phone/fax.
1960 if (!AddAutofillProfilePieces(profile, db_))
1961 return false;
1962 }
1963
1964 if (!db_->Execute("DROP TABLE autofill_profiles"))
1965 return false;
1966
1967 if (!db_->Execute(
1968 "ALTER TABLE autofill_profiles_temp RENAME TO autofill_profiles")) {
1969 return false;
1970 }
1971 }
1972
1973 // Remove the labels column from the credit_cards table.
1974 if (db_->DoesColumnExist("credit_cards", "label")) {
1975 if (!db_->Execute("CREATE TABLE credit_cards_temp ( "
1976 "guid VARCHAR PRIMARY KEY, "
1977 "name_on_card VARCHAR, "
1978 "expiration_month INTEGER, "
1979 "expiration_year INTEGER, "
1980 "card_number_encrypted BLOB, "
1981 "date_modified INTEGER NOT NULL DEFAULT 0)")) {
1982 return false;
1983 }
1984
1985 if (!db_->Execute(
1986 "INSERT INTO credit_cards_temp "
1987 "SELECT guid, name_on_card, expiration_month, "
1988 "expiration_year, card_number_encrypted, date_modified "
1989 "FROM credit_cards")) {
1990 return false;
1991 }
1992
1993 if (!db_->Execute("DROP TABLE credit_cards"))
1994 return false;
1995
1996 if (!db_->Execute("ALTER TABLE credit_cards_temp RENAME TO credit_cards"))
1997 return false;
1998 }
1999
2000 return true;
2001 }
2002
2003 // Test the existence of the |country_code| column as an indication that
2004 // we need a migration. It is possible that the new |autofill_profiles|
2005 // schema is in place because the table was newly created when migrating
2006 // from a pre-version-22 database.
2007 bool AutofillTable::MigrateToVersion34ProfilesBasedOnCountryCode() {
2008 if (!db_->DoesColumnExist("autofill_profiles", "country_code")) {
2009 if (!db_->Execute("ALTER TABLE autofill_profiles ADD COLUMN "
2010 "country_code VARCHAR")) {
2011 return false;
2012 }
2013
2014 // Set all the |country_code| fields to match existing |country| values.
2015 sql::Statement s(db_->GetUniqueStatement("SELECT guid, country "
2016 "FROM autofill_profiles"));
2017
2018 if (!s)
2019 return false;
2020
2021 while (s.Step()) {
2022 sql::Statement update_s(
2023 db_->GetUniqueStatement("UPDATE autofill_profiles "
2024 "SET country_code=? WHERE guid=?"));
2025 if (!update_s)
2026 return false;
2027
2028 string16 country = s.ColumnString16(1);
2029 std::string app_locale = AutofillCountry::ApplicationLocale();
2030 update_s.BindString(0, AutofillCountry::GetCountryCode(country,
2031 app_locale));
2032 update_s.BindString(1, s.ColumnString(0));
2033
2034 if (!update_s.Run())
2035 return false;
2036 }
2037 }
2038
2039 return true;
2040 }
2041
2042 // Correct all country codes with value "UK" to be "GB". This data
2043 // was mistakenly introduced in build 686.0. This migration is to clean
2044 // it up. See http://crbug.com/74511 for details.
2045 bool AutofillTable::MigrateToVersion35GreatBritainCountryCodes() {
2046 sql::Statement s(db_->GetUniqueStatement(
2047 "UPDATE autofill_profiles SET country_code=\"GB\" "
2048 "WHERE country_code=\"UK\""));
2049
2050 return s.Run();
2051 }
2052
2053 // Merge and cull older profiles where possible.
2054 bool AutofillTable::MigrateToVersion36MergeAndCullOlderProfiles() {
2055 sql::Statement s(db_->GetUniqueStatement(
2056 "SELECT guid, date_modified FROM autofill_profiles"));
2057 if (!s)
2058 return false;
2059
2060 // Accumulate the good profiles.
2061 std::vector<AutofillProfile> accumulated_profiles;
2062 std::vector<AutofillProfile*> accumulated_profiles_p;
2063 std::map<std::string, int64> modification_map;
2064 while (s.Step()) {
2065 std::string guid = s.ColumnString(0);
2066 int64 date_modified = s.ColumnInt64(1);
2067 modification_map.insert(
2068 std::pair<std::string, int64>(guid, date_modified));
2069 AutofillProfile* profile = NULL;
2070 if (!GetAutofillProfile(guid, &profile))
2071 return false;
2072
2073 scoped_ptr<AutofillProfile> p(profile);
2074
2075 if (PersonalDataManager::IsValidLearnableProfile(*p)) {
2076 std::vector<AutofillProfile> merged_profiles;
2077 bool merged = PersonalDataManager::MergeProfile(
2078 *p, accumulated_profiles_p, &merged_profiles);
2079
2080 std::swap(accumulated_profiles, merged_profiles);
2081
2082 accumulated_profiles_p.clear();
2083 accumulated_profiles_p.resize(accumulated_profiles.size());
2084 std::transform(accumulated_profiles.begin(),
2085 accumulated_profiles.end(),
2086 accumulated_profiles_p.begin(),
2087 address_of<AutofillProfile>);
2088
2089 // If the profile got merged trash the original.
2090 if (merged)
2091 AddAutofillGUIDToTrash(p->guid());
2092
2093 } else {
2094 // An invalid profile, so trash it.
2095 AddAutofillGUIDToTrash(p->guid());
2096 }
2097 }
2098
2099 // Drop the current profiles.
2100 if (!ClearAutofillProfiles())
2101 return false;
2102
2103 // Add the newly merged profiles back in.
2104 for (std::vector<AutofillProfile>::const_iterator
2105 iter = accumulated_profiles.begin();
2106 iter != accumulated_profiles.end();
2107 ++iter) {
2108 if (!AddAutofillProfile(*iter))
2109 return false;
2110
2111 // Fix up the original modification date.
2112 std::map<std::string, int64>::const_iterator date_item =
2113 modification_map.find(iter->guid());
2114 if (date_item == modification_map.end())
2115 return false;
2116
2117 sql::Statement s_date(db_->GetUniqueStatement(
2118 "UPDATE autofill_profiles SET date_modified=? "
2119 "WHERE guid=?"));
2120 s_date.BindInt64(0, date_item->second);
2121 s_date.BindString(1, iter->guid());
2122 if (!s_date.Run())
2123 return false;
2124 }
2125
2126 return true;
2127 }
OLDNEW
« no previous file with comments | « chrome/browser/webdata/autofill_table.h ('k') | chrome/browser/webdata/autofill_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698