普通文本  |  645行  |  30.9 KB

// Copyright (c) 2011 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/autofill_country.h"

#include <stddef.h>
#include <stdint.h>
#include <map>
#include <utility>

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "base/stl_util-inl.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#ifndef ANDROID
#include "chrome/browser/browser_process.h"
#endif
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "unicode/coll.h"
#include "unicode/locid.h"
#include "unicode/ucol.h"
#include "unicode/uloc.h"
#include "unicode/unistr.h"
#include "unicode/urename.h"
#include "unicode/utypes.h"

namespace {

struct CountryData {
  std::string country_code;
  int postal_code_label_id;
  int state_label_id;
};

// The maximum capacity needed to store a locale up to the country code.
const size_t kLocaleCapacity =
    ULOC_LANG_CAPACITY + ULOC_SCRIPT_CAPACITY + ULOC_COUNTRY_CAPACITY + 1;

// Maps country codes to localized label string identifiers.
const CountryData kCountryData[] = {
  {"AD", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PARISH},
  {"AE", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_EMIRATE},
  {"AF", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"AG", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"AI", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"AL", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"AM", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"AN", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"AO", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"AQ", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"AR", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_STATE},
  {"AS", IDS_AUTOFILL_DIALOG_ZIP_CODE,    IDS_AUTOFILL_DIALOG_STATE},
  {"AT", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"AU", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_STATE},
  {"AW", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"AX", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"AZ", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"BA", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"BB", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PARISH},
  {"BD", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"BE", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"BF", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"BG", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"BH", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"BI", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"BJ", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"BL", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"BM", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"BN", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"BO", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"BR", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_STATE},
  {"BS", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_ISLAND},
  {"BT", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"BV", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"BW", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"BY", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"BZ", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"CA", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"CC", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"CD", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"CF", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"CG", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"CH", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"CI", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"CK", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"CL", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_STATE},
  {"CM", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"CN", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"CO", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"CR", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"CV", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_ISLAND},
  {"CX", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"CY", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"CZ", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"DE", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"DJ", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"DK", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"DM", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"DO", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"DZ", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"EC", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"EE", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"EG", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"EH", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"ER", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"ES", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"ET", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"FI", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"FJ", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"FK", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"FM", IDS_AUTOFILL_DIALOG_ZIP_CODE,    IDS_AUTOFILL_DIALOG_STATE},
  {"FO", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"FR", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"GA", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"GB", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_COUNTY},
  {"GD", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"GE", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"GF", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"GG", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"GH", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"GI", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"GL", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"GM", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"GN", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"GP", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"GQ", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"GR", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"GS", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"GT", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"GU", IDS_AUTOFILL_DIALOG_ZIP_CODE,    IDS_AUTOFILL_DIALOG_STATE},
  {"GW", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"GY", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"HK", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_AREA},
  {"HM", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"HN", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"HR", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"HT", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"HU", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"ID", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"IE", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_COUNTY},
  {"IL", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"IM", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"IN", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_STATE},
  {"IO", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"IQ", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"IS", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"IT", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"JE", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"JM", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PARISH},
  {"JO", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"JP", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PREFECTURE},
  {"KE", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"KG", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"KH", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"KI", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_ISLAND},
  {"KM", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"KN", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_ISLAND},
  {"KP", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"KR", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"KW", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"KY", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_ISLAND},
  {"KZ", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"LA", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"LB", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"LC", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"LI", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"LK", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"LR", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"LS", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"LT", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"LU", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"LV", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"LY", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"MA", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"MC", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"MD", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"ME", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"MF", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"MG", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"MH", IDS_AUTOFILL_DIALOG_ZIP_CODE,    IDS_AUTOFILL_DIALOG_STATE},
  {"MK", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"ML", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"MN", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"MO", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"MP", IDS_AUTOFILL_DIALOG_ZIP_CODE,    IDS_AUTOFILL_DIALOG_STATE},
  {"MQ", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"MR", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"MS", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"MT", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"MU", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"MV", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"MW", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"MX", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_STATE},
  {"MY", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_STATE},
  {"MZ", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"NA", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"NC", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"NE", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"NF", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"NG", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_STATE},
  {"NI", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_DEPARTMENT},
  {"NL", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"NO", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"NP", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"NR", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_DISTRICT},
  {"NU", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"NZ", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"OM", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"PA", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"PE", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"PF", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_ISLAND},
  {"PG", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"PH", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"PK", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"PL", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"PM", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"PN", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"PR", IDS_AUTOFILL_DIALOG_ZIP_CODE,    IDS_AUTOFILL_DIALOG_PROVINCE},
  {"PS", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"PT", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"PW", IDS_AUTOFILL_DIALOG_ZIP_CODE,    IDS_AUTOFILL_DIALOG_STATE},
  {"PY", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"QA", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"RE", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"RO", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"RS", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"RU", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"RW", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"SA", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"SB", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"SC", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_ISLAND},
  {"SE", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"SG", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"SH", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"SI", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"SJ", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"SK", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"SL", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"SM", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"SN", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"SO", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"SR", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"ST", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"SV", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"SZ", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"TC", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"TD", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"TF", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"TG", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"TH", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"TJ", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"TK", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"TL", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"TM", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"TN", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"TO", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"TR", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"TT", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"TV", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_ISLAND},
  {"TW", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_COUNTY},
  {"TZ", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"UA", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"UG", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"UM", IDS_AUTOFILL_DIALOG_ZIP_CODE,    IDS_AUTOFILL_DIALOG_STATE},
  {"US", IDS_AUTOFILL_DIALOG_ZIP_CODE,    IDS_AUTOFILL_DIALOG_STATE},
  {"UY", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"UZ", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"VA", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"VC", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"VE", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"VG", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"VI", IDS_AUTOFILL_DIALOG_ZIP_CODE,    IDS_AUTOFILL_DIALOG_STATE},
  {"VN", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"VU", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"WF", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"WS", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"YE", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"YT", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"ZA", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"ZM", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
  {"ZW", IDS_AUTOFILL_DIALOG_POSTAL_CODE, IDS_AUTOFILL_DIALOG_PROVINCE},
};

// A singleton class that encapsulates a map from country codes to country data.
class CountryDataMap {
 public:
  // A const iterator over the wrapped map data.
  typedef std::map<std::string, CountryData>::const_iterator Iterator;

  static CountryDataMap* GetInstance();
  static const Iterator Begin();
  static const Iterator End();
  static const Iterator Find(const std::string& country_code);

 private:
  CountryDataMap();
  friend struct DefaultSingletonTraits<CountryDataMap>;

  std::map<std::string, CountryData> country_data_;

  DISALLOW_COPY_AND_ASSIGN(CountryDataMap);
};

// static
CountryDataMap* CountryDataMap::GetInstance() {
  return Singleton<CountryDataMap>::get();
}

CountryDataMap::CountryDataMap() {
  // Add all the countries we have explicit data for.
  for (size_t i = 0; i < arraysize(kCountryData); ++i) {
    const CountryData& data = kCountryData[i];
    country_data_.insert(std::make_pair(data.country_code, data));
  }

  // Add any other countries that ICU knows about, falling back to default data
  // values.
  for (const char* const* country_pointer = icu::Locale::getISOCountries();
       *country_pointer;
       ++country_pointer) {
    std::string country_code = *country_pointer;
    if (!country_data_.count(country_code)) {
      CountryData data = {
        country_code,
        IDS_AUTOFILL_DIALOG_POSTAL_CODE,
        IDS_AUTOFILL_DIALOG_PROVINCE
      };
      country_data_.insert(std::make_pair(country_code, data));
    }
  }
}

const CountryDataMap::Iterator CountryDataMap::Begin() {
  return GetInstance()->country_data_.begin();
}

const CountryDataMap::Iterator CountryDataMap::End() {
  return GetInstance()->country_data_.end();
}

const CountryDataMap::Iterator CountryDataMap::Find(
    const std::string& country_code) {
  return GetInstance()->country_data_.find(country_code);
}

// A singleton class that encapsulates mappings from country names to their
// corresponding country codes.
class CountryNames {
 public:
  static CountryNames* GetInstance();

  // Returns the country code corresponding to |country|, which should be a
  // country code or country name localized to |locale|.
  const std::string GetCountryCode(const string16& country,
                                   const std::string& locale);

 private:
  CountryNames();
  ~CountryNames();
  friend struct DefaultSingletonTraits<CountryNames>;

  // Populates |locales_to_localized_names_| with the mapping of country names
  // localized to |locale| to their corresponding country codes.
  void AddLocalizedNamesForLocale(const std::string& locale);

  // Interprets |country_name| as a full country name localized to the given
  // |locale| and returns the corresponding country code stored in
  // |locales_to_localized_names_|, or an empty string if there is none.
  const std::string GetCountryCodeForLocalizedName(const string16& country_name,
                                                   const std::string& locale);

  // Returns an ICU collator -- i.e. string comparator -- appropriate for the
  // given |locale|.
  icu::Collator* GetCollatorForLocale(const std::string& locale);

  // Returns the ICU sort key corresponding to |str| for the given |collator|.
  // Uses |buffer| as temporary storage, and might resize |buffer| as a side-
  // effect. |buffer_size| should specify the |buffer|'s size, and is updated if
  // the |buffer| is resized.
  const std::string GetSortKey(const icu::Collator& collator,
                               const icu::UnicodeString& str,
                               scoped_array<uint8_t>* buffer,
                               int32_t* buffer_size) const;


  // Maps from common country names, including 2- and 3-letter country codes,
  // to the corresponding 2-letter country codes. The keys are uppercase ASCII
  // strings.
  std::map<std::string, std::string> common_names_;

  // The outer map keys are ICU locale identifiers.
  // The inner maps map from localized country names to their corresponding
  // country codes. The inner map keys are ICU collation sort keys corresponding
  // to the target localized country name.
  std::map<std::string, std::map<std::string, std::string> >
      locales_to_localized_names_;

  // Maps ICU locale names to their corresponding collators.
  std::map<std::string, icu::Collator*> collators_;

  DISALLOW_COPY_AND_ASSIGN(CountryNames);
};

// static
CountryNames* CountryNames::GetInstance() {
  return Singleton<CountryNames>::get();
}

CountryNames::CountryNames() {
  // Add 2- and 3-letter ISO country codes.
  for (CountryDataMap::Iterator it = CountryDataMap::Begin();
       it != CountryDataMap::End();
       ++it) {
    const std::string& country_code = it->first;
    std::string iso3_country_code =
    icu::Locale(NULL, country_code.c_str()).getISO3Country();

    common_names_.insert(std::make_pair(country_code, country_code));
    common_names_.insert(std::make_pair(iso3_country_code, country_code));
  }

  // Add a few other common synonyms.
  common_names_.insert(std::make_pair("UNITED STATES OF AMERICA", "US"));
  common_names_.insert(std::make_pair("GREAT BRITAIN", "GB"));
  common_names_.insert(std::make_pair("UK", "GB"));
  common_names_.insert(std::make_pair("BRASIL", "BR"));
  common_names_.insert(std::make_pair("DEUTSCHLAND", "DE"));
}

CountryNames::~CountryNames() {
  STLDeleteContainerPairSecondPointers(collators_.begin(),
                                       collators_.end());
}

const std::string CountryNames::GetCountryCode(const string16& country,
                                               const std::string& locale) {
  // First, check common country names, including 2- and 3-letter country codes.
  std::string country_utf8 = UTF16ToUTF8(StringToUpperASCII(country));
  std::map<std::string, std::string>::const_iterator result =
      common_names_.find(country_utf8);
  if (result != common_names_.end())
    return result->second;

  // Next, check country names localized to |locale|.
  std::string country_code = GetCountryCodeForLocalizedName(country, locale);
  if (!country_code.empty())
    return country_code;

  // Finally, check country names localized to US English.
  return GetCountryCodeForLocalizedName(country, "en_US");
}

void CountryNames::AddLocalizedNamesForLocale(const std::string& locale) {
  // Nothing to do if we've previously added the localized names for the given
  // |locale|.
  if (locales_to_localized_names_.count(locale))
    return;

  std::map<std::string, std::string> localized_names;

  icu::Locale icu_locale(locale.c_str());
  const icu::Collator* collator = GetCollatorForLocale(locale);

  int32_t buffer_size = 1000;
  scoped_array<uint8_t> buffer(new uint8_t[buffer_size]);

  for (CountryDataMap::Iterator it = CountryDataMap::Begin();
       it != CountryDataMap::End();
       ++it) {
    const std::string& country_code = it->first;

    icu::Locale country_locale(NULL, country_code.c_str());
    icu::UnicodeString country_name;
    country_locale.getDisplayName(icu_locale, country_name);
    std::string sort_key = GetSortKey(*collator,
                                      country_name,
                                      &buffer,
                                      &buffer_size);

    localized_names.insert(std::make_pair(sort_key, country_code));
  }

  locales_to_localized_names_.insert(std::make_pair(locale, localized_names));
}

const std::string CountryNames::GetCountryCodeForLocalizedName(
    const string16& country_name,
    const std::string& locale) {
  AddLocalizedNamesForLocale(locale);

  icu::Collator* collator = GetCollatorForLocale(locale);

  // As recommended[1] by ICU, initialize the buffer size to four times the
  // source string length.
  // [1] http://userguide.icu-project.org/collation/api#TOC-Examples
  int32_t buffer_size = country_name.size() * 4;
  scoped_array<uint8_t> buffer(new uint8_t[buffer_size]);
  std::string sort_key = GetSortKey(*collator,
                                    country_name.c_str(),
                                    &buffer,
                                    &buffer_size);

  const std::map<std::string, std::string>& localized_names =
      locales_to_localized_names_[locale];
  std::map<std::string, std::string>::const_iterator result =
      localized_names.find(sort_key);

  if (result != localized_names.end())
    return result->second;

  return std::string();
}

icu::Collator* CountryNames::GetCollatorForLocale(const std::string& locale) {
  if (!collators_.count(locale)) {
    icu::Locale icu_locale(locale.c_str());
    UErrorCode ignored = U_ZERO_ERROR;
    icu::Collator* collator(icu::Collator::createInstance(icu_locale, ignored));

    // Compare case-insensitively and ignoring punctuation.
    ignored = U_ZERO_ERROR;
    collator->setAttribute(UCOL_STRENGTH, UCOL_SECONDARY, ignored);
    ignored = U_ZERO_ERROR;
    collator->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, ignored);

    collators_.insert(std::make_pair(locale, collator));
  }

  return collators_[locale];
}

const std::string CountryNames::GetSortKey(const icu::Collator& collator,
                                           const icu::UnicodeString& str,
                                           scoped_array<uint8_t>* buffer,
                                           int32_t* buffer_size) const {
  DCHECK(buffer);
  DCHECK(buffer_size);

  int32_t expected_size = collator.getSortKey(str, buffer->get(), *buffer_size);
  if (expected_size > *buffer_size) {
    // If there wasn't enough space, grow the buffer and try again.
    *buffer_size = expected_size;
    buffer->reset(new uint8_t[*buffer_size]);
    DCHECK(buffer->get());

    expected_size = collator.getSortKey(str, buffer->get(), *buffer_size);
    DCHECK_EQ(*buffer_size, expected_size);
  }

  return std::string(reinterpret_cast<const char*>(buffer->get()));
}

// Returns the country name corresponding to |country_code|, localized to the
// |display_locale|.
string16 GetDisplayName(const std::string& country_code,
                        const icu::Locale& display_locale) {
  icu::Locale country_locale(NULL, country_code.c_str());
  icu::UnicodeString name;
  country_locale.getDisplayName(display_locale, name);

  DCHECK_GT(name.length(), 0);
  return string16(name.getBuffer(), name.length());
}

}  // namespace

AutofillCountry::AutofillCountry(const std::string& country_code,
                                 const std::string& locale) {
  const CountryDataMap::Iterator result = CountryDataMap::Find(country_code);
  DCHECK(result != CountryDataMap::End());
  const CountryData& data = result->second;

  country_code_ = country_code;
  name_ = GetDisplayName(country_code, icu::Locale(locale.c_str()));
  postal_code_label_ = l10n_util::GetStringUTF16(data.postal_code_label_id);
  state_label_ = l10n_util::GetStringUTF16(data.state_label_id);
}

AutofillCountry::~AutofillCountry() {
}

// static
void AutofillCountry::GetAvailableCountries(
    std::vector<std::string>* country_codes) {
  DCHECK(country_codes);

  for (CountryDataMap::Iterator it = CountryDataMap::Begin();
       it != CountryDataMap::End();
       ++it) {
    country_codes->push_back(it->first);
  }
}

// static
const std::string AutofillCountry::CountryCodeForLocale(
    const std::string& locale) {
  // Add likely subtags to the locale. In particular, add any likely country
  // subtags -- e.g. for locales like "ru" that only include the language.
  std::string likely_locale;
  UErrorCode error_ignored = U_ZERO_ERROR;
  uloc_addLikelySubtags(locale.c_str(),
                        WriteInto(&likely_locale, kLocaleCapacity),
                        kLocaleCapacity,
                        &error_ignored);

  // Extract the country code.
  std::string country_code = icu::Locale(likely_locale.c_str()).getCountry();

  // TODO(isherman): Return an empty string and update the clients instead.
  // Default to the United States if we have no better guess.
  if (CountryDataMap::Find(country_code) == CountryDataMap::End())
    return "US";

  return country_code;
}

// static
const std::string AutofillCountry::GetCountryCode(const string16& country,
                                                  const std::string& locale) {
  return CountryNames::GetInstance()->GetCountryCode(country, locale);
}

// static
const std::string AutofillCountry::ApplicationLocale() {
#ifdef ANDROID
  return l10n_util::GetApplicationLocale();
#else
  return g_browser_process->GetApplicationLocale();
#endif
}

AutofillCountry::AutofillCountry(const std::string& country_code,
                                 const string16& name,
                                 const string16& postal_code_label,
                                 const string16& state_label)
    : country_code_(country_code),
      name_(name),
      postal_code_label_(postal_code_label),
      state_label_(state_label) {
}