diff --git a/widget/android/EventDispatcher.cpp b/widget/android/EventDispatcher.cpp index 8810f0b5d737..5e8cee1def91 100644 --- a/widget/android/EventDispatcher.cpp +++ b/widget/android/EventDispatcher.cpp @@ -467,49 +467,21 @@ nsresult UnboxArrayObject(JSContext* aCx, const jni::Object::LocalRef& aData, return NS_OK; } -template -jfieldID GetValueFieldID(const char* aType) { - MOZ_ASSERT(NS_IsMainThread()); - JNIEnv* const env = jni::GetGeckoThreadEnv(); - const jfieldID id = env->GetFieldID( - typename T::Context(env, nullptr).ClassRef(), "value", aType); - env->ExceptionClear(); - return id; -} - nsresult UnboxValue(JSContext* aCx, const jni::Object::LocalRef& aData, JS::MutableHandleValue aOut) { - static jfieldID booleanValueField = GetValueFieldID("Z"); - static jfieldID intValueField = GetValueFieldID("I"); - static jfieldID doubleValueField = GetValueFieldID("D"); + using jni::Java2Native; if (!aData) { aOut.setNull(); } else if (aData.IsInstanceOf()) { - if (booleanValueField) { - aOut.setBoolean(aData.Env()->GetBooleanField( - aData.Get(), booleanValueField) != JNI_FALSE); - MOZ_CATCH_JNI_EXCEPTION(aData.Env()); - } else { - aOut.setBoolean(java::sdk::Boolean::Ref::From(aData)->BooleanValue()); - } + aOut.setBoolean(Java2Native(aData, aData.Env())); } else if (aData.IsInstanceOf()) { - if (intValueField) { - aOut.setInt32(aData.Env()->GetIntField(aData.Get(), intValueField)); - MOZ_CATCH_JNI_EXCEPTION(aData.Env()); - } else { - aOut.setInt32(java::sdk::Number::Ref::From(aData)->IntValue()); - } + aOut.setInt32(Java2Native(aData, aData.Env())); } else if (aData.IsInstanceOf() || aData.IsInstanceOf()) { aOut.setInt32(java::sdk::Number::Ref::From(aData)->IntValue()); } else if (aData.IsInstanceOf()) { - if (doubleValueField) { - aOut.setNumber( - aData.Env()->GetDoubleField(aData.Get(), doubleValueField)); - } else { - aOut.setNumber(java::sdk::Number::Ref::From(aData)->DoubleValue()); - } + aOut.setNumber(Java2Native(aData, aData.Env())); } else if (aData.IsInstanceOf() || aData.IsInstanceOf()) { aOut.setNumber(java::sdk::Number::Ref::From(aData)->DoubleValue()); diff --git a/widget/android/jni/Conversions.cpp b/widget/android/jni/Conversions.cpp new file mode 100644 index 000000000000..fed46f961ddf --- /dev/null +++ b/widget/android/jni/Conversions.cpp @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "Conversions.h" +#include "JavaBuiltins.h" + +namespace mozilla { +namespace jni { + +template +jfieldID GetValueFieldID(JNIEnv* aEnv, const char* aType) { + const jfieldID id = aEnv->GetFieldID( + typename T::Context(aEnv, nullptr).ClassRef(), "value", aType); + aEnv->ExceptionClear(); + return id; +} + +// Cached locations of the primitive types within their standard boxed objects +// to skip doing that lookup on every get. +static jfieldID gBooleanValueField; +static jfieldID gIntValueField; +static jfieldID gDoubleValueField; + +void InitConversionStatics() { + MOZ_ASSERT(NS_IsMainThread()); + JNIEnv* const env = jni::GetGeckoThreadEnv(); + gBooleanValueField = GetValueFieldID(env, "Z"); + gIntValueField = GetValueFieldID(env, "I"); + gDoubleValueField = GetValueFieldID(env, "D"); +} + +template <> +bool Java2Native(mozilla::jni::Object::Param aData, JNIEnv* aEnv) { + MOZ_ASSERT(aData.IsInstanceOf()); + + bool result = false; + if (gBooleanValueField) { + if (!aEnv) { + aEnv = jni::GetEnvForThread(); + } + result = + aEnv->GetBooleanField(aData.Get(), gBooleanValueField) != JNI_FALSE; + MOZ_CATCH_JNI_EXCEPTION(aEnv); + } else { + result = java::sdk::Boolean::Ref::From(aData)->BooleanValue(); + } + + return result; +} + +template <> +int Java2Native(mozilla::jni::Object::Param aData, JNIEnv* aEnv) { + MOZ_ASSERT(aData.IsInstanceOf()); + + int result = 0; + if (gIntValueField) { + if (!aEnv) { + aEnv = jni::GetEnvForThread(); + } + result = aEnv->GetIntField(aData.Get(), gIntValueField); + MOZ_CATCH_JNI_EXCEPTION(aEnv); + } else { + result = java::sdk::Number::Ref::From(aData)->IntValue(); + } + + return result; +} + +template <> +double Java2Native(mozilla::jni::Object::Param aData, JNIEnv* aEnv) { + MOZ_ASSERT(aData.IsInstanceOf()); + + double result = 0; + if (gDoubleValueField) { + if (!aEnv) { + aEnv = jni::GetEnvForThread(); + } + result = aEnv->GetDoubleField(aData.Get(), gDoubleValueField); + MOZ_CATCH_JNI_EXCEPTION(aEnv); + } else { + result = java::sdk::Number::Ref::From(aData)->DoubleValue(); + } + + return result; +} + +} // namespace jni +} // namespace mozilla diff --git a/widget/android/jni/Conversions.h b/widget/android/jni/Conversions.h new file mode 100644 index 000000000000..1d9e20acc72f --- /dev/null +++ b/widget/android/jni/Conversions.h @@ -0,0 +1,23 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_jni_Conversions_h__ +#define mozilla_jni_Conversions_h__ + +#include "mozilla/jni/Refs.h" + +namespace mozilla { +namespace jni { + +template +ArgType Java2Native(mozilla::jni::Object::Param, JNIEnv* aEnv = nullptr); + +void InitConversionStatics(); + +} // namespace jni +} // namespace mozilla + +#endif // mozilla_jni_Conversions_h__ diff --git a/widget/android/jni/moz.build b/widget/android/jni/moz.build index b48ca4199e95..4fe6a70f28bc 100644 --- a/widget/android/jni/moz.build +++ b/widget/android/jni/moz.build @@ -9,6 +9,7 @@ with Files("**"): EXPORTS.mozilla.jni += [ 'Accessors.h', + 'Conversions.h', 'GeckoBundleUtils.h', 'Natives.h', 'Refs.h', @@ -17,6 +18,7 @@ EXPORTS.mozilla.jni += [ ] UNIFIED_SOURCES += [ + 'Conversions.cpp', 'Utils.cpp', ] diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index 0e3c65b26f8d..61c1532ced55 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -1368,6 +1368,7 @@ void nsWindow::GeckoViewSupport::AttachAccessibility( } void nsWindow::InitNatives() { + jni::InitConversionStatics(); nsWindow::GeckoViewSupport::Base::Init(); nsWindow::LayerViewSupport::Init(); nsWindow::NPZCSupport::Init();