Bug 1337078 - Improve the use of Android API in OSPreferences r=snorp

Add BrowserLocaleManager.refreshLocales, a native function which calls OSPreferences::Refresh, and BrowserLocaleManager.getLocale, which returns the current locale string. Use these in place of observing modification of the intl.locale.os pref.
This commit is contained in:
Dylan Roeh 2017-11-10 09:20:04 -06:00
parent bbddef77bd
commit ebd39f9ce0
10 changed files with 158 additions and 20 deletions

View File

@ -24,14 +24,9 @@
#define MATCH_OS_LOCALE_PREF "intl.locale.matchOS"
#define SELECTED_LOCALE_PREF "general.useragent.locale"
//XXX: This pref is used only by Android and we use it to emulate
// retrieving OS locale until we get proper hook into JNI in bug 1337078.
#define ANDROID_OS_LOCALE_PREF "intl.locale.os"
static const char* kObservedPrefs[] = {
MATCH_OS_LOCALE_PREF,
SELECTED_LOCALE_PREF,
ANDROID_OS_LOCALE_PREF,
nullptr
};
@ -575,16 +570,10 @@ LocaleService::Observe(nsISupports *aSubject, const char *aTopic,
RequestedLocalesChanged();
} else {
NS_ConvertUTF16toUTF8 pref(aData);
// This is a temporary solution until we get bug 1337078 landed.
if (pref.EqualsLiteral(ANDROID_OS_LOCALE_PREF)) {
OSPreferences::GetInstance()->Refresh();
}
// At the moment the only thing we're observing are settings indicating
// user requested locales.
if (pref.EqualsLiteral(MATCH_OS_LOCALE_PREF) ||
pref.EqualsLiteral(SELECTED_LOCALE_PREF) ||
pref.EqualsLiteral(ANDROID_OS_LOCALE_PREF)) {
pref.EqualsLiteral(SELECTED_LOCALE_PREF)) {
RequestedLocalesChanged();
}
}

View File

@ -7,22 +7,25 @@
#include "OSPreferences.h"
#include "mozilla/Preferences.h"
#include "FennecJNIWrappers.h"
#include "GeneratedJNIWrappers.h"
using namespace mozilla::intl;
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.
//
if (!mozilla::jni::IsAvailable()) {
return false;
}
//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.
nsAutoCString locale;
Preferences::GetCString("intl.locale.os", locale);
if (!locale.IsEmpty()) {
aLocaleList.AppendElement(locale);
auto locale = mozilla::jni::IsFennec() ? java::BrowserLocaleManager::GetLocale() :
java::GeckoAppShell::GetDefaultLocale();
if (locale) {
aLocaleList.AppendElement(locale->ToCString());
return true;
}
return false;

View File

@ -17,6 +17,7 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.gecko.annotation.ReflectionTarget;
import org.mozilla.gecko.annotation.WrapForJNI;
import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.gecko.util.GeckoJarReader;
@ -225,6 +226,12 @@ public class BrowserLocaleManager implements LocaleManager {
data.putString("languageTag", Locales.getLanguageTag(osLocale));
EventDispatcher.getInstance().dispatch("Locale:OS", data);
if (GeckoThread.isRunning()) {
refreshLocales();
} else {
GeckoThread.queueNativeCall(BrowserLocaleManager.class, "refreshLocales");
}
}
@Override
@ -451,4 +458,18 @@ public class BrowserLocaleManager implements LocaleManager {
public String getFallbackLocaleTag() {
return FALLBACK_LOCALE_TAG;
}
@WrapForJNI
public static native void refreshLocales();
@WrapForJNI
private static String getLocale() {
try {
return Locales.getLocaleManager().getCurrentLocale(GeckoAppShell.getApplicationContext()).toString();
} catch (NullPointerException e) {
Log.i(LOG_TAG, "Couldn't get current locale.");
return null;
}
}
}

View File

@ -20,6 +20,7 @@ import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TreeMap;
@ -1864,4 +1865,9 @@ public class GeckoAppShell
}
return Integer.parseInt(prop);
}
@WrapForJNI
public static String getDefaultLocale() {
return Locale.getDefault().toString();
}
}

View File

@ -318,6 +318,14 @@ auto GeckoAppShell::GetCurrentNetworkInformation() -> mozilla::jni::DoubleArray:
return mozilla::jni::Method<GetCurrentNetworkInformation_t>::Call(GeckoAppShell::Context(), nullptr);
}
constexpr char GeckoAppShell::GetDefaultLocale_t::name[];
constexpr char GeckoAppShell::GetDefaultLocale_t::signature[];
auto GeckoAppShell::GetDefaultLocale() -> mozilla::jni::String::LocalRef
{
return mozilla::jni::Method<GetDefaultLocale_t>::Call(GeckoAppShell::Context(), nullptr);
}
constexpr char GeckoAppShell::GetDensity_t::name[];
constexpr char GeckoAppShell::GetDensity_t::signature[];

View File

@ -898,6 +898,25 @@ public:
static auto GetCurrentNetworkInformation() -> mozilla::jni::DoubleArray::LocalRef;
struct GetDefaultLocale_t {
typedef GeckoAppShell Owner;
typedef mozilla::jni::String::LocalRef ReturnType;
typedef mozilla::jni::String::Param SetterType;
typedef mozilla::jni::Args<> Args;
static constexpr char name[] = "getDefaultLocale";
static constexpr char signature[] =
"()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::ANY;
static const mozilla::jni::DispatchTarget dispatchTarget =
mozilla::jni::DispatchTarget::CURRENT;
};
static auto GetDefaultLocale() -> mozilla::jni::String::LocalRef;
struct GetDensity_t {
typedef GeckoAppShell Owner;
typedef float ReturnType;

View File

@ -38,6 +38,21 @@ const JNINativeMethod ANRReporter::Natives<Impl>::methods[] = {
::template Wrap<&Impl::RequestNativeStack>)
};
template<class Impl>
class BrowserLocaleManager::Natives : public mozilla::jni::NativeImpl<BrowserLocaleManager, Impl>
{
public:
static const JNINativeMethod methods[1];
};
template<class Impl>
const JNINativeMethod BrowserLocaleManager::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<BrowserLocaleManager::RefreshLocales_t>(
mozilla::jni::NativeStub<BrowserLocaleManager::RefreshLocales_t, Impl>
::template Wrap<&Impl::RefreshLocales>)
};
template<class Impl>
class GeckoJavaSampler::Natives : public mozilla::jni::NativeImpl<GeckoJavaSampler, Impl>
{

View File

@ -24,6 +24,20 @@ constexpr char ANRReporter::ReleaseNativeStack_t::signature[];
constexpr char ANRReporter::RequestNativeStack_t::name[];
constexpr char ANRReporter::RequestNativeStack_t::signature[];
const char BrowserLocaleManager::name[] =
"org/mozilla/gecko/BrowserLocaleManager";
constexpr char BrowserLocaleManager::GetLocale_t::name[];
constexpr char BrowserLocaleManager::GetLocale_t::signature[];
auto BrowserLocaleManager::GetLocale() -> mozilla::jni::String::LocalRef
{
return mozilla::jni::Method<GetLocale_t>::Call(BrowserLocaleManager::Context(), nullptr);
}
constexpr char BrowserLocaleManager::RefreshLocales_t::name[];
constexpr char BrowserLocaleManager::RefreshLocales_t::signature[];
const char DownloadsIntegration::name[] =
"org/mozilla/gecko/DownloadsIntegration";

View File

@ -79,6 +79,55 @@ public:
template<class Impl> class Natives;
};
class BrowserLocaleManager : public mozilla::jni::ObjectBase<BrowserLocaleManager>
{
public:
static const char name[];
explicit BrowserLocaleManager(const Context& ctx) : ObjectBase<BrowserLocaleManager>(ctx) {}
struct GetLocale_t {
typedef BrowserLocaleManager Owner;
typedef mozilla::jni::String::LocalRef ReturnType;
typedef mozilla::jni::String::Param SetterType;
typedef mozilla::jni::Args<> Args;
static constexpr char name[] = "getLocale";
static constexpr char signature[] =
"()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::ANY;
static const mozilla::jni::DispatchTarget dispatchTarget =
mozilla::jni::DispatchTarget::CURRENT;
};
static auto GetLocale() -> mozilla::jni::String::LocalRef;
struct RefreshLocales_t {
typedef BrowserLocaleManager Owner;
typedef void ReturnType;
typedef void SetterType;
typedef mozilla::jni::Args<> Args;
static constexpr char name[] = "refreshLocales";
static constexpr char signature[] =
"()V";
static const bool isStatic = true;
static const mozilla::jni::ExceptionMode exceptionMode =
mozilla::jni::ExceptionMode::ABORT;
static const mozilla::jni::CallingThread callingThread =
mozilla::jni::CallingThread::ANY;
static const mozilla::jni::DispatchTarget dispatchTarget =
mozilla::jni::DispatchTarget::CURRENT;
};
static const mozilla::jni::CallingThread callingThread =
mozilla::jni::CallingThread::ANY;
template<class Impl> class Natives;
};
class DownloadsIntegration : public mozilla::jni::ObjectBase<DownloadsIntegration>
{
public:

View File

@ -37,6 +37,7 @@
#include "mozilla/Preferences.h"
#include "mozilla/Hal.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/intl/OSPreferences.h"
#include "prenv.h"
#include "AndroidBridge.h"
@ -380,6 +381,18 @@ public:
}
};
class BrowserLocaleManagerSupport final
: public java::BrowserLocaleManager::Natives<BrowserLocaleManagerSupport>
{
public:
static void RefreshLocales()
{
intl::OSPreferences::GetInstance()->Refresh();
}
};
nsAppShell::nsAppShell()
: mSyncRunFinished(*(sAppShellLock = new Mutex("nsAppShell")),
"nsAppShell.SyncRun")
@ -412,6 +425,7 @@ nsAppShell::nsAppShell()
nsWindow::InitNatives();
if (jni::IsFennec()) {
BrowserLocaleManagerSupport::Init();
mozilla::ANRReporter::Init();
mozilla::MemoryMonitor::Init();
mozilla::widget::Telemetry::Init();