| Index: components/autofill/core/browser/autofill_field.cc
|
| diff --git a/components/autofill/core/browser/autofill_field.cc b/components/autofill/core/browser/autofill_field.cc
|
| index bad3b5b680c23c43149930ab8782e3cc08793dd6..3fec668f3c76a5ac2fafe459bbaf27fb767da343 100644
|
| --- a/components/autofill/core/browser/autofill_field.cc
|
| +++ b/components/autofill/core/browser/autofill_field.cc
|
| @@ -66,6 +66,65 @@ bool SetSelectControlValue(const base::string16& value,
|
| 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,
|
| + FormFieldData* field) {
|
| + base::string16 value_lowercase = StringToLowerASCII(value);
|
| + DCHECK_EQ(field->option_values.size(), field->option_contents.size());
|
| + int best_match = -1;
|
| +
|
| + for (size_t i = 0; i < field->option_values.size(); ++i) {
|
| + if (StringToLowerASCII(field->option_values[i]).find(value_lowercase) !=
|
| + std::string::npos ||
|
| + StringToLowerASCII(field->option_contents[i]).find(value_lowercase) !=
|
| + std::string::npos) {
|
| + // The best match is the shortest one.
|
| + if (best_match == -1 ||
|
| + field->option_values[best_match].size() >
|
| + field->option_values[i].size()) {
|
| + best_match = i;
|
| + }
|
| + }
|
| + }
|
| +
|
| + 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) {
|
| + base::string16 value_lowercase = StringToLowerASCII(value);
|
| + std::vector<base::string16> tokenized;
|
| + DCHECK_EQ(field->option_values.size(), field->option_contents.size());
|
| +
|
| + for (size_t i = 0; i < field->option_values.size(); ++i) {
|
| + base::SplitStringAlongWhitespace(
|
| + StringToLowerASCII(field->option_values[i]), &tokenized);
|
| + if (std::find(tokenized.begin(), tokenized.end(), value_lowercase) !=
|
| + tokenized.end()) {
|
| + field->value = field->option_values[i];
|
| + return true;
|
| + }
|
| +
|
| + base::SplitStringAlongWhitespace(
|
| + StringToLowerASCII(field->option_contents[i]), &tokenized);
|
| + if (std::find(tokenized.begin(), tokenized.end(), value_lowercase) !=
|
| + tokenized.end()) {
|
| + field->value = field->option_values[i];
|
| + return true;
|
| + }
|
| + }
|
| +
|
| + return false;
|
| +}
|
|
|
| // Try to fill a numeric |value| into the given |field|.
|
| bool FillNumericSelectControl(int value,
|
| @@ -88,11 +147,24 @@ bool FillStateSelectControl(const base::string16& value,
|
| base::string16 full, abbreviation;
|
| state_names::GetNameAndAbbreviation(value, &full, &abbreviation);
|
|
|
| - // Try the abbreviation first.
|
| - if (!abbreviation.empty() && SetSelectControlValue(abbreviation, field))
|
| + // 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;
|
| + }
|
| +
|
| + // Then try an inexact match of the full name.
|
| + if (!full.empty() && SetSelectControlValueSubstringMatch(full, field)) {
|
| + return true;
|
| + }
|
|
|
| - return !full.empty() && SetSelectControlValue(full, field);
|
| + // Then try an inexact match of the abbreviation name.
|
| + return !abbreviation.empty() &&
|
| + SetSelectControlValueTokenMatch(abbreviation, field);
|
| }
|
|
|
| bool FillCountrySelectControl(const base::string16& value,
|
|
|