summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-24 00:15:39 +0000
committerjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-24 00:15:39 +0000
commit967d2f2e58b4364ef4f67ca88c9fc5e31e781381 (patch)
treec72a06eb1b1913e053522cfe45ccb234225fb145 /chrome
parent0d8a8a96caf5667356a182770f1a10505f3370aa (diff)
downloadchromium_src-967d2f2e58b4364ef4f67ca88c9fc5e31e781381.zip
chromium_src-967d2f2e58b4364ef4f67ca88c9fc5e31e781381.tar.gz
chromium_src-967d2f2e58b4364ef4f67ca88c9fc5e31e781381.tar.bz2
AutoFill: Try harder to fill select controls with variations on states,
countries and months. BUG=38222,46861 TEST=none Review URL: http://codereview.chromium.org/2878052 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@53554 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/autofill/autofill_manager.cc18
-rw-r--r--chrome/browser/autofill/autofill_manager.h6
-rw-r--r--chrome/browser/autofill/select_control_handler.cc519
-rw-r--r--chrome/browser/autofill/select_control_handler.h30
-rw-r--r--chrome/chrome_browser.gypi2
5 files changed, 572 insertions, 3 deletions
diff --git a/chrome/browser/autofill/autofill_manager.cc b/chrome/browser/autofill/autofill_manager.cc
index ec80991..b5b28fe 100644
--- a/chrome/browser/autofill/autofill_manager.cc
+++ b/chrome/browser/autofill/autofill_manager.cc
@@ -11,6 +11,7 @@
#include "chrome/browser/autofill/autofill_dialog.h"
#include "chrome/browser/autofill/autofill_cc_infobar_delegate.h"
#include "chrome/browser/autofill/form_structure.h"
+#include "chrome/browser/autofill/select_control_handler.h"
#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/render_view_host.h"
@@ -342,8 +343,7 @@ bool AutoFillManager::FillAutoFillFormData(int query_id,
AutoFillType autofill_type(field->type());
if (credit_card &&
autofill_type.group() == AutoFillType::CREDIT_CARD) {
- result.fields[i].set_value(
- credit_card->GetFieldText(autofill_type));
+ FillCreditCardFormField(credit_card, autofill_type, &result.fields[j]);
} else if (credit_card &&
autofill_type.group() == AutoFillType::ADDRESS_BILLING) {
FillBillingFormField(credit_card, autofill_type, &result.fields[j]);
@@ -643,6 +643,18 @@ void AutoFillManager::FillBillingFormField(const CreditCard* credit_card,
}
}
+void AutoFillManager::FillCreditCardFormField(const CreditCard* credit_card,
+ AutoFillType type,
+ webkit_glue::FormField* field) {
+ DCHECK(credit_card);
+ DCHECK(field);
+
+ if (field->form_control_type() == ASCIIToUTF16("select-one"))
+ autofill::FillSelectControl(credit_card, type, field);
+ else
+ field->set_value(credit_card->GetFieldText(type));
+}
+
void AutoFillManager::FillFormField(const AutoFillProfile* profile,
AutoFillType type,
webkit_glue::FormField* field) {
@@ -653,7 +665,7 @@ void AutoFillManager::FillFormField(const AutoFillProfile* profile,
FillPhoneNumberField(profile, field);
} else {
if (field->form_control_type() == ASCIIToUTF16("select-one"))
- FillSelectOneField(profile, type, field);
+ autofill::FillSelectControl(profile, type, field);
else
field->set_value(profile->GetFieldText(type));
}
diff --git a/chrome/browser/autofill/autofill_manager.h b/chrome/browser/autofill/autofill_manager.h
index f6574d1..ba53fbb 100644
--- a/chrome/browser/autofill/autofill_manager.h
+++ b/chrome/browser/autofill/autofill_manager.h
@@ -136,6 +136,12 @@ class AutoFillManager : public RenderViewHostDelegate::AutoFill,
AutoFillType type,
webkit_glue::FormField* field);
+ // Set |field| argument's value based on |type| and contents of the
+ // |credit_card|.
+ void FillCreditCardFormField(const CreditCard* credit_card,
+ AutoFillType type,
+ webkit_glue::FormField* field);
+
// Set |field| argument's value based on |type| and contents of the |profile|.
void FillFormField(const AutoFillProfile* profile,
AutoFillType type,
diff --git a/chrome/browser/autofill/select_control_handler.cc b/chrome/browser/autofill/select_control_handler.cc
new file mode 100644
index 0000000..dff9d97
--- /dev/null
+++ b/chrome/browser/autofill/select_control_handler.cc
@@ -0,0 +1,519 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/autofill/select_control_handler.h"
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "base/string16.h"
+#include "chrome/browser/autofill/form_group.h"
+#include "webkit/glue/form_field.h"
+
+namespace {
+
+// TODO(jhawkins): Add more states/provinces. See http://crbug.com/45039.
+
+class State {
+ public:
+ const char* name;
+ const char* abbreviation;
+
+ static const State all_states[];
+
+ static string16 Abbreviation(const string16& name);
+ static string16 FullName(const string16& abbreviation);
+};
+
+const State State::all_states[] = {
+ { "alabama", "al" },
+ { "alaska", "ak" },
+ { "arizona", "az" },
+ { "arkansas", "ar" },
+ { "california", "ca" },
+ { "colorado", "co" },
+ { "connecticut", "ct" },
+ { "delaware", "de" },
+ { "district of columbia", "dc" },
+ { "florida", "fl" },
+ { "georgia", "ga" },
+ { "hawaii", "hi" },
+ { "idaho", "id" },
+ { "illinois", "il" },
+ { "indiana", "in" },
+ { "iowa", "ia" },
+ { "kansas", "ks" },
+ { "kentucky", "ky" },
+ { "louisiana", "la" },
+ { "maine", "me" },
+ { "maryland", "md" },
+ { "massachusetts", "ma" },
+ { "michigan", "mi" },
+ { "minnesota", "mv" },
+ { "mississippi", "ms" },
+ { "missouri", "mo" },
+ { "montana", "mt" },
+ { "nebraska", "ne" },
+ { "nevada", "nv" },
+ { "new hampshire", "nh" },
+ { "new jersey", "nj" },
+ { "new mexico", "nm" },
+ { "new york", "ny" },
+ { "north carolina", "nc" },
+ { "north dakota", "nd" },
+ { "ohio", "oh" },
+ { "oklahoma", "ok" },
+ { "oregon", "or" },
+ { "pennsylvania", "pa" },
+ { "puerto rico", "pr" },
+ { "rhode island", "ri" },
+ { "south carolina", "sc" },
+ { "south dakota", "sd" },
+ { "tennessee", "tn" },
+ { "texas", "tx" },
+ { "utah", "ut" },
+ { "vermont", "vt" },
+ { "virginia", "va" },
+ { "washington", "wa" },
+ { "west Virginia", "wv" },
+ { "wisconsin", "wi" },
+ { "wyoming", "wy" },
+ { NULL, NULL }
+};
+
+string16 State::Abbreviation(const string16& name) {
+ for (const State *s = all_states ; s->name ; ++s)
+ if (LowerCaseEqualsASCII(name, s->name))
+ return ASCIIToUTF16(s->abbreviation);
+ return string16();
+}
+
+string16 State::FullName(const string16& abbreviation) {
+ for (const State *s = all_states ; s->name ; ++s)
+ if (LowerCaseEqualsASCII(abbreviation, s->abbreviation))
+ return ASCIIToUTF16(s->name);
+ return string16();
+}
+
+// Holds valid country names, their 2 letter abbreviation, and maps from
+// the former to the latter
+class Country {
+ public:
+ const char* name;
+ const char* abbreviation;
+
+ static const Country all_countries[];
+
+ static string16 Abbreviation(const string16 &name);
+ static string16 FullName(const string16& abbreviation);
+};
+
+// A list of all English country names and code elements. ISO 3166.
+const Country Country::all_countries[] = {
+ { "united states", "us" },
+ { "afghanistan", "af" },
+ { "aland islands", "ax" },
+ { "albania", "al" },
+ { "algeria", "dz" },
+ { "american samoa", "as" },
+ { "andorra", "ad" },
+ { "angola", "ao" },
+ { "anguilla", "ai" },
+ { "antarctica", "aq" },
+ { "antigua and barbuda", "ag" },
+ { "argentina", "ar" },
+ { "armenia", "am" },
+ { "aruba", "aw" },
+ { "australia", "au" },
+ { "austria", "at" },
+ { "azerbaijan", "az" },
+ { "bahamas", "bs" },
+ { "bahrain", "bh" },
+ { "bangladesh", "bd" },
+ { "barbados", "bb" },
+ { "belarus", "by" },
+ { "belgium", "be" },
+ { "belize", "bz" },
+ { "benin", "bj" },
+ { "bermuda", "bm" },
+ { "bhutan", "bt" },
+ { "bolivia", "bo" },
+ { "bosnia and herzegovina", "ba" },
+ { "botswana", "bw" },
+ { "bouvet island", "bv" },
+ { "brazil", "br" },
+ { "british indian ocean territory", "io" },
+ { "brunei darussalam", "bn" },
+ { "bulgaria", "bg" },
+ { "burkina faso", "bf" },
+ { "burundi", "bi" },
+ { "cambodia", "kh" },
+ { "cameroon", "cm" },
+ { "canada", "ca" },
+ { "cape verde", "cv" },
+ { "cayman islands", "ky" },
+ { "central african republic", "cf" },
+ { "chad", "td" },
+ { "chile", "cl" },
+ { "china", "cn" },
+ { "christmas island", "cx" },
+ { "cocos (keeling) islands", "cc" },
+ { "colombia", "co" },
+ { "comoros", "km" },
+ { "congo", "cg" },
+ { "congo (dem. rep.)", "cd" },
+ { "cook islands", "ck" },
+ { "costa rica", "cr" },
+ { "cote d'ivoire", "ci" },
+ { "croatia", "hr" },
+ { "cuba", "cu" },
+ { "cyprus", "cy" },
+ { "czech republic", "cz" },
+ { "denmark", "dk" },
+ { "djibouti", "dj" },
+ { "dominica", "dm" },
+ { "dominican republic", "do" },
+ { "ecuador", "ec" },
+ { "egypt", "eg" },
+ { "el salvador", "sv" },
+ { "equatorial guinea", "gq" },
+ { "eritrea", "er" },
+ { "estonia", "ee" },
+ { "ethiopia", "et" },
+ { "falkland islands (malvinas)", "fk" },
+ { "faroe islands", "fo" },
+ { "fiji", "fj" },
+ { "finland", "fi" },
+ { "france", "fr" },
+ { "french guiana", "gf" },
+ { "french polynesia", "pf" },
+ { "gabon", "ga" },
+ { "gambia", "gm" },
+ { "georgia", "ge" },
+ { "germany", "de" },
+ { "ghana", "gh" },
+ { "gibraltar", "gi" },
+ { "greece", "gr" },
+ { "greenland", "gl" },
+ { "grenada", "gd" },
+ { "guadeloupe", "gp" },
+ { "guam", "gu" },
+ { "guatemala", "gt" },
+ { "guernsey", "cg" },
+ { "guinea", "gn" },
+ { "guinea-bissau", "gw" },
+ { "guyana", "gy" },
+ { "haiti", "ht" },
+ { "heard island and mcdonald islands", "hm" },
+ { "holy see (vatica city state)", "va" },
+ { "honduras", "hn" },
+ { "hong kong", "hk" },
+ { "hungary", "hu" },
+ { "iceland", "is" },
+ { "india", "in" },
+ { "indonesia", "id" },
+ { "iran", "ir" },
+ { "iraq", "iq" },
+ { "ireland", "ie" },
+ { "isle of man", "im" },
+ { "israel", "il" },
+ { "italy", "it" },
+ { "ivory coast", "ci" },
+ { "jamaica", "jm" },
+ { "japan", "jp" },
+ { "jersey", "je" },
+ { "jordan", "jo" },
+ { "kazakhstan", "kz" },
+ { "kenya", "ke" },
+ { "kiribati", "ki" },
+ { "korea (north)", "kp" },
+ { "korea (south)", "kr" },
+ { "kuwait", "kw" },
+ { "kyrgyzstan", "kg" },
+ { "laos", "la" },
+ { "latvia", "lv" },
+ { "lebanon", "lb" },
+ { "lesotho", "ls" },
+ { "liberia", "lr" },
+ { "libya", "ly" },
+ { "liechtenstein", "li" },
+ { "lithuania", "lt" },
+ { "luxembourg", "lu" },
+ { "macao", "mo" },
+ { "macedonia", "mk" },
+ { "madagascar", "mg" },
+ { "malawi", "mw" },
+ { "malaysia", "my" },
+ { "maldives", "mv" },
+ { "mali", "ml" },
+ { "malta", "mt" },
+ { "marshall islands", "mh" },
+ { "martinique", "mq" },
+ { "mauritania", "mr" },
+ { "mauritius", "mu" },
+ { "mayotte", "yt" },
+ { "mexico", "mx" },
+ { "micronesia", "fm" },
+ { "moldova", "md" },
+ { "monaco", "mc" },
+ { "mongolia", "mn" },
+ { "montserrat", "ms" },
+ { "morocco", "ma" },
+ { "mozambique", "mz" },
+ { "myanmar", "mm" },
+ { "namibia", "na" },
+ { "nepal", "np" },
+ { "netherlands", "nl" },
+ { "netherlands antilles", "an" },
+ { "new caledonia", "nc" },
+ { "new zealand", "nz" },
+ { "nicaragua", "ni" },
+ { "niger", "ne" },
+ { "nigeria", "ng" },
+ { "niue", "nu" },
+ { "norfolk island", "nf" },
+ { "northern mariana islands", "mp" },
+ { "norway", "no" },
+ { "oman", "om" },
+ { "pakistan", "pk" },
+ { "palau", "pw" },
+ { "palestine", "ps" },
+ { "panama", "pa" },
+ { "papua new guinea", "pg" },
+ { "paraguay", "py" },
+ { "peru", "pe" },
+ { "philippines", "ph" },
+ { "pitcairn", "pn" },
+ { "poland", "pl" },
+ { "portugal", "pt" },
+ { "puerto rico", "pr" },
+ { "qatar", "qa" },
+ { "reunion", "re" },
+ { "romania", "ro" },
+ { "russia", "ru" },
+ { "rwanda", "rw" },
+ { "saint helena", "sh" },
+ { "saint kitts and nevis", "kn" },
+ { "saint lucia", "lc" },
+ { "saint pierre and miquelon", "pm" },
+ { "saint vincent and the grenadines", "vc" },
+ { "samoa", "ws" },
+ { "san marino", "sm" },
+ { "sao tome and principe", "st" },
+ { "saudi arabia", "sa" },
+ { "senegal", "sn" },
+ { "serbia and montenegro", "cs" },
+ { "seychelles", "sc" },
+ { "sierra leone", "sl" },
+ { "singapore", "sg" },
+ { "slovakia", "sk" },
+ { "slovenia", "si" },
+ { "solomon islands", "sb" },
+ { "somalia", "so" },
+ { "south africa", "za" },
+ { "south georgia and the south sandwich islands", "gs" },
+ { "spain", "es" },
+ { "sri lanka", "lk" },
+ { "sudan", "sd" },
+ { "suriname", "sr" },
+ { "svalbard and jan mayen", "sj" },
+ { "swaziland", "sz" },
+ { "sweden", "se" },
+ { "switzerland", "ch" },
+ { "syria", "sy" },
+ { "taiwan", "tw" },
+ { "tajikistan", "tj" },
+ { "tanzania", "tz" },
+ { "thailand", "th" },
+ { "timor-leste", "tl" },
+ { "togo", "tg" },
+ { "tokelau", "tk" },
+ { "tonga", "to" },
+ { "trinidad and tobago", "tt" },
+ { "tunisia", "tn" },
+ { "turkey", "tr" },
+ { "turkmenistan", "tm" },
+ { "turks and caicos islands", "tc" },
+ { "tuvalu", "tv" },
+ { "uganda", "ug" },
+ { "ukraine", "ua" },
+ { "united arab emirates", "ae" },
+ { "united kingdom", "gb" },
+ { "u.s. minor outlying islands", "um" },
+ { "uruguay", "uy" },
+ { "uzbekistan", "uz" },
+ { "vanuatu", "vu" },
+ { "venezuela", "ve" },
+ { "vietnam", "vn" },
+ { "virgin islands, british", "vg" },
+ { "virgin islands, u.s.", "vi" },
+ { "wallis and futuna", "wf" },
+ { "western sahara", "eh" },
+ { "yemen", "ye" },
+ { "zambia", "zm" },
+ { "zimbabwe", "zw" },
+ { NULL, NULL }
+};
+
+string16 Country::Abbreviation(const string16& name) {
+ for (const Country *s = all_countries ; s->name ; ++s)
+ if (LowerCaseEqualsASCII(name, s->name))
+ return ASCIIToUTF16(s->abbreviation);
+ return string16();
+}
+
+string16 Country::FullName(const string16& abbreviation) {
+ for (const Country *s = all_countries ; s->name ; ++s)
+ if (LowerCaseEqualsASCII(abbreviation, s->abbreviation))
+ return ASCIIToUTF16(s->name);
+ return string16();
+}
+
+const char* const kMonthsAbbreviated[] = {
+ NULL, // Padding so index 1 = month 1 = January.
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+};
+
+const char* const kMonthsFull[] = {
+ NULL, // Padding so index 1 = month 1 = January.
+ "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December",
+};
+
+// Returns true if the value was successfully set, meaning |value| was found in
+// the list of select options in |field|.
+bool SetSelectControlValue(const string16& value,
+ webkit_glue::FormField* field) {
+ string16 value_lowercase = StringToLowerASCII(value);
+
+ for (std::vector<string16>::const_iterator iter =
+ field->option_strings().begin();
+ iter != field->option_strings().end(); ++iter) {
+ if (value_lowercase == StringToLowerASCII(*iter)) {
+ field->set_value(*iter);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool FillStateSelectControl(const string16& value,
+ webkit_glue::FormField* field) {
+ if (value.empty())
+ return false;
+
+ string16 abbrev, full;
+ if (value.size() < 4U) {
+ abbrev = value;
+ full = State::FullName(value);
+ } else {
+ abbrev = State::Abbreviation(value);
+ full = value;
+ }
+
+ // Try the abbreviation name first.
+ if (!abbrev.empty() && SetSelectControlValue(abbrev, field))
+ return true;
+
+ if (full.empty())
+ return false;
+
+ return SetSelectControlValue(full, field);
+}
+
+bool FillCountrySelectControl(const string16& value,
+ webkit_glue::FormField* field) {
+ if (value.empty())
+ return false;
+
+ string16 abbrev, full;
+ if (value.size() < 4U) {
+ abbrev = value;
+ full = Country::FullName(value);
+ } else {
+ abbrev = Country::Abbreviation(value);
+ full = value;
+ }
+
+ // Try the abbreviation name first.
+ if (!abbrev.empty() && SetSelectControlValue(abbrev, field))
+ return true;
+
+ if (full.empty())
+ return false;
+
+ return SetSelectControlValue(full, field);
+}
+
+bool FillExpirationMonthSelectControl(const string16& value,
+ webkit_glue::FormField* field) {
+ if (value.empty())
+ return false;
+
+ if (SetSelectControlValue(value, field))
+ return true;
+
+ int index = 0;
+ if (!StringToInt(value, &index) ||
+ index <= 0 ||
+ static_cast<size_t>(index) >= arraysize(kMonthsFull))
+ return false;
+
+ bool filled =
+ SetSelectControlValue(ASCIIToUTF16(kMonthsAbbreviated[index]), field) ||
+ SetSelectControlValue(ASCIIToUTF16(kMonthsFull[index]), field);
+ return filled;
+}
+
+} // namespace
+
+namespace autofill {
+
+void FillSelectControl(const FormGroup* form_group,
+ AutoFillType type,
+ webkit_glue::FormField* field) {
+ DCHECK(form_group);
+ DCHECK(field);
+ DCHECK(field->form_control_type() == ASCIIToUTF16("select-one"));
+
+ string16 value;
+ string16 field_text = form_group->GetFieldText(type);
+ for (size_t i = 0; i < field->option_strings().size(); ++i) {
+ if (form_group->GetFieldText(type) == field->option_strings()[i]) {
+ // An exact match, use it.
+ value = form_group->GetFieldText(type);
+ break;
+ }
+
+ if (StringToLowerASCII(field->option_strings()[i]) ==
+ StringToLowerASCII(field_text)) {
+ // A match, but not in the same case. Save it in case an exact match is
+ // not found.
+ value = field->option_strings()[i];
+ }
+ }
+
+ if (!value.empty()) {
+ field->set_value(value);
+ return;
+ }
+
+ if (type.field_type() == ADDRESS_HOME_STATE ||
+ type.field_type() == ADDRESS_BILLING_STATE) {
+ FillStateSelectControl(field_text, field);
+ } else if (type.field_type() == ADDRESS_HOME_COUNTRY ||
+ type.field_type() == ADDRESS_BILLING_COUNTRY) {
+ FillCountrySelectControl(field_text, field);
+ } else if (type.field_type() == CREDIT_CARD_EXP_MONTH) {
+ FillExpirationMonthSelectControl(field_text, field);
+ }
+
+ return;
+}
+
+} // namespace autofill
diff --git a/chrome/browser/autofill/select_control_handler.h b/chrome/browser/autofill/select_control_handler.h
new file mode 100644
index 0000000..d434070
--- /dev/null
+++ b/chrome/browser/autofill/select_control_handler.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_AUTOFILL_SELECT_CONTROL_HANDLER_H_
+#define CHROME_BROWSER_AUTOFILL_SELECT_CONTROL_HANDLER_H_
+
+#include "chrome/browser/autofill/autofill_type.h"
+
+class FormGroup;
+
+namespace webkit_glue {
+class FormField;
+} // namespace webkit_glue
+
+namespace autofill {
+
+// TODO(jhawkins): This definitely needs tests.
+
+// Fills a select-one control with the appropriate value from |form_group|.
+// Finds the matching value for field types that we know contain different
+// variations of a value, e.g., (tx, TX, Texas) or credit card expiration
+// months, e.g., (04, April).
+void FillSelectControl(const FormGroup* form_group,
+ AutoFillType type,
+ webkit_glue::FormField* field);
+
+} // namespace autofill
+
+#endif // CHROME_BROWSER_AUTOFILL_SELECT_CONTROL_HANDLER_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 849abcf..a4087f6 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -181,6 +181,8 @@
'browser/autofill/phone_field.h',
'browser/autofill/phone_number.cc',
'browser/autofill/phone_number.h',
+ 'browser/autofill/select_control_handler.cc',
+ 'browser/autofill/select_control_handler.h',
'browser/automation/automation_autocomplete_edit_tracker.h',
'browser/automation/automation_browser_tracker.h',
'browser/automation/extension_automation_constants.h',