autofill_field.cc revision f2477e01787aa58f445919b809d89e252beef54f
1// Copyright 2013 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 "components/autofill/core/browser/autofill_field.h" 6 7#include "base/logging.h" 8#include "base/sha1.h" 9#include "base/strings/string_number_conversions.h" 10#include "base/strings/string_split.h" 11#include "base/strings/string_util.h" 12#include "base/strings/utf_string_conversions.h" 13#include "components/autofill/core/browser/autofill_country.h" 14#include "components/autofill/core/browser/autofill_type.h" 15#include "components/autofill/core/browser/phone_number.h" 16#include "components/autofill/core/browser/state_names.h" 17#include "grit/component_strings.h" 18#include "ui/base/l10n/l10n_util.h" 19 20using base::StringToInt; 21 22namespace autofill { 23namespace { 24 25const char* const kMonthsAbbreviated[] = { 26 NULL, // Padding so index 1 = month 1 = January. 27 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 28 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 29}; 30 31const char* const kMonthsFull[] = { 32 NULL, // Padding so index 1 = month 1 = January. 33 "January", "February", "March", "April", "May", "June", 34 "July", "August", "September", "October", "November", "December", 35}; 36 37// Returns true if the value was successfully set, meaning |value| was found in 38// the list of select options in |field|. 39bool SetSelectControlValue(const base::string16& value, 40 FormFieldData* field) { 41 base::string16 value_lowercase = StringToLowerASCII(value); 42 43 DCHECK_EQ(field->option_values.size(), field->option_contents.size()); 44 base::string16 best_match; 45 for (size_t i = 0; i < field->option_values.size(); ++i) { 46 if (value == field->option_values[i] || 47 value == field->option_contents[i]) { 48 // An exact match, use it. 49 best_match = field->option_values[i]; 50 break; 51 } 52 53 if (value_lowercase == StringToLowerASCII(field->option_values[i]) || 54 value_lowercase == StringToLowerASCII(field->option_contents[i])) { 55 // A match, but not in the same case. Save it in case an exact match is 56 // not found. 57 best_match = field->option_values[i]; 58 } 59 } 60 61 if (best_match.empty()) 62 return false; 63 64 field->value = best_match; 65 return true; 66} 67 68 69// Try to fill a numeric |value| into the given |field|. 70bool FillNumericSelectControl(int value, 71 FormFieldData* field) { 72 DCHECK_EQ(field->option_values.size(), field->option_contents.size()); 73 for (size_t i = 0; i < field->option_values.size(); ++i) { 74 int option; 75 if ((StringToInt(field->option_values[i], &option) && option == value) || 76 (StringToInt(field->option_contents[i], &option) && option == value)) { 77 field->value = field->option_values[i]; 78 return true; 79 } 80 } 81 82 return false; 83} 84 85bool FillStateSelectControl(const base::string16& value, 86 FormFieldData* field) { 87 base::string16 full, abbreviation; 88 state_names::GetNameAndAbbreviation(value, &full, &abbreviation); 89 90 // Try the abbreviation first. 91 if (!abbreviation.empty() && SetSelectControlValue(abbreviation, field)) 92 return true; 93 94 return !full.empty() && SetSelectControlValue(full, field); 95} 96 97bool FillCountrySelectControl(const base::string16& value, 98 const std::string& app_locale, 99 FormFieldData* field_data) { 100 std::string country_code = AutofillCountry::GetCountryCode(value, app_locale); 101 if (country_code.empty()) 102 return false; 103 104 DCHECK_EQ(field_data->option_values.size(), 105 field_data->option_contents.size()); 106 for (size_t i = 0; i < field_data->option_values.size(); ++i) { 107 // Canonicalize each <option> value to a country code, and compare to the 108 // target country code. 109 base::string16 value = field_data->option_values[i]; 110 base::string16 contents = field_data->option_contents[i]; 111 if (country_code == AutofillCountry::GetCountryCode(value, app_locale) || 112 country_code == AutofillCountry::GetCountryCode(contents, app_locale)) { 113 field_data->value = value; 114 return true; 115 } 116 } 117 118 return false; 119} 120 121bool FillExpirationMonthSelectControl(const base::string16& value, 122 FormFieldData* field) { 123 int index = 0; 124 if (!StringToInt(value, &index) || 125 index <= 0 || 126 static_cast<size_t>(index) >= arraysize(kMonthsFull)) 127 return false; 128 129 bool filled = 130 SetSelectControlValue(ASCIIToUTF16(kMonthsAbbreviated[index]), field) || 131 SetSelectControlValue(ASCIIToUTF16(kMonthsFull[index]), field) || 132 FillNumericSelectControl(index, field); 133 return filled; 134} 135 136// Returns true if the last two digits in |year| match those in |str|. 137bool LastTwoDigitsMatch(const base::string16& year, 138 const base::string16& str) { 139 int year_int; 140 int str_int; 141 if (!StringToInt(year, &year_int) || !StringToInt(str, &str_int)) 142 return false; 143 144 return (year_int % 100) == (str_int % 100); 145} 146 147// Try to fill a year |value| into the given |field| by comparing the last two 148// digits of the year to the field's options. 149bool FillYearSelectControl(const base::string16& value, 150 FormFieldData* field) { 151 if (value.size() != 2U && value.size() != 4U) 152 return false; 153 154 DCHECK_EQ(field->option_values.size(), field->option_contents.size()); 155 for (size_t i = 0; i < field->option_values.size(); ++i) { 156 if (LastTwoDigitsMatch(value, field->option_values[i]) || 157 LastTwoDigitsMatch(value, field->option_contents[i])) { 158 field->value = field->option_values[i]; 159 return true; 160 } 161 } 162 163 return false; 164} 165 166// Try to fill a credit card type |value| (Visa, MasterCard, etc.) into the 167// given |field|. 168bool FillCreditCardTypeSelectControl(const base::string16& value, 169 FormFieldData* field) { 170 // Try stripping off spaces. 171 base::string16 value_stripped; 172 RemoveChars(StringToLowerASCII(value), kWhitespaceUTF16, &value_stripped); 173 174 for (size_t i = 0; i < field->option_values.size(); ++i) { 175 base::string16 option_value_lowercase; 176 RemoveChars(StringToLowerASCII(field->option_values[i]), kWhitespaceUTF16, 177 &option_value_lowercase); 178 base::string16 option_contents_lowercase; 179 RemoveChars(StringToLowerASCII(field->option_contents[i]), kWhitespaceUTF16, 180 &option_contents_lowercase); 181 182 // Perform a case-insensitive comparison; but fill the form with the 183 // original text, not the lowercased version. 184 if (value_stripped == option_value_lowercase || 185 value_stripped == option_contents_lowercase) { 186 field->value = field->option_values[i]; 187 return true; 188 } 189 } 190 191 // For American Express, also try filling as "AmEx". 192 if (value == l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_AMEX)) 193 return FillCreditCardTypeSelectControl(ASCIIToUTF16("AmEx"), field); 194 195 return false; 196} 197 198// Set |field_data|'s value to |number|, or possibly an appropriate substring of 199// |number|. The |field| specifies the type of the phone and whether this is a 200// phone prefix or suffix. 201void FillPhoneNumberField(const AutofillField& field, 202 const base::string16& number, 203 FormFieldData* field_data) { 204 // Check to see if the size field matches the "prefix" or "suffix" sizes and 205 // fill accordingly. 206 base::string16 value = number; 207 if (number.length() == 208 PhoneNumber::kPrefixLength + PhoneNumber::kSuffixLength) { 209 if (field.phone_part() == AutofillField::PHONE_PREFIX || 210 field_data->max_length == PhoneNumber::kPrefixLength) { 211 value = number.substr(PhoneNumber::kPrefixOffset, 212 PhoneNumber::kPrefixLength); 213 } else if (field.phone_part() == AutofillField::PHONE_SUFFIX || 214 field_data->max_length == PhoneNumber::kSuffixLength) { 215 value = number.substr(PhoneNumber::kSuffixOffset, 216 PhoneNumber::kSuffixLength); 217 } 218 } 219 220 field_data->value = value; 221} 222 223// Fills in the select control |field| with |value|. If an exact match is not 224// found, falls back to alternate filling strategies based on the |type|. 225void FillSelectControl(const AutofillType& type, 226 const base::string16& value, 227 const std::string& app_locale, 228 FormFieldData* field) { 229 DCHECK_EQ("select-one", field->form_control_type); 230 231 // Guard against corrupted values passed over IPC. 232 if (field->option_values.size() != field->option_contents.size()) 233 return; 234 235 if (value.empty()) 236 return; 237 238 // First, search for exact matches. 239 if (SetSelectControlValue(value, field)) 240 return; 241 242 // If that fails, try specific fallbacks based on the field type. 243 ServerFieldType storable_type = type.GetStorableType(); 244 if (storable_type == ADDRESS_HOME_STATE) { 245 FillStateSelectControl(value, field); 246 } else if (storable_type == ADDRESS_HOME_COUNTRY) { 247 FillCountrySelectControl(value, app_locale, field); 248 } else if (storable_type == CREDIT_CARD_EXP_MONTH) { 249 FillExpirationMonthSelectControl(value, field); 250 } else if (storable_type == CREDIT_CARD_EXP_2_DIGIT_YEAR || 251 storable_type == CREDIT_CARD_EXP_4_DIGIT_YEAR) { 252 FillYearSelectControl(value, field); 253 } else if (storable_type == CREDIT_CARD_TYPE) { 254 FillCreditCardTypeSelectControl(value, field); 255 } 256} 257 258// Fills in the month control |field| with |value|. |value| should be a date 259// formatted as MM/YYYY. If it isn't, filling will fail. 260bool FillMonthControl(const base::string16& value, FormFieldData* field) { 261 // Autofill formats a combined date as month/year. 262 std::vector<base::string16> pieces; 263 base::SplitString(value, char16('/'), &pieces); 264 if (pieces.size() != 2) 265 return false; 266 267 // HTML5 input="month" is formatted as year-month. 268 base::string16 month = pieces[0]; 269 base::string16 year = pieces[1]; 270 if ((month.size() != 1 && month.size() != 2) || year.size() != 4) 271 return false; 272 273 // HTML5 input="month" expects zero-padded months. 274 if (month.size() == 1) 275 month = ASCIIToUTF16("0") + month; 276 277 field->value = year + ASCIIToUTF16("-") + month; 278 return true; 279} 280 281// Fills |field| with the street address in |value|. Translates newlines into 282// equivalent separators when necessary, i.e. when filling a single-line field. 283void FillStreetAddress(const base::string16& value, 284 FormFieldData* field) { 285 if (field->form_control_type == "textarea") { 286 field->value = value; 287 return; 288 } 289 290 base::string16 one_line_value; 291 const char16 kNewline[] = { '\n', 0 }; 292 const base::string16 separator = 293 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_LINE_SEPARATOR); 294 ReplaceChars(value, kNewline, separator, &one_line_value); 295 field->value = one_line_value; 296} 297 298std::string Hash32Bit(const std::string& str) { 299 std::string hash_bin = base::SHA1HashString(str); 300 DCHECK_EQ(20U, hash_bin.length()); 301 302 uint32 hash32 = ((hash_bin[0] & 0xFF) << 24) | 303 ((hash_bin[1] & 0xFF) << 16) | 304 ((hash_bin[2] & 0xFF) << 8) | 305 (hash_bin[3] & 0xFF); 306 307 return base::UintToString(hash32); 308} 309 310} // namespace 311 312AutofillField::AutofillField() 313 : server_type_(NO_SERVER_DATA), 314 heuristic_type_(UNKNOWN_TYPE), 315 html_type_(HTML_TYPE_UNKNOWN), 316 html_mode_(HTML_MODE_NONE), 317 phone_part_(IGNORED) { 318} 319 320AutofillField::AutofillField(const FormFieldData& field, 321 const base::string16& unique_name) 322 : FormFieldData(field), 323 unique_name_(unique_name), 324 server_type_(NO_SERVER_DATA), 325 heuristic_type_(UNKNOWN_TYPE), 326 html_type_(HTML_TYPE_UNKNOWN), 327 html_mode_(HTML_MODE_NONE), 328 phone_part_(IGNORED) { 329} 330 331AutofillField::~AutofillField() {} 332 333void AutofillField::set_heuristic_type(ServerFieldType type) { 334 if (type >= 0 && type < MAX_VALID_FIELD_TYPE && 335 type != FIELD_WITH_DEFAULT_VALUE) { 336 heuristic_type_ = type; 337 } else { 338 NOTREACHED(); 339 // This case should not be reachable; but since this has potential 340 // implications on data uploaded to the server, better safe than sorry. 341 heuristic_type_ = UNKNOWN_TYPE; 342 } 343} 344 345void AutofillField::set_server_type(ServerFieldType type) { 346 // Chrome no longer supports fax numbers, but the server still does. 347 if (type >= PHONE_FAX_NUMBER && type <= PHONE_FAX_WHOLE_NUMBER) 348 return; 349 350 server_type_ = type; 351} 352 353void AutofillField::SetHtmlType(HtmlFieldType type, HtmlFieldMode mode) { 354 html_type_ = type; 355 html_mode_ = mode; 356 357 if (type == HTML_TYPE_TEL_LOCAL_PREFIX) 358 phone_part_ = PHONE_PREFIX; 359 else if (type == HTML_TYPE_TEL_LOCAL_SUFFIX) 360 phone_part_ = PHONE_SUFFIX; 361 else 362 phone_part_ = IGNORED; 363} 364 365AutofillType AutofillField::Type() const { 366 if (html_type_ != HTML_TYPE_UNKNOWN) 367 return AutofillType(html_type_, html_mode_); 368 369 if (server_type_ != NO_SERVER_DATA) 370 return AutofillType(server_type_); 371 372 return AutofillType(heuristic_type_); 373} 374 375bool AutofillField::IsEmpty() const { 376 return value.empty(); 377} 378 379std::string AutofillField::FieldSignature() const { 380 std::string field_name = UTF16ToUTF8(name); 381 std::string field_string = field_name + "&" + form_control_type; 382 return Hash32Bit(field_string); 383} 384 385bool AutofillField::IsFieldFillable() const { 386 return !Type().IsUnknown(); 387} 388 389// static 390void AutofillField::FillFormField(const AutofillField& field, 391 const base::string16& value, 392 const std::string& app_locale, 393 FormFieldData* field_data) { 394 AutofillType type = field.Type(); 395 396 if (type.GetStorableType() == PHONE_HOME_NUMBER) 397 FillPhoneNumberField(field, value, field_data); 398 else if (field_data->form_control_type == "select-one") 399 FillSelectControl(type, value, app_locale, field_data); 400 else if (field_data->form_control_type == "month") 401 FillMonthControl(value, field_data); 402 else if (type.GetStorableType() == ADDRESS_HOME_STREET_ADDRESS) 403 FillStreetAddress(value, field_data); 404 else 405 field_data->value = value; 406} 407 408} // namespace autofill 409