| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/webdata/autofill_util.h" | |
| 6 | |
| 7 #include "app/sql/statement.h" | |
| 8 #include "base/logging.h" | |
| 9 #include "base/time.h" | |
| 10 #include "chrome/browser/autofill/autofill_profile.h" | |
| 11 #include "chrome/browser/autofill/autofill_type.h" | |
| 12 #include "chrome/browser/autofill/credit_card.h" | |
| 13 #include "chrome/browser/password_manager/encryptor.h" | |
| 14 #include "chrome/common/guid.h" | |
| 15 | |
| 16 using base::Time; | |
| 17 | |
| 18 namespace autofill_util { | |
| 19 | |
| 20 // The maximum length allowed for form data. | |
| 21 const size_t kMaxDataLength = 1024; | |
| 22 | |
| 23 string16 LimitDataSize(const string16& data) { | |
| 24 if (data.size() > kMaxDataLength) | |
| 25 return data.substr(0, kMaxDataLength); | |
| 26 | |
| 27 return data; | |
| 28 } | |
| 29 | |
| 30 void BindAutofillProfileToStatement(const AutofillProfile& profile, | |
| 31 sql::Statement* s) { | |
| 32 DCHECK(guid::IsValidGUID(profile.guid())); | |
| 33 s->BindString(0, profile.guid()); | |
| 34 | |
| 35 string16 text = profile.GetInfo(COMPANY_NAME); | |
| 36 s->BindString16(1, LimitDataSize(text)); | |
| 37 text = profile.GetInfo(ADDRESS_HOME_LINE1); | |
| 38 s->BindString16(2, LimitDataSize(text)); | |
| 39 text = profile.GetInfo(ADDRESS_HOME_LINE2); | |
| 40 s->BindString16(3, LimitDataSize(text)); | |
| 41 text = profile.GetInfo(ADDRESS_HOME_CITY); | |
| 42 s->BindString16(4, LimitDataSize(text)); | |
| 43 text = profile.GetInfo(ADDRESS_HOME_STATE); | |
| 44 s->BindString16(5, LimitDataSize(text)); | |
| 45 text = profile.GetInfo(ADDRESS_HOME_ZIP); | |
| 46 s->BindString16(6, LimitDataSize(text)); | |
| 47 text = profile.GetInfo(ADDRESS_HOME_COUNTRY); | |
| 48 s->BindString16(7, LimitDataSize(text)); | |
| 49 std::string country_code = profile.CountryCode(); | |
| 50 s->BindString(8, country_code); | |
| 51 s->BindInt64(9, Time::Now().ToTimeT()); | |
| 52 } | |
| 53 | |
| 54 AutofillProfile* AutofillProfileFromStatement(const sql::Statement& s) { | |
| 55 AutofillProfile* profile = new AutofillProfile; | |
| 56 profile->set_guid(s.ColumnString(0)); | |
| 57 DCHECK(guid::IsValidGUID(profile->guid())); | |
| 58 | |
| 59 profile->SetInfo(COMPANY_NAME, s.ColumnString16(1)); | |
| 60 profile->SetInfo(ADDRESS_HOME_LINE1, s.ColumnString16(2)); | |
| 61 profile->SetInfo(ADDRESS_HOME_LINE2, s.ColumnString16(3)); | |
| 62 profile->SetInfo(ADDRESS_HOME_CITY, s.ColumnString16(4)); | |
| 63 profile->SetInfo(ADDRESS_HOME_STATE, s.ColumnString16(5)); | |
| 64 profile->SetInfo(ADDRESS_HOME_ZIP, s.ColumnString16(6)); | |
| 65 // Intentionally skip column 7, which stores the localized country name. | |
| 66 profile->SetCountryCode(s.ColumnString(8)); | |
| 67 // Intentionally skip column 9, which stores the profile's modification date. | |
| 68 | |
| 69 return profile; | |
| 70 } | |
| 71 | |
| 72 void BindCreditCardToStatement(const CreditCard& credit_card, | |
| 73 sql::Statement* s) { | |
| 74 DCHECK(guid::IsValidGUID(credit_card.guid())); | |
| 75 s->BindString(0, credit_card.guid()); | |
| 76 | |
| 77 string16 text = credit_card.GetInfo(CREDIT_CARD_NAME); | |
| 78 s->BindString16(1, LimitDataSize(text)); | |
| 79 text = credit_card.GetInfo(CREDIT_CARD_EXP_MONTH); | |
| 80 s->BindString16(2, LimitDataSize(text)); | |
| 81 text = credit_card.GetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR); | |
| 82 s->BindString16(3, LimitDataSize(text)); | |
| 83 text = credit_card.GetInfo(CREDIT_CARD_NUMBER); | |
| 84 std::string encrypted_data; | |
| 85 Encryptor::EncryptString16(text, &encrypted_data); | |
| 86 s->BindBlob(4, encrypted_data.data(), | |
| 87 static_cast<int>(encrypted_data.length())); | |
| 88 s->BindInt64(5, Time::Now().ToTimeT()); | |
| 89 } | |
| 90 | |
| 91 CreditCard* CreditCardFromStatement(const sql::Statement& s) { | |
| 92 CreditCard* credit_card = new CreditCard; | |
| 93 | |
| 94 credit_card->set_guid(s.ColumnString(0)); | |
| 95 DCHECK(guid::IsValidGUID(credit_card->guid())); | |
| 96 | |
| 97 credit_card->SetInfo(CREDIT_CARD_NAME, s.ColumnString16(1)); | |
| 98 credit_card->SetInfo(CREDIT_CARD_EXP_MONTH, | |
| 99 s.ColumnString16(2)); | |
| 100 credit_card->SetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, | |
| 101 s.ColumnString16(3)); | |
| 102 int encrypted_number_len = s.ColumnByteLength(4); | |
| 103 string16 credit_card_number; | |
| 104 if (encrypted_number_len) { | |
| 105 std::string encrypted_number; | |
| 106 encrypted_number.resize(encrypted_number_len); | |
| 107 memcpy(&encrypted_number[0], s.ColumnBlob(4), encrypted_number_len); | |
| 108 Encryptor::DecryptString16(encrypted_number, &credit_card_number); | |
| 109 } | |
| 110 credit_card->SetInfo(CREDIT_CARD_NUMBER, credit_card_number); | |
| 111 // Intentionally skip column 5, which stores the modification date. | |
| 112 | |
| 113 return credit_card; | |
| 114 } | |
| 115 | |
| 116 bool AddAutofillProfileNamesToProfile(sql::Connection* db, | |
| 117 AutofillProfile* profile) { | |
| 118 sql::Statement s(db->GetUniqueStatement( | |
| 119 "SELECT guid, first_name, middle_name, last_name " | |
| 120 "FROM autofill_profile_names " | |
| 121 "WHERE guid=?")); | |
| 122 if (!s) { | |
| 123 NOTREACHED() << "Statement prepare failed"; | |
| 124 return false; | |
| 125 } | |
| 126 s.BindString(0, profile->guid()); | |
| 127 | |
| 128 std::vector<string16> first_names; | |
| 129 std::vector<string16> middle_names; | |
| 130 std::vector<string16> last_names; | |
| 131 while (s.Step()) { | |
| 132 DCHECK_EQ(profile->guid(), s.ColumnString(0)); | |
| 133 first_names.push_back(s.ColumnString16(1)); | |
| 134 middle_names.push_back(s.ColumnString16(2)); | |
| 135 last_names.push_back(s.ColumnString16(3)); | |
| 136 } | |
| 137 profile->SetMultiInfo(NAME_FIRST, first_names); | |
| 138 profile->SetMultiInfo(NAME_MIDDLE, middle_names); | |
| 139 profile->SetMultiInfo(NAME_LAST, last_names); | |
| 140 return true; | |
| 141 } | |
| 142 | |
| 143 bool AddAutofillProfileEmailsToProfile(sql::Connection* db, | |
| 144 AutofillProfile* profile) { | |
| 145 sql::Statement s(db->GetUniqueStatement( | |
| 146 "SELECT guid, email " | |
| 147 "FROM autofill_profile_emails " | |
| 148 "WHERE guid=?")); | |
| 149 if (!s) { | |
| 150 NOTREACHED() << "Statement prepare failed"; | |
| 151 return false; | |
| 152 } | |
| 153 s.BindString(0, profile->guid()); | |
| 154 | |
| 155 std::vector<string16> emails; | |
| 156 while (s.Step()) { | |
| 157 DCHECK_EQ(profile->guid(), s.ColumnString(0)); | |
| 158 emails.push_back(s.ColumnString16(1)); | |
| 159 } | |
| 160 profile->SetMultiInfo(EMAIL_ADDRESS, emails); | |
| 161 return true; | |
| 162 } | |
| 163 | |
| 164 bool AddAutofillProfilePhonesToProfile(sql::Connection* db, | |
| 165 AutofillProfile* profile) { | |
| 166 sql::Statement s(db->GetUniqueStatement( | |
| 167 "SELECT guid, type, number " | |
| 168 "FROM autofill_profile_phones " | |
| 169 "WHERE guid=? AND type=?")); | |
| 170 if (!s) { | |
| 171 NOTREACHED() << "Statement prepare failed"; | |
| 172 return false; | |
| 173 } | |
| 174 s.BindString(0, profile->guid()); | |
| 175 s.BindInt(1, kAutofillPhoneNumber); | |
| 176 | |
| 177 std::vector<string16> numbers; | |
| 178 while (s.Step()) { | |
| 179 DCHECK_EQ(profile->guid(), s.ColumnString(0)); | |
| 180 numbers.push_back(s.ColumnString16(2)); | |
| 181 } | |
| 182 profile->SetMultiInfo(PHONE_HOME_WHOLE_NUMBER, numbers); | |
| 183 return true; | |
| 184 } | |
| 185 | |
| 186 bool AddAutofillProfileFaxesToProfile(sql::Connection* db, | |
| 187 AutofillProfile* profile) { | |
| 188 sql::Statement s(db->GetUniqueStatement( | |
| 189 "SELECT guid, type, number " | |
| 190 "FROM autofill_profile_phones " | |
| 191 "WHERE guid=? AND type=?")); | |
| 192 if (!s) { | |
| 193 NOTREACHED() << "Statement prepare failed"; | |
| 194 return false; | |
| 195 } | |
| 196 s.BindString(0, profile->guid()); | |
| 197 s.BindInt(1, kAutofillFaxNumber); | |
| 198 | |
| 199 std::vector<string16> numbers; | |
| 200 while (s.Step()) { | |
| 201 DCHECK_EQ(profile->guid(), s.ColumnString(0)); | |
| 202 numbers.push_back(s.ColumnString16(2)); | |
| 203 } | |
| 204 profile->SetMultiInfo(PHONE_FAX_WHOLE_NUMBER, numbers); | |
| 205 return true; | |
| 206 } | |
| 207 | |
| 208 | |
| 209 bool AddAutofillProfileNames(const AutofillProfile& profile, | |
| 210 sql::Connection* db) { | |
| 211 std::vector<string16> first_names; | |
| 212 profile.GetMultiInfo(NAME_FIRST, &first_names); | |
| 213 std::vector<string16> middle_names; | |
| 214 profile.GetMultiInfo(NAME_MIDDLE, &middle_names); | |
| 215 std::vector<string16> last_names; | |
| 216 profile.GetMultiInfo(NAME_LAST, &last_names); | |
| 217 DCHECK_EQ(first_names.size(), middle_names.size()); | |
| 218 DCHECK_EQ(middle_names.size(), last_names.size()); | |
| 219 | |
| 220 for (size_t i = 0; i < first_names.size(); ++i) { | |
| 221 // Add the new name. | |
| 222 sql::Statement s(db->GetUniqueStatement( | |
| 223 "INSERT INTO autofill_profile_names" | |
| 224 " (guid, first_name, middle_name, last_name) " | |
| 225 "VALUES (?,?,?,?)")); | |
| 226 if (!s) { | |
| 227 NOTREACHED(); | |
| 228 return false; | |
| 229 } | |
| 230 s.BindString(0, profile.guid()); | |
| 231 s.BindString16(1, first_names[i]); | |
| 232 s.BindString16(2, middle_names[i]); | |
| 233 s.BindString16(3, last_names[i]); | |
| 234 | |
| 235 if (!s.Run()) { | |
| 236 NOTREACHED(); | |
| 237 return false; | |
| 238 } | |
| 239 } | |
| 240 return true; | |
| 241 } | |
| 242 | |
| 243 bool AddAutofillProfileEmails(const AutofillProfile& profile, | |
| 244 sql::Connection* db) { | |
| 245 std::vector<string16> emails; | |
| 246 profile.GetMultiInfo(EMAIL_ADDRESS, &emails); | |
| 247 | |
| 248 for (size_t i = 0; i < emails.size(); ++i) { | |
| 249 // Add the new email. | |
| 250 sql::Statement s(db->GetUniqueStatement( | |
| 251 "INSERT INTO autofill_profile_emails" | |
| 252 " (guid, email) " | |
| 253 "VALUES (?,?)")); | |
| 254 if (!s) { | |
| 255 NOTREACHED(); | |
| 256 return false; | |
| 257 } | |
| 258 s.BindString(0, profile.guid()); | |
| 259 s.BindString16(1, emails[i]); | |
| 260 | |
| 261 if (!s.Run()) { | |
| 262 NOTREACHED(); | |
| 263 return false; | |
| 264 } | |
| 265 } | |
| 266 return true; | |
| 267 } | |
| 268 | |
| 269 bool AddAutofillProfilePhones(const AutofillProfile& profile, | |
| 270 AutofillPhoneType phone_type, | |
| 271 sql::Connection* db) { | |
| 272 AutofillFieldType field_type; | |
| 273 if (phone_type == kAutofillPhoneNumber) { | |
| 274 field_type = PHONE_HOME_WHOLE_NUMBER; | |
| 275 } else if (phone_type == kAutofillFaxNumber) { | |
| 276 field_type = PHONE_FAX_WHOLE_NUMBER; | |
| 277 } else { | |
| 278 NOTREACHED(); | |
| 279 return false; | |
| 280 } | |
| 281 | |
| 282 std::vector<string16> numbers; | |
| 283 profile.GetMultiInfo(field_type, &numbers); | |
| 284 | |
| 285 for (size_t i = 0; i < numbers.size(); ++i) { | |
| 286 // Add the new number. | |
| 287 sql::Statement s(db->GetUniqueStatement( | |
| 288 "INSERT INTO autofill_profile_phones" | |
| 289 " (guid, type, number) " | |
| 290 "VALUES (?,?,?)")); | |
| 291 if (!s) { | |
| 292 NOTREACHED(); | |
| 293 return false; | |
| 294 } | |
| 295 s.BindString(0, profile.guid()); | |
| 296 s.BindInt(1, phone_type); | |
| 297 s.BindString16(2, numbers[i]); | |
| 298 | |
| 299 if (!s.Run()) { | |
| 300 NOTREACHED(); | |
| 301 return false; | |
| 302 } | |
| 303 } | |
| 304 return true; | |
| 305 } | |
| 306 | |
| 307 bool AddAutofillProfilePieces(const AutofillProfile& profile, | |
| 308 sql::Connection* db) { | |
| 309 if (!AddAutofillProfileNames(profile, db)) | |
| 310 return false; | |
| 311 | |
| 312 if (!AddAutofillProfileEmails(profile, db)) | |
| 313 return false; | |
| 314 | |
| 315 if (!AddAutofillProfilePhones(profile, kAutofillPhoneNumber, db)) | |
| 316 return false; | |
| 317 | |
| 318 if (!AddAutofillProfilePhones(profile, kAutofillFaxNumber, db)) | |
| 319 return false; | |
| 320 | |
| 321 return true; | |
| 322 } | |
| 323 | |
| 324 bool RemoveAutofillProfilePieces(const std::string& guid, sql::Connection* db) { | |
| 325 sql::Statement s1(db->GetUniqueStatement( | |
| 326 "DELETE FROM autofill_profile_names WHERE guid = ?")); | |
| 327 if (!s1) { | |
| 328 NOTREACHED() << "Statement prepare failed"; | |
| 329 return false; | |
| 330 } | |
| 331 | |
| 332 s1.BindString(0, guid); | |
| 333 if (!s1.Run()) | |
| 334 return false; | |
| 335 | |
| 336 sql::Statement s2(db->GetUniqueStatement( | |
| 337 "DELETE FROM autofill_profile_emails WHERE guid = ?")); | |
| 338 if (!s2) { | |
| 339 NOTREACHED() << "Statement prepare failed"; | |
| 340 return false; | |
| 341 } | |
| 342 | |
| 343 s2.BindString(0, guid); | |
| 344 if (!s2.Run()) | |
| 345 return false; | |
| 346 | |
| 347 sql::Statement s3(db->GetUniqueStatement( | |
| 348 "DELETE FROM autofill_profile_phones WHERE guid = ?")); | |
| 349 if (!s3) { | |
| 350 NOTREACHED() << "Statement prepare failed"; | |
| 351 return false; | |
| 352 } | |
| 353 | |
| 354 s3.BindString(0, guid); | |
| 355 return s3.Run(); | |
| 356 } | |
| 357 | |
| 358 } // namespace autofill_util | |
| OLD | NEW |