// 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) {
}