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

Unified Diff: components/autofill/core/browser/country_names.cc

Issue 1582353006: CountryNames: Separate data creation from usage (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@571610_exposeCountryNamesToTesting
Patch Set: More Android fixes Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/autofill/core/browser/country_names.cc
diff --git a/components/autofill/core/browser/country_names.cc b/components/autofill/core/browser/country_names.cc
index ce94dbb1591661fa3b576c383c47c73ca5b5d26d..d2370803db5089e93cadc1012768c82bc72d7ac6 100644
--- a/components/autofill/core/browser/country_names.cc
+++ b/components/autofill/core/browser/country_names.cc
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <utility>
+#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
@@ -21,6 +22,11 @@
namespace autofill {
namespace {
+// A copy of the application locale string, which should be ready for
+// CountryName's construction.
+static base::LazyInstance<std::string> g_application_locale =
+ LAZY_INSTANCE_INITIALIZER;
+
// 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
@@ -74,19 +80,103 @@ std::map<std::string, std::string> GetCommonNames() {
return common_names;
}
+// Creates collator for |locale| and sets its attributes as needed.
+scoped_ptr<icu::Collator> CreateCollator(const icu::Locale& locale) {
+ scoped_ptr<icu::Collator> collator(
+ autofill::l10n::GetCollatorForLocale(locale));
+ if (!collator)
+ return nullptr;
+
+ // Compare case-insensitively and ignoring punctuation.
+ UErrorCode ignored = U_ZERO_ERROR;
+ collator->setAttribute(UCOL_STRENGTH, UCOL_SECONDARY, ignored);
+ ignored = U_ZERO_ERROR;
+ collator->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, ignored);
+
+ return collator;
+}
+
+// If |locale| is different from "en_US", returns a collator for "en_US" and
+// sets its attributes as appropriate. Otherwise returns null.
+scoped_ptr<icu::Collator> CreateDefaultCollator(const icu::Locale& locale) {
+ icu::Locale default_locale("en_US");
+
+ if (default_locale != locale)
+ return CreateCollator(default_locale);
+
+ return nullptr;
+}
+
+// Returns the mapping of country names localized to |locale| to their
+// corresponding country codes. The provided |collator| should be suitable for
+// the locale. The collator being null is handled gracefully by returning an
+// empty string, to account for the very rare cases when the collator fails to
Ilya Sherman 2016/01/21 02:07:56 nit: s/string/map
vabr (Chromium) 2016/01/22 17:36:42 Done.
+// initialize.
+std::map<std::string, std::string> GetLocalizedNames(
+ const std::string& locale,
+ const icu::Collator* collator) {
+ if (!collator)
+ return std::map<std::string, std::string>();
+
+ std::map<std::string, std::string> localized_names;
+ int32_t buffer_size = 1000;
+ scoped_ptr<uint8_t[]> buffer(new uint8_t[buffer_size]);
+
+ for (const std::string& country_code :
+ CountryDataMap::GetInstance()->country_codes()) {
+ base::string16 country_name =
+ l10n_util::GetDisplayNameForCountry(country_code, locale);
+ std::string sort_key =
+ GetSortKey(*collator, country_name, &buffer, &buffer_size);
+
+ localized_names.insert(std::make_pair(sort_key, country_code));
+ }
+ return localized_names;
+}
+
+// If |locale| represents a different locale than "en_US", returns
+// GetLocalizedNames("en_US", collator). Otherwise returns an empty map.
+std::map<std::string, std::string> GetDefaultLocalizedNames(
+ const std::string& locale,
+ const icu::Collator* collator) {
+ icu::Locale locale_object(locale.c_str());
+ icu::Locale default_locale("en_US");
+
+ if (default_locale != locale_object)
Ilya Sherman 2016/01/21 02:07:56 If you pass the default_collotor_ into this method
vabr (Chromium) 2016/01/22 17:36:41 You are correct, thanks for catching this! Removed
+ return GetLocalizedNames("en_US", collator);
+
+ return std::map<std::string, std::string>();
+}
+
} // namespace
+void SetLocaleString(std::string locale) {
+ static bool initialized = false;
+ if (!initialized) {
+ initialized = true;
+ g_application_locale.Get() = std::move(locale);
+ }
Ilya Sherman 2016/01/21 02:07:56 I think it would be good to DCHECK that the locale
Ilya Sherman 2016/01/21 02:07:56 Tracking |initialized| here seems not necessary --
vabr (Chromium) 2016/01/22 17:36:42 I'm not sure how to do that. LazyInstance does not
vabr (Chromium) 2016/01/22 17:36:42 So apparently, Chrome might be expected to be able
+}
+
// static
CountryNames* CountryNames::GetInstance() {
return base::Singleton<CountryNames>::get();
}
-CountryNames::CountryNames() : common_names_(GetCommonNames()) {}
+CountryNames::CountryNames(const std::string& locale_name)
+ : locale_(locale_name.c_str()),
+ collator_(CreateCollator(locale_)),
+ default_collator_(CreateDefaultCollator(locale_)),
+ common_names_(GetCommonNames()),
+ localized_names_(GetLocalizedNames(locale_name, collator_.get())),
+ default_localized_names_(
+ GetDefaultLocalizedNames(locale_name, collator_.get())) {}
Ilya Sherman 2016/01/21 02:07:56 Why doesn't this use the default_collator_?
vabr (Chromium) 2016/01/22 17:36:41 I got myself confused with all the default stuff,
+
+CountryNames::CountryNames() : CountryNames(g_application_locale.Get()) {}
Ilya Sherman 2016/01/21 02:07:56 Please DCHECK that g_application_locale is non-emp
vabr (Chromium) 2016/01/22 17:36:42 Done.
CountryNames::~CountryNames() = default;
-const std::string CountryNames::GetCountryCode(const base::string16& country,
- const std::string& locale_name) {
+const std::string CountryNames::GetCountryCode(const base::string16& country) {
// First, check common country names, including 2- and 3-letter country codes.
std::string country_utf8 = base::UTF16ToUTF8(base::ToUpperASCII(country));
const auto result = common_names_.find(country_utf8);
@@ -94,66 +184,35 @@ const std::string CountryNames::GetCountryCode(const base::string16& country,
return result->second;
// Next, check country names localized to the current locale.
- icu::Locale locale(locale_name.c_str());
- std::string country_code = GetCountryCodeForLocalizedName(country, locale);
+ std::string country_code =
+ GetCountryCodeForLocalizedName(country, localized_names_, *collator_);
if (!country_code.empty())
return country_code;
icu::Locale default_locale("en_US");
// Finally, check country names localized to US English, unless done already.
- if (default_locale != locale)
- return GetCountryCodeForLocalizedName(country, default_locale);
-
- return std::string();
-}
-
-void CountryNames::AddLocalizedNamesForLocale(const std::string& locale,
- const icu::Collator& collator) {
- // 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;
- int32_t buffer_size = 1000;
- scoped_ptr<uint8_t[]> buffer(new uint8_t[buffer_size]);
-
- for (const std::string& country_code :
- CountryDataMap::GetInstance()->country_codes()) {
- base::string16 country_name =
- l10n_util::GetDisplayNameForCountry(country_code, locale);
- std::string sort_key =
- GetSortKey(collator, country_name, &buffer, &buffer_size);
-
- localized_names.insert(std::make_pair(sort_key, country_code));
+ if (default_locale != locale_) {
+ DCHECK(default_collator_);
Ilya Sherman 2016/01/21 02:07:56 nit: You could just write "if (default_collator_)"
vabr (Chromium) 2016/01/22 17:36:42 Done.
+ return GetCountryCodeForLocalizedName(country, default_localized_names_,
+ *default_collator_);
}
- locales_to_localized_names_.insert(std::make_pair(locale, localized_names));
+ return std::string();
}
const std::string CountryNames::GetCountryCodeForLocalizedName(
const base::string16& country_name,
- const icu::Locale& locale) {
- const icu::Collator* collator = GetCollatorForLocale(locale);
- // In very rare cases, the collator fails to initialize.
- if (!collator)
- return std::string();
-
- std::string locale_name = locale.getName();
- AddLocalizedNamesForLocale(locale_name, *collator);
-
+ const std::map<std::string, std::string>& localized_names,
+ const icu::Collator& collator) {
// 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_ptr<uint8_t[]> buffer(new uint8_t[buffer_size]);
std::string sort_key =
- GetSortKey(*collator, country_name, &buffer, &buffer_size);
+ GetSortKey(collator, country_name, &buffer, &buffer_size);
- const std::map<std::string, std::string>& localized_names =
- locales_to_localized_names_[locale_name];
- std::map<std::string, std::string>::const_iterator result =
- localized_names.find(sort_key);
+ auto result = localized_names.find(sort_key);
if (result != localized_names.end())
return result->second;
@@ -161,25 +220,4 @@ const std::string CountryNames::GetCountryCodeForLocalizedName(
return std::string();
}
-const icu::Collator* CountryNames::GetCollatorForLocale(
- const icu::Locale& locale) {
- std::string locale_name = locale.getName();
- if (!ContainsKey(collators_, locale_name)) {
- scoped_ptr<icu::Collator> collator(
- autofill::l10n::GetCollatorForLocale(locale));
- if (!collator)
- return nullptr;
-
- // Compare case-insensitively and ignoring punctuation.
- UErrorCode ignored = U_ZERO_ERROR;
- collator->setAttribute(UCOL_STRENGTH, UCOL_SECONDARY, ignored);
- ignored = U_ZERO_ERROR;
- collator->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, ignored);
-
- collators_[locale_name] = std::move(collator);
- }
-
- return collators_[locale_name].get();
-}
-
} // namespace autofill

Powered by Google App Engine
This is Rietveld 408576698