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 |