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); | 71 l10n::CaseInsensitiveCompare compare; |
Lei Zhang
2015/04/11 02:44:17
Not used?
Evan Stade
2015/04/13 18:13:43
Done.
| |
84 DCHECK_EQ(field->option_values.size(), field->option_contents.size()); | 72 DCHECK_EQ(field->option_values.size(), field->option_contents.size()); |
85 int best_match = -1; | 73 int best_match = -1; |
86 | 74 |
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 (base::i18n::StringSearchIgnoringCaseAndAccents( |
Lei Zhang
2015/04/11 02:44:17
Create a FixedPatternStringSearchIgnoringCaseAndAc
Evan Stade
2015/04/13 18:13:43
Done.
| |
89 std::string::npos || | 77 value, field->option_values[i], nullptr, nullptr) || |
90 base::StringToLowerASCII(field->option_contents[i]).find( | 78 base::i18n::StringSearchIgnoringCaseAndAccents( |
91 value_lowercase) != std::string::npos) { | 79 value, field->option_contents[i], nullptr, nullptr)) { |
92 // The best match is the shortest one. | 80 // The best match is the shortest one. |
93 if (best_match == -1 || | 81 if (best_match == -1 || |
94 field->option_values[best_match].size() > | 82 field->option_values[best_match].size() > |
95 field->option_values[i].size()) { | 83 field->option_values[i].size()) { |
96 best_match = i; | 84 best_match = i; |
97 } | 85 } |
98 } | 86 } |
99 } | 87 } |
100 | 88 |
101 if (best_match >= 0) { | 89 if (best_match >= 0) { |
102 field->value = field->option_values[best_match]; | 90 field->value = field->option_values[best_match]; |
103 return true; | 91 return true; |
104 } | 92 } |
105 | 93 |
106 return false; | 94 return false; |
107 } | 95 } |
108 | 96 |
109 // Like SetSelectControlValue, but searches within the field values and options | 97 // Like SetSelectControlValue, but searches within the field values and options |
110 // for |value|. First it tokenizes the options, then tries to match against | 98 // 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". | 99 // tokens. For example, "NC - North Carolina" would match "nc" but not "ca". |
112 bool SetSelectControlValueTokenMatch(const base::string16& value, | 100 bool SetSelectControlValueTokenMatch(const base::string16& value, |
113 FormFieldData* field) { | 101 FormFieldData* field) { |
114 base::string16 value_lowercase = base::StringToLowerASCII(value); | |
115 std::vector<base::string16> tokenized; | 102 std::vector<base::string16> tokenized; |
116 DCHECK_EQ(field->option_values.size(), field->option_contents.size()); | 103 DCHECK_EQ(field->option_values.size(), field->option_contents.size()); |
104 l10n::CaseInsensitiveCompare compare; | |
117 | 105 |
118 for (size_t i = 0; i < field->option_values.size(); ++i) { | 106 for (size_t i = 0; i < field->option_values.size(); ++i) { |
119 base::SplitStringAlongWhitespace( | 107 base::SplitStringAlongWhitespace(field->option_values[i], &tokenized); |
120 base::StringToLowerASCII(field->option_values[i]), &tokenized); | 108 if (std::find_if(tokenized.begin(), tokenized.end(), |
121 if (std::find(tokenized.begin(), tokenized.end(), value_lowercase) != | 109 [&compare, value](base::string16& rhs) { |
122 tokenized.end()) { | 110 return compare.StringsEqual(value, rhs); |
111 }) != tokenized.end()) { | |
123 field->value = field->option_values[i]; | 112 field->value = field->option_values[i]; |
124 return true; | 113 return true; |
125 } | 114 } |
126 | 115 |
127 base::SplitStringAlongWhitespace( | 116 base::SplitStringAlongWhitespace(field->option_contents[i], &tokenized); |
128 base::StringToLowerASCII(field->option_contents[i]), &tokenized); | 117 if (std::find_if(tokenized.begin(), tokenized.end(), |
129 if (std::find(tokenized.begin(), tokenized.end(), value_lowercase) != | 118 [&compare, value](base::string16& rhs) { |
130 tokenized.end()) { | 119 return compare.StringsEqual(value, rhs); |
120 }) != tokenized.end()) { | |
131 field->value = field->option_values[i]; | 121 field->value = field->option_values[i]; |
132 return true; | 122 return true; |
133 } | 123 } |
134 } | 124 } |
135 | 125 |
136 return false; | 126 return false; |
137 } | 127 } |
138 | 128 |
139 // Try to fill a numeric |value| into the given |field|. | 129 // Try to fill a numeric |value| into the given |field|. |
140 bool FillNumericSelectControl(int value, | 130 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)) { | 185 country_code == AutofillCountry::GetCountryCode(contents, app_locale)) { |
196 field_data->value = value; | 186 field_data->value = value; |
197 return true; | 187 return true; |
198 } | 188 } |
199 } | 189 } |
200 | 190 |
201 return false; | 191 return false; |
202 } | 192 } |
203 | 193 |
204 bool FillExpirationMonthSelectControl(const base::string16& value, | 194 bool FillExpirationMonthSelectControl(const base::string16& value, |
195 const std::string& app_locale, | |
205 FormFieldData* field) { | 196 FormFieldData* field) { |
206 int index = 0; | 197 int index = 0; |
207 if (!StringToInt(value, &index) || | 198 if (!StringToInt(value, &index) || index <= 0 || |
208 index <= 0 || | 199 static_cast<size_t>(index) > 12) { |
Lei Zhang
2015/04/11 02:44:17
Probably don't need the static_cast anymore.
Evan Stade
2015/04/13 18:13:43
Done.
| |
209 static_cast<size_t>(index) >= arraysize(kMonthsFull)) | |
210 return false; | 200 return false; |
201 } | |
211 | 202 |
212 bool filled = | 203 for (const base::string16& option_value : field->option_values) { |
213 SetSelectControlValue(ASCIIToUTF16(kMonthsAbbreviated[index]), field) || | 204 int converted_value = 0; |
214 SetSelectControlValue(ASCIIToUTF16(kMonthsFull[index]), field) || | 205 if (CreditCard::ConvertMonth(option_value, app_locale, &converted_value) && |
215 FillNumericSelectControl(index, field); | 206 index == converted_value) { |
216 return filled; | 207 field->value = option_value; |
208 return true; | |
209 } | |
210 } | |
211 | |
212 for (const base::string16& option_contents : field->option_contents) { | |
213 int converted_contents = 0; | |
214 if (CreditCard::ConvertMonth(option_contents, app_locale, | |
215 &converted_contents) && | |
216 index == converted_contents) { | |
217 field->value = option_contents; | |
218 return true; | |
219 } | |
220 } | |
221 | |
222 return FillNumericSelectControl(index, field); | |
217 } | 223 } |
218 | 224 |
219 // Returns true if the last two digits in |year| match those in |str|. | 225 // Returns true if the last two digits in |year| match those in |str|. |
220 bool LastTwoDigitsMatch(const base::string16& year, | 226 bool LastTwoDigitsMatch(const base::string16& year, |
221 const base::string16& str) { | 227 const base::string16& str) { |
222 int year_int; | 228 int year_int; |
223 int str_int; | 229 int str_int; |
224 if (!StringToInt(year, &year_int) || !StringToInt(str, &str_int)) | 230 if (!StringToInt(year, &year_int) || !StringToInt(str, &str_int)) |
225 return false; | 231 return false; |
226 | 232 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
309 if (SetSelectControlValue(value, field)) | 315 if (SetSelectControlValue(value, field)) |
310 return true; | 316 return true; |
311 | 317 |
312 // If that fails, try specific fallbacks based on the field type. | 318 // If that fails, try specific fallbacks based on the field type. |
313 ServerFieldType storable_type = type.GetStorableType(); | 319 ServerFieldType storable_type = type.GetStorableType(); |
314 if (storable_type == ADDRESS_HOME_STATE) { | 320 if (storable_type == ADDRESS_HOME_STATE) { |
315 return FillStateSelectControl(value, field); | 321 return FillStateSelectControl(value, field); |
316 } else if (storable_type == ADDRESS_HOME_COUNTRY) { | 322 } else if (storable_type == ADDRESS_HOME_COUNTRY) { |
317 return FillCountrySelectControl(value, app_locale, field); | 323 return FillCountrySelectControl(value, app_locale, field); |
318 } else if (storable_type == CREDIT_CARD_EXP_MONTH) { | 324 } else if (storable_type == CREDIT_CARD_EXP_MONTH) { |
319 return FillExpirationMonthSelectControl(value, field); | 325 return FillExpirationMonthSelectControl(value, app_locale, field); |
320 } else if (storable_type == CREDIT_CARD_EXP_2_DIGIT_YEAR || | 326 } else if (storable_type == CREDIT_CARD_EXP_2_DIGIT_YEAR || |
321 storable_type == CREDIT_CARD_EXP_4_DIGIT_YEAR) { | 327 storable_type == CREDIT_CARD_EXP_4_DIGIT_YEAR) { |
322 return FillYearSelectControl(value, field); | 328 return FillYearSelectControl(value, field); |
323 } else if (storable_type == CREDIT_CARD_TYPE) { | 329 } else if (storable_type == CREDIT_CARD_TYPE) { |
324 return FillCreditCardTypeSelectControl(value, field); | 330 return FillCreditCardTypeSelectControl(value, field); |
325 } | 331 } |
326 | 332 |
327 return false; | 333 return false; |
328 } | 334 } |
329 | 335 |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
550 if (compare.StringsEqual(value_stripped, option_contents)) { | 556 if (compare.StringsEqual(value_stripped, option_contents)) { |
551 if (index) | 557 if (index) |
552 *index = i; | 558 *index = i; |
553 return true; | 559 return true; |
554 } | 560 } |
555 } | 561 } |
556 return false; | 562 return false; |
557 } | 563 } |
558 | 564 |
559 } // namespace autofill | 565 } // namespace autofill |
OLD | NEW |