OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } | |
OLD | NEW |