Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(582)

Side by Side Diff: components/autofill/core/browser/autofill_field.cc

Issue 1080883002: Remove some more bad ASCII-centric autofill code. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: tests Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698