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; |
26 } // anonymous namespace | 42 |
| 43 // TODO(dhollowa): Find a common place for this. It is duplicated in |
| 44 // personal_data_manager.cc. |
| 45 template<typename T> |
| 46 T* address_of(T& v) { |
| 47 return &v; |
| 48 } |
| 49 |
| 50 // The maximum length allowed for form data. |
| 51 const size_t kMaxDataLength = 1024; |
| 52 |
| 53 string16 LimitDataSize(const string16& data) { |
| 54 if (data.size() > kMaxDataLength) |
| 55 return data.substr(0, kMaxDataLength); |
| 56 |
| 57 return data; |
| 58 } |
| 59 |
| 60 void BindAutofillProfileToStatement(const AutofillProfile& profile, |
| 61 sql::Statement* s) { |
| 62 DCHECK(guid::IsValidGUID(profile.guid())); |
| 63 s->BindString(0, profile.guid()); |
| 64 |
| 65 string16 text = profile.GetInfo(COMPANY_NAME); |
| 66 s->BindString16(1, LimitDataSize(text)); |
| 67 text = profile.GetInfo(ADDRESS_HOME_LINE1); |
| 68 s->BindString16(2, LimitDataSize(text)); |
| 69 text = profile.GetInfo(ADDRESS_HOME_LINE2); |
| 70 s->BindString16(3, LimitDataSize(text)); |
| 71 text = profile.GetInfo(ADDRESS_HOME_CITY); |
| 72 s->BindString16(4, LimitDataSize(text)); |
| 73 text = profile.GetInfo(ADDRESS_HOME_STATE); |
| 74 s->BindString16(5, LimitDataSize(text)); |
| 75 text = profile.GetInfo(ADDRESS_HOME_ZIP); |
| 76 s->BindString16(6, LimitDataSize(text)); |
| 77 text = profile.GetInfo(ADDRESS_HOME_COUNTRY); |
| 78 s->BindString16(7, LimitDataSize(text)); |
| 79 std::string country_code = profile.CountryCode(); |
| 80 s->BindString(8, country_code); |
| 81 s->BindInt64(9, Time::Now().ToTimeT()); |
| 82 } |
| 83 |
| 84 AutofillProfile* AutofillProfileFromStatement(const sql::Statement& s) { |
| 85 AutofillProfile* profile = new AutofillProfile; |
| 86 profile->set_guid(s.ColumnString(0)); |
| 87 DCHECK(guid::IsValidGUID(profile->guid())); |
| 88 |
| 89 profile->SetInfo(COMPANY_NAME, s.ColumnString16(1)); |
| 90 profile->SetInfo(ADDRESS_HOME_LINE1, s.ColumnString16(2)); |
| 91 profile->SetInfo(ADDRESS_HOME_LINE2, s.ColumnString16(3)); |
| 92 profile->SetInfo(ADDRESS_HOME_CITY, s.ColumnString16(4)); |
| 93 profile->SetInfo(ADDRESS_HOME_STATE, s.ColumnString16(5)); |
| 94 profile->SetInfo(ADDRESS_HOME_ZIP, s.ColumnString16(6)); |
| 95 // Intentionally skip column 7, which stores the localized country name. |
| 96 profile->SetCountryCode(s.ColumnString(8)); |
| 97 // Intentionally skip column 9, which stores the profile's modification date. |
| 98 |
| 99 return profile; |
| 100 } |
| 101 |
| 102 void BindCreditCardToStatement(const CreditCard& credit_card, |
| 103 sql::Statement* s) { |
| 104 DCHECK(guid::IsValidGUID(credit_card.guid())); |
| 105 s->BindString(0, credit_card.guid()); |
| 106 |
| 107 string16 text = credit_card.GetInfo(CREDIT_CARD_NAME); |
| 108 s->BindString16(1, LimitDataSize(text)); |
| 109 text = credit_card.GetInfo(CREDIT_CARD_EXP_MONTH); |
| 110 s->BindString16(2, LimitDataSize(text)); |
| 111 text = credit_card.GetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR); |
| 112 s->BindString16(3, LimitDataSize(text)); |
| 113 text = credit_card.GetInfo(CREDIT_CARD_NUMBER); |
| 114 std::string encrypted_data; |
| 115 Encryptor::EncryptString16(text, &encrypted_data); |
| 116 s->BindBlob(4, encrypted_data.data(), |
| 117 static_cast<int>(encrypted_data.length())); |
| 118 s->BindInt64(5, Time::Now().ToTimeT()); |
| 119 } |
| 120 |
| 121 CreditCard* CreditCardFromStatement(const sql::Statement& s) { |
| 122 CreditCard* credit_card = new CreditCard; |
| 123 |
| 124 credit_card->set_guid(s.ColumnString(0)); |
| 125 DCHECK(guid::IsValidGUID(credit_card->guid())); |
| 126 |
| 127 credit_card->SetInfo(CREDIT_CARD_NAME, s.ColumnString16(1)); |
| 128 credit_card->SetInfo(CREDIT_CARD_EXP_MONTH, |
| 129 s.ColumnString16(2)); |
| 130 credit_card->SetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, |
| 131 s.ColumnString16(3)); |
| 132 int encrypted_number_len = s.ColumnByteLength(4); |
| 133 string16 credit_card_number; |
| 134 if (encrypted_number_len) { |
| 135 std::string encrypted_number; |
| 136 encrypted_number.resize(encrypted_number_len); |
| 137 memcpy(&encrypted_number[0], s.ColumnBlob(4), encrypted_number_len); |
| 138 Encryptor::DecryptString16(encrypted_number, &credit_card_number); |
| 139 } |
| 140 credit_card->SetInfo(CREDIT_CARD_NUMBER, credit_card_number); |
| 141 // Intentionally skip column 5, which stores the modification date. |
| 142 |
| 143 return credit_card; |
| 144 } |
| 145 |
| 146 bool AddAutofillProfileNamesToProfile(sql::Connection* db, |
| 147 AutofillProfile* profile) { |
| 148 sql::Statement s(db->GetUniqueStatement( |
| 149 "SELECT guid, first_name, middle_name, last_name " |
| 150 "FROM autofill_profile_names " |
| 151 "WHERE guid=?")); |
| 152 if (!s) { |
| 153 NOTREACHED() << "Statement prepare failed"; |
| 154 return false; |
| 155 } |
| 156 s.BindString(0, profile->guid()); |
| 157 |
| 158 std::vector<string16> first_names; |
| 159 std::vector<string16> middle_names; |
| 160 std::vector<string16> last_names; |
| 161 while (s.Step()) { |
| 162 DCHECK_EQ(profile->guid(), s.ColumnString(0)); |
| 163 first_names.push_back(s.ColumnString16(1)); |
| 164 middle_names.push_back(s.ColumnString16(2)); |
| 165 last_names.push_back(s.ColumnString16(3)); |
| 166 } |
| 167 profile->SetMultiInfo(NAME_FIRST, first_names); |
| 168 profile->SetMultiInfo(NAME_MIDDLE, middle_names); |
| 169 profile->SetMultiInfo(NAME_LAST, last_names); |
| 170 return true; |
| 171 } |
| 172 |
| 173 bool AddAutofillProfileEmailsToProfile(sql::Connection* db, |
| 174 AutofillProfile* profile) { |
| 175 sql::Statement s(db->GetUniqueStatement( |
| 176 "SELECT guid, email " |
| 177 "FROM autofill_profile_emails " |
| 178 "WHERE guid=?")); |
| 179 if (!s) { |
| 180 NOTREACHED() << "Statement prepare failed"; |
| 181 return false; |
| 182 } |
| 183 s.BindString(0, profile->guid()); |
| 184 |
| 185 std::vector<string16> emails; |
| 186 while (s.Step()) { |
| 187 DCHECK_EQ(profile->guid(), s.ColumnString(0)); |
| 188 emails.push_back(s.ColumnString16(1)); |
| 189 } |
| 190 profile->SetMultiInfo(EMAIL_ADDRESS, emails); |
| 191 return true; |
| 192 } |
| 193 |
| 194 bool AddAutofillProfilePhonesToProfile(sql::Connection* db, |
| 195 AutofillProfile* profile) { |
| 196 sql::Statement s(db->GetUniqueStatement( |
| 197 "SELECT guid, type, number " |
| 198 "FROM autofill_profile_phones " |
| 199 "WHERE guid=? AND type=?")); |
| 200 if (!s) { |
| 201 NOTREACHED() << "Statement prepare failed"; |
| 202 return false; |
| 203 } |
| 204 s.BindString(0, profile->guid()); |
| 205 s.BindInt(1, kAutofillPhoneNumber); |
| 206 |
| 207 std::vector<string16> numbers; |
| 208 while (s.Step()) { |
| 209 DCHECK_EQ(profile->guid(), s.ColumnString(0)); |
| 210 numbers.push_back(s.ColumnString16(2)); |
| 211 } |
| 212 profile->SetMultiInfo(PHONE_HOME_WHOLE_NUMBER, numbers); |
| 213 return true; |
| 214 } |
| 215 |
| 216 bool AddAutofillProfileFaxesToProfile(sql::Connection* db, |
| 217 AutofillProfile* profile) { |
| 218 sql::Statement s(db->GetUniqueStatement( |
| 219 "SELECT guid, type, number " |
| 220 "FROM autofill_profile_phones " |
| 221 "WHERE guid=? AND type=?")); |
| 222 if (!s) { |
| 223 NOTREACHED() << "Statement prepare failed"; |
| 224 return false; |
| 225 } |
| 226 s.BindString(0, profile->guid()); |
| 227 s.BindInt(1, kAutofillFaxNumber); |
| 228 |
| 229 std::vector<string16> numbers; |
| 230 while (s.Step()) { |
| 231 DCHECK_EQ(profile->guid(), s.ColumnString(0)); |
| 232 numbers.push_back(s.ColumnString16(2)); |
| 233 } |
| 234 profile->SetMultiInfo(PHONE_FAX_WHOLE_NUMBER, numbers); |
| 235 return true; |
| 236 } |
| 237 |
| 238 |
| 239 bool AddAutofillProfileNames(const AutofillProfile& profile, |
| 240 sql::Connection* db) { |
| 241 std::vector<string16> first_names; |
| 242 profile.GetMultiInfo(NAME_FIRST, &first_names); |
| 243 std::vector<string16> middle_names; |
| 244 profile.GetMultiInfo(NAME_MIDDLE, &middle_names); |
| 245 std::vector<string16> last_names; |
| 246 profile.GetMultiInfo(NAME_LAST, &last_names); |
| 247 DCHECK_EQ(first_names.size(), middle_names.size()); |
| 248 DCHECK_EQ(middle_names.size(), last_names.size()); |
| 249 |
| 250 for (size_t i = 0; i < first_names.size(); ++i) { |
| 251 // Add the new name. |
| 252 sql::Statement s(db->GetUniqueStatement( |
| 253 "INSERT INTO autofill_profile_names" |
| 254 " (guid, first_name, middle_name, last_name) " |
| 255 "VALUES (?,?,?,?)")); |
| 256 if (!s) { |
| 257 NOTREACHED(); |
| 258 return false; |
| 259 } |
| 260 s.BindString(0, profile.guid()); |
| 261 s.BindString16(1, first_names[i]); |
| 262 s.BindString16(2, middle_names[i]); |
| 263 s.BindString16(3, last_names[i]); |
| 264 |
| 265 if (!s.Run()) { |
| 266 NOTREACHED(); |
| 267 return false; |
| 268 } |
| 269 } |
| 270 return true; |
| 271 } |
| 272 |
| 273 bool AddAutofillProfileEmails(const AutofillProfile& profile, |
| 274 sql::Connection* db) { |
| 275 std::vector<string16> emails; |
| 276 profile.GetMultiInfo(EMAIL_ADDRESS, &emails); |
| 277 |
| 278 for (size_t i = 0; i < emails.size(); ++i) { |
| 279 // Add the new email. |
| 280 sql::Statement s(db->GetUniqueStatement( |
| 281 "INSERT INTO autofill_profile_emails" |
| 282 " (guid, email) " |
| 283 "VALUES (?,?)")); |
| 284 if (!s) { |
| 285 NOTREACHED(); |
| 286 return false; |
| 287 } |
| 288 s.BindString(0, profile.guid()); |
| 289 s.BindString16(1, emails[i]); |
| 290 |
| 291 if (!s.Run()) { |
| 292 NOTREACHED(); |
| 293 return false; |
| 294 } |
| 295 } |
| 296 return true; |
| 297 } |
| 298 |
| 299 bool AddAutofillProfilePhones(const AutofillProfile& profile, |
| 300 AutofillPhoneType phone_type, |
| 301 sql::Connection* db) { |
| 302 AutofillFieldType field_type; |
| 303 if (phone_type == kAutofillPhoneNumber) { |
| 304 field_type = PHONE_HOME_WHOLE_NUMBER; |
| 305 } else if (phone_type == kAutofillFaxNumber) { |
| 306 field_type = PHONE_FAX_WHOLE_NUMBER; |
| 307 } else { |
| 308 NOTREACHED(); |
| 309 return false; |
| 310 } |
| 311 |
| 312 std::vector<string16> numbers; |
| 313 profile.GetMultiInfo(field_type, &numbers); |
| 314 |
| 315 for (size_t i = 0; i < numbers.size(); ++i) { |
| 316 // Add the new number. |
| 317 sql::Statement s(db->GetUniqueStatement( |
| 318 "INSERT INTO autofill_profile_phones" |
| 319 " (guid, type, number) " |
| 320 "VALUES (?,?,?)")); |
| 321 if (!s) { |
| 322 NOTREACHED(); |
| 323 return false; |
| 324 } |
| 325 s.BindString(0, profile.guid()); |
| 326 s.BindInt(1, phone_type); |
| 327 s.BindString16(2, numbers[i]); |
| 328 |
| 329 if (!s.Run()) { |
| 330 NOTREACHED(); |
| 331 return false; |
| 332 } |
| 333 } |
| 334 return true; |
| 335 } |
| 336 |
| 337 bool AddAutofillProfilePieces(const AutofillProfile& profile, |
| 338 sql::Connection* db) { |
| 339 if (!AddAutofillProfileNames(profile, db)) |
| 340 return false; |
| 341 |
| 342 if (!AddAutofillProfileEmails(profile, db)) |
| 343 return false; |
| 344 |
| 345 if (!AddAutofillProfilePhones(profile, kAutofillPhoneNumber, db)) |
| 346 return false; |
| 347 |
| 348 if (!AddAutofillProfilePhones(profile, kAutofillFaxNumber, db)) |
| 349 return false; |
| 350 |
| 351 return true; |
| 352 } |
| 353 |
| 354 bool RemoveAutofillProfilePieces(const std::string& guid, sql::Connection* db) { |
| 355 sql::Statement s1(db->GetUniqueStatement( |
| 356 "DELETE FROM autofill_profile_names WHERE guid = ?")); |
| 357 if (!s1) { |
| 358 NOTREACHED() << "Statement prepare failed"; |
| 359 return false; |
| 360 } |
| 361 |
| 362 s1.BindString(0, guid); |
| 363 if (!s1.Run()) |
| 364 return false; |
| 365 |
| 366 sql::Statement s2(db->GetUniqueStatement( |
| 367 "DELETE FROM autofill_profile_emails WHERE guid = ?")); |
| 368 if (!s2) { |
| 369 NOTREACHED() << "Statement prepare failed"; |
| 370 return false; |
| 371 } |
| 372 |
| 373 s2.BindString(0, guid); |
| 374 if (!s2.Run()) |
| 375 return false; |
| 376 |
| 377 sql::Statement s3(db->GetUniqueStatement( |
| 378 "DELETE FROM autofill_profile_phones WHERE guid = ?")); |
| 379 if (!s3) { |
| 380 NOTREACHED() << "Statement prepare failed"; |
| 381 return false; |
| 382 } |
| 383 |
| 384 s3.BindString(0, guid); |
| 385 return s3.Run(); |
| 386 } |
| 387 |
| 388 } // namespace |
27 | 389 |
28 bool AutofillTable::Init() { | 390 bool AutofillTable::Init() { |
29 return (InitMainTable() && InitCreditCardsTable() && InitDatesTable() && | 391 return (InitMainTable() && InitCreditCardsTable() && InitDatesTable() && |
30 InitProfilesTable() && InitProfileNamesTable() && | 392 InitProfilesTable() && InitProfileNamesTable() && |
31 InitProfileEmailsTable() && InitProfilePhonesTable() && | 393 InitProfileEmailsTable() && InitProfilePhonesTable() && |
32 InitProfileTrashTable()); | 394 InitProfileTrashTable()); |
33 } | 395 } |
34 | 396 |
35 bool AutofillTable::IsSyncable() { | 397 bool AutofillTable::IsSyncable() { |
36 return true; | 398 return true; |
(...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after 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 // Add the card_number_encrypted column if credit card table was not |
| 1515 // created in this build (otherwise the column already exists). |
| 1516 // WARNING: Do not change the order of the execution of the SQL |
| 1517 // statements in this case! Profile corruption and data migration |
| 1518 // issues WILL OCCUR. See http://crbug.com/10913 |
| 1519 // |
| 1520 // The problem is that if a user has a profile which was created before |
| 1521 // r37036, when the credit_cards table was added, and then failed to |
| 1522 // update this profile between the credit card addition and the addition |
| 1523 // of the "encrypted" columns (44963), the next data migration will put |
| 1524 // the user's profile in an incoherent state: The user will update from |
| 1525 // a data profile set to be earlier than 22, and therefore pass through |
| 1526 // this update case. But because the user did not have a credit_cards |
| 1527 // table before starting Chrome, it will have just been initialized |
| 1528 // above, and so already have these columns -- and thus this data |
| 1529 // update step will have failed. |
| 1530 // |
| 1531 // The false assumption in this case is that at this step in the |
| 1532 // migration, the user has a credit card table, and that this |
| 1533 // table does not include encrypted columns! |
| 1534 // Because this case does not roll back the complete set of SQL |
| 1535 // transactions properly in case of failure (that is, it does not |
| 1536 // roll back the table initialization done above), the incoherent |
| 1537 // profile will now see itself as being at version 22 -- but include a |
| 1538 // fully initialized credit_cards table. Every time Chrome runs, it |
| 1539 // will try to update the web database and fail at this step, unless |
| 1540 // we allow for the faulty assumption described above by checking for |
| 1541 // the existence of the columns only AFTER we've executed the commands |
| 1542 // to add them. |
| 1543 bool AutofillTable::MigrateToVersion23AddCardNumberEncryptedColumn() { |
| 1544 if (!db_->DoesColumnExist("credit_cards", "card_number_encrypted")) { |
| 1545 if (!db_->Execute("ALTER TABLE credit_cards ADD COLUMN " |
| 1546 "card_number_encrypted BLOB DEFAULT NULL")) { |
| 1547 LOG(WARNING) << "Could not add card_number_encrypted to " |
| 1548 "credit_cards table."; |
| 1549 return false; |
| 1550 } |
| 1551 } |
| 1552 |
| 1553 if (!db_->DoesColumnExist("credit_cards", "verification_code_encrypted")) { |
| 1554 if (!db_->Execute("ALTER TABLE credit_cards ADD COLUMN " |
| 1555 "verification_code_encrypted BLOB DEFAULT NULL")) { |
| 1556 LOG(WARNING) << "Could not add verification_code_encrypted to " |
| 1557 "credit_cards table."; |
| 1558 return false; |
| 1559 } |
| 1560 } |
| 1561 |
| 1562 return true; |
| 1563 } |
| 1564 |
| 1565 // One-time cleanup for http://crbug.com/38364 - In the presence of |
| 1566 // multi-byte UTF-8 characters, that bug could cause Autofill strings |
| 1567 // to grow larger and more corrupt with each save. The cleanup removes |
| 1568 // any row with a string field larger than a reasonable size. The string |
| 1569 // fields examined here are precisely the ones that were subject to |
| 1570 // corruption by the original bug. |
| 1571 bool AutofillTable::MigrateToVersion24CleanupOversizedStringFields() { |
| 1572 const std::string autofill_is_too_big = |
| 1573 "max(length(name), length(value)) > 500"; |
| 1574 |
| 1575 const std::string credit_cards_is_too_big = |
| 1576 "max(length(label), length(name_on_card), length(type), " |
| 1577 " length(expiration_month), length(expiration_year), " |
| 1578 " length(billing_address), length(shipping_address) " |
| 1579 ") > 500"; |
| 1580 |
| 1581 const std::string autofill_profiles_is_too_big = |
| 1582 "max(length(label), length(first_name), " |
| 1583 " length(middle_name), length(last_name), length(email), " |
| 1584 " length(company_name), length(address_line_1), " |
| 1585 " length(address_line_2), length(city), length(state), " |
| 1586 " length(zipcode), length(country), length(phone), " |
| 1587 " length(fax)) > 500"; |
| 1588 |
| 1589 std::string query = "DELETE FROM autofill_dates WHERE pair_id IN (" |
| 1590 "SELECT pair_id FROM autofill WHERE " + autofill_is_too_big + ")"; |
| 1591 |
| 1592 if (!db_->Execute(query.c_str())) |
| 1593 return false; |
| 1594 |
| 1595 query = "DELETE FROM autofill WHERE " + autofill_is_too_big; |
| 1596 |
| 1597 if (!db_->Execute(query.c_str())) |
| 1598 return false; |
| 1599 |
| 1600 // Only delete from legacy credit card tables where specific columns exist. |
| 1601 if (db_->DoesColumnExist("credit_cards", "label") && |
| 1602 db_->DoesColumnExist("credit_cards", "name_on_card") && |
| 1603 db_->DoesColumnExist("credit_cards", "type") && |
| 1604 db_->DoesColumnExist("credit_cards", "expiration_month") && |
| 1605 db_->DoesColumnExist("credit_cards", "expiration_year") && |
| 1606 db_->DoesColumnExist("credit_cards", "billing_address") && |
| 1607 db_->DoesColumnExist("credit_cards", "shipping_address") && |
| 1608 db_->DoesColumnExist("autofill_profiles", "label")) { |
| 1609 query = "DELETE FROM credit_cards WHERE (" + credit_cards_is_too_big + |
| 1610 ") OR label IN (SELECT label FROM autofill_profiles WHERE " + |
| 1611 autofill_profiles_is_too_big + ")"; |
| 1612 |
| 1613 if (!db_->Execute(query.c_str())) |
| 1614 return false; |
| 1615 } |
| 1616 |
| 1617 if (db_->DoesColumnExist("autofill_profiles", "label")) { |
| 1618 query = "DELETE FROM autofill_profiles WHERE " + |
| 1619 autofill_profiles_is_too_big; |
| 1620 |
| 1621 if (!db_->Execute(query.c_str())) |
| 1622 return false; |
| 1623 } |
| 1624 |
| 1625 return true; |
| 1626 } |
| 1627 |
| 1628 // Change the credit_cards.billing_address column from a string to an |
| 1629 // int. The stored string is the label of an address, so we have to |
| 1630 // select the unique ID of this address using the label as a foreign |
| 1631 // key into the |autofill_profiles| table. |
| 1632 bool AutofillTable::MigrateToVersion27UpdateLegacyCreditCards() { |
| 1633 // Only migrate from legacy credit card tables where specific columns |
| 1634 // exist. |
| 1635 if (!(db_->DoesColumnExist("credit_cards", "unique_id") && |
| 1636 db_->DoesColumnExist("credit_cards", "billing_address") && |
| 1637 db_->DoesColumnExist("autofill_profiles", "unique_id"))) { |
| 1638 return true; |
| 1639 } |
| 1640 |
| 1641 std::string stmt = |
| 1642 "SELECT credit_cards.unique_id, autofill_profiles.unique_id " |
| 1643 "FROM autofill_profiles, credit_cards " |
| 1644 "WHERE credit_cards.billing_address = autofill_profiles.label"; |
| 1645 sql::Statement s(db_->GetUniqueStatement(stmt.c_str())); |
| 1646 if (!s) |
| 1647 return false; |
| 1648 |
| 1649 std::map<int, int> cc_billing_map; |
| 1650 while (s.Step()) |
| 1651 cc_billing_map[s.ColumnInt(0)] = s.ColumnInt(1); |
| 1652 |
| 1653 // Windows already stores the IDs as strings in |billing_address|. Try |
| 1654 // to convert those. |
| 1655 if (cc_billing_map.empty()) { |
| 1656 std::string stmt = "SELECT unique_id,billing_address FROM credit_cards"; |
| 1657 sql::Statement s(db_->GetUniqueStatement(stmt.c_str())); |
| 1658 if (!s) |
| 1659 return false; |
| 1660 |
| 1661 while (s.Step()) { |
| 1662 int id = 0; |
| 1663 if (base::StringToInt(s.ColumnString(1), &id)) |
| 1664 cc_billing_map[s.ColumnInt(0)] = id; |
| 1665 } |
| 1666 } |
| 1667 |
| 1668 if (!db_->Execute("CREATE TABLE credit_cards_temp ( " |
| 1669 "label VARCHAR, " |
| 1670 "unique_id INTEGER PRIMARY KEY, " |
| 1671 "name_on_card VARCHAR, " |
| 1672 "type VARCHAR, " |
| 1673 "card_number VARCHAR, " |
| 1674 "expiration_month INTEGER, " |
| 1675 "expiration_year INTEGER, " |
| 1676 "verification_code VARCHAR, " |
| 1677 "billing_address INTEGER, " |
| 1678 "shipping_address VARCHAR, " |
| 1679 "card_number_encrypted BLOB, " |
| 1680 "verification_code_encrypted BLOB)")) { |
| 1681 return false; |
| 1682 } |
| 1683 |
| 1684 if (!db_->Execute( |
| 1685 "INSERT INTO credit_cards_temp " |
| 1686 "SELECT label,unique_id,name_on_card,type,card_number," |
| 1687 "expiration_month,expiration_year,verification_code,0," |
| 1688 "shipping_address,card_number_encrypted," |
| 1689 "verification_code_encrypted FROM credit_cards")) { |
| 1690 return false; |
| 1691 } |
| 1692 |
| 1693 if (!db_->Execute("DROP TABLE credit_cards")) |
| 1694 return false; |
| 1695 |
| 1696 if (!db_->Execute("ALTER TABLE credit_cards_temp RENAME TO credit_cards")) |
| 1697 return false; |
| 1698 |
| 1699 for (std::map<int, int>::const_iterator iter = cc_billing_map.begin(); |
| 1700 iter != cc_billing_map.end(); ++iter) { |
| 1701 sql::Statement s(db_->GetCachedStatement( |
| 1702 SQL_FROM_HERE, |
| 1703 "UPDATE credit_cards SET billing_address=? WHERE unique_id=?")); |
| 1704 if (!s) |
| 1705 return false; |
| 1706 |
| 1707 s.BindInt(0, (*iter).second); |
| 1708 s.BindInt(1, (*iter).first); |
| 1709 |
| 1710 if (!s.Run()) |
| 1711 return false; |
| 1712 } |
| 1713 |
| 1714 return true; |
| 1715 } |
| 1716 |
| 1717 bool AutofillTable::MigrateToVersion30AddDateModifed() { |
| 1718 // Add date_modified to autofill_profiles. |
| 1719 if (!db_->DoesColumnExist("autofill_profiles", "date_modified")) { |
| 1720 if (!db_->Execute("ALTER TABLE autofill_profiles ADD COLUMN " |
| 1721 "date_modified INTEGER NON NULL DEFAULT 0")) { |
| 1722 return false; |
| 1723 } |
| 1724 |
| 1725 sql::Statement s(db_->GetUniqueStatement( |
| 1726 "UPDATE autofill_profiles SET date_modified=?")); |
| 1727 if (!s) |
| 1728 return false; |
| 1729 |
| 1730 s.BindInt64(0, Time::Now().ToTimeT()); |
| 1731 |
| 1732 if (!s.Run()) |
| 1733 return false; |
| 1734 } |
| 1735 |
| 1736 // Add date_modified to credit_cards. |
| 1737 if (!db_->DoesColumnExist("credit_cards", "date_modified")) { |
| 1738 if (!db_->Execute("ALTER TABLE credit_cards ADD COLUMN " |
| 1739 "date_modified INTEGER NON NULL DEFAULT 0")) { |
| 1740 return false; |
| 1741 } |
| 1742 |
| 1743 sql::Statement s(db_->GetUniqueStatement( |
| 1744 "UPDATE credit_cards SET date_modified=?")); |
| 1745 if (!s) |
| 1746 return false; |
| 1747 |
| 1748 s.BindInt64(0, Time::Now().ToTimeT()); |
| 1749 |
| 1750 if (!s.Run()) |
| 1751 return false; |
| 1752 } |
| 1753 |
| 1754 return true; |
| 1755 } |
| 1756 |
| 1757 bool AutofillTable::MigrateToVersion31AddGUIDToCreditCardsAndProfiles() { |
| 1758 // Note that we need to check for the guid column's existence due to the |
| 1759 // fact that for a version 22 database the |autofill_profiles| table |
| 1760 // gets created fresh with |InitAutofillProfilesTable|. |
| 1761 if (!db_->DoesColumnExist("autofill_profiles", "guid")) { |
| 1762 if (!db_->Execute("ALTER TABLE autofill_profiles ADD COLUMN " |
| 1763 "guid VARCHAR NOT NULL DEFAULT \"\"")) { |
| 1764 return false; |
| 1765 } |
| 1766 |
| 1767 // Set all the |guid| fields to valid values. |
| 1768 |
| 1769 sql::Statement s(db_->GetUniqueStatement("SELECT unique_id " |
| 1770 "FROM autofill_profiles")); |
| 1771 if (!s) |
| 1772 return false; |
| 1773 |
| 1774 while (s.Step()) { |
| 1775 sql::Statement update_s( |
| 1776 db_->GetUniqueStatement("UPDATE autofill_profiles " |
| 1777 "SET guid=? WHERE unique_id=?")); |
| 1778 if (!update_s) |
| 1779 return false; |
| 1780 update_s.BindString(0, guid::GenerateGUID()); |
| 1781 update_s.BindInt(1, s.ColumnInt(0)); |
| 1782 |
| 1783 if (!update_s.Run()) |
| 1784 return false; |
| 1785 } |
| 1786 } |
| 1787 |
| 1788 // Note that we need to check for the guid column's existence due to the |
| 1789 // fact that for a version 22 database the |autofill_profiles| table |
| 1790 // gets created fresh with |InitAutofillProfilesTable|. |
| 1791 if (!db_->DoesColumnExist("credit_cards", "guid")) { |
| 1792 if (!db_->Execute("ALTER TABLE credit_cards ADD COLUMN " |
| 1793 "guid VARCHAR NOT NULL DEFAULT \"\"")) { |
| 1794 return false; |
| 1795 } |
| 1796 |
| 1797 // Set all the |guid| fields to valid values. |
| 1798 |
| 1799 sql::Statement s(db_->GetUniqueStatement("SELECT unique_id " |
| 1800 "FROM credit_cards")); |
| 1801 if (!s) |
| 1802 return false; |
| 1803 |
| 1804 while (s.Step()) { |
| 1805 sql::Statement update_s( |
| 1806 db_->GetUniqueStatement("UPDATE credit_cards " |
| 1807 "set guid=? WHERE unique_id=?")); |
| 1808 if (!update_s) |
| 1809 return false; |
| 1810 update_s.BindString(0, guid::GenerateGUID()); |
| 1811 update_s.BindInt(1, s.ColumnInt(0)); |
| 1812 |
| 1813 if (!update_s.Run()) |
| 1814 return false; |
| 1815 } |
| 1816 } |
| 1817 |
| 1818 return true; |
| 1819 } |
| 1820 |
| 1821 bool AutofillTable::MigrateToVersion32UpdateProfilesAndCreditCards() { |
| 1822 if (db_->DoesColumnExist("autofill_profiles", "unique_id")) { |
| 1823 if (!db_->Execute("CREATE TABLE autofill_profiles_temp ( " |
| 1824 "guid VARCHAR PRIMARY KEY, " |
| 1825 "label VARCHAR, " |
| 1826 "first_name VARCHAR, " |
| 1827 "middle_name VARCHAR, " |
| 1828 "last_name VARCHAR, " |
| 1829 "email VARCHAR, " |
| 1830 "company_name VARCHAR, " |
| 1831 "address_line_1 VARCHAR, " |
| 1832 "address_line_2 VARCHAR, " |
| 1833 "city VARCHAR, " |
| 1834 "state VARCHAR, " |
| 1835 "zipcode VARCHAR, " |
| 1836 "country VARCHAR, " |
| 1837 "phone VARCHAR, " |
| 1838 "fax VARCHAR, " |
| 1839 "date_modified INTEGER NOT NULL DEFAULT 0)")) { |
| 1840 return false; |
| 1841 } |
| 1842 |
| 1843 if (!db_->Execute( |
| 1844 "INSERT INTO autofill_profiles_temp " |
| 1845 "SELECT guid, label, first_name, middle_name, last_name, email, " |
| 1846 "company_name, address_line_1, address_line_2, city, state, " |
| 1847 "zipcode, country, phone, fax, date_modified " |
| 1848 "FROM autofill_profiles")) { |
| 1849 return false; |
| 1850 } |
| 1851 |
| 1852 if (!db_->Execute("DROP TABLE autofill_profiles")) |
| 1853 return false; |
| 1854 |
| 1855 if (!db_->Execute( |
| 1856 "ALTER TABLE autofill_profiles_temp RENAME TO autofill_profiles")) { |
| 1857 return false; |
| 1858 } |
| 1859 } |
| 1860 |
| 1861 if (db_->DoesColumnExist("credit_cards", "unique_id")) { |
| 1862 if (!db_->Execute("CREATE TABLE credit_cards_temp ( " |
| 1863 "guid VARCHAR PRIMARY KEY, " |
| 1864 "label VARCHAR, " |
| 1865 "name_on_card VARCHAR, " |
| 1866 "expiration_month INTEGER, " |
| 1867 "expiration_year INTEGER, " |
| 1868 "card_number_encrypted BLOB, " |
| 1869 "date_modified INTEGER NOT NULL DEFAULT 0)")) { |
| 1870 return false; |
| 1871 } |
| 1872 |
| 1873 if (!db_->Execute( |
| 1874 "INSERT INTO credit_cards_temp " |
| 1875 "SELECT guid, label, name_on_card, expiration_month, " |
| 1876 "expiration_year, card_number_encrypted, date_modified " |
| 1877 "FROM credit_cards")) { |
| 1878 return false; |
| 1879 } |
| 1880 |
| 1881 if (!db_->Execute("DROP TABLE credit_cards")) |
| 1882 return false; |
| 1883 |
| 1884 if (!db_->Execute("ALTER TABLE credit_cards_temp RENAME TO credit_cards")) |
| 1885 return false; |
| 1886 } |
| 1887 |
| 1888 return true; |
| 1889 } |
| 1890 |
| 1891 // Test the existence of the |first_name| column as an indication that |
| 1892 // we need a migration. It is possible that the new |autofill_profiles| |
| 1893 // schema is in place because the table was newly created when migrating |
| 1894 // from a pre-version-22 database. |
| 1895 bool AutofillTable::MigrateToVersion33ProfilesBasedOnFirstName() { |
| 1896 if (db_->DoesColumnExist("autofill_profiles", "first_name")) { |
| 1897 // Create autofill_profiles_temp table that will receive the data. |
| 1898 if (!db_->DoesTableExist("autofill_profiles_temp")) { |
| 1899 if (!db_->Execute("CREATE TABLE autofill_profiles_temp ( " |
| 1900 "guid VARCHAR PRIMARY KEY, " |
| 1901 "company_name VARCHAR, " |
| 1902 "address_line_1 VARCHAR, " |
| 1903 "address_line_2 VARCHAR, " |
| 1904 "city VARCHAR, " |
| 1905 "state VARCHAR, " |
| 1906 "zipcode VARCHAR, " |
| 1907 "country VARCHAR, " |
| 1908 "date_modified INTEGER NOT NULL DEFAULT 0)")) { |
| 1909 return false; |
| 1910 } |
| 1911 } |
| 1912 |
| 1913 sql::Statement s(db_->GetUniqueStatement( |
| 1914 "SELECT guid, first_name, middle_name, last_name, email, " |
| 1915 "company_name, address_line_1, address_line_2, city, state, " |
| 1916 "zipcode, country, phone, fax, date_modified " |
| 1917 "FROM autofill_profiles")); |
| 1918 while (s.Step()) { |
| 1919 AutofillProfile profile; |
| 1920 profile.set_guid(s.ColumnString(0)); |
| 1921 DCHECK(guid::IsValidGUID(profile.guid())); |
| 1922 |
| 1923 profile.SetInfo(NAME_FIRST, s.ColumnString16(1)); |
| 1924 profile.SetInfo(NAME_MIDDLE, s.ColumnString16(2)); |
| 1925 profile.SetInfo(NAME_LAST, s.ColumnString16(3)); |
| 1926 profile.SetInfo(EMAIL_ADDRESS, s.ColumnString16(4)); |
| 1927 profile.SetInfo(COMPANY_NAME, s.ColumnString16(5)); |
| 1928 profile.SetInfo(ADDRESS_HOME_LINE1, s.ColumnString16(6)); |
| 1929 profile.SetInfo(ADDRESS_HOME_LINE2, s.ColumnString16(7)); |
| 1930 profile.SetInfo(ADDRESS_HOME_CITY, s.ColumnString16(8)); |
| 1931 profile.SetInfo(ADDRESS_HOME_STATE, s.ColumnString16(9)); |
| 1932 profile.SetInfo(ADDRESS_HOME_ZIP, s.ColumnString16(10)); |
| 1933 profile.SetInfo(ADDRESS_HOME_COUNTRY, s.ColumnString16(11)); |
| 1934 profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, s.ColumnString16(12)); |
| 1935 profile.SetInfo(PHONE_FAX_WHOLE_NUMBER, s.ColumnString16(13)); |
| 1936 int64 date_modified = s.ColumnInt64(14); |
| 1937 |
| 1938 sql::Statement s_insert(db_->GetUniqueStatement( |
| 1939 "INSERT INTO autofill_profiles_temp" |
| 1940 "(guid, company_name, address_line_1, address_line_2, city," |
| 1941 " state, zipcode, country, date_modified)" |
| 1942 "VALUES (?,?,?,?,?,?,?,?,?)")); |
| 1943 if (!s) |
| 1944 return false; |
| 1945 |
| 1946 s_insert.BindString(0, profile.guid()); |
| 1947 s_insert.BindString16(1, profile.GetInfo(COMPANY_NAME)); |
| 1948 s_insert.BindString16(2, profile.GetInfo(ADDRESS_HOME_LINE1)); |
| 1949 s_insert.BindString16(3, profile.GetInfo(ADDRESS_HOME_LINE2)); |
| 1950 s_insert.BindString16(4, profile.GetInfo(ADDRESS_HOME_CITY)); |
| 1951 s_insert.BindString16(5, profile.GetInfo(ADDRESS_HOME_STATE)); |
| 1952 s_insert.BindString16(6, profile.GetInfo(ADDRESS_HOME_ZIP)); |
| 1953 s_insert.BindString16(7, profile.GetInfo(ADDRESS_HOME_COUNTRY)); |
| 1954 s_insert.BindInt64(8, date_modified); |
| 1955 |
| 1956 if (!s_insert.Run()) |
| 1957 return false; |
| 1958 |
| 1959 // Add the other bits: names, emails, and phone/fax. |
| 1960 if (!AddAutofillProfilePieces(profile, db_)) |
| 1961 return false; |
| 1962 } |
| 1963 |
| 1964 if (!db_->Execute("DROP TABLE autofill_profiles")) |
| 1965 return false; |
| 1966 |
| 1967 if (!db_->Execute( |
| 1968 "ALTER TABLE autofill_profiles_temp RENAME TO autofill_profiles")) { |
| 1969 return false; |
| 1970 } |
| 1971 } |
| 1972 |
| 1973 // Remove the labels column from the credit_cards table. |
| 1974 if (db_->DoesColumnExist("credit_cards", "label")) { |
| 1975 if (!db_->Execute("CREATE TABLE credit_cards_temp ( " |
| 1976 "guid VARCHAR PRIMARY KEY, " |
| 1977 "name_on_card VARCHAR, " |
| 1978 "expiration_month INTEGER, " |
| 1979 "expiration_year INTEGER, " |
| 1980 "card_number_encrypted BLOB, " |
| 1981 "date_modified INTEGER NOT NULL DEFAULT 0)")) { |
| 1982 return false; |
| 1983 } |
| 1984 |
| 1985 if (!db_->Execute( |
| 1986 "INSERT INTO credit_cards_temp " |
| 1987 "SELECT guid, name_on_card, expiration_month, " |
| 1988 "expiration_year, card_number_encrypted, date_modified " |
| 1989 "FROM credit_cards")) { |
| 1990 return false; |
| 1991 } |
| 1992 |
| 1993 if (!db_->Execute("DROP TABLE credit_cards")) |
| 1994 return false; |
| 1995 |
| 1996 if (!db_->Execute("ALTER TABLE credit_cards_temp RENAME TO credit_cards")) |
| 1997 return false; |
| 1998 } |
| 1999 |
| 2000 return true; |
| 2001 } |
| 2002 |
| 2003 // Test the existence of the |country_code| column as an indication that |
| 2004 // we need a migration. It is possible that the new |autofill_profiles| |
| 2005 // schema is in place because the table was newly created when migrating |
| 2006 // from a pre-version-22 database. |
| 2007 bool AutofillTable::MigrateToVersion34ProfilesBasedOnCountryCode() { |
| 2008 if (!db_->DoesColumnExist("autofill_profiles", "country_code")) { |
| 2009 if (!db_->Execute("ALTER TABLE autofill_profiles ADD COLUMN " |
| 2010 "country_code VARCHAR")) { |
| 2011 return false; |
| 2012 } |
| 2013 |
| 2014 // Set all the |country_code| fields to match existing |country| values. |
| 2015 sql::Statement s(db_->GetUniqueStatement("SELECT guid, country " |
| 2016 "FROM autofill_profiles")); |
| 2017 |
| 2018 if (!s) |
| 2019 return false; |
| 2020 |
| 2021 while (s.Step()) { |
| 2022 sql::Statement update_s( |
| 2023 db_->GetUniqueStatement("UPDATE autofill_profiles " |
| 2024 "SET country_code=? WHERE guid=?")); |
| 2025 if (!update_s) |
| 2026 return false; |
| 2027 |
| 2028 string16 country = s.ColumnString16(1); |
| 2029 std::string app_locale = AutofillCountry::ApplicationLocale(); |
| 2030 update_s.BindString(0, AutofillCountry::GetCountryCode(country, |
| 2031 app_locale)); |
| 2032 update_s.BindString(1, s.ColumnString(0)); |
| 2033 |
| 2034 if (!update_s.Run()) |
| 2035 return false; |
| 2036 } |
| 2037 } |
| 2038 |
| 2039 return true; |
| 2040 } |
| 2041 |
| 2042 // Correct all country codes with value "UK" to be "GB". This data |
| 2043 // was mistakenly introduced in build 686.0. This migration is to clean |
| 2044 // it up. See http://crbug.com/74511 for details. |
| 2045 bool AutofillTable::MigrateToVersion35GreatBritainCountryCodes() { |
| 2046 sql::Statement s(db_->GetUniqueStatement( |
| 2047 "UPDATE autofill_profiles SET country_code=\"GB\" " |
| 2048 "WHERE country_code=\"UK\"")); |
| 2049 |
| 2050 return s.Run(); |
| 2051 } |
| 2052 |
| 2053 // Merge and cull older profiles where possible. |
| 2054 bool AutofillTable::MigrateToVersion36MergeAndCullOlderProfiles() { |
| 2055 sql::Statement s(db_->GetUniqueStatement( |
| 2056 "SELECT guid, date_modified FROM autofill_profiles")); |
| 2057 if (!s) |
| 2058 return false; |
| 2059 |
| 2060 // Accumulate the good profiles. |
| 2061 std::vector<AutofillProfile> accumulated_profiles; |
| 2062 std::vector<AutofillProfile*> accumulated_profiles_p; |
| 2063 std::map<std::string, int64> modification_map; |
| 2064 while (s.Step()) { |
| 2065 std::string guid = s.ColumnString(0); |
| 2066 int64 date_modified = s.ColumnInt64(1); |
| 2067 modification_map.insert( |
| 2068 std::pair<std::string, int64>(guid, date_modified)); |
| 2069 AutofillProfile* profile = NULL; |
| 2070 if (!GetAutofillProfile(guid, &profile)) |
| 2071 return false; |
| 2072 |
| 2073 scoped_ptr<AutofillProfile> p(profile); |
| 2074 |
| 2075 if (PersonalDataManager::IsValidLearnableProfile(*p)) { |
| 2076 std::vector<AutofillProfile> merged_profiles; |
| 2077 bool merged = PersonalDataManager::MergeProfile( |
| 2078 *p, accumulated_profiles_p, &merged_profiles); |
| 2079 |
| 2080 std::swap(accumulated_profiles, merged_profiles); |
| 2081 |
| 2082 accumulated_profiles_p.clear(); |
| 2083 accumulated_profiles_p.resize(accumulated_profiles.size()); |
| 2084 std::transform(accumulated_profiles.begin(), |
| 2085 accumulated_profiles.end(), |
| 2086 accumulated_profiles_p.begin(), |
| 2087 address_of<AutofillProfile>); |
| 2088 |
| 2089 // If the profile got merged trash the original. |
| 2090 if (merged) |
| 2091 AddAutofillGUIDToTrash(p->guid()); |
| 2092 |
| 2093 } else { |
| 2094 // An invalid profile, so trash it. |
| 2095 AddAutofillGUIDToTrash(p->guid()); |
| 2096 } |
| 2097 } |
| 2098 |
| 2099 // Drop the current profiles. |
| 2100 if (!ClearAutofillProfiles()) |
| 2101 return false; |
| 2102 |
| 2103 // Add the newly merged profiles back in. |
| 2104 for (std::vector<AutofillProfile>::const_iterator |
| 2105 iter = accumulated_profiles.begin(); |
| 2106 iter != accumulated_profiles.end(); |
| 2107 ++iter) { |
| 2108 if (!AddAutofillProfile(*iter)) |
| 2109 return false; |
| 2110 |
| 2111 // Fix up the original modification date. |
| 2112 std::map<std::string, int64>::const_iterator date_item = |
| 2113 modification_map.find(iter->guid()); |
| 2114 if (date_item == modification_map.end()) |
| 2115 return false; |
| 2116 |
| 2117 sql::Statement s_date(db_->GetUniqueStatement( |
| 2118 "UPDATE autofill_profiles SET date_modified=? " |
| 2119 "WHERE guid=?")); |
| 2120 s_date.BindInt64(0, date_item->second); |
| 2121 s_date.BindString(1, iter->guid()); |
| 2122 if (!s_date.Run()) |
| 2123 return false; |
| 2124 } |
| 2125 |
| 2126 return true; |
| 2127 } |
OLD | NEW |