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