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

Side by Side Diff: chrome/browser/autofill/select_control_handler.cc

Issue 6484022: Autofill i18n: Set postal code and state field labels based on the selected country. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Still needs tests Created 9 years, 10 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "chrome/browser/autofill/select_control_handler.h" 5 #include "chrome/browser/autofill/select_control_handler.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/string_number_conversions.h" 11 #include "base/string_number_conversions.h"
12 #include "base/string16.h" 12 #include "base/string16.h"
13 #include "base/utf_string_conversions.h" 13 #include "base/utf_string_conversions.h"
14 #include "chrome/browser/autofill/autofill_country.h"
15 #include "chrome/browser/autofill/autofill_profile.h"
14 #include "chrome/browser/autofill/form_group.h" 16 #include "chrome/browser/autofill/form_group.h"
15 #include "webkit/glue/form_field.h" 17 #include "webkit/glue/form_field.h"
16 18
17 namespace { 19 namespace {
18 20
19 // TODO(jhawkins): Add more states/provinces. See http://crbug.com/45039. 21 // TODO(jhawkins): Add more states/provinces. See http://crbug.com/45039.
20 22
21 class State { 23 class State {
22 public: 24 public:
23 const char* name; 25 const char* name;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 return string16(); 94 return string16();
93 } 95 }
94 96
95 string16 State::FullName(const string16& abbreviation) { 97 string16 State::FullName(const string16& abbreviation) {
96 for (const State *s = all_states ; s->name ; ++s) 98 for (const State *s = all_states ; s->name ; ++s)
97 if (LowerCaseEqualsASCII(abbreviation, s->abbreviation)) 99 if (LowerCaseEqualsASCII(abbreviation, s->abbreviation))
98 return ASCIIToUTF16(s->name); 100 return ASCIIToUTF16(s->name);
99 return string16(); 101 return string16();
100 } 102 }
101 103
102 // Holds valid country names, their 2 letter abbreviation, and maps from
103 // the former to the latter
104 class Country {
105 public:
106 const char* name;
107 const char* abbreviation;
108
109 static const Country all_countries[];
110
111 static string16 Abbreviation(const string16 &name);
112 static string16 FullName(const string16& abbreviation);
113 };
114
115 // A list of all English country names and code elements. ISO 3166.
116 const Country Country::all_countries[] = {
117 { "united states", "us" },
118 { "afghanistan", "af" },
119 { "aland islands", "ax" },
120 { "albania", "al" },
121 { "algeria", "dz" },
122 { "american samoa", "as" },
123 { "andorra", "ad" },
124 { "angola", "ao" },
125 { "anguilla", "ai" },
126 { "antarctica", "aq" },
127 { "antigua and barbuda", "ag" },
128 { "argentina", "ar" },
129 { "armenia", "am" },
130 { "aruba", "aw" },
131 { "australia", "au" },
132 { "austria", "at" },
133 { "azerbaijan", "az" },
134 { "bahamas", "bs" },
135 { "bahrain", "bh" },
136 { "bangladesh", "bd" },
137 { "barbados", "bb" },
138 { "belarus", "by" },
139 { "belgium", "be" },
140 { "belize", "bz" },
141 { "benin", "bj" },
142 { "bermuda", "bm" },
143 { "bhutan", "bt" },
144 { "bolivia", "bo" },
145 { "bosnia and herzegovina", "ba" },
146 { "botswana", "bw" },
147 { "bouvet island", "bv" },
148 { "brazil", "br" },
149 { "british indian ocean territory", "io" },
150 { "brunei darussalam", "bn" },
151 { "bulgaria", "bg" },
152 { "burkina faso", "bf" },
153 { "burundi", "bi" },
154 { "cambodia", "kh" },
155 { "cameroon", "cm" },
156 { "canada", "ca" },
157 { "cape verde", "cv" },
158 { "cayman islands", "ky" },
159 { "central african republic", "cf" },
160 { "chad", "td" },
161 { "chile", "cl" },
162 { "china", "cn" },
163 { "christmas island", "cx" },
164 { "cocos (keeling) islands", "cc" },
165 { "colombia", "co" },
166 { "comoros", "km" },
167 { "congo", "cg" },
168 { "congo (dem. rep.)", "cd" },
169 { "cook islands", "ck" },
170 { "costa rica", "cr" },
171 { "cote d'ivoire", "ci" },
172 { "croatia", "hr" },
173 { "cuba", "cu" },
174 { "cyprus", "cy" },
175 { "czech republic", "cz" },
176 { "denmark", "dk" },
177 { "djibouti", "dj" },
178 { "dominica", "dm" },
179 { "dominican republic", "do" },
180 { "ecuador", "ec" },
181 { "egypt", "eg" },
182 { "el salvador", "sv" },
183 { "equatorial guinea", "gq" },
184 { "eritrea", "er" },
185 { "estonia", "ee" },
186 { "ethiopia", "et" },
187 { "falkland islands (malvinas)", "fk" },
188 { "faroe islands", "fo" },
189 { "fiji", "fj" },
190 { "finland", "fi" },
191 { "france", "fr" },
192 { "french guiana", "gf" },
193 { "french polynesia", "pf" },
194 { "gabon", "ga" },
195 { "gambia", "gm" },
196 { "georgia", "ge" },
197 { "germany", "de" },
198 { "ghana", "gh" },
199 { "gibraltar", "gi" },
200 { "greece", "gr" },
201 { "greenland", "gl" },
202 { "grenada", "gd" },
203 { "guadeloupe", "gp" },
204 { "guam", "gu" },
205 { "guatemala", "gt" },
206 { "guernsey", "cg" },
207 { "guinea", "gn" },
208 { "guinea-bissau", "gw" },
209 { "guyana", "gy" },
210 { "haiti", "ht" },
211 { "heard island and mcdonald islands", "hm" },
212 { "holy see (vatica city state)", "va" },
213 { "honduras", "hn" },
214 { "hong kong", "hk" },
215 { "hungary", "hu" },
216 { "iceland", "is" },
217 { "india", "in" },
218 { "indonesia", "id" },
219 { "iran", "ir" },
220 { "iraq", "iq" },
221 { "ireland", "ie" },
222 { "isle of man", "im" },
223 { "israel", "il" },
224 { "italy", "it" },
225 { "ivory coast", "ci" },
226 { "jamaica", "jm" },
227 { "japan", "jp" },
228 { "jersey", "je" },
229 { "jordan", "jo" },
230 { "kazakhstan", "kz" },
231 { "kenya", "ke" },
232 { "kiribati", "ki" },
233 { "korea (north)", "kp" },
234 { "korea (south)", "kr" },
235 { "kuwait", "kw" },
236 { "kyrgyzstan", "kg" },
237 { "laos", "la" },
238 { "latvia", "lv" },
239 { "lebanon", "lb" },
240 { "lesotho", "ls" },
241 { "liberia", "lr" },
242 { "libya", "ly" },
243 { "liechtenstein", "li" },
244 { "lithuania", "lt" },
245 { "luxembourg", "lu" },
246 { "macao", "mo" },
247 { "macedonia", "mk" },
248 { "madagascar", "mg" },
249 { "malawi", "mw" },
250 { "malaysia", "my" },
251 { "maldives", "mv" },
252 { "mali", "ml" },
253 { "malta", "mt" },
254 { "marshall islands", "mh" },
255 { "martinique", "mq" },
256 { "mauritania", "mr" },
257 { "mauritius", "mu" },
258 { "mayotte", "yt" },
259 { "mexico", "mx" },
260 { "micronesia", "fm" },
261 { "moldova", "md" },
262 { "monaco", "mc" },
263 { "mongolia", "mn" },
264 { "montserrat", "ms" },
265 { "morocco", "ma" },
266 { "mozambique", "mz" },
267 { "myanmar", "mm" },
268 { "namibia", "na" },
269 { "nepal", "np" },
270 { "netherlands", "nl" },
271 { "netherlands antilles", "an" },
272 { "new caledonia", "nc" },
273 { "new zealand", "nz" },
274 { "nicaragua", "ni" },
275 { "niger", "ne" },
276 { "nigeria", "ng" },
277 { "niue", "nu" },
278 { "norfolk island", "nf" },
279 { "northern mariana islands", "mp" },
280 { "norway", "no" },
281 { "oman", "om" },
282 { "pakistan", "pk" },
283 { "palau", "pw" },
284 { "palestine", "ps" },
285 { "panama", "pa" },
286 { "papua new guinea", "pg" },
287 { "paraguay", "py" },
288 { "peru", "pe" },
289 { "philippines", "ph" },
290 { "pitcairn", "pn" },
291 { "poland", "pl" },
292 { "portugal", "pt" },
293 { "puerto rico", "pr" },
294 { "qatar", "qa" },
295 { "reunion", "re" },
296 { "romania", "ro" },
297 { "russia", "ru" },
298 { "rwanda", "rw" },
299 { "saint helena", "sh" },
300 { "saint kitts and nevis", "kn" },
301 { "saint lucia", "lc" },
302 { "saint pierre and miquelon", "pm" },
303 { "saint vincent and the grenadines", "vc" },
304 { "samoa", "ws" },
305 { "san marino", "sm" },
306 { "sao tome and principe", "st" },
307 { "saudi arabia", "sa" },
308 { "senegal", "sn" },
309 { "serbia and montenegro", "cs" },
310 { "seychelles", "sc" },
311 { "sierra leone", "sl" },
312 { "singapore", "sg" },
313 { "slovakia", "sk" },
314 { "slovenia", "si" },
315 { "solomon islands", "sb" },
316 { "somalia", "so" },
317 { "south africa", "za" },
318 { "south georgia and the south sandwich islands", "gs" },
319 { "spain", "es" },
320 { "sri lanka", "lk" },
321 { "sudan", "sd" },
322 { "suriname", "sr" },
323 { "svalbard and jan mayen", "sj" },
324 { "swaziland", "sz" },
325 { "sweden", "se" },
326 { "switzerland", "ch" },
327 { "syria", "sy" },
328 { "taiwan", "tw" },
329 { "tajikistan", "tj" },
330 { "tanzania", "tz" },
331 { "thailand", "th" },
332 { "timor-leste", "tl" },
333 { "togo", "tg" },
334 { "tokelau", "tk" },
335 { "tonga", "to" },
336 { "trinidad and tobago", "tt" },
337 { "tunisia", "tn" },
338 { "turkey", "tr" },
339 { "turkmenistan", "tm" },
340 { "turks and caicos islands", "tc" },
341 { "tuvalu", "tv" },
342 { "uganda", "ug" },
343 { "ukraine", "ua" },
344 { "united arab emirates", "ae" },
345 { "united kingdom", "gb" },
346 { "u.s. minor outlying islands", "um" },
347 { "uruguay", "uy" },
348 { "uzbekistan", "uz" },
349 { "vanuatu", "vu" },
350 { "venezuela", "ve" },
351 { "vietnam", "vn" },
352 { "virgin islands, british", "vg" },
353 { "virgin islands, u.s.", "vi" },
354 { "wallis and futuna", "wf" },
355 { "western sahara", "eh" },
356 { "yemen", "ye" },
357 { "zambia", "zm" },
358 { "zimbabwe", "zw" },
359 { NULL, NULL }
360 };
361
362 string16 Country::Abbreviation(const string16& name) {
363 for (const Country *s = all_countries ; s->name ; ++s)
364 if (LowerCaseEqualsASCII(name, s->name))
365 return ASCIIToUTF16(s->abbreviation);
366 return string16();
367 }
368
369 string16 Country::FullName(const string16& abbreviation) {
370 for (const Country *s = all_countries ; s->name ; ++s)
371 if (LowerCaseEqualsASCII(abbreviation, s->abbreviation))
372 return ASCIIToUTF16(s->name);
373 return string16();
374 }
375
376 const char* const kMonthsAbbreviated[] = { 104 const char* const kMonthsAbbreviated[] = {
377 NULL, // Padding so index 1 = month 1 = January. 105 NULL, // Padding so index 1 = month 1 = January.
378 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 106 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
379 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 107 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
380 }; 108 };
381 109
382 const char* const kMonthsFull[] = { 110 const char* const kMonthsFull[] = {
383 NULL, // Padding so index 1 = month 1 = January. 111 NULL, // Padding so index 1 = month 1 = January.
384 "January", "February", "March", "April", "May", "June", 112 "January", "February", "March", "April", "May", "June",
385 "July", "August", "September", "October", "November", "December", 113 "July", "August", "September", "October", "November", "December",
(...skipping 16 matching lines...) Expand all
402 if (value_lowercase == StringToLowerASCII(*iter)) { 130 if (value_lowercase == StringToLowerASCII(*iter)) {
403 field->set_value(*iter); 131 field->set_value(*iter);
404 return true; 132 return true;
405 } 133 }
406 } 134 }
407 135
408 return false; 136 return false;
409 } 137 }
410 138
411 bool FillStateSelectControl(const string16& value, 139 bool FillStateSelectControl(const string16& value,
412 webkit_glue::FormField* field) { 140 webkit_glue::FormField* field) {
dhollowa 2011/02/17 00:55:28 A DCHECK(!value.empty()) might be worthwhile here
Ilya Sherman 2011/02/17 23:09:11 Nothing will go wrong if value is empty -- it'll j
413 if (value.empty())
414 return false;
415
416 string16 abbrev, full; 141 string16 abbrev, full;
417 if (value.size() < 4U) { 142 if (value.size() < 4U) {
418 abbrev = value; 143 abbrev = value;
419 full = State::FullName(value); 144 full = State::FullName(value);
420 } else { 145 } else {
421 abbrev = State::Abbreviation(value); 146 abbrev = State::Abbreviation(value);
422 full = value; 147 full = value;
423 } 148 }
424 149
425 // Try the abbreviation name first. 150 // Try the abbreviation name first.
426 if (!abbrev.empty() && SetSelectControlValue(abbrev, field)) 151 if (!abbrev.empty() && SetSelectControlValue(abbrev, field))
427 return true; 152 return true;
428 153
429 if (full.empty()) 154 if (full.empty())
430 return false; 155 return false;
431 156
432 return SetSelectControlValue(full, field); 157 return SetSelectControlValue(full, field);
433 } 158 }
434 159
435 bool FillCountrySelectControl(const string16& value, 160 bool FillCountrySelectControl(const FormGroup& form_group,
dhollowa 2011/02/17 00:55:28 This looks very much like |SetSelectControlValue|.
Ilya Sherman 2011/02/17 23:09:11 The caller already tries the full country string.
dhollowa 2011/02/17 23:36:47 Makes sense, ya. On 2011/02/17 23:09:11, Ilya She
436 webkit_glue::FormField* field) { 161 webkit_glue::FormField* field) {
437 if (value.empty()) 162 const AutoFillProfile& profile =
438 return false; 163 static_cast<const AutoFillProfile&>(form_group);
164 std::string country_code = profile.CountryCode();
439 165
440 string16 abbrev, full; 166 for (std::vector<string16>::const_iterator iter =
441 if (value.size() < 4U) { 167 field->option_strings().begin();
442 abbrev = value; 168 iter != field->option_strings().end();
443 full = Country::FullName(value); 169 ++iter) {
444 } else { 170 if (country_code == AutoFillCountry::GetCountryCode(*iter)) {
445 abbrev = Country::Abbreviation(value); 171 field->set_value(*iter);
446 full = value; 172 return true;
173 }
447 } 174 }
448 175
449 // Try the abbreviation name first. 176 return false;
450 if (!abbrev.empty() && SetSelectControlValue(abbrev, field))
451 return true;
452
453 if (full.empty())
454 return false;
455
456 return SetSelectControlValue(full, field);
457 } 177 }
458 178
459 bool FillExpirationMonthSelectControl(const string16& value, 179 bool FillExpirationMonthSelectControl(const string16& value,
460 webkit_glue::FormField* field) { 180 webkit_glue::FormField* field) {
dhollowa 2011/02/17 00:55:28 A DCHECK(!value.empty()) might be worthwhile here
Ilya Sherman 2011/02/17 23:09:11 An empty value would just trip the "return false;"
dhollowa 2011/02/17 23:36:47 Ok. On 2011/02/17 23:09:11, Ilya Sherman wrote:
461 if (value.empty())
462 return false;
463
464 if (SetSelectControlValue(value, field))
465 return true;
466
467 int index = 0; 181 int index = 0;
dhollowa 2011/02/17 00:55:28 This no longer tries both the and full month strin
Ilya Sherman 2011/02/17 23:09:11 The caller already tries the full month value.
dhollowa 2011/02/17 23:36:47 Makes sense, ya. On 2011/02/17 23:09:11, Ilya She
468 if (!base::StringToInt(value, &index) || 182 if (!base::StringToInt(value, &index) ||
469 index <= 0 || 183 index <= 0 ||
470 static_cast<size_t>(index) >= arraysize(kMonthsFull)) 184 static_cast<size_t>(index) >= arraysize(kMonthsFull))
471 return false; 185 return false;
472 186
473 bool filled = 187 bool filled =
474 SetSelectControlValue(ASCIIToUTF16(kMonthsAbbreviated[index]), field) || 188 SetSelectControlValue(ASCIIToUTF16(kMonthsAbbreviated[index]), field) ||
475 SetSelectControlValue(ASCIIToUTF16(kMonthsFull[index]), field) || 189 SetSelectControlValue(ASCIIToUTF16(kMonthsFull[index]), field) ||
476 SetSelectControlValue(ASCIIToUTF16(kMonthsNumeric[index]), field); 190 SetSelectControlValue(ASCIIToUTF16(kMonthsNumeric[index]), field);
477 return filled; 191 return filled;
478 } 192 }
479 193
480 } // namespace 194 } // namespace
481 195
482 namespace autofill { 196 namespace autofill {
483 197
484 void FillSelectControl(const FormGroup& form_group, 198 void FillSelectControl(const FormGroup& form_group,
485 AutoFillType type, 199 AutoFillType type,
486 webkit_glue::FormField* field) { 200 webkit_glue::FormField* field) {
487 DCHECK(field); 201 DCHECK(field);
488 DCHECK(field->form_control_type() == ASCIIToUTF16("select-one")); 202 DCHECK(field->form_control_type() == ASCIIToUTF16("select-one"));
489 203
204 string16 field_text = form_group.GetFieldText(type);
205 if (field_text.empty())
206 return;
207
490 string16 value; 208 string16 value;
491 string16 field_text = form_group.GetFieldText(type);
492 for (size_t i = 0; i < field->option_strings().size(); ++i) { 209 for (size_t i = 0; i < field->option_strings().size(); ++i) {
493 if (field_text == field->option_strings()[i]) { 210 if (field_text == field->option_strings()[i]) {
494 // An exact match, use it. 211 // An exact match, use it.
495 value = field_text; 212 value = field_text;
496 break; 213 break;
497 } 214 }
498 215
499 if (StringToLowerASCII(field->option_strings()[i]) == 216 if (StringToLowerASCII(field->option_strings()[i]) ==
500 StringToLowerASCII(field_text)) { 217 StringToLowerASCII(field_text)) {
501 // A match, but not in the same case. Save it in case an exact match is 218 // A match, but not in the same case. Save it in case an exact match is
502 // not found. 219 // not found.
503 value = field->option_strings()[i]; 220 value = field->option_strings()[i];
504 } 221 }
505 } 222 }
506 223
507 if (!value.empty()) { 224 if (!value.empty()) {
508 field->set_value(value); 225 field->set_value(value);
509 return; 226 return;
510 } 227 }
511 228
512 if (type.field_type() == ADDRESS_HOME_STATE || 229 if (type.field_type() == ADDRESS_HOME_STATE ||
513 type.field_type() == ADDRESS_BILLING_STATE) { 230 type.field_type() == ADDRESS_BILLING_STATE) {
514 FillStateSelectControl(field_text, field); 231 FillStateSelectControl(field_text, field);
515 } else if (type.field_type() == ADDRESS_HOME_COUNTRY || 232 } else if (type.field_type() == ADDRESS_HOME_COUNTRY ||
516 type.field_type() == ADDRESS_BILLING_COUNTRY) { 233 type.field_type() == ADDRESS_BILLING_COUNTRY) {
517 FillCountrySelectControl(field_text, field); 234 FillCountrySelectControl(form_group, field);
518 } else if (type.field_type() == CREDIT_CARD_EXP_MONTH) { 235 } else if (type.field_type() == CREDIT_CARD_EXP_MONTH) {
519 FillExpirationMonthSelectControl(field_text, field); 236 FillExpirationMonthSelectControl(field_text, field);
520 } 237 }
521 238
522 return; 239 return;
523 } 240 }
524 241
525 } // namespace autofill 242 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698