Bug 1337078 - Improve the use of Android API in OSPreferences; r?jchen draft
authorbrainbreaker <gautamprajapati06@gmail.com>
Mon, 22 May 2017 21:11:44 +0530
changeset 582448 9c753ffe728748b4efbddbe6185b5b5a1083b9bb
parent 582447 8f4d2d35cb317235f30f4e3738ad3df16d2f9f3f
child 629774 1838180ffa4c1872b75c6bada1dff75fa43c6e65
push id60087
push userbmo:gautamprajapati06@gmail.com
push dateMon, 22 May 2017 15:55:18 +0000
reviewersjchen
bugs1337078
milestone55.0a1
Bug 1337078 - Improve the use of Android API in OSPreferences; r?jchen MozReview-Commit-ID: GWSjP5bUquE
intl/locale/android/OSPreferences_android.cpp
mobile/android/base/java/org/mozilla/gecko/Locales.java
widget/android/GeneratedJNIWrappers.cpp
widget/android/GeneratedJNIWrappers.h
widget/android/bindings/Locale-classes.txt
widget/android/bindings/moz.build
--- a/intl/locale/android/OSPreferences_android.cpp
+++ b/intl/locale/android/OSPreferences_android.cpp
@@ -1,36 +1,42 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "OSPreferences.h"
 #include "mozilla/Preferences.h"
+#include "GeneratedJNIWrappers.h"
+#include "Locale.h"
 
 using namespace mozilla::intl;
 
-bool
-OSPreferences::ReadSystemLocales(nsTArray<nsCString>& aLocaleList)
+if (!jni::IsAvailable()) {
+   return false;
+}
+
+bool OSPreferences::ReadSystemLocales(nsTArray<nsCString>& aLocaleList)
 {
-  //XXX: This is a quite sizable hack to work around the fact that we cannot
-  //     retrieve OS locale in C++ without reaching out to JNI.
-  //     Once we fix this (bug 1337078), this hack should not be necessary.
-  //
-  //XXX: Notice, this value may be empty on an early read. In that case
-  //     we won't add anything to the return list so that it doesn't get
-  //     cached in mSystemLocales.
-  nsAdoptingCString locale = Preferences::GetCString("intl.locale.os");
-  if (!locale.IsEmpty()) {
-    aLocaleList.AppendElement(locale);
+  namespace jni = mozilla::jni;
+  namespace java = mozilla::java;
+
+  // Call Locale.getDefault to get the default locale
+  java::sdk::Locale::LocalRef locale;
+  NS_ENSURE_SUCCESS(java::sdk::Locale::GetDefault(&locale), false);
+
+  // Call Locales.getLanguage to get the language string from locale.
+  nsCString language = java::Locales::GetLanguage(locale)->ToCString();
+
+  if (!language.IsEmpty()) {
+    aLocaleList.AppendElement(language);
     return true;
   }
   return false;
 }
 
-bool
-OSPreferences::ReadDateTimePattern(DateTimeFormatStyle aDateStyle,
+bool OSPreferences::ReadDateTimePattern(DateTimeFormatStyle aDateStyle,
                                    DateTimeFormatStyle aTimeStyle,
                                    const nsACString& aLocale, nsAString& aRetVal)
 {
   return false;
 }
--- a/mobile/android/base/java/org/mozilla/gecko/Locales.java
+++ b/mobile/android/base/java/org/mozilla/gecko/Locales.java
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko;
 
 import java.lang.reflect.Method;
 import java.util.Locale;
 
 import org.mozilla.gecko.LocaleManager;
+import org.mozilla.gecko.annotation.WrapForJNI;
 
 import android.app.Activity;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.StrictMode;
 import android.support.v4.app.FragmentActivity;
 import android.support.v7.app.AppCompatActivity;
 
@@ -76,16 +77,17 @@ public class Locales {
      * Sometimes we want just the language for a locale, not the entire language
      * tag. But Java's .getLanguage method is wrong.
      *
      * This method is equivalent to the first part of
      * {@link Locales#getLanguageTag(Locale)}.
      *
      * @return a language string, such as "he" for the Hebrew locales.
      */
+    @WrapForJNI(calledFrom = "gecko")
     public static String getLanguage(final Locale locale) {
         // Can, but should never be, an empty string.
         final String language = locale.getLanguage();
 
         // Modernize certain language codes.
         if (language.equals("iw")) {
             return "he";
         }
--- a/widget/android/GeneratedJNIWrappers.cpp
+++ b/widget/android/GeneratedJNIWrappers.cpp
@@ -948,16 +948,27 @@ constexpr char GeckoView::Window::Reatta
 constexpr char GeckoView::Window::SetState_t::name[];
 constexpr char GeckoView::Window::SetState_t::signature[];
 
 auto GeckoView::Window::SetState(mozilla::jni::Object::Param a0) const -> void
 {
     return mozilla::jni::Method<SetState_t>::Call(Window::mCtx, nullptr, a0);
 }
 
+const char Locales::name[] =
+        "org/mozilla/gecko/Locales";
+
+constexpr char Locales::GetLanguage_t::name[];
+constexpr char Locales::GetLanguage_t::signature[];
+
+auto Locales::GetLanguage(mozilla::jni::Object::Param a0) -> mozilla::jni::String::LocalRef
+{
+    return mozilla::jni::Method<GetLanguage_t>::Call(Locales::Context(), nullptr, a0);
+}
+
 const char PrefsHelper::name[] =
         "org/mozilla/gecko/PrefsHelper";
 
 constexpr char PrefsHelper::CallPrefHandler_t::name[];
 constexpr char PrefsHelper::CallPrefHandler_t::signature[];
 
 auto PrefsHelper::CallPrefHandler(mozilla::jni::Object::Param a0, int32_t a1, mozilla::jni::String::Param a2, bool a3, int32_t a4, mozilla::jni::String::Param a5) -> void
 {
--- a/widget/android/GeneratedJNIWrappers.h
+++ b/widget/android/GeneratedJNIWrappers.h
@@ -2914,16 +2914,48 @@ public:
     auto SetState(mozilla::jni::Object::Param) const -> void;
 
     static const mozilla::jni::CallingThread callingThread =
             mozilla::jni::CallingThread::ANY;
 
     template<class Impl> class Natives;
 };
 
+class Locales : public mozilla::jni::ObjectBase<Locales>
+{
+public:
+    static const char name[];
+
+    explicit Locales(const Context& ctx) : ObjectBase<Locales>(ctx) {}
+
+    struct GetLanguage_t {
+        typedef Locales Owner;
+        typedef mozilla::jni::String::LocalRef ReturnType;
+        typedef mozilla::jni::String::Param SetterType;
+        typedef mozilla::jni::Args<
+                mozilla::jni::Object::Param> Args;
+        static constexpr char name[] = "getLanguage";
+        static constexpr char signature[] =
+                "(Ljava/util/Locale;)Ljava/lang/String;";
+        static const bool isStatic = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+        static const mozilla::jni::CallingThread callingThread =
+                mozilla::jni::CallingThread::GECKO;
+        static const mozilla::jni::DispatchTarget dispatchTarget =
+                mozilla::jni::DispatchTarget::CURRENT;
+    };
+
+    static auto GetLanguage(mozilla::jni::Object::Param) -> mozilla::jni::String::LocalRef;
+
+    static const mozilla::jni::CallingThread callingThread =
+            mozilla::jni::CallingThread::GECKO;
+
+};
+
 class PrefsHelper : public mozilla::jni::ObjectBase<PrefsHelper>
 {
 public:
     static const char name[];
 
     explicit PrefsHelper(const Context& ctx) : ObjectBase<PrefsHelper>(ctx) {}
 
     struct CallPrefHandler_t {
new file mode 100644
--- /dev/null
+++ b/widget/android/bindings/Locale-classes.txt
@@ -0,0 +1,1 @@
+[java.util.Locale = exceptionMode:nsresult]
\ No newline at end of file
--- a/widget/android/bindings/moz.build
+++ b/widget/android/bindings/moz.build
@@ -8,16 +8,17 @@ with Files("**"):
     BUG_COMPONENT = ("Firefox for Android", "Graphics, Panning and Zooming")
 
 # List of stems to generate .cpp and .h files for.  To add a stem, add it to
 # this list and ensure that $(stem)-classes.txt exists in this directory.
 generated = [
     'AndroidBuild',
     'AndroidRect',
     'KeyEvent',
+    'Locale',
     'MediaCodec',
     'MotionEvent',
     'SurfaceTexture',
     'ViewConfiguration'
 ]
 
 SOURCES += ['!%s.cpp' % stem for stem in generated]