Chromium Code Reviews| 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 |