// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/autofill/core/browser/field_filler.h"

#include <stdint.h>

#include "base/feature_list.h"
#include "base/i18n/case_conversion.h"
#include "base/i18n/string_search.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/address_normalizer.h"
#include "components/autofill/core/browser/autofill_country.h"
#include "components/autofill/core/browser/autofill_data_model.h"
#include "components/autofill/core/browser/autofill_data_util.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/country_names.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/phone_number.h"
#include "components/autofill/core/browser/state_names.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_l10n_util.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/strings/grit/components_strings.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_formatter.h"
#include "ui/base/l10n/l10n_util.h"

using base::ASCIIToUTF16;
using base::StringToInt;

namespace autofill {

namespace {

// Returns true if the value was successfully set, meaning |value| was found in
// the list of select options in |field|. Optionally, the caller may pass
// |best_match_index| which will be set to the index of the best match.
bool SetSelectControlValue(const base::string16& value,
                           FormFieldData* field,
                           size_t* best_match_index = nullptr) {
  l10n::CaseInsensitiveCompare compare;

  DCHECK_EQ(field->option_values.size(), field->option_contents.size());
  base::string16 best_match;
  for (size_t i = 0; i < field->option_values.size(); ++i) {
    if (value == field->option_values[i] ||
        value == field->option_contents[i]) {
      // An exact match, use it.
      best_match = field->option_values[i];
      if (best_match_index)
        *best_match_index = i;
      break;
    }

    if (compare.StringsEqual(value, field->option_values[i]) ||
        compare.StringsEqual(value, field->option_contents[i])) {
      // A match, but not in the same case. Save it in case an exact match is
      // not found.
      best_match = field->option_values[i];
      if (best_match_index)
        *best_match_index = i;
    }
  }

  if (best_match.empty())
    return false;

  field->value = best_match;
  return true;
}

// Like SetSelectControlValue, but searches within the field values and options
// for |value|. For example, "NC - North Carolina" would match "north carolina".
bool SetSelectControlValueSubstringMatch(const base::string16& value,
                                         bool ignore_whitespace,
                                         FormFieldData* field) {
  int best_match = FieldFiller::FindShortestSubstringMatchInSelect(
      value, ignore_whitespace, field);

  if (best_match >= 0) {
    field->value = field->option_values[best_match];
    return true;
  }

  return false;
}

// Like SetSelectControlValue, but searches within the field values and options
// for |value|. First it tokenizes the options, then tries to match against
// tokens. For example, "NC - North Carolina" would match "nc" but not "ca".
bool SetSelectControlValueTokenMatch(const base::string16& value,
                                     FormFieldData* field) {
  std::vector<base::string16> tokenized;
  DCHECK_EQ(field->option_values.size(), field->option_contents.size());
  l10n::CaseInsensitiveCompare compare;

  for (size_t i = 0; i < field->option_values.size(); ++i) {
    tokenized =
        base::SplitString(field->option_values[i], base::kWhitespaceASCIIAs16,
                          base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
    if (std::find_if(tokenized.begin(), tokenized.end(),
                     [&compare, value](base::string16& rhs) {
                       return compare.StringsEqual(value, rhs);
                     }) != tokenized.end()) {
      field->value = field->option_values[i];
      return true;
    }

    tokenized =
        base::SplitString(field->option_contents[i], base::kWhitespaceASCIIAs16,
                          base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
    if (std::find_if(tokenized.begin(), tokenized.end(),
                     [&compare, value](base::string16& rhs) {
                       return compare.StringsEqual(value, rhs);
                     }) != tokenized.end()) {
      field->value = field->option_values[i];
      return true;
    }
  }

  return false;
}

// Helper method to normalize the |admin_area| for the given |country_code|.
// The value in |admin_area| will be overwritten.
bool NormalizeAdminAreaForCountryCode(base::string16* admin_area,
                                      const std::string& country_code,
                                      AddressNormalizer* address_normalizer) {
  DCHECK(address_normalizer);
  DCHECK(admin_area);
  if (admin_area->empty() || country_code.empty())
    return false;

  AutofillProfile tmp_profile;
  tmp_profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(country_code));
  tmp_profile.SetRawInfo(ADDRESS_HOME_STATE, *admin_area);
  if (!address_normalizer->NormalizeAddressSync(&tmp_profile))
    return false;

  *admin_area = tmp_profile.GetRawInfo(ADDRESS_HOME_STATE);
  return true;
}

// Will normalize |value| and the options in |field| with |address_normalizer|
// (which should not be null), and return whether the fill was successful.
bool SetNormalizedStateSelectControlValue(
    const base::string16& value,
    FormFieldData* field,
    const std::string& country_code,
    AddressNormalizer* address_normalizer) {
  DCHECK(address_normalizer);
  // We attempt to normalize a copy of the field value. If normalization was not
  // successful, it means the rules were probably not loaded. Give up. Note that
  // the normalizer will fetch the rule for next time it's called.
  // TODO(crbug.com/788417): We should probably sanitize |value| before
  // normalizing.
  base::string16 field_value = value;
  if (!NormalizeAdminAreaForCountryCode(&field_value, country_code,
                                        address_normalizer)) {
    return false;
  }

  // If successful, try filling the normalized value with the existing field
  // |options|.
  if (SetSelectControlValue(field_value, field))
    return true;

  // Normalize the |field| options in place, using a copy.
  // TODO(crbug.com/788417): We should probably sanitize the values in
  // |field_copy| before normalizing.
  FormFieldData field_copy(*field);
  bool normalized = false;
  for (size_t i = 0; i < field_copy.option_values.size(); ++i) {
    normalized |= NormalizeAdminAreaForCountryCode(
        &field_copy.option_values[i], country_code, address_normalizer);
    normalized |= NormalizeAdminAreaForCountryCode(
        &field_copy.option_contents[i], country_code, address_normalizer);
  }

  // If at least some normalization happened on the field options, try filling
  // them with |field_value|.
  size_t best_match_index = 0;
  if (normalized &&
      SetSelectControlValue(field_value, &field_copy, &best_match_index)) {
    // |best_match_index| now points to the option in |field->option_values|
    // that corresponds to our best match. Update |field| with the answer.
    field->value = field->option_values[best_match_index];
    return true;
  }

  return false;
}

// Try to fill a numeric |value| into the given |field|.
bool FillNumericSelectControl(int value, FormFieldData* field) {
  DCHECK_EQ(field->option_values.size(), field->option_contents.size());
  for (size_t i = 0; i < field->option_values.size(); ++i) {
    int option;
    if ((StringToInt(field->option_values[i], &option) && option == value) ||
        (StringToInt(field->option_contents[i], &option) && option == value)) {
      field->value = field->option_values[i];
      return true;
    }
  }

  return false;
}

bool FillStateSelectControl(const base::string16& value,
                            FormFieldData* field,
                            const std::string& country_code,
                            AddressNormalizer* address_normalizer) {
  base::string16 full;
  base::string16 abbreviation;
  // |abbreviation| will be empty for non-US countries.
  state_names::GetNameAndAbbreviation(value, &full, &abbreviation);

  // Try an exact match of the abbreviation first.
  if (!abbreviation.empty() && SetSelectControlValue(abbreviation, field)) {
    return true;
  }

  // Try an exact match of the full name.
  if (!full.empty() && SetSelectControlValue(full, field)) {
    return true;
  }

  // Try an inexact match of the full name.
  if (!full.empty() &&
      SetSelectControlValueSubstringMatch(full, false, field)) {
    return true;
  }

  // Try an inexact match of the abbreviation name.
  if (!abbreviation.empty() &&
      SetSelectControlValueTokenMatch(abbreviation, field)) {
    return true;
  }

  // Try to match a normalized |value| of the state and the |field| options.
  if (address_normalizer &&
      SetNormalizedStateSelectControlValue(value, field, country_code,
                                           address_normalizer)) {
    return true;
  }

  return false;
}

bool FillCountrySelectControl(const base::string16& value,
                              FormFieldData* field_data) {
  std::string country_code = CountryNames::GetInstance()->GetCountryCode(value);
  if (country_code.empty())
    return false;

  DCHECK_EQ(field_data->option_values.size(),
            field_data->option_contents.size());
  for (size_t i = 0; i < field_data->option_values.size(); ++i) {
    // Canonicalize each <option> value to a country code, and compare to the
    // target country code.
    base::string16 value = field_data->option_values[i];
    base::string16 contents = field_data->option_contents[i];
    if (country_code == CountryNames::GetInstance()->GetCountryCode(value) ||
        country_code == CountryNames::GetInstance()->GetCountryCode(contents)) {
      field_data->value = value;
      return true;
    }
  }

  return false;
}

// Attempt to fill the user's expiration month |value| inside the <select>
// |field|. Since |value| is well defined but the website's |field| option
// values may not be, some heuristics are run to cover all observed cases.
bool FillExpirationMonthSelectControl(const base::string16& value,
                                      const std::string& app_locale,
                                      FormFieldData* field) {
  // |value| is defined to be between 1 and 12, inclusively.
  int month = 0;
  if (!StringToInt(value, &month) || month <= 0 || month > 12)
    return false;

  // Trim the whitespace and specific prefixes used in AngularJS from the
  // select values before attempting to convert them to months.
  std::vector<base::string16> trimmed_values(field->option_values.size());
  const base::string16 kNumberPrefix = ASCIIToUTF16("number:");
  const base::string16 kStringPrefix = ASCIIToUTF16("string:");
  for (size_t i = 0; i < field->option_values.size(); ++i) {
    base::TrimWhitespace(field->option_values[i], base::TRIM_ALL,
                         &trimmed_values[i]);
    base::ReplaceFirstSubstringAfterOffset(&trimmed_values[i], 0, kNumberPrefix,
                                           ASCIIToUTF16(""));
    base::ReplaceFirstSubstringAfterOffset(&trimmed_values[i], 0, kStringPrefix,
                                           ASCIIToUTF16(""));
  }

  if (trimmed_values.size() == 12) {
    // The select presumable only contains the year's months.
    // If the first value of the select is 0, decrement the value of |month| so
    // January is associated with 0 instead of 1.
    int first_value;
    if (StringToInt(trimmed_values[0], &first_value) && first_value == 0)
      --month;
  } else if (trimmed_values.size() == 13) {
    // The select presumably uses the first value as a placeholder.
    int first_value;
    // If the first value is not a number or is a negative one, check the second
    // value and apply the same logic as if there was no placeholder.
    if (!StringToInt(trimmed_values[0], &first_value) || first_value < 0) {
      int second_value;
      if (StringToInt(trimmed_values[1], &second_value) && second_value == 0)
        --month;
    } else if (first_value == 1) {
      // If the first value of the select is 1, increment the value of |month|
      // to skip the placeholder value (January = 2).
      ++month;
    }
  }

  // Attempt to match the user's |month| with the field's value attributes.
  for (size_t i = 0; i < trimmed_values.size(); ++i) {
    int converted_value = 0;
    // We use the trimmed value to match with |month|, but the original select
    // value to fill the field (otherwise filling wouldn't work).
    if (CreditCard::ConvertMonth(trimmed_values[i], app_locale,
                                 &converted_value) &&
        month == converted_value) {
      field->value = field->option_values[i];
      return true;
    }
  }

  // Attempt to match with each of the options' content.
  for (size_t i = 0; i < field->option_contents.size(); ++i) {
    int converted_contents = 0;
    if (CreditCard::ConvertMonth(field->option_contents[i], app_locale,
                                 &converted_contents) &&
        month == converted_contents) {
      field->value = field->option_values[i];
      return true;
    }
  }

  return FillNumericSelectControl(month, field);
}

// Returns true if the last two digits in |year| match those in |str|.
bool LastTwoDigitsMatch(const base::string16& year, const base::string16& str) {
  int year_int;
  int str_int;
  if (!StringToInt(year, &year_int) || !StringToInt(str, &str_int))
    return false;

  return (year_int % 100) == (str_int % 100);
}

// Try to fill a year |value| into the given |field| by comparing the last two
// digits of the year to the field's options.
bool FillYearSelectControl(const base::string16& value, FormFieldData* field) {
  if (value.size() != 2U && value.size() != 4U)
    return false;

  DCHECK_EQ(field->option_values.size(), field->option_contents.size());
  for (size_t i = 0; i < field->option_values.size(); ++i) {
    if (LastTwoDigitsMatch(value, field->option_values[i]) ||
        LastTwoDigitsMatch(value, field->option_contents[i])) {
      field->value = field->option_values[i];
      return true;
    }
  }

  return false;
}

// Try to fill a credit card type |value| (Visa, Mastercard, etc.) into the
// given |field|. We ignore whitespace when filling credit card types to
// allow for cases such as "Master card".

bool FillCreditCardTypeSelectControl(const base::string16& value,
                                     FormFieldData* field) {
  if (SetSelectControlValueSubstringMatch(value, /* ignore_whitespace= */ true,
                                          field)) {
    return true;
  }
  if (value == l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_AMEX)) {
    // For American Express, also try filling as "AmEx".
    return SetSelectControlValueSubstringMatch(
        ASCIIToUTF16("AmEx"), /* ignore_whitespace= */ true, field);
  }
  return false;
}

// Set |field_data|'s value to |number|, or possibly an appropriate substring of
// |number|.  The |field| specifies the type of the phone and whether this is a
// phone prefix or suffix.
void FillPhoneNumberField(const AutofillField& field,
                          const base::string16& number,
                          FormFieldData* field_data) {
  field_data->value =
      FieldFiller::GetPhoneNumberValue(field, number, *field_data);
}

// Set |field_data|'s value to |number|, or possibly an appropriate substring
// of |number| for cases where credit card number splits across multiple HTML
// form input fields.
// The |field| specifies the |credit_card_number_offset_| to the substring
// within credit card number.
void FillCreditCardNumberField(const AutofillField& field,
                               const base::string16& number,
                               FormFieldData* field_data) {
  base::string16 value = number;

  // |field|'s max_length truncates credit card number to fit within.
  if (field.credit_card_number_offset() < value.length())
    value = value.substr(field.credit_card_number_offset());

  field_data->value = value;
}

// Fills in the select control |field| with |value|. If an exact match is not
// found, falls back to alternate filling strategies based on the |type|.
bool FillSelectControl(const AutofillType& type,
                       const base::string16& value,
                       FormFieldData* field,
                       const AutofillDataModel& data_model,
                       const std::string& app_locale,
                       AddressNormalizer* address_normalizer) {
  DCHECK_EQ("select-one", field->form_control_type);

  // Guard against corrupted values passed over IPC.
  if (field->option_values.size() != field->option_contents.size())
    return false;

  ServerFieldType storable_type = type.GetStorableType();

  // Credit card expiration month is checked first since an exact match on value
  // may not be correct.
  if (storable_type == CREDIT_CARD_EXP_MONTH)
    return FillExpirationMonthSelectControl(value, app_locale, field);

  // Search for exact matches.
  if (SetSelectControlValue(value, field))
    return true;

  // If that fails, try specific fallbacks based on the field type.
  if (storable_type == ADDRESS_HOME_STATE) {
    // Safe to cast the data model to AutofillProfile here.
    const std::string country_code = data_util::GetCountryCodeWithFallback(
        static_cast<const AutofillProfile&>(data_model), app_locale);
    return FillStateSelectControl(value, field, country_code,
                                  address_normalizer);
  }
  if (storable_type == ADDRESS_HOME_COUNTRY)
    return FillCountrySelectControl(value, field);
  if (storable_type == CREDIT_CARD_EXP_2_DIGIT_YEAR ||
      storable_type == CREDIT_CARD_EXP_4_DIGIT_YEAR) {
    return FillYearSelectControl(value, field);
  }
  if (storable_type == CREDIT_CARD_TYPE)
    return FillCreditCardTypeSelectControl(value, field);

  return false;
}

// Fills in the month control |field| with the expiration date in |card|.
void FillMonthControl(const CreditCard& card, FormFieldData* field) {
  field->value = card.Expiration4DigitYearAsString() + ASCIIToUTF16("-") +
                 card.ExpirationMonthAsString();
}

// Fills |field| with the street address in |value|. Translates newlines into
// equivalent separators when necessary, i.e. when filling a single-line field.
// The separators depend on |address_language_code|.
void FillStreetAddress(const base::string16& value,
                       const std::string& address_language_code,
                       FormFieldData* field) {
  if (field->form_control_type == "textarea") {
    field->value = value;
    return;
  }

  ::i18n::addressinput::AddressData address_data;
  address_data.language_code = address_language_code;
  address_data.address_line =
      base::SplitString(base::UTF16ToUTF8(value), "\n", base::TRIM_WHITESPACE,
                        base::SPLIT_WANT_ALL);
  std::string line;
  ::i18n::addressinput::GetStreetAddressLinesAsSingleLine(address_data, &line);
  field->value = base::UTF8ToUTF16(line);
}

// Returns whether the |field| was filled with the state in |value| or its
// abbreviation. First looks if |value| fits directly in the field, then looks
// if the abbreviation of |value| fits. Does not fill if neither |value| or its
// abbreviation are too long for the field.
bool FillStateText(const base::string16& value, FormFieldData* field) {
  if (field->max_length == 0 || field->max_length >= value.size()) {
    // Fill the state value directly.
    field->value = value;
    return true;
  }
  // Fill with the state abbreviation.
  base::string16 abbreviation;
  state_names::GetNameAndAbbreviation(value, nullptr, &abbreviation);
  if (!abbreviation.empty() && field->max_length >= abbreviation.size()) {
    field->value = base::i18n::ToUpper(abbreviation);
    return true;
  }
  return false;
}

// Fills the expiration year |value| into the |field|. Uses the |field_type|
// and the |field|'s max_length attribute to determine if the |value| needs to
// be truncated.
void FillExpirationYearInput(base::string16 value,
                             ServerFieldType field_type,
                             FormFieldData* field) {
  // If the |field_type| requires only 2 digits, keep only the last 2 digits of
  // |value|.
  if (field_type == CREDIT_CARD_EXP_2_DIGIT_YEAR && value.length() > 2)
    value = value.substr(value.length() - 2, 2);

  if (field->max_length == 0 || field->max_length >= value.size()) {
    // No length restrictions, fill the year value directly.
    field->value = value;
  } else {
    // Truncate the front of |value| to keep only the number of characters equal
    // to the |field|'s max length.
    field->value =
        value.substr(value.length() - field->max_length, field->max_length);
  }
}

// Returns whether the expiration date |value| was filled into the |field|.
// Uses the |field|'s max_length attribute to determine if the |value| needs to
// be truncated. |value| should be a date formatted as either MM/YY or MM/YYYY.
// If it isn't, the field doesn't get filled.
bool FillExpirationDateInput(const base::string16& value,
                             FormFieldData* field) {
  const base::string16 kSeparator = ASCIIToUTF16("/");
  // Autofill formats a combined date as month/year.
  std::vector<base::string16> pieces = base::SplitString(
      value, kSeparator, base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  if (pieces.size() != 2)
    return false;

  base::string16 month = pieces[0];
  base::string16 year = pieces[1];
  if (month.length() != 2 || (year.length() != 2 && year.length() != 4))
    return false;

  switch (field->max_length) {
    case 1:
    case 2:
    case 3:
      return false;
    case 4:
      // Field likely expects MMYY
      if (year.length() != 2) {
        // Shorten year to 2 characters from 4
        year = year.substr(2);
      }

      field->value = month + year;
      break;
    case 5:
      // Field likely expects MM/YY
      if (year.length() != 2) {
        // Shorten year to 2 characters
        year = year.substr(2);
        field->value = month + kSeparator + year;
      } else {
        field->value = value;
      }
      break;
    case 6:
    case 7:
      if (year.length() != 4) {
        // Will normalize 2-digit years to the 4-digit version.
        year = ASCIIToUTF16("20") + year;
      }

      if (field->max_length == 6) {
        // Field likely expects MMYYYY
        field->value = month + year;
      } else {
        // Field likely expects MM/YYYY
        field->value = month + kSeparator + year;
      }
      break;
    default:
      // Includes the case where max_length is not specified (0).
      field->value = month + kSeparator + year;
  }

  return true;
}

base::string16 RemoveWhitespace(const base::string16& value) {
  base::string16 stripped_value;
  base::RemoveChars(value, base::kWhitespaceUTF16, &stripped_value);
  return stripped_value;
}

}  // namespace

FieldFiller::FieldFiller(const std::string& app_locale,
                         AddressNormalizer* address_normalizer)
    : app_locale_(app_locale), address_normalizer_(address_normalizer) {}

FieldFiller::~FieldFiller() {}

bool FieldFiller::FillFormField(const AutofillField& field,
                                const AutofillDataModel& data_model,
                                FormFieldData* field_data,
                                const base::string16& cvc) {
  const AutofillType type = field.Type();

  // Don't fill if autocomplete=off is set on |field| on desktop for non credit
  // card related fields.
  if (!base::FeatureList::IsEnabled(features::kAutofillAlwaysFillAddresses) &&
      !field.should_autocomplete && IsDesktopPlatform() &&
      (type.group() != CREDIT_CARD)) {
    return false;
  }

  // Check for the validity of the data. Leave the field empty if the data is
  // invalid and the relevant feature is enabled.
  bool use_server_validation = base::FeatureList::IsEnabled(
      autofill::features::kAutofillProfileServerValidation);
  bool use_client_validation = base::FeatureList::IsEnabled(
      autofill::features::kAutofillProfileClientValidation);
  ServerFieldType server_field_type = type.GetStorableType();

  if ((use_client_validation &&
       data_model.GetValidityState(server_field_type,
                                   AutofillProfile::CLIENT) ==
           AutofillProfile::INVALID) ||
      (use_server_validation &&
       data_model.GetValidityState(server_field_type,
                                   AutofillProfile::SERVER) ==
           AutofillProfile::INVALID)) {
    return false;
  }

  base::string16 value = data_model.GetInfo(type, app_locale_);
  if (type.GetStorableType() == CREDIT_CARD_VERIFICATION_CODE)
    value = cvc;

  // Do not attempt to fill empty values as it would skew the metrics.
  if (value.empty())
    return false;

  if (type.group() == PHONE_HOME) {
    FillPhoneNumberField(field, value, field_data);
    return true;
  }
  if (field_data->form_control_type == "select-one") {
    return FillSelectControl(type, value, field_data, data_model, app_locale_,
                             address_normalizer_);
  }
  if (field_data->form_control_type == "month") {
    // Safe to cast to CreditCard here because month control type only applying
    // to credit card expirations.
    FillMonthControl(static_cast<const CreditCard&>(data_model), field_data);
    return true;
  }
  if (type.GetStorableType() == ADDRESS_HOME_STREET_ADDRESS) {
    // Safe to cast to AutofillProfile here because of the address |type|.
    const std::string profile_language_code =
        static_cast<const AutofillProfile&>(data_model).language_code();
    FillStreetAddress(value, profile_language_code, field_data);
    return true;
  }
  if (type.GetStorableType() == CREDIT_CARD_NUMBER) {
    FillCreditCardNumberField(field, value, field_data);
    return true;
  }
  if (type.GetStorableType() == ADDRESS_HOME_STATE)
    return FillStateText(value, field_data);
  if (field_data->form_control_type == "text" &&
      (type.GetStorableType() == CREDIT_CARD_EXP_2_DIGIT_YEAR ||
       type.GetStorableType() == CREDIT_CARD_EXP_4_DIGIT_YEAR)) {
    FillExpirationYearInput(value, type.GetStorableType(), field_data);
    return true;
  }
  if (field_data->form_control_type == "text" &&
      (type.GetStorableType() == CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR ||
       type.GetStorableType() == CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR)) {
    return FillExpirationDateInput(value, field_data);
  }

  field_data->value = value;
  return true;
}

// TODO(crbug.com/581514): Add support for filling only the prefix/suffix for
// phone numbers with 10 or 11 digits.
// static
base::string16 FieldFiller::GetPhoneNumberValue(
    const AutofillField& field,
    const base::string16& number,
    const FormFieldData& field_data) {
  // TODO(crbug.com/581485): Investigate the use of libphonenumber here.
  // Check to see if the |field| size matches the "prefix" or "suffix" size or
  // if the field was labeled as such. If so, return the appropriate substring.
  if (number.length() ==
      PhoneNumber::kPrefixLength + PhoneNumber::kSuffixLength) {
    if (field.phone_part() == AutofillField::PHONE_PREFIX ||
        field_data.max_length == PhoneNumber::kPrefixLength) {
      return number.substr(PhoneNumber::kPrefixOffset,
                           PhoneNumber::kPrefixLength);
    }

    if (field.phone_part() == AutofillField::PHONE_SUFFIX ||
        field_data.max_length == PhoneNumber::kSuffixLength) {
      return number.substr(PhoneNumber::kSuffixOffset,
                           PhoneNumber::kSuffixLength);
    }
  }

  // If no max length was specified, return the complete number.
  if (field_data.max_length == 0)
    return number;

  // If |number| exceeds the maximum size of the field, cut the first part to
  // provide a valid number for the field. For example, the number 15142365264
  // with a field with a max length of 10 would return 5142365264, thus removing
  // the country code and remaining valid.
  if (number.length() > field_data.max_length) {
    return number.substr(number.length() - field_data.max_length,
                         field_data.max_length);
  }

  return number;
}

// static
int FieldFiller::FindShortestSubstringMatchInSelect(
    const base::string16& value,
    bool ignore_whitespace,
    const FormFieldData* field) {
  DCHECK_EQ(field->option_values.size(), field->option_contents.size());

  int best_match = -1;

  base::string16 value_stripped =
      ignore_whitespace ? RemoveWhitespace(value) : value;
  base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents searcher(
      value_stripped);

  for (size_t i = 0; i < field->option_values.size(); ++i) {
    base::string16 option_value =
        ignore_whitespace ? RemoveWhitespace(field->option_values[i])
                          : field->option_values[i];
    base::string16 option_content =
        ignore_whitespace ? RemoveWhitespace(field->option_contents[i])
                          : field->option_contents[i];
    if (searcher.Search(option_value, nullptr, nullptr) ||
        searcher.Search(option_content, nullptr, nullptr)) {
      if (best_match == -1 || field->option_values[best_match].size() >
                                  field->option_values[i].size()) {
        best_match = i;
      }
    }
  }
  return best_match;
}

}  // namespace autofill
