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

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: 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
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;
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
26 } // anonymous namespace 388 } // anonymous namespace
dhollowa 2011/04/04 16:13:20 nit: s/anonymous namespace/namespace/
Bons 2011/04/05 11:05:13 Done.
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 bool AutofillTable::AddCardNumberEncryptedColumnForVersion23() {
1515 // Add the card_number_encrypted column if credit card table was not
dhollowa 2011/04/04 16:13:20 This comment block now describes the migration met
Bons 2011/04/05 11:05:13 Done.
1516 // created in this build (otherwise the column already exists).
1517 // WARNING: Do not change the order of the execution of the SQL
1518 // statements in this case! Profile corruption and data migration
1519 // issues WILL OCCUR. See http://crbug.com/10913
1520 //
1521 // The problem is that if a user has a profile which was created before
1522 // r37036, when the credit_cards table was added, and then failed to
1523 // update this profile between the credit card addition and the addition
1524 // of the "encrypted" columns (44963), the next data migration will put
1525 // the user's profile in an incoherent state: The user will update from
1526 // a data profile set to be earlier than 22, and therefore pass through
1527 // this update case. But because the user did not have a credit_cards
1528 // table before starting Chrome, it will have just been initialized
1529 // above, and so already have these columns -- and thus this data
1530 // update step will have failed.
1531 //
1532 // The false assumption in this case is that at this step in the
1533 // migration, the user has a credit card table, and that this
1534 // table does not include encrypted columns!
1535 // Because this case does not roll back the complete set of SQL
1536 // transactions properly in case of failure (that is, it does not
1537 // roll back the table initialization done above), the incoherent
1538 // profile will now see itself as being at version 22 -- but include a
1539 // fully initialized credit_cards table. Every time Chrome runs, it
1540 // will try to update the web database and fail at this step, unless
1541 // we allow for the faulty assumption described above by checking for
1542 // the existence of the columns only AFTER we've executed the commands
1543 // to add them.
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 bool AutofillTable::CleanupOversizedStringFieldsForVersion24() {
1566 // One-time cleanup for http://crbug.com/38364 - In the presence of
1567 // multi-byte UTF-8 characters, that bug could cause Autofill strings
1568 // to grow larger and more corrupt with each save. The cleanup removes
1569 // any row with a string field larger than a reasonable size. The string
1570 // fields examined here are precisely the ones that were subject to
1571 // corruption by the original bug.
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 bool AutofillTable::UpdateLegacyCreditCardsForVersion27() {
1629 // Only migrate from legacy credit card tables where specific columns
1630 // exist.
1631 if (!(db_->DoesColumnExist("credit_cards", "unique_id") &&
1632 db_->DoesColumnExist("credit_cards", "billing_address") &&
1633 db_->DoesColumnExist("autofill_profiles", "unique_id"))) {
1634 return true;
1635 }
1636
1637 // Change the credit_cards.billing_address column from a string to an
1638 // int. The stored string is the label of an address, so we have to
1639 // select the unique ID of this address using the label as a foreign
1640 // key into the |autofill_profiles| table.
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::AddDateModifedForVersion30() {
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::AddGUIDToCreditCardsAndProfilesForVersion31() {
1758 // Add |guid| column to |autofill_profiles| table.
1759 // Note that we need to check for the guid column's existence due to the
1760 // fact that for a version 22 database the |autofill_profiles| table
1761 // gets created fresh with |InitAutofillProfilesTable|.
1762 if (!db_->DoesColumnExist("autofill_profiles", "guid")) {
1763 if (!db_->Execute("ALTER TABLE autofill_profiles ADD COLUMN "
1764 "guid VARCHAR NOT NULL DEFAULT \"\"")) {
1765 return false;
1766 }
1767
1768 // Set all the |guid| fields to valid values.
1769
1770 sql::Statement s(db_->GetUniqueStatement("SELECT unique_id "
1771 "FROM autofill_profiles"));
1772 if (!s)
1773 return false;
1774
1775 while (s.Step()) {
1776 sql::Statement update_s(
1777 db_->GetUniqueStatement("UPDATE autofill_profiles "
1778 "SET guid=? WHERE unique_id=?"));
1779 if (!update_s)
1780 return false;
1781 update_s.BindString(0, guid::GenerateGUID());
1782 update_s.BindInt(1, s.ColumnInt(0));
1783
1784 if (!update_s.Run())
1785 return false;
1786 }
1787 }
1788
1789 // Add |guid| column to |credit_cards| table.
1790 // Note that we need to check for the guid column's existence due to the
1791 // fact that for a version 22 database the |autofill_profiles| table
1792 // gets created fresh with |InitAutofillProfilesTable|.
1793 if (!db_->DoesColumnExist("credit_cards", "guid")) {
1794 if (!db_->Execute("ALTER TABLE credit_cards ADD COLUMN "
1795 "guid VARCHAR NOT NULL DEFAULT \"\"")) {
1796 return false;
1797 }
1798
1799 // Set all the |guid| fields to valid values.
1800
1801 sql::Statement s(db_->GetUniqueStatement("SELECT unique_id "
1802 "FROM credit_cards"));
1803 if (!s)
1804 return false;
1805
1806 while (s.Step()) {
1807 sql::Statement update_s(
1808 db_->GetUniqueStatement("UPDATE credit_cards "
1809 "set guid=? WHERE unique_id=?"));
1810 if (!update_s)
1811 return false;
1812 update_s.BindString(0, guid::GenerateGUID());
1813 update_s.BindInt(1, s.ColumnInt(0));
1814
1815 if (!update_s.Run())
1816 return false;
1817 }
1818 }
1819
1820 return true;
1821 }
1822
1823 bool AutofillTable::UpdateProfilesAndCreditCardsForVersion32() {
1824 if (db_->DoesColumnExist("autofill_profiles", "unique_id")) {
1825 if (!db_->Execute("CREATE TABLE autofill_profiles_temp ( "
1826 "guid VARCHAR PRIMARY KEY, "
1827 "label VARCHAR, "
1828 "first_name VARCHAR, "
1829 "middle_name VARCHAR, "
1830 "last_name VARCHAR, "
1831 "email VARCHAR, "
1832 "company_name VARCHAR, "
1833 "address_line_1 VARCHAR, "
1834 "address_line_2 VARCHAR, "
1835 "city VARCHAR, "
1836 "state VARCHAR, "
1837 "zipcode VARCHAR, "
1838 "country VARCHAR, "
1839 "phone VARCHAR, "
1840 "fax VARCHAR, "
1841 "date_modified INTEGER NOT NULL DEFAULT 0)")) {
1842 return false;
1843 }
1844
1845 if (!db_->Execute(
1846 "INSERT INTO autofill_profiles_temp "
1847 "SELECT guid, label, first_name, middle_name, last_name, email, "
1848 "company_name, address_line_1, address_line_2, city, state, "
1849 "zipcode, country, phone, fax, date_modified "
1850 "FROM autofill_profiles")) {
1851 return false;
1852 }
1853
1854 if (!db_->Execute("DROP TABLE autofill_profiles"))
1855 return false;
1856
1857 if (!db_->Execute(
1858 "ALTER TABLE autofill_profiles_temp RENAME TO autofill_profiles")) {
1859 return false;
1860 }
1861 }
1862
1863 if (db_->DoesColumnExist("credit_cards", "unique_id")) {
1864 if (!db_->Execute("CREATE TABLE credit_cards_temp ( "
1865 "guid VARCHAR PRIMARY KEY, "
1866 "label VARCHAR, "
1867 "name_on_card VARCHAR, "
1868 "expiration_month INTEGER, "
1869 "expiration_year INTEGER, "
1870 "card_number_encrypted BLOB, "
1871 "date_modified INTEGER NOT NULL DEFAULT 0)")) {
1872 return false;
1873 }
1874
1875 if (!db_->Execute(
1876 "INSERT INTO credit_cards_temp "
1877 "SELECT guid, label, name_on_card, expiration_month, "
1878 "expiration_year, card_number_encrypted, date_modified "
1879 "FROM credit_cards")) {
1880 return false;
1881 }
1882
1883 if (!db_->Execute("DROP TABLE credit_cards"))
1884 return false;
1885
1886 if (!db_->Execute("ALTER TABLE credit_cards_temp RENAME TO credit_cards"))
1887 return false;
1888 }
1889
1890 return true;
1891 }
1892
1893 bool AutofillTable::UpdateProfilesBasedOnFirstNameForVersion33() {
1894 // Test the existence of the |first_name| column as an indication that
1895 // we need a migration. It is possible that the new |autofill_profiles|
1896 // schema is in place because the table was newly created when migrating
1897 // from a pre-version-22 database.
1898 if (db_->DoesColumnExist("autofill_profiles", "first_name")) {
1899 // Create autofill_profiles_temp table that will receive the data.
1900 if (!db_->DoesTableExist("autofill_profiles_temp")) {
1901 if (!db_->Execute("CREATE TABLE autofill_profiles_temp ( "
1902 "guid VARCHAR PRIMARY KEY, "
1903 "company_name VARCHAR, "
1904 "address_line_1 VARCHAR, "
1905 "address_line_2 VARCHAR, "
1906 "city VARCHAR, "
1907 "state VARCHAR, "
1908 "zipcode VARCHAR, "
1909 "country VARCHAR, "
1910 "date_modified INTEGER NOT NULL DEFAULT 0)")) {
1911 return false;
1912 }
1913 }
1914
1915 sql::Statement s(db_->GetUniqueStatement(
1916 "SELECT guid, first_name, middle_name, last_name, email, "
1917 "company_name, address_line_1, address_line_2, city, state, "
1918 "zipcode, country, phone, fax, date_modified "
1919 "FROM autofill_profiles"));
1920 while (s.Step()) {
1921 AutofillProfile profile;
1922 profile.set_guid(s.ColumnString(0));
1923 DCHECK(guid::IsValidGUID(profile.guid()));
1924
1925 profile.SetInfo(NAME_FIRST, s.ColumnString16(1));
1926 profile.SetInfo(NAME_MIDDLE, s.ColumnString16(2));
1927 profile.SetInfo(NAME_LAST, s.ColumnString16(3));
1928 profile.SetInfo(EMAIL_ADDRESS, s.ColumnString16(4));
1929 profile.SetInfo(COMPANY_NAME, s.ColumnString16(5));
1930 profile.SetInfo(ADDRESS_HOME_LINE1, s.ColumnString16(6));
1931 profile.SetInfo(ADDRESS_HOME_LINE2, s.ColumnString16(7));
1932 profile.SetInfo(ADDRESS_HOME_CITY, s.ColumnString16(8));
1933 profile.SetInfo(ADDRESS_HOME_STATE, s.ColumnString16(9));
1934 profile.SetInfo(ADDRESS_HOME_ZIP, s.ColumnString16(10));
1935 profile.SetInfo(ADDRESS_HOME_COUNTRY, s.ColumnString16(11));
1936 profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, s.ColumnString16(12));
1937 profile.SetInfo(PHONE_FAX_WHOLE_NUMBER, s.ColumnString16(13));
1938 int64 date_modified = s.ColumnInt64(14);
1939
1940 sql::Statement s_insert(db_->GetUniqueStatement(
1941 "INSERT INTO autofill_profiles_temp"
1942 "(guid, company_name, address_line_1, address_line_2, city,"
1943 " state, zipcode, country, date_modified)"
1944 "VALUES (?,?,?,?,?,?,?,?,?)"));
1945 if (!s)
1946 return false;
1947
1948 s_insert.BindString(0, profile.guid());
1949 s_insert.BindString16(1, profile.GetInfo(COMPANY_NAME));
1950 s_insert.BindString16(2, profile.GetInfo(ADDRESS_HOME_LINE1));
1951 s_insert.BindString16(3, profile.GetInfo(ADDRESS_HOME_LINE2));
1952 s_insert.BindString16(4, profile.GetInfo(ADDRESS_HOME_CITY));
1953 s_insert.BindString16(5, profile.GetInfo(ADDRESS_HOME_STATE));
1954 s_insert.BindString16(6, profile.GetInfo(ADDRESS_HOME_ZIP));
1955 s_insert.BindString16(7, profile.GetInfo(ADDRESS_HOME_COUNTRY));
1956 s_insert.BindInt64(8, date_modified);
1957
1958 if (!s_insert.Run())
1959 return false;
1960
1961 // Add the other bits: names, emails, and phone/fax.
1962 if (!AddAutofillProfilePieces(profile, db_))
1963 return false;
1964 }
1965
1966 if (!db_->Execute("DROP TABLE autofill_profiles"))
1967 return false;
1968
1969 if (!db_->Execute(
1970 "ALTER TABLE autofill_profiles_temp RENAME TO autofill_profiles")) {
1971 return false;
1972 }
1973 }
1974
1975 // Remove the labels column from the credit_cards table.
1976 if (db_->DoesColumnExist("credit_cards", "label")) {
1977 if (!db_->Execute("CREATE TABLE credit_cards_temp ( "
1978 "guid VARCHAR PRIMARY KEY, "
1979 "name_on_card VARCHAR, "
1980 "expiration_month INTEGER, "
1981 "expiration_year INTEGER, "
1982 "card_number_encrypted BLOB, "
1983 "date_modified INTEGER NOT NULL DEFAULT 0)")) {
1984 return false;
1985 }
1986
1987 if (!db_->Execute(
1988 "INSERT INTO credit_cards_temp "
1989 "SELECT guid, name_on_card, expiration_month, "
1990 "expiration_year, card_number_encrypted, date_modified "
1991 "FROM credit_cards")) {
1992 return false;
1993 }
1994
1995 if (!db_->Execute("DROP TABLE credit_cards"))
1996 return false;
1997
1998 if (!db_->Execute("ALTER TABLE credit_cards_temp RENAME TO credit_cards"))
1999 return false;
2000 }
2001
2002 return true;
2003 }
2004
2005 bool AutofillTable::UpdatesProfilesBasedOnCountryCodeForVersion34() {
2006 // Test the existence of the |country_code| column as an indication that
2007 // we need a migration. It is possible that the new |autofill_profiles|
2008 // schema is in place because the table was newly created when migrating
2009 // from a pre-version-22 database.
2010 if (!db_->DoesColumnExist("autofill_profiles", "country_code")) {
2011 if (!db_->Execute("ALTER TABLE autofill_profiles ADD COLUMN "
2012 "country_code VARCHAR")) {
2013 return false;
2014 }
2015
2016 // Set all the |country_code| fields to match existing |country| values.
2017 sql::Statement s(db_->GetUniqueStatement("SELECT guid, country "
2018 "FROM autofill_profiles"));
2019
2020 if (!s)
2021 return false;
2022
2023 while (s.Step()) {
2024 sql::Statement update_s(
2025 db_->GetUniqueStatement("UPDATE autofill_profiles "
2026 "SET country_code=? WHERE guid=?"));
2027 if (!update_s)
2028 return false;
2029
2030 string16 country = s.ColumnString16(1);
2031 std::string app_locale = AutofillCountry::ApplicationLocale();
2032 update_s.BindString(0, AutofillCountry::GetCountryCode(country,
2033 app_locale));
2034 update_s.BindString(1, s.ColumnString(0));
2035
2036 if (!update_s.Run())
2037 return false;
2038 }
2039 }
2040
2041 return true;
2042 }
2043
2044 bool AutofillTable::CorrectGreatBritainCountryCodesForVersion35() {
2045 // Correct all country codes with value "UK" to be "GB". This data
2046 // was mistakenly introduced in build 686.0. This migration is to clean
2047 // it up. See http://crbug.com/74511 for details.
2048 sql::Statement s(db_->GetUniqueStatement(
2049 "UPDATE autofill_profiles SET country_code=\"GB\" "
2050 "WHERE country_code=\"UK\""));
2051
2052 return s.Run();
2053 }
2054
2055 bool AutofillTable::MergeAndCullOlderProfilesForVersion36() {
2056 // Merge and cull older profiles where possible.
2057 sql::Statement s(db_->GetUniqueStatement(
2058 "SELECT guid, date_modified FROM autofill_profiles"));
2059 if (!s)
2060 return false;
2061
2062 // Accumulate the good profiles.
2063 std::vector<AutofillProfile> accumulated_profiles;
2064 std::vector<AutofillProfile*> accumulated_profiles_p;
2065 std::map<std::string, int64> modification_map;
2066 while (s.Step()) {
2067 std::string guid = s.ColumnString(0);
2068 int64 date_modified = s.ColumnInt64(1);
2069 modification_map.insert(
2070 std::pair<std::string, int64>(guid, date_modified));
2071 AutofillProfile* profile = NULL;
2072 if (!GetAutofillProfile(guid, &profile))
2073 return false;
2074
2075 scoped_ptr<AutofillProfile> p(profile);
2076
2077 if (PersonalDataManager::IsValidLearnableProfile(*p)) {
2078 std::vector<AutofillProfile> merged_profiles;
2079 bool merged = PersonalDataManager::MergeProfile(
2080 *p, accumulated_profiles_p, &merged_profiles);
2081
2082 std::swap(accumulated_profiles, merged_profiles);
2083
2084 accumulated_profiles_p.clear();
2085 accumulated_profiles_p.resize(accumulated_profiles.size());
2086 std::transform(accumulated_profiles.begin(),
2087 accumulated_profiles.end(),
2088 accumulated_profiles_p.begin(),
2089 address_of<AutofillProfile>);
2090
2091 // If the profile got merged trash the original.
2092 if (merged)
2093 AddAutofillGUIDToTrash(p->guid());
2094
2095 } else {
2096 // An invalid profile, so trash it.
2097 AddAutofillGUIDToTrash(p->guid());
2098 }
2099 }
2100
2101 // Drop the current profiles.
2102 if (!ClearAutofillProfiles())
2103 return false;
2104
2105 // Add the newly merged profiles back in.
2106 for (std::vector<AutofillProfile>::const_iterator
2107 iter = accumulated_profiles.begin();
2108 iter != accumulated_profiles.end();
2109 ++iter) {
2110 if (!AddAutofillProfile(*iter))
2111 return false;
2112
2113 // Fix up the original modification date.
2114 std::map<std::string, int64>::const_iterator date_item =
2115 modification_map.find(iter->guid());
2116 if (date_item == modification_map.end())
2117 return false;
2118
2119 sql::Statement s_date(db_->GetUniqueStatement(
2120 "UPDATE autofill_profiles SET date_modified=? "
2121 "WHERE guid=?"));
2122 s_date.BindInt64(0, date_item->second);
2123 s_date.BindString(1, iter->guid());
2124 if (!s_date.Run())
2125 return false;
2126 }
2127
2128 return true;
2129 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698