| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/autofill/core/browser/autofill_field.h" | 5 #include "components/autofill/core/browser/autofill_field.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/i18n/string_compare.h" | 8 #include "base/i18n/string_search.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/metrics/field_trial.h" | 10 #include "base/metrics/field_trial.h" |
| 11 #include "base/sha1.h" | 11 #include "base/sha1.h" |
| 12 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
| 13 #include "base/strings/string_split.h" | 13 #include "base/strings/string_split.h" |
| 14 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
| 15 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
| 16 #include "components/autofill/core/browser/autofill_country.h" | 16 #include "components/autofill/core/browser/autofill_country.h" |
| 17 #include "components/autofill/core/browser/autofill_type.h" | 17 #include "components/autofill/core/browser/autofill_type.h" |
| 18 #include "components/autofill/core/browser/credit_card.h" |
| 18 #include "components/autofill/core/browser/phone_number.h" | 19 #include "components/autofill/core/browser/phone_number.h" |
| 19 #include "components/autofill/core/browser/state_names.h" | 20 #include "components/autofill/core/browser/state_names.h" |
| 20 #include "components/autofill/core/common/autofill_l10n_util.h" | 21 #include "components/autofill/core/common/autofill_l10n_util.h" |
| 21 #include "components/autofill/core/common/autofill_switches.h" | 22 #include "components/autofill/core/common/autofill_switches.h" |
| 22 #include "grit/components_strings.h" | 23 #include "grit/components_strings.h" |
| 23 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_da
ta.h" | 24 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_da
ta.h" |
| 24 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_fo
rmatter.h" | 25 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_fo
rmatter.h" |
| 25 #include "ui/base/l10n/l10n_util.h" | 26 #include "ui/base/l10n/l10n_util.h" |
| 26 | 27 |
| 27 using ::i18n::addressinput::AddressData; | 28 using ::i18n::addressinput::AddressData; |
| 28 using ::i18n::addressinput::GetStreetAddressLinesAsSingleLine; | 29 using ::i18n::addressinput::GetStreetAddressLinesAsSingleLine; |
| 29 using base::ASCIIToUTF16; | 30 using base::ASCIIToUTF16; |
| 30 using base::StringToInt; | 31 using base::StringToInt; |
| 31 | 32 |
| 32 namespace autofill { | 33 namespace autofill { |
| 33 namespace { | 34 namespace { |
| 34 | 35 |
| 35 const char* const kMonthsAbbreviated[] = { | |
| 36 NULL, // Padding so index 1 = month 1 = January. | |
| 37 "Jan", "Feb", "Mar", "Apr", "May", "Jun", | |
| 38 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", | |
| 39 }; | |
| 40 | |
| 41 const char* const kMonthsFull[] = { | |
| 42 NULL, // Padding so index 1 = month 1 = January. | |
| 43 "January", "February", "March", "April", "May", "June", | |
| 44 "July", "August", "September", "October", "November", "December", | |
| 45 }; | |
| 46 | |
| 47 // Returns true if the value was successfully set, meaning |value| was found in | 36 // Returns true if the value was successfully set, meaning |value| was found in |
| 48 // the list of select options in |field|. | 37 // the list of select options in |field|. |
| 49 bool SetSelectControlValue(const base::string16& value, | 38 bool SetSelectControlValue(const base::string16& value, |
| 50 FormFieldData* field) { | 39 FormFieldData* field) { |
| 51 base::string16 value_lowercase = base::StringToLowerASCII(value); | 40 l10n::CaseInsensitiveCompare compare; |
| 52 | 41 |
| 53 DCHECK_EQ(field->option_values.size(), field->option_contents.size()); | 42 DCHECK_EQ(field->option_values.size(), field->option_contents.size()); |
| 54 base::string16 best_match; | 43 base::string16 best_match; |
| 55 for (size_t i = 0; i < field->option_values.size(); ++i) { | 44 for (size_t i = 0; i < field->option_values.size(); ++i) { |
| 56 if (value == field->option_values[i] || | 45 if (value == field->option_values[i] || |
| 57 value == field->option_contents[i]) { | 46 value == field->option_contents[i]) { |
| 58 // An exact match, use it. | 47 // An exact match, use it. |
| 59 best_match = field->option_values[i]; | 48 best_match = field->option_values[i]; |
| 60 break; | 49 break; |
| 61 } | 50 } |
| 62 | 51 |
| 63 if (value_lowercase == base::StringToLowerASCII(field->option_values[i]) || | 52 if (compare.StringsEqual(value, field->option_values[i]) || |
| 64 value_lowercase == | 53 compare.StringsEqual(value, field->option_contents[i])) { |
| 65 base::StringToLowerASCII(field->option_contents[i])) { | |
| 66 // A match, but not in the same case. Save it in case an exact match is | 54 // A match, but not in the same case. Save it in case an exact match is |
| 67 // not found. | 55 // not found. |
| 68 best_match = field->option_values[i]; | 56 best_match = field->option_values[i]; |
| 69 } | 57 } |
| 70 } | 58 } |
| 71 | 59 |
| 72 if (best_match.empty()) | 60 if (best_match.empty()) |
| 73 return false; | 61 return false; |
| 74 | 62 |
| 75 field->value = best_match; | 63 field->value = best_match; |
| 76 return true; | 64 return true; |
| 77 } | 65 } |
| 78 | 66 |
| 79 // Like SetSelectControlValue, but searches within the field values and options | 67 // Like SetSelectControlValue, but searches within the field values and options |
| 80 // for |value|. For example, "NC - North Carolina" would match "north carolina". | 68 // for |value|. For example, "NC - North Carolina" would match "north carolina". |
| 81 bool SetSelectControlValueSubstringMatch(const base::string16& value, | 69 bool SetSelectControlValueSubstringMatch(const base::string16& value, |
| 82 FormFieldData* field) { | 70 FormFieldData* field) { |
| 83 base::string16 value_lowercase = base::StringToLowerASCII(value); | |
| 84 DCHECK_EQ(field->option_values.size(), field->option_contents.size()); | 71 DCHECK_EQ(field->option_values.size(), field->option_contents.size()); |
| 85 int best_match = -1; | 72 int best_match = -1; |
| 86 | 73 |
| 74 base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents searcher(value); |
| 87 for (size_t i = 0; i < field->option_values.size(); ++i) { | 75 for (size_t i = 0; i < field->option_values.size(); ++i) { |
| 88 if (base::StringToLowerASCII(field->option_values[i]).find(value_lowercase)
!= | 76 if (searcher.Search(field->option_values[i], nullptr, nullptr) || |
| 89 std::string::npos || | 77 searcher.Search(field->option_contents[i], nullptr, nullptr)) { |
| 90 base::StringToLowerASCII(field->option_contents[i]).find( | |
| 91 value_lowercase) != std::string::npos) { | |
| 92 // The best match is the shortest one. | 78 // The best match is the shortest one. |
| 93 if (best_match == -1 || | 79 if (best_match == -1 || |
| 94 field->option_values[best_match].size() > | 80 field->option_values[best_match].size() > |
| 95 field->option_values[i].size()) { | 81 field->option_values[i].size()) { |
| 96 best_match = i; | 82 best_match = i; |
| 97 } | 83 } |
| 98 } | 84 } |
| 99 } | 85 } |
| 100 | 86 |
| 101 if (best_match >= 0) { | 87 if (best_match >= 0) { |
| 102 field->value = field->option_values[best_match]; | 88 field->value = field->option_values[best_match]; |
| 103 return true; | 89 return true; |
| 104 } | 90 } |
| 105 | 91 |
| 106 return false; | 92 return false; |
| 107 } | 93 } |
| 108 | 94 |
| 109 // Like SetSelectControlValue, but searches within the field values and options | 95 // Like SetSelectControlValue, but searches within the field values and options |
| 110 // for |value|. First it tokenizes the options, then tries to match against | 96 // for |value|. First it tokenizes the options, then tries to match against |
| 111 // tokens. For example, "NC - North Carolina" would match "nc" but not "ca". | 97 // tokens. For example, "NC - North Carolina" would match "nc" but not "ca". |
| 112 bool SetSelectControlValueTokenMatch(const base::string16& value, | 98 bool SetSelectControlValueTokenMatch(const base::string16& value, |
| 113 FormFieldData* field) { | 99 FormFieldData* field) { |
| 114 base::string16 value_lowercase = base::StringToLowerASCII(value); | |
| 115 std::vector<base::string16> tokenized; | 100 std::vector<base::string16> tokenized; |
| 116 DCHECK_EQ(field->option_values.size(), field->option_contents.size()); | 101 DCHECK_EQ(field->option_values.size(), field->option_contents.size()); |
| 102 l10n::CaseInsensitiveCompare compare; |
| 117 | 103 |
| 118 for (size_t i = 0; i < field->option_values.size(); ++i) { | 104 for (size_t i = 0; i < field->option_values.size(); ++i) { |
| 119 base::SplitStringAlongWhitespace( | 105 base::SplitStringAlongWhitespace(field->option_values[i], &tokenized); |
| 120 base::StringToLowerASCII(field->option_values[i]), &tokenized); | 106 if (std::find_if(tokenized.begin(), tokenized.end(), |
| 121 if (std::find(tokenized.begin(), tokenized.end(), value_lowercase) != | 107 [&compare, value](base::string16& rhs) { |
| 122 tokenized.end()) { | 108 return compare.StringsEqual(value, rhs); |
| 109 }) != tokenized.end()) { |
| 123 field->value = field->option_values[i]; | 110 field->value = field->option_values[i]; |
| 124 return true; | 111 return true; |
| 125 } | 112 } |
| 126 | 113 |
| 127 base::SplitStringAlongWhitespace( | 114 base::SplitStringAlongWhitespace(field->option_contents[i], &tokenized); |
| 128 base::StringToLowerASCII(field->option_contents[i]), &tokenized); | 115 if (std::find_if(tokenized.begin(), tokenized.end(), |
| 129 if (std::find(tokenized.begin(), tokenized.end(), value_lowercase) != | 116 [&compare, value](base::string16& rhs) { |
| 130 tokenized.end()) { | 117 return compare.StringsEqual(value, rhs); |
| 118 }) != tokenized.end()) { |
| 131 field->value = field->option_values[i]; | 119 field->value = field->option_values[i]; |
| 132 return true; | 120 return true; |
| 133 } | 121 } |
| 134 } | 122 } |
| 135 | 123 |
| 136 return false; | 124 return false; |
| 137 } | 125 } |
| 138 | 126 |
| 139 // Try to fill a numeric |value| into the given |field|. | 127 // Try to fill a numeric |value| into the given |field|. |
| 140 bool FillNumericSelectControl(int value, | 128 bool FillNumericSelectControl(int value, |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 country_code == AutofillCountry::GetCountryCode(contents, app_locale)) { | 183 country_code == AutofillCountry::GetCountryCode(contents, app_locale)) { |
| 196 field_data->value = value; | 184 field_data->value = value; |
| 197 return true; | 185 return true; |
| 198 } | 186 } |
| 199 } | 187 } |
| 200 | 188 |
| 201 return false; | 189 return false; |
| 202 } | 190 } |
| 203 | 191 |
| 204 bool FillExpirationMonthSelectControl(const base::string16& value, | 192 bool FillExpirationMonthSelectControl(const base::string16& value, |
| 193 const std::string& app_locale, |
| 205 FormFieldData* field) { | 194 FormFieldData* field) { |
| 206 int index = 0; | 195 int index = 0; |
| 207 if (!StringToInt(value, &index) || | 196 if (!StringToInt(value, &index) || index <= 0 || index > 12) |
| 208 index <= 0 || | |
| 209 static_cast<size_t>(index) >= arraysize(kMonthsFull)) | |
| 210 return false; | 197 return false; |
| 211 | 198 |
| 212 bool filled = | 199 for (const base::string16& option_value : field->option_values) { |
| 213 SetSelectControlValue(ASCIIToUTF16(kMonthsAbbreviated[index]), field) || | 200 int converted_value = 0; |
| 214 SetSelectControlValue(ASCIIToUTF16(kMonthsFull[index]), field) || | 201 if (CreditCard::ConvertMonth(option_value, app_locale, &converted_value) && |
| 215 FillNumericSelectControl(index, field); | 202 index == converted_value) { |
| 216 return filled; | 203 field->value = option_value; |
| 204 return true; |
| 205 } |
| 206 } |
| 207 |
| 208 for (const base::string16& option_contents : field->option_contents) { |
| 209 int converted_contents = 0; |
| 210 if (CreditCard::ConvertMonth(option_contents, app_locale, |
| 211 &converted_contents) && |
| 212 index == converted_contents) { |
| 213 field->value = option_contents; |
| 214 return true; |
| 215 } |
| 216 } |
| 217 |
| 218 return FillNumericSelectControl(index, field); |
| 217 } | 219 } |
| 218 | 220 |
| 219 // Returns true if the last two digits in |year| match those in |str|. | 221 // Returns true if the last two digits in |year| match those in |str|. |
| 220 bool LastTwoDigitsMatch(const base::string16& year, | 222 bool LastTwoDigitsMatch(const base::string16& year, |
| 221 const base::string16& str) { | 223 const base::string16& str) { |
| 222 int year_int; | 224 int year_int; |
| 223 int str_int; | 225 int str_int; |
| 224 if (!StringToInt(year, &year_int) || !StringToInt(str, &str_int)) | 226 if (!StringToInt(year, &year_int) || !StringToInt(str, &str_int)) |
| 225 return false; | 227 return false; |
| 226 | 228 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 if (SetSelectControlValue(value, field)) | 311 if (SetSelectControlValue(value, field)) |
| 310 return true; | 312 return true; |
| 311 | 313 |
| 312 // If that fails, try specific fallbacks based on the field type. | 314 // If that fails, try specific fallbacks based on the field type. |
| 313 ServerFieldType storable_type = type.GetStorableType(); | 315 ServerFieldType storable_type = type.GetStorableType(); |
| 314 if (storable_type == ADDRESS_HOME_STATE) { | 316 if (storable_type == ADDRESS_HOME_STATE) { |
| 315 return FillStateSelectControl(value, field); | 317 return FillStateSelectControl(value, field); |
| 316 } else if (storable_type == ADDRESS_HOME_COUNTRY) { | 318 } else if (storable_type == ADDRESS_HOME_COUNTRY) { |
| 317 return FillCountrySelectControl(value, app_locale, field); | 319 return FillCountrySelectControl(value, app_locale, field); |
| 318 } else if (storable_type == CREDIT_CARD_EXP_MONTH) { | 320 } else if (storable_type == CREDIT_CARD_EXP_MONTH) { |
| 319 return FillExpirationMonthSelectControl(value, field); | 321 return FillExpirationMonthSelectControl(value, app_locale, field); |
| 320 } else if (storable_type == CREDIT_CARD_EXP_2_DIGIT_YEAR || | 322 } else if (storable_type == CREDIT_CARD_EXP_2_DIGIT_YEAR || |
| 321 storable_type == CREDIT_CARD_EXP_4_DIGIT_YEAR) { | 323 storable_type == CREDIT_CARD_EXP_4_DIGIT_YEAR) { |
| 322 return FillYearSelectControl(value, field); | 324 return FillYearSelectControl(value, field); |
| 323 } else if (storable_type == CREDIT_CARD_TYPE) { | 325 } else if (storable_type == CREDIT_CARD_TYPE) { |
| 324 return FillCreditCardTypeSelectControl(value, field); | 326 return FillCreditCardTypeSelectControl(value, field); |
| 325 } | 327 } |
| 326 | 328 |
| 327 return false; | 329 return false; |
| 328 } | 330 } |
| 329 | 331 |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 if (compare.StringsEqual(value_stripped, option_contents)) { | 552 if (compare.StringsEqual(value_stripped, option_contents)) { |
| 551 if (index) | 553 if (index) |
| 552 *index = i; | 554 *index = i; |
| 553 return true; | 555 return true; |
| 554 } | 556 } |
| 555 } | 557 } |
| 556 return false; | 558 return false; |
| 557 } | 559 } |
| 558 | 560 |
| 559 } // namespace autofill | 561 } // namespace autofill |
| OLD | NEW |