summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/android/java/org/chromium/base/LocaleUtils.java26
-rw-r--r--base/android/locale_utils.cc94
-rw-r--r--base/android/locale_utils.h29
-rw-r--r--base/base.gyp2
-rw-r--r--base/base.gypi3
-rw-r--r--build/all_android.gyp2
-rw-r--r--build/android/gtest_filter/ui_unittests_disabled2
-rw-r--r--chrome/browser/autofill/autofill_country.cc37
-rw-r--r--testing/android/native_test_launcher.cc2
-rw-r--r--ui/base/l10n/l10n_util.cc47
-rw-r--r--ui/base/l10n/l10n_util.h6
-rw-r--r--ui/base/l10n/l10n_util_unittest.cc21
-rw-r--r--ui/ui_unittests.gypi52
13 files changed, 282 insertions, 41 deletions
diff --git a/base/android/java/org/chromium/base/LocaleUtils.java b/base/android/java/org/chromium/base/LocaleUtils.java
new file mode 100644
index 0000000..6bca1f7
--- /dev/null
+++ b/base/android/java/org/chromium/base/LocaleUtils.java
@@ -0,0 +1,26 @@
+// Copyright (c) 2012 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.
+
+package org.chromium.base;
+
+import java.util.Locale;
+
+/**
+ * This class provides the locale related methods for the native library.
+ */
+class LocaleUtils {
+
+ private LocaleUtils() { /* cannot be instantiated */ }
+
+ /**
+ * @return the default locale.
+ */
+ @CalledByNative
+ public static String getDefaultLocale() {
+ Locale locale = Locale.getDefault();
+ String language = locale.getLanguage();
+ String country = locale.getCountry();
+ return country.isEmpty() ? language : language + "-" + country;
+ }
+}
diff --git a/base/android/locale_utils.cc b/base/android/locale_utils.cc
new file mode 100644
index 0000000..c2a88cf
--- /dev/null
+++ b/base/android/locale_utils.cc
@@ -0,0 +1,94 @@
+// Copyright (c) 2012 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 "base/android/locale_utils.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "jni/locale_utils_jni.h"
+#include "unicode/uloc.h"
+
+namespace base {
+namespace android {
+
+std::string GetDefaultLocale() {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jstring> locale = Java_LocaleUtils_getDefaultLocale(env);
+ return ConvertJavaStringToUTF8(locale);
+}
+
+namespace {
+
+// Common prototype of ICU uloc_getXXX() functions.
+typedef int32_t (*UlocGetComponentFunc)(const char*, char*, int32_t,
+ UErrorCode*);
+
+std::string GetLocaleComponent(const std::string& locale,
+ UlocGetComponentFunc uloc_func,
+ int32_t max_capacity) {
+ std::string result;
+ UErrorCode error = U_ZERO_ERROR;
+ int32_t actual_length = uloc_func(locale.c_str(),
+ WriteInto(&result, max_capacity),
+ max_capacity,
+ &error);
+ DCHECK(U_SUCCESS(error));
+ DCHECK(actual_length < max_capacity);
+ result.resize(actual_length);
+ return result;
+}
+
+ScopedJavaLocalRef<jobject> NewJavaLocale(
+ JNIEnv* env,
+ ScopedJavaLocalRef<jclass> locale_class,
+ jmethodID constructor_id,
+ const std::string& locale) {
+ // TODO(wangxianzhu): Use new Locale API once Android supports scripts.
+ std::string language = GetLocaleComponent(
+ locale, uloc_getLanguage, ULOC_LANG_CAPACITY);
+ std::string country = GetLocaleComponent(
+ locale, uloc_getCountry, ULOC_COUNTRY_CAPACITY);
+ std::string variant = GetLocaleComponent(
+ locale, uloc_getVariant, ULOC_FULLNAME_CAPACITY);
+ return ScopedJavaLocalRef<jobject>(
+ env, env->NewObject(
+ locale_class.obj(), constructor_id,
+ ConvertUTF8ToJavaString(env, language).obj(),
+ ConvertUTF8ToJavaString(env, country).obj(),
+ ConvertUTF8ToJavaString(env, variant).obj()));
+}
+
+} // namespace
+
+string16 GetDisplayNameForLocale(const std::string& locale,
+ const std::string& display_locale) {
+ JNIEnv* env = AttachCurrentThread();
+
+ ScopedJavaLocalRef<jclass> locale_class = GetClass(env, "java/util/Locale");
+ jmethodID constructor_id = GetMethodID(
+ env, locale_class, "<init>",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
+ ScopedJavaLocalRef<jobject> java_locale = NewJavaLocale(
+ env, locale_class, constructor_id, locale);
+ ScopedJavaLocalRef<jobject> java_display_locale = NewJavaLocale(
+ env, locale_class, constructor_id, display_locale);
+
+ jmethodID method_id = GetMethodID(env, locale_class, "getDisplayName",
+ "(Ljava/util/Locale;)Ljava/lang/String;");
+ ScopedJavaLocalRef<jstring> java_result(
+ env,
+ static_cast<jstring>(env->CallObjectMethod(java_locale.obj(), method_id,
+ java_display_locale.obj())));
+ return ConvertJavaStringToUTF16(java_result);
+}
+
+bool RegisterLocaleUtils(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+} // namespace android
+} // namespace base
diff --git a/base/android/locale_utils.h b/base/android/locale_utils.h
new file mode 100644
index 0000000..35d0015
--- /dev/null
+++ b/base/android/locale_utils.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2012 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 BASE_ANDROID_LOCALE_UTILS_H_
+#define BASE_ANDROID_LOCALE_UTILS_H_
+#pragma once
+
+#include <jni.h>
+
+#include <string>
+
+#include "base/string16.h"
+
+namespace base {
+namespace android {
+
+// Return the current default locale of the device.
+std::string GetDefaultLocale();
+
+string16 GetDisplayNameForLocale(const std::string& locale,
+ const std::string& display_locale);
+
+bool RegisterLocaleUtils(JNIEnv* env);
+
+} // namespace android
+} // namespace base
+
+#endif // BASE_ANDROID_LOCALE_UTILS_H_
diff --git a/base/base.gyp b/base/base.gyp
index e048d09..8de65df 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -538,11 +538,13 @@
'variables': {
'java_sources': [
'android/java/org/chromium/base/BuildInfo.java',
+ 'android/java/org/chromium/base/LocaleUtils.java',
'android/java/org/chromium/base/PathUtils.java',
'android/java/org/chromium/base/SystemMessageHandler.java',
],
'jni_headers': [
'<(SHARED_INTERMEDIATE_DIR)/base/jni/build_info_jni.h',
+ '<(SHARED_INTERMEDIATE_DIR)/base/jni/locale_utils_jni.h',
'<(SHARED_INTERMEDIATE_DIR)/base/jni/path_utils_jni.h',
'<(SHARED_INTERMEDIATE_DIR)/base/jni/system_message_handler_jni.h',
],
diff --git a/base/base.gypi b/base/base.gypi
index 4c96ebd..c19658f 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -39,6 +39,8 @@
'android/jni_registrar.h',
'android/jni_string.cc',
'android/jni_string.h',
+ 'android/locale_utils.cc',
+ 'android/locale_utils.h',
'android/path_utils.cc',
'android/path_utils.h',
'at_exit.cc',
@@ -696,6 +698,7 @@
'dependencies': [
'symbolize',
'../third_party/ashmem/ashmem.gyp:ashmem',
+ '../third_party/icu/icu.gyp:icuuc',
'base_java',
'base_jni_headers',
],
diff --git a/build/all_android.gyp b/build/all_android.gyp
index 424425a..ad99339 100644
--- a/build/all_android.gyp
+++ b/build/all_android.gyp
@@ -60,6 +60,7 @@
# Unit test bundles packaged as an apk.
'../base/base.gyp:base_unittests_apk',
'../ipc/ipc.gyp:ipc_tests_apk',
+ '../ui/ui.gyp:ui_unittests_apk',
],
}]
],
@@ -81,7 +82,6 @@
'type': 'none',
'dependencies': [
'../content/content.gyp:content_browsertests',
- '../ui/ui.gyp:gfx_unittests',
],
},
], # targets
diff --git a/build/android/gtest_filter/ui_unittests_disabled b/build/android/gtest_filter/ui_unittests_disabled
index 4f4406f..f0a6c2b 100644
--- a/build/android/gtest_filter/ui_unittests_disabled
+++ b/build/android/gtest_filter/ui_unittests_disabled
@@ -41,6 +41,8 @@ ImageTest.SkiaToSkia
ImageTest.SkiaToSkiaRef
ImageTest.SwapRepresentations
L10nUtilTest.GetAppLocale
+L10nUtilTest.GetDisplayNameForCountry
+L10nUtilTest.GetDisplayNameForLocale
TextEliderTest.ElideEmail
TextEliderTest.ElideEmailMoreSpace
TextEliderTest.ElideRectangleText
diff --git a/chrome/browser/autofill/autofill_country.cc b/chrome/browser/autofill/autofill_country.cc
index 4a83bd0..2dea6af 100644
--- a/chrome/browser/autofill/autofill_country.cc
+++ b/chrome/browser/autofill/autofill_country.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -390,7 +390,7 @@ class CountryNames {
// 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,
+ const string16& str,
scoped_array<uint8_t>* buffer,
int32_t* buffer_size) const;
@@ -482,10 +482,7 @@ void CountryNames::AddLocalizedNamesForLocale(const std::string& 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]);
@@ -493,10 +490,8 @@ void CountryNames::AddLocalizedNamesForLocale(const std::string& locale) {
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);
+ string16 country_name = l10n_util::GetDisplayNameForCountry(country_code,
+ locale);
std::string sort_key = GetSortKey(*collator,
country_name,
&buffer,
@@ -521,7 +516,7 @@ const std::string CountryNames::GetCountryCodeForLocalizedName(
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(),
+ country_name,
&buffer,
&buffer_size);
@@ -555,38 +550,28 @@ icu::Collator* CountryNames::GetCollatorForLocale(const std::string& locale) {
}
const std::string CountryNames::GetSortKey(const icu::Collator& collator,
- const icu::UnicodeString& str,
+ const string16& 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);
+ icu::UnicodeString icu_str(str.c_str(), str.length());
+ int32_t expected_size = collator.getSortKey(icu_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);
+ expected_size = collator.getSortKey(icu_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,
@@ -596,7 +581,7 @@ AutofillCountry::AutofillCountry(const std::string& country_code,
const CountryData& data = result->second;
country_code_ = country_code;
- name_ = GetDisplayName(country_code, icu::Locale(locale.c_str()));
+ name_ = l10n_util::GetDisplayNameForCountry(country_code, locale);
postal_code_label_ = l10n_util::GetStringUTF16(data.postal_code_label_id);
state_label_ = l10n_util::GetStringUTF16(data.state_label_id);
}
diff --git a/testing/android/native_test_launcher.cc b/testing/android/native_test_launcher.cc
index 1555fbe..5e600b8 100644
--- a/testing/android/native_test_launcher.cc
+++ b/testing/android/native_test_launcher.cc
@@ -6,6 +6,7 @@
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
+#include "base/android/locale_utils.h"
#include "base/android/path_utils.h"
#include "base/android/scoped_java_ref.h"
#include "base/at_exit.h"
@@ -150,6 +151,7 @@ void LibraryLoadedOnMainThread(JNIEnv* env) {
false); // Tick count
VLOG(0) << "Chromium logging enabled: level = " << logging::GetMinLogLevel()
<< ", default verbosity = " << logging::GetVlogVerbosity();
+ base::android::RegisterLocaleUtils(env);
base::android::RegisterPathUtils(env);
}
diff --git a/ui/base/l10n/l10n_util.cc b/ui/base/l10n/l10n_util.cc
index 6cf4608..f6c1b32 100644
--- a/ui/base/l10n/l10n_util.cc
+++ b/ui/base/l10n/l10n_util.cc
@@ -27,6 +27,10 @@
#include "unicode/rbbi.h"
#include "unicode/uloc.h"
+#if defined(OS_ANDROID)
+#include "base/android/locale_utils.h"
+#endif
+
#if defined(OS_LINUX)
#include <glib.h>
#endif
@@ -474,26 +478,49 @@ string16 GetDisplayNameForLocale(const std::string& locale,
// #1 and #2 wouldn't work if display_locale != current UI locale although
// we can think of additional hack to work around the problem.
// #3 can be potentially expensive.
- if (locale_code == "zh-CN")
+ bool is_zh = false;
+ if (locale_code == "zh-CN") {
locale_code = "zh-Hans";
- else if (locale_code == "zh-TW")
+ is_zh = true;
+ } else if (locale_code == "zh-TW") {
locale_code = "zh-Hant";
-
- UErrorCode error = U_ZERO_ERROR;
- const int kBufferSize = 1024;
+ is_zh = true;
+ }
string16 display_name;
- int actual_size = uloc_getDisplayName(locale_code.c_str(),
- display_locale.c_str(),
- WriteInto(&display_name, kBufferSize), kBufferSize - 1, &error);
- DCHECK(U_SUCCESS(error));
- display_name.resize(actual_size);
+#if defined(OS_ANDROID)
+ // Use Java API to get locale display name so that we can remove most of
+ // the lang data from icu data to reduce binary size, except for zh-Hans and
+ // zh-Hant because the current Android Java API doesn't support scripts.
+ // TODO(wangxianzhu): remove the special handling of zh-Hans and zh-Hant once
+ // Android Java API supports scripts.
+ if (!is_zh) {
+ display_name = base::android::GetDisplayNameForLocale(locale_code,
+ display_locale);
+ } else
+#endif
+ {
+ UErrorCode error = U_ZERO_ERROR;
+ const int kBufferSize = 1024;
+
+ int actual_size = uloc_getDisplayName(locale_code.c_str(),
+ display_locale.c_str(),
+ WriteInto(&display_name, kBufferSize), kBufferSize - 1, &error);
+ DCHECK(U_SUCCESS(error));
+ display_name.resize(actual_size);
+ }
+
// Add an RTL mark so parentheses are properly placed.
if (is_for_ui && base::i18n::IsRTL())
display_name.push_back(static_cast<char16>(base::i18n::kRightToLeftMark));
return display_name;
}
+string16 GetDisplayNameForCountry(const std::string& country_code,
+ const std::string& display_locale) {
+ return GetDisplayNameForLocale("_" + country_code, display_locale, false);
+}
+
std::string NormalizeLocale(const std::string& locale) {
std::string normalized_locale(locale);
std::replace(normalized_locale.begin(), normalized_locale.end(), '-', '_');
diff --git a/ui/base/l10n/l10n_util.h b/ui/base/l10n/l10n_util.h
index 48ec68a..2eae6de 100644
--- a/ui/base/l10n/l10n_util.h
+++ b/ui/base/l10n/l10n_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -51,6 +51,10 @@ UI_EXPORT string16 GetDisplayNameForLocale(const std::string& locale,
const std::string& display_locale,
bool is_for_ui);
+// Returns the display name of the |country_code| in |display_locale|.
+UI_EXPORT string16 GetDisplayNameForCountry(const std::string& country_code,
+ const std::string& display_locale);
+
// Converts all - into _, to be consistent with ICU and file system names.
UI_EXPORT std::string NormalizeLocale(const std::string& locale);
diff --git a/ui/base/l10n/l10n_util_unittest.cc b/ui/base/l10n/l10n_util_unittest.cc
index 971d7ce..a9b51fd 100644
--- a/ui/base/l10n/l10n_util_unittest.cc
+++ b/ui/base/l10n/l10n_util_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -303,7 +303,7 @@ TEST_F(L10nUtilTest, SortStringsUsingFunction) {
STLDeleteElements(&strings);
}
-TEST_F(L10nUtilTest, LocaleDisplayName) {
+TEST_F(L10nUtilTest, GetDisplayNameForLocale) {
// TODO(jungshik): Make this test more extensive.
// Test zh-CN and zh-TW are treated as zh-Hans and zh-Hant.
string16 result = l10n_util::GetDisplayNameForLocale("zh-CN", "en", false);
@@ -318,6 +318,12 @@ TEST_F(L10nUtilTest, LocaleDisplayName) {
result = l10n_util::GetDisplayNameForLocale("es-419", "en", false);
EXPECT_EQ(ASCIIToUTF16("Spanish (Latin America)"), result);
+ result = l10n_util::GetDisplayNameForLocale("-BR", "en", false);
+ EXPECT_EQ(ASCIIToUTF16("Brazil"), result);
+
+ result = l10n_util::GetDisplayNameForLocale("xyz-xyz", "en", false);
+ EXPECT_EQ(ASCIIToUTF16("xyz (XYZ)"), result);
+
// ToUpper and ToLower should work with embedded NULLs.
const size_t length_with_null = 4;
char16 buf_with_null[length_with_null] = { 0, 'a', 0, 'b' };
@@ -334,6 +340,17 @@ TEST_F(L10nUtilTest, LocaleDisplayName) {
lower_with_null[2] == 0 && lower_with_null[3] == 'b');
}
+TEST_F(L10nUtilTest, GetDisplayNameForCountry) {
+ string16 result = l10n_util::GetDisplayNameForCountry("BR", "en");
+ EXPECT_EQ(ASCIIToUTF16("Brazil"), result);
+
+ result = l10n_util::GetDisplayNameForCountry("419", "en");
+ EXPECT_EQ(ASCIIToUTF16("Latin America"), result);
+
+ result = l10n_util::GetDisplayNameForCountry("xyz", "en");
+ EXPECT_EQ(ASCIIToUTF16("XYZ"), result);
+}
+
TEST_F(L10nUtilTest, GetParentLocales) {
std::vector<std::string> locales;
const std::string top_locale("sr_Cyrl_RS");
diff --git a/ui/ui_unittests.gypi b/ui/ui_unittests.gypi
index 77965dc..1b68db7 100644
--- a/ui/ui_unittests.gypi
+++ b/ui/ui_unittests.gypi
@@ -29,7 +29,7 @@
},
{
'target_name': 'ui_unittests',
- 'type': 'executable',
+ 'type': '<(gtest_target_type)',
'includes': [
'base/ime/ime_unittests.gypi',
],
@@ -154,6 +154,11 @@
'gfx/interpolated_transform_unittest.cc',
],
}],
+ ['OS=="android" and "<(gtest_target_type)"=="shared_library"', {
+ 'dependencies': [
+ '../testing/android/native_test.gyp:native_test_native_code',
+ ],
+ }],
['use_glib == 1', {
'dependencies': [
'../build/linux/system.gyp:pangocairo',
@@ -206,4 +211,49 @@
],
},
],
+ 'conditions': [
+ # Special target to wrap a <(gtest_target_type)==shared_library
+ # ui_unittests into an android apk for execution.
+ # See base.gyp for TODO(jrg)s about this strategy.
+ ['OS=="android" and "<(gtest_target_type)"=="shared_library"', {
+ 'targets': [
+ {
+ 'target_name': 'ui_unittests_apk',
+ 'type': 'none',
+ 'dependencies': [
+ 'ui_unittests',
+ ],
+ 'actions': [
+ {
+ # Generate apk files (including source and antfile) from
+ # a template, and builds them.
+ 'action_name': 'generate_and_build',
+ 'inputs': [
+ '../testing/android/generate_native_test.py',
+ '<(PRODUCT_DIR)/lib.target/libui_unittests.so',
+ '<(PRODUCT_DIR)/chromium_base.jar',
+ ],
+ 'outputs': [
+ '<(PRODUCT_DIR)/ChromeNativeTests_ui_unittests-debug.apk',
+ ],
+ 'action': [
+ '../testing/android/generate_native_test.py',
+ '--native_library',
+ '<(PRODUCT_DIR)/lib.target/libui_unittests.so',
+ # TODO(jrg): find a better way to specify jar
+ # dependencies. Hard coding seems fragile.
+ '--jar',
+ '<(PRODUCT_DIR)/chromium_base.jar',
+ '--output',
+ '<(PRODUCT_DIR)/ui_unittests_apk',
+ '--ant-args',
+ '-DPRODUCT_DIR=<(PRODUCT_DIR)',
+ '--ant-compile'
+ ],
+ },
+ ]
+ },
+ ],
+ }],
+ ],
}