autofill_field.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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 base::RemoveChars(StringToLowerASCII(value), base::kWhitespaceUTF16, 173 &value_stripped); 174 175 for (size_t i = 0; i < field->option_values.size(); ++i) { 176 base::string16 option_value_lowercase; 177 base::RemoveChars(StringToLowerASCII(field->option_values[i]), 178 base::kWhitespaceUTF16, &option_value_lowercase); 179 base::string16 option_contents_lowercase; 180 base::RemoveChars(StringToLowerASCII(field->option_contents[i]), 181 base::kWhitespaceUTF16, &option_contents_lowercase); 182 183 // Perform a case-insensitive comparison; but fill the form with the 184 // original text, not the lowercased version. 185 if (value_stripped == option_value_lowercase || 186 value_stripped == option_contents_lowercase) { 187 field->value = field->option_values[i]; 188 return true; 189 } 190 } 191 192 // For American Express, also try filling as "AmEx". 193 if (value == l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_AMEX)) 194 return FillCreditCardTypeSelectControl(ASCIIToUTF16("AmEx"), field); 195 196 return false; 197} 198 199// Set |field_data|'s value to |number|, or possibly an appropriate substring of 200// |number|. The |field| specifies the type of the phone and whether this is a 201// phone prefix or suffix. 202void FillPhoneNumberField(const AutofillField& field, 203 const base::string16& number, 204 FormFieldData* field_data) { 205 // Check to see if the size field matches the "prefix" or "suffix" sizes and 206 // fill accordingly. 207 base::string16 value = number; 208 if (number.length() == 209 PhoneNumber::kPrefixLength + PhoneNumber::kSuffixLength) { 210 if (field.phone_part() == AutofillField::PHONE_PREFIX || 211 field_data->max_length == PhoneNumber::kPrefixLength) { 212 value = number.substr(PhoneNumber::kPrefixOffset, 213 PhoneNumber::kPrefixLength); 214 } else if (field.phone_part() == AutofillField::PHONE_SUFFIX || 215 field_data->max_length == PhoneNumber::kSuffixLength) { 216 value = number.substr(PhoneNumber::kSuffixOffset, 217 PhoneNumber::kSuffixLength); 218 } 219 } 220 221 field_data->value = value; 222} 223 224// Fills in the select control |field| with |value|. If an exact match is not 225// found, falls back to alternate filling strategies based on the |type|. 226void FillSelectControl(const AutofillType& type, 227 const base::string16& value, 228 const std::string& app_locale, 229 FormFieldData* field) { 230 DCHECK_EQ("select-one", field->form_control_type); 231 232 // Guard against corrupted values passed over IPC. 233 if (field->option_values.size() != field->option_contents.size()) 234 return; 235 236 if (value.empty()) 237 return; 238 239 // First, search for exact matches. 240 if (SetSelectControlValue(value, field)) 241 return; 242 243 // If that fails, try specific fallbacks based on the field type. 244 ServerFieldType storable_type = type.GetStorableType(); 245 if (storable_type == ADDRESS_HOME_STATE) { 246 FillStateSelectControl(value, field); 247 } else if (storable_type == ADDRESS_HOME_COUNTRY) { 248 FillCountrySelectControl(value, app_locale, field); 249 } else if (storable_type == CREDIT_CARD_EXP_MONTH) { 250 FillExpirationMonthSelectControl(value, field); 251 } else if (storable_type == CREDIT_CARD_EXP_2_DIGIT_YEAR || 252 storable_type == CREDIT_CARD_EXP_4_DIGIT_YEAR) { 253 FillYearSelectControl(value, field); 254 } else if (storable_type == CREDIT_CARD_TYPE) { 255 FillCreditCardTypeSelectControl(value, field); 256 } 257} 258 259// Fills in the month control |field| with |value|. |value| should be a date 260// formatted as MM/YYYY. If it isn't, filling will fail. 261bool FillMonthControl(const base::string16& value, FormFieldData* field) { 262 // Autofill formats a combined date as month/year. 263 std::vector<base::string16> pieces; 264 base::SplitString(value, char16('/'), &pieces); 265 if (pieces.size() != 2) 266 return false; 267 268 // HTML5 input="month" is formatted as year-month. 269 base::string16 month = pieces[0]; 270 base::string16 year = pieces[1]; 271 if ((month.size() != 1 && month.size() != 2) || year.size() != 4) 272 return false; 273 274 // HTML5 input="month" expects zero-padded months. 275 if (month.size() == 1) 276 month = ASCIIToUTF16("0") + month; 277 278 field->value = year + ASCIIToUTF16("-") + month; 279 return true; 280} 281 282// Fills |field| with the street address in |value|. Translates newlines into 283// equivalent separators when necessary, i.e. when filling a single-line field. 284void FillStreetAddress(const base::string16& value, 285 FormFieldData* field) { 286 if (field->form_control_type == "textarea") { 287 field->value = value; 288 return; 289 } 290 291 base::string16 one_line_value; 292 const char16 kNewline[] = { '\n', 0 }; 293 const base::string16 separator = 294 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_LINE_SEPARATOR); 295 base::ReplaceChars(value, kNewline, separator, &one_line_value); 296 field->value = one_line_value; 297} 298 299std::string Hash32Bit(const std::string& str) { 300 std::string hash_bin = base::SHA1HashString(str); 301 DCHECK_EQ(20U, hash_bin.length()); 302 303 uint32 hash32 = ((hash_bin[0] & 0xFF) << 24) | 304 ((hash_bin[1] & 0xFF) << 16) | 305 ((hash_bin[2] & 0xFF) << 8) | 306 (hash_bin[3] & 0xFF); 307 308 return base::UintToString(hash32); 309} 310 311} // namespace 312 313AutofillField::AutofillField() 314 : server_type_(NO_SERVER_DATA), 315 heuristic_type_(UNKNOWN_TYPE), 316 html_type_(HTML_TYPE_UNKNOWN), 317 html_mode_(HTML_MODE_NONE), 318 phone_part_(IGNORED) { 319} 320 321AutofillField::AutofillField(const FormFieldData& field, 322 const base::string16& unique_name) 323 : FormFieldData(field), 324 unique_name_(unique_name), 325 server_type_(NO_SERVER_DATA), 326 heuristic_type_(UNKNOWN_TYPE), 327 html_type_(HTML_TYPE_UNKNOWN), 328 html_mode_(HTML_MODE_NONE), 329 phone_part_(IGNORED) { 330} 331 332AutofillField::~AutofillField() {} 333 334void AutofillField::set_heuristic_type(ServerFieldType type) { 335 if (type >= 0 && type < MAX_VALID_FIELD_TYPE && 336 type != FIELD_WITH_DEFAULT_VALUE) { 337 heuristic_type_ = type; 338 } else { 339 NOTREACHED(); 340 // This case should not be reachable; but since this has potential 341 // implications on data uploaded to the server, better safe than sorry. 342 heuristic_type_ = UNKNOWN_TYPE; 343 } 344} 345 346void AutofillField::set_server_type(ServerFieldType type) { 347 // Chrome no longer supports fax numbers, but the server still does. 348 if (type >= PHONE_FAX_NUMBER && type <= PHONE_FAX_WHOLE_NUMBER) 349 return; 350 351 server_type_ = type; 352} 353 354void AutofillField::SetHtmlType(HtmlFieldType type, HtmlFieldMode mode) { 355 html_type_ = type; 356 html_mode_ = mode; 357 358 if (type == HTML_TYPE_TEL_LOCAL_PREFIX) 359 phone_part_ = PHONE_PREFIX; 360 else if (type == HTML_TYPE_TEL_LOCAL_SUFFIX) 361 phone_part_ = PHONE_SUFFIX; 362 else 363 phone_part_ = IGNORED; 364} 365 366AutofillType AutofillField::Type() const { 367 if (html_type_ != HTML_TYPE_UNKNOWN) 368 return AutofillType(html_type_, html_mode_); 369 370 if (server_type_ != NO_SERVER_DATA) 371 return AutofillType(server_type_); 372 373 return AutofillType(heuristic_type_); 374} 375 376bool AutofillField::IsEmpty() const { 377 return value.empty(); 378} 379 380std::string AutofillField::FieldSignature() const { 381 std::string field_name = UTF16ToUTF8(name); 382 std::string field_string = field_name + "&" + form_control_type; 383 return Hash32Bit(field_string); 384} 385 386bool AutofillField::IsFieldFillable() const { 387 return !Type().IsUnknown(); 388} 389 390// static 391void AutofillField::FillFormField(const AutofillField& field, 392 const base::string16& value, 393 const std::string& app_locale, 394 FormFieldData* field_data) { 395 AutofillType type = field.Type(); 396 397 if (type.GetStorableType() == PHONE_HOME_NUMBER) 398 FillPhoneNumberField(field, value, field_data); 399 else if (field_data->form_control_type == "select-one") 400 FillSelectControl(type, value, app_locale, field_data); 401 else if (field_data->form_control_type == "month") 402 FillMonthControl(value, field_data); 403 else if (type.GetStorableType() == ADDRESS_HOME_STREET_ADDRESS) 404 FillStreetAddress(value, field_data); 405 else 406 field_data->value = value; 407} 408 409} // namespace autofill 410