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