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