Logo Search packages:      
Sourcecode: chromium-browser version File versions  Download package

select_control_handler.cc

// 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

Generated by  Doxygen 1.6.0   Back to index