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

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: fix test 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
« no previous file with comments | « no previous file | components/autofill/core/browser/autofill_field_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | components/autofill/core/browser/autofill_field_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698