diff --git a/widget/android/jni/Accessors.h b/widget/android/jni/Accessors.h index 21129c7c0b29..821cad9545e8 100644 --- a/widget/android/jni/Accessors.h +++ b/widget/android/jni/Accessors.h @@ -9,7 +9,7 @@ #include "AndroidBridge.h" namespace mozilla { -namespace jni{ +namespace jni { namespace { @@ -31,23 +31,16 @@ struct Value } -// Base class for Method<>, Field<>, and Constructor<>. -class Accessor { -public: - template - static jclass EnsureClassRef(JNIEnv* env) - { - if (!Cls::sClassRef) { - MOZ_ALWAYS_TRUE(Cls::sClassRef = - AndroidBridge::GetClassGlobalRef(env, Cls::name)); - } - return Cls::sClassRef; - } -private: +// Base class for Method<>, Field<>, and Constructor<>. +class Accessor +{ static void GetNsresult(JNIEnv* env, nsresult* rv) { if (env->ExceptionCheck()) { +#ifdef DEBUG + env->ExceptionDescribe(); +#endif env->ExceptionClear(); *rv = NS_ERROR_FAILURE; } else { @@ -56,26 +49,16 @@ private: } protected: - // Called before making a JNIEnv call. - template - static JNIEnv* BeginAccess() - { - JNIEnv* const env = Traits::isMultithreaded - ? GetEnvForThread() : GetGeckoThreadEnv(); - - EnsureClassRef(env); - return env; - } - // Called after making a JNIEnv call. template - static void EndAccess(JNIEnv* env, nsresult* rv) + static void EndAccess(const typename Traits::Owner::Context& ctx, + nsresult* rv) { if (Traits::exceptionMode == ExceptionMode::ABORT) { - MOZ_CATCH_JNI_EXCEPTION(env); + MOZ_CATCH_JNI_EXCEPTION(ctx.Env()); } else if (Traits::exceptionMode == ExceptionMode::NSRESULT) { - GetNsresult(env, rv); + GetNsresult(ctx.Env(), rv); } } }; @@ -86,39 +69,37 @@ template class Method : public Accessor { typedef Accessor Base; - typedef typename Traits::Owner Owner; + typedef typename Traits::Owner::Context Context; protected: static jmethodID sID; - static JNIEnv* BeginAccess() + static void BeginAccess(const Context& ctx) { - JNIEnv* const env = Base::BeginAccess(); - if (sID) { - return env; + return; } if (Traits::isStatic) { MOZ_ALWAYS_TRUE(sID = AndroidBridge::GetStaticMethodID( - env, Traits::Owner::sClassRef, Traits::name, Traits::signature)); + ctx.Env(), ctx.ClassRef(), Traits::name, Traits::signature)); } else { MOZ_ALWAYS_TRUE(sID = AndroidBridge::GetMethodID( - env, Traits::Owner::sClassRef, Traits::name, Traits::signature)); + ctx.Env(), ctx.ClassRef(), Traits::name, Traits::signature)); } - return env; } - static void EndAccess(JNIEnv* env, nsresult* rv) + static void EndAccess(const Context& ctx, nsresult* rv) { - return Base::EndAccess(env, rv); + return Base::EndAccess(ctx, rv); } public: template - static ReturnType Call(const Owner* cls, nsresult* rv, const Args&... args) + static ReturnType Call(const Context& ctx, nsresult* rv, const Args&... args) { - JNIEnv* const env = BeginAccess(); + JNIEnv* const env = ctx.Env(); + BeginAccess(ctx); jvalue jargs[] = { Value(TypeAdapter::FromNative(env, args)).val ... @@ -127,11 +108,11 @@ public: auto result = TypeAdapter::ToNative(env, Traits::isStatic ? (env->*TypeAdapter::StaticCall)( - Owner::sClassRef, sID, jargs) : + ctx.RawClassRef(), sID, jargs) : (env->*TypeAdapter::Call)( - cls->mInstance, sID, jargs)); + ctx.Get(), sID, jargs)); - EndAccess(env, rv); + EndAccess(ctx, rv); return result; } }; @@ -146,26 +127,27 @@ template class Method : public Method { typedef Method Base; - typedef typename Traits::Owner Owner; + typedef typename Traits::Owner::Context Context; public: template - static void Call(const Owner* cls, nsresult* rv, + static void Call(const Context& ctx, nsresult* rv, const Args&... args) { - JNIEnv* const env = Base::BeginAccess(); + JNIEnv* const env = ctx.Env(); + Base::BeginAccess(ctx); jvalue jargs[] = { Value(TypeAdapter::FromNative(env, args)).val ... }; if (Traits::isStatic) { - env->CallStaticVoidMethodA(Owner::sClassRef, Base::sID, jargs); + env->CallStaticVoidMethodA(ctx.RawClassRef(), Base::sID, jargs); } else { - env->CallVoidMethodA(cls->mInstance, Base::sID, jargs); + env->CallVoidMethodA(ctx.Get(), Base::sID, jargs); } - Base::EndAccess(env, rv); + Base::EndAccess(ctx, rv); } }; @@ -173,25 +155,26 @@ public: // Constructor<> is used to construct a JNI instance given a traits class. template class Constructor : protected Method { - typedef typename Traits::Owner Owner; + typedef typename Traits::Owner::Context Context; typedef typename Traits::ReturnType ReturnType; typedef Method Base; public: template - static ReturnType Call(const Owner* cls, nsresult* rv, + static ReturnType Call(const Context& ctx, nsresult* rv, const Args&... args) { - JNIEnv* const env = Base::BeginAccess(); + JNIEnv* const env = ctx.Env(); + Base::BeginAccess(ctx); jvalue jargs[] = { Value(TypeAdapter::FromNative(env, args)).val ... }; auto result = TypeAdapter::ToNative( - env, env->NewObjectA(Owner::sClassRef, Base::sID, jargs)); + env, env->NewObjectA(ctx.RawClassRef(), Base::sID, jargs)); - Base::EndAccess(env, rv); + Base::EndAccess(ctx, rv); return result; } }; @@ -202,7 +185,7 @@ template class Field : public Accessor { typedef Accessor Base; - typedef typename Traits::Owner Owner; + typedef typename Traits::Owner::Context Context; typedef typename Traits::ReturnType GetterType; typedef typename Traits::SetterType SetterType; @@ -210,62 +193,61 @@ private: static jfieldID sID; - static JNIEnv* BeginAccess() + static void BeginAccess(const Context& ctx) { - JNIEnv* const env = Base::BeginAccess(); - if (sID) { - return env; + return; } if (Traits::isStatic) { MOZ_ALWAYS_TRUE(sID = AndroidBridge::GetStaticFieldID( - env, Traits::Owner::sClassRef, Traits::name, Traits::signature)); + ctx.Env(), ctx.ClassRef(), Traits::name, Traits::signature)); } else { MOZ_ALWAYS_TRUE(sID = AndroidBridge::GetFieldID( - env, Traits::Owner::sClassRef, Traits::name, Traits::signature)); + ctx.Env(), ctx.ClassRef(), Traits::name, Traits::signature)); } - return env; } - static void EndAccess(JNIEnv* env, nsresult* rv) + static void EndAccess(const Context& ctx, nsresult* rv) { - return Base::EndAccess(env, rv); + return Base::EndAccess(ctx, rv); } public: - static GetterType Get(const Owner* cls, nsresult* rv) + static GetterType Get(const Context& ctx, nsresult* rv) { - JNIEnv* const env = BeginAccess(); + JNIEnv* const env = ctx.Env(); + BeginAccess(ctx); auto result = TypeAdapter::ToNative( env, Traits::isStatic ? (env->*TypeAdapter::StaticGet) - (Owner::sClassRef, sID) : + (ctx.RawClassRef(), sID) : (env->*TypeAdapter::Get) - (cls->mInstance, sID)); + (ctx.Get(), sID)); - EndAccess(env, rv); + EndAccess(ctx, rv); return result; } - static void Set(const Owner* cls, nsresult* rv, SetterType val) + static void Set(const Context& ctx, nsresult* rv, SetterType val) { - JNIEnv* const env = BeginAccess(); + JNIEnv* const env = ctx.Env(); + BeginAccess(ctx); if (Traits::isStatic) { (env->*TypeAdapter::StaticSet)( - Owner::sClassRef, sID, + ctx.RawClassRef(), sID, TypeAdapter::FromNative(env, val)); } else { (env->*TypeAdapter::Set)( - cls->mInstance, sID, + ctx.Get(), sID, TypeAdapter::FromNative(env, val)); } - EndAccess(env, rv); + EndAccess(ctx, rv); } }; @@ -275,7 +257,7 @@ template jfieldID Field::sID; // Define the sClassRef member declared in Refs.h and // used by Method and Field above. -template jclass Class::sClassRef; +template jclass Context::sClassRef; } // namespace jni } // namespace mozilla diff --git a/widget/android/jni/Natives.h b/widget/android/jni/Natives.h index 459b353475b7..b768176a34d2 100644 --- a/widget/android/jni/Natives.h +++ b/widget/android/jni/Natives.h @@ -239,24 +239,24 @@ struct ProxyArg } }; -template -struct ProxyArg> +template +struct ProxyArg> { // Ref types need to be saved by global ref. - typedef typename T::GlobalRef Type; - typedef typename TypeAdapter>::JNIType JNIType; + typedef typename C::GlobalRef Type; + typedef typename TypeAdapter>::JNIType JNIType; static void Clear(JNIEnv* env, Type& ref) { ref.Clear(env); } static Type From(JNIEnv* env, JNIType val) { - return Type(env, T::Ref::From(val)); + return Type(env, C::Ref::From(val)); } }; -template struct ProxyArg : ProxyArg {}; -template<> struct ProxyArg> : ProxyArg> {}; -template struct ProxyArg> : ProxyArg> {}; +template struct ProxyArg : ProxyArg {}; +template<> struct ProxyArg : ProxyArg {}; +template struct ProxyArg> : ProxyArg {}; // ProxyNativeCall implements the functor object that is passed to // UsesNativeCallProxy::OnNativeCall @@ -268,11 +268,11 @@ class ProxyNativeCall template friend class NativeStubImpl; - // "this arg" refers to the ClassObject::LocalRef (for static methods) or + // "this arg" refers to the Class::LocalRef (for static methods) or // Owner::LocalRef (for instance methods) that we optionally (as indicated // by HasThisArg) pass into the destination C++ function. typedef typename mozilla::Conditional::Type ThisArgClass; + Class, Owner>::Type ThisArgClass; typedef typename mozilla::Conditional::Type ThisArgJNIType; @@ -280,7 +280,7 @@ class ProxyNativeCall // Method template parameter in NativeStubImpl::Wrap. typedef typename mozilla::Conditional::Type, typename mozilla::Conditional typename mozilla::EnableIf::Type - Call(const ClassObject::LocalRef& cls, + Call(const Class::LocalRef& cls, mozilla::IndexSequence) const { (*mNativeCall)(cls, mozilla::Get(mArgs)...); @@ -316,7 +316,7 @@ class ProxyNativeCall template typename mozilla::EnableIf::Type - Call(const ClassObject::LocalRef& cls, + Call(const Class::LocalRef& cls, mozilla::IndexSequence) const { (*mNativeCall)(mozilla::Get(mArgs)...); @@ -531,7 +531,7 @@ public: static MOZ_JNICALL void Wrap(JNIEnv* env, jobject instance) { if (mozilla::IsBaseOf::value) { - auto cls = ClassObject::LocalRef::Adopt( + auto cls = Class::LocalRef::Adopt( env, env->GetObjectClass(instance)); Dispatch(ProxyNativeCall( @@ -566,14 +566,14 @@ public: } // Static method with class reference - template + template static MOZ_JNICALL ReturnJNIType Wrap(JNIEnv* env, jclass cls, typename TypeAdapter::JNIType... args) { static_assert(!mozilla::IsBaseOf::value, "Native call proxy only supports void return type"); - auto clazz = ClassObject::LocalRef::Adopt(env, cls); + auto clazz = Class::LocalRef::Adopt(env, cls); const auto res = TypeAdapter::FromNative(env, (*Method)(clazz, TypeAdapter::ToNative(env, args)...)); clazz.Forget(); @@ -604,7 +604,7 @@ public: } // Static method with class reference - template + template static MOZ_JNICALL void Wrap(JNIEnv* env, jclass cls, typename TypeAdapter::JNIType... args) { @@ -614,7 +614,7 @@ public: Args...>(Method, env, cls, args...)); return; } - auto clazz = ClassObject::LocalRef::Adopt(env, cls); + auto clazz = Class::LocalRef::Adopt(env, cls); (*Method)(clazz, TypeAdapter::ToNative(env, args)...); clazz.Forget(); } @@ -656,11 +656,11 @@ public: if (sInited) { return; } - JNIEnv* const env = GetEnvForThread(); - MOZ_ALWAYS_TRUE(!env->RegisterNatives( - Accessor::EnsureClassRef(env), - Natives::methods, - sizeof(Natives::methods) / sizeof(Natives::methods[0]))); + const auto& ctx = typename Cls::Context(); + ctx.Env()->RegisterNatives( + ctx.ClassRef(), Natives::methods, + sizeof(Natives::methods) / sizeof(Natives::methods[0])); + MOZ_CATCH_JNI_EXCEPTION(ctx.Env()); sInited = true; } diff --git a/widget/android/jni/Refs.h b/widget/android/jni/Refs.h index a954016641b8..b51ad64af00f 100644 --- a/widget/android/jni/Refs.h +++ b/widget/android/jni/Refs.h @@ -13,30 +13,16 @@ namespace mozilla { namespace jni { -class Accessor; -template class Constructor; -template class Field; -template class Method; - // Wrapped object reference (e.g. jobject, jclass, etc...) -template class Ref; +template class Ref; +// Represents a calling context for JNI methods. +template class Context; // Wrapped local reference that inherits from Ref. template class LocalRef; // Wrapped global reference that inherits from Ref. template class GlobalRef; - -// Type used for a reference parameter. Default is a wrapped object -// reference, but ParamImpl can be specialized to define custom behavior, -// e.g. a StringParam class that automatically converts nsAString& and -// nsACString& to a jstring. -template struct ParamImpl { typedef Ref Type; }; -template using Param = typename ParamImpl::Type; - -namespace detail { - -template struct TypeAdapter; - -} // namespace detail +// Wrapped dangling reference that's owned by someone else. +template class DependentRef; // How exception during a JNI call should be treated. @@ -58,150 +44,109 @@ template struct Args {}; -// Base class for all JNI binding classes. -// Templated so that we have one sClassRef for each class. -template -class Class -{ - friend class Accessor; - template friend class Constructor; - template friend class Field; - template friend class Method; - -private: - static jclass sClassRef; // global reference - -protected: - jobject mInstance; // local or global reference - - Class(jobject instance) : mInstance(instance) {} -}; - - -// Binding for a plain jobject. -class Object : public Class -{ -protected: - Object(jobject instance) : Class(instance) {} - -public: - typedef jni::Ref Ref; - typedef jni::LocalRef LocalRef; - typedef jni::GlobalRef GlobalRef; - typedef const jni::Param& Param; - - static constexpr char name[] = "java/lang/Object"; -}; - - -// Binding for a built-in object reference other than jobject. -template -class TypedObject : public Class> -{ - typedef TypedObject Self; - -protected: - TypedObject(jobject instance) : Class>(instance) {} - -public: - typedef jni::Ref Ref; - typedef jni::LocalRef LocalRef; - typedef jni::GlobalRef GlobalRef; - typedef const jni::Param& Param; - - static const char name[]; -}; - -// Define bindings for built-in types. -typedef TypedObject String; -typedef TypedObject ClassObject; -typedef TypedObject Throwable; - -typedef TypedObject BooleanArray; -typedef TypedObject ByteArray; -typedef TypedObject CharArray; -typedef TypedObject ShortArray; -typedef TypedObject IntArray; -typedef TypedObject LongArray; -typedef TypedObject FloatArray; -typedef TypedObject DoubleArray; -typedef TypedObject ObjectArray; - -template<> struct ParamImpl { class Type; }; - +class Object; // Base class for Ref and its specializations. -template -class RefBase : protected Cls +template +class Ref { - typedef RefBase Self; - typedef void (Self::*bool_type)() const; + template friend class Ref; + + using Self = Ref; + using bool_type = void (Self::*)() const; void non_null_reference() const {} + // A Cls-derivative that allows copying + // (e.g. when acting as a return value). + struct CopyableCtx : public Context + { + CopyableCtx(JNIEnv* env, Type instance) + : Context(env, instance) + {} + + CopyableCtx(const CopyableCtx& cls) + : Context(cls.Env(), cls.Get()) + {} + }; + + // Private copy constructor so that there's no danger of assigning a + // temporary LocalRef/GlobalRef to a Ref, and potentially use the Ref + // after the source had been freed. + Ref(const Ref&) = default; + protected: - RefBase(jobject instance) : Cls(instance) {} + static JNIEnv* FindEnv() + { + return Cls::isMultithreaded ? GetEnvForThread() : GetGeckoThreadEnv(); + } + + Type mInstance; + + // Protected jobject constructor because outside code should be using + // Ref::From. Using Ref::From makes it very easy to see which code is using + // raw JNI types for future refactoring. + explicit Ref(Type instance) : mInstance(instance) {} public: + using JNIType = Type; + // Construct a Ref form a raw JNI reference. - static Ref From(JNIType obj) + static Ref From(JNIType obj) { - return Ref(static_cast(obj)); + return Ref(obj); } // Construct a Ref form a generic object reference. - static Ref From(const RefBase& obj) + static Ref From(const Ref& obj) { - return Ref(obj.Get()); + return Ref(JNIType(obj.Get())); } + MOZ_IMPLICIT Ref(decltype(nullptr)) : mInstance(nullptr) {} + // Get the raw JNI reference. JNIType Get() const { - return static_cast(Cls::mInstance); + return mInstance; } - bool operator==(const RefBase& other) const + bool operator==(const Ref& other) const { // Treat two references of the same object as being the same. - return Cls::mInstance == other.mInstance && - GetEnvForThread()->IsSameObject( - Cls::mInstance, other.mInstance) != JNI_FALSE; + return mInstance == other.mInstance || JNI_FALSE != + FindEnv()->IsSameObject(mInstance, other.mInstance); } - bool operator!=(const RefBase& other) const + bool operator!=(const Ref& other) const { return !operator==(other); } bool operator==(decltype(nullptr)) const { - return !Cls::mInstance; + return !mInstance; } bool operator!=(decltype(nullptr)) const { - return !!Cls::mInstance; + return !!mInstance; } - Cls* operator->() + CopyableCtx operator->() const { - MOZ_ASSERT(Cls::mInstance); - return this; - } - - const Cls* operator->() const - { - MOZ_ASSERT(Cls::mInstance); - return this; + return CopyableCtx(FindEnv(), mInstance); } // Any ref can be cast to an object ref. - operator Ref() const; + operator Ref() const + { + return Ref(mInstance); + } // Null checking (e.g. !!ref) using the safe-bool idiom. operator bool_type() const { - return Cls::mInstance ? &Self::non_null_reference : nullptr; + return mInstance ? &Self::non_null_reference : nullptr; } // We don't allow implicit conversion to jobject because that can lead @@ -216,62 +161,150 @@ public: }; -// Wrapped object reference (e.g. jobject, jclass, etc...) -template -class Ref : public RefBase +// Represents a calling context for JNI methods. +template +class Context : public Ref { - template friend class RefBase; - friend struct detail::TypeAdapter>; + using Ref = jni::Ref; - typedef RefBase Base; + static jclass sClassRef; // global reference protected: - // Protected jobject constructor because outside code should be using - // Ref::From. Using Ref::From makes it very easy to see which code is using - // raw JNI types for future refactoring. - Ref(jobject instance) : Base(instance) {} - - // Protected copy constructor so that there's no danger of assigning a - // temporary LocalRef/GlobalRef to a Ref, and potentially use the Ref - // after the source had been freed. - Ref(const Ref& ref) : Base(ref.mInstance) {} + JNIEnv* const mEnv; public: - MOZ_IMPLICIT Ref(decltype(nullptr)) : Base(nullptr) {} + static const char name[]; + + static jclass RawClassRef() + { + return sClassRef; + } + + Context() + : Ref(nullptr) + , mEnv(Ref::FindEnv()) + {} + + Context(JNIEnv* env, Type instance) + : Ref(instance) + , mEnv(env) + {} + + jclass ClassRef() const + { + if (!sClassRef) { + sClassRef = GetClassGlobalRef(mEnv, name); + } + return sClassRef; + } + + JNIEnv* Env() const + { + return mEnv; + } + + bool operator==(const Ref& other) const + { + // Treat two references of the same object as being the same. + return Ref::mInstance == other.mInstance || JNI_FALSE != + mEnv->IsSameObject(Ref::mInstance, other.mInstance); + } + + bool operator!=(const Ref& other) const + { + return !operator==(other); + } + + bool operator==(decltype(nullptr)) const + { + return !Ref::mInstance; + } + + bool operator!=(decltype(nullptr)) const + { + return !!Ref::mInstance; + } + + Cls operator->() const + { + MOZ_ASSERT(Ref::mInstance, "Null jobject"); + return Cls(*this); + } }; -template -RefBase::operator Ref() const +template +class ObjectBase { - return Ref(Cls::mInstance); -} +protected: + const jni::Context& mCtx; + jclass ClassRef() const { return mCtx.ClassRef(); } + JNIEnv* Env() const { return mCtx.Env(); } + Type Instance() const { return mCtx.Get(); } +public: + using Ref = jni::Ref; + using Context = jni::Context; + using LocalRef = jni::LocalRef; + using GlobalRef = jni::GlobalRef; + using Param = const Ref&; + + static const bool isMultithreaded = true; + + explicit ObjectBase(const Context& ctx) : mCtx(ctx) {} + + Cls* operator->() + { + return static_cast(this); + } +}; + +// Binding for a plain jobject. +class Object : public ObjectBase +{ +public: + explicit Object(const Context& ctx) : ObjectBase(ctx) {} +}; + +// Binding for a built-in object reference other than jobject. template -class Ref> - : public RefBase, T> +class TypedObject : public ObjectBase, T> { - friend class RefBase, T>; - friend struct detail::TypeAdapter>>; - - typedef RefBase, T> Base; - -protected: - Ref(jobject instance) : Base(instance) {} - - Ref(const Ref& ref) : Base(ref.mInstance) {} - public: - MOZ_IMPLICIT Ref(decltype(nullptr)) : Base(nullptr) {} + explicit TypedObject(const Context, T>& ctx) + : ObjectBase, T>(ctx) + {} }; -namespace { +// Define bindings for built-in types. +using String = TypedObject; +using Class = TypedObject; +using Throwable = TypedObject; + +using BooleanArray = TypedObject; +using ByteArray = TypedObject; +using CharArray = TypedObject; +using ShortArray = TypedObject; +using IntArray = TypedObject; +using LongArray = TypedObject; +using FloatArray = TypedObject; +using DoubleArray = TypedObject; +using ObjectArray = TypedObject; + + +namespace detail { // See explanation in LocalRef. -template struct GenericObject { typedef Object Type; }; -template<> struct GenericObject { typedef struct {} Type; }; +template struct GenericObject { using Type = Object; }; +template<> struct GenericObject +{ + struct Type { + using Ref = jni::Ref; + using Context = jni::Context; + }; +}; template struct GenericLocalRef { template struct Type : jni::Object {}; @@ -284,45 +317,40 @@ template<> struct GenericLocalRef } // namespace template -class LocalRef : public Ref +class LocalRef : public Cls::Context { template friend class LocalRef; -private: + using Ctx = typename Cls::Context; + using Ref = typename Cls::Ref; + using JNIType = typename Ref::JNIType; + // In order to be able to convert LocalRef to LocalRef, we // need constructors and copy assignment operators that take in a // LocalRef argument. However, if Cls *is* Object, we would have // duplicated constructors and operators with LocalRef arguments. To // avoid this conflict, we use GenericObject, which is defined as Object for // LocalRef and defined as a dummy class for LocalRef. - typedef typename GenericObject::Type GenericObject; + using GenericObject = typename detail::GenericObject::Type; // Similarly, GenericLocalRef is useed to convert LocalRef to, // LocalRef. It's defined as LocalRef for Cls == Object, // and defined as a dummy template class for Cls != Object. template using GenericLocalRef - = typename GenericLocalRef::template Type; + = typename detail::GenericLocalRef::template Type; - static jobject NewLocalRef(JNIEnv* env, jobject obj) + static JNIType NewLocalRef(JNIEnv* env, JNIType obj) { - if (!obj) { - return nullptr; - } - return env->NewLocalRef(obj); + return JNIType(obj ? env->NewLocalRef(obj) : nullptr); } - JNIEnv* const mEnv; - - LocalRef(JNIEnv* env, jobject instance) - : Ref(instance) - , mEnv(env) - {} + LocalRef(JNIEnv* env, JNIType instance) : Ctx(env, instance) {} LocalRef& swap(LocalRef& other) { auto instance = other.mInstance; - other.mInstance = Ref::mInstance; - Ref::mInstance = instance; + other.mInstance = Ctx::mInstance; + Ctx::mInstance = instance; return *this; } @@ -330,92 +358,78 @@ public: // Construct a LocalRef from a raw JNI local reference. Unlike Ref::From, // LocalRef::Adopt returns a LocalRef that will delete the local reference // when going out of scope. - static LocalRef Adopt(jobject instance) + static LocalRef Adopt(JNIType instance) { - return LocalRef(GetEnvForThread(), instance); + return LocalRef(Ref::FindEnv(), instance); } - static LocalRef Adopt(JNIEnv* env, jobject instance) + static LocalRef Adopt(JNIEnv* env, JNIType instance) { return LocalRef(env, instance); } // Copy constructor. LocalRef(const LocalRef& ref) - : Ref(NewLocalRef(ref.mEnv, ref.mInstance)) - , mEnv(ref.mEnv) + : Ctx(ref.mEnv, NewLocalRef(ref.mEnv, ref.mInstance)) {} // Move constructor. LocalRef(LocalRef&& ref) - : Ref(ref.mInstance) - , mEnv(ref.mEnv) + : Ctx(ref.mEnv, ref.mInstance) { ref.mInstance = nullptr; } - explicit LocalRef(JNIEnv* env = GetEnvForThread()) - : Ref(nullptr) - , mEnv(env) + explicit LocalRef(JNIEnv* env = Ref::FindEnv()) + : Ctx(env, nullptr) {} // Construct a LocalRef from any Ref, // which means creating a new local reference. - MOZ_IMPLICIT LocalRef(const Ref& ref) - : Ref(nullptr) - , mEnv(GetEnvForThread()) + MOZ_IMPLICIT LocalRef(const Ref& ref) + : Ctx(Ref::FindEnv(), nullptr) { - Ref::mInstance = NewLocalRef(mEnv, ref.Get()); + Ctx::mInstance = NewLocalRef(Ctx::mEnv, ref.Get()); } - LocalRef(JNIEnv* env, const Ref& ref) - : Ref(NewLocalRef(env, ref.Get())) - , mEnv(env) + LocalRef(JNIEnv* env, const Ref& ref) + : Ctx(env, NewLocalRef(env, ref.Get())) {} // Move a LocalRef into a LocalRef without // creating/deleting local references. MOZ_IMPLICIT LocalRef(LocalRef&& ref) - : Ref(ref.mInstance) - , mEnv(ref.mEnv) + : Ctx(ref.mEnv, JNIType(ref.mInstance)) { ref.mInstance = nullptr; } template MOZ_IMPLICIT LocalRef(GenericLocalRef&& ref) - : Ref(ref.mInstance) - , mEnv(ref.mEnv) + : Ctx(ref.mEnv, ref.mInstance) { ref.mInstance = nullptr; } // Implicitly converts nullptr to LocalRef. MOZ_IMPLICIT LocalRef(decltype(nullptr)) - : Ref(nullptr) - , mEnv(GetEnvForThread()) + : Ctx(Ref::FindEnv(), nullptr) {} ~LocalRef() { - if (Ref::mInstance) { - mEnv->DeleteLocalRef(Ref::mInstance); - Ref::mInstance = nullptr; + if (Ctx::mInstance) { + Ctx::mEnv->DeleteLocalRef(Ctx::mInstance); + Ctx::mInstance = nullptr; } } - // Get the JNIEnv* associated with this local reference. - JNIEnv* Env() const - { - return mEnv; - } - // Get the raw JNI reference that can be used as a return value. // Returns the same JNI type (jobject, jstring, etc.) as the underlying Ref. - auto Forget() -> decltype(Ref(nullptr).Get()) + typename Ref::JNIType Forget() { - const auto obj = Ref::Get(); - Ref::mInstance = nullptr; + const auto obj = Ctx::Get(); + Ctx::mInstance = nullptr; return obj; } @@ -424,9 +438,9 @@ public: return swap(ref); } - LocalRef& operator=(const Ref& ref) + LocalRef& operator=(const Ref& ref) { - LocalRef newRef(mEnv, ref); + LocalRef newRef(Ctx::mEnv, ref); return swap(newRef); } @@ -445,87 +459,86 @@ public: LocalRef& operator=(decltype(nullptr)) { - LocalRef newRef(mEnv, nullptr); + LocalRef newRef(Ctx::mEnv, nullptr); return swap(newRef); } }; template -class GlobalRef : public Ref +class GlobalRef : public Cls::Ref { -private: - static jobject NewGlobalRef(JNIEnv* env, jobject instance) + using Ref = typename Cls::Ref; + using JNIType = typename Ref::JNIType; + + static JNIType NewGlobalRef(JNIEnv* env, JNIType instance) { - if (!instance) { - return nullptr; - } - return env->NewGlobalRef(instance); + return JNIType(instance ? env->NewGlobalRef(instance) : nullptr); } GlobalRef& swap(GlobalRef& other) { auto instance = other.mInstance; - other.mInstance = Ref::mInstance; - Ref::mInstance = instance; + other.mInstance = Ref::mInstance; + Ref::mInstance = instance; return *this; } public: GlobalRef() - : Ref(nullptr) + : Ref(nullptr) {} // Copy constructor GlobalRef(const GlobalRef& ref) - : Ref(NewGlobalRef(GetEnvForThread(), ref.mInstance)) + : Ref(NewGlobalRef(Ref::FindEnv(), ref.mInstance)) {} // Move constructor GlobalRef(GlobalRef&& ref) - : Ref(ref.mInstance) + : Ref(ref.mInstance) { ref.mInstance = nullptr; } - MOZ_IMPLICIT GlobalRef(const Ref& ref) - : Ref(NewGlobalRef(GetEnvForThread(), ref.Get())) + MOZ_IMPLICIT GlobalRef(const Ref& ref) + : Ref(NewGlobalRef(Ref::FindEnv(), ref.Get())) {} - GlobalRef(JNIEnv* env, const Ref& ref) - : Ref(NewGlobalRef(env, ref.Get())) + GlobalRef(JNIEnv* env, const Ref& ref) + : Ref(NewGlobalRef(env, ref.Get())) {} MOZ_IMPLICIT GlobalRef(const LocalRef& ref) - : Ref(NewGlobalRef(ref.Env(), ref.Get())) + : Ref(NewGlobalRef(ref.Env(), ref.Get())) {} // Implicitly converts nullptr to GlobalRef. MOZ_IMPLICIT GlobalRef(decltype(nullptr)) - : Ref(nullptr) + : Ref(nullptr) {} ~GlobalRef() { - if (Ref::mInstance) { - Clear(GetEnvForThread()); + if (Ref::mInstance) { + Clear(Ref::FindEnv()); } } // Get the raw JNI reference that can be used as a return value. // Returns the same JNI type (jobject, jstring, etc.) as the underlying Ref. - auto Forget() -> decltype(Ref(nullptr).Get()) + typename Ref::JNIType Forget() { - const auto obj = Ref::Get(); - Ref::mInstance = nullptr; + const auto obj = Ref::Get(); + Ref::mInstance = nullptr; return obj; } void Clear(JNIEnv* env) { - if (Ref::mInstance) { - env->DeleteGlobalRef(Ref::mInstance); - Ref::mInstance = nullptr; + if (Ref::mInstance) { + env->DeleteGlobalRef(Ref::mInstance); + Ref::mInstance = nullptr; } } @@ -534,7 +547,13 @@ public: return swap(ref); } - GlobalRef& operator=(const Ref& ref) + GlobalRef& operator=(const Ref& ref) + { + GlobalRef newRef(ref); + return swap(newRef); + } + + GlobalRef& operator=(const LocalRef& ref) { GlobalRef newRef(ref); return swap(newRef); @@ -548,53 +567,179 @@ public: }; -// Ref specialization for arrays. -template -class ArrayRefBase : public RefBase +template +class DependentRef : public Cls::Ref { - typedef RefBase Base; - -protected: - ArrayRefBase(jobject instance) : Base(instance) {} - - ArrayRefBase(const ArrayRefBase& ref) : Base(ref.mInstance) {} + using Ref = typename Cls::Ref; public: + DependentRef(typename Ref::JNIType instance) + : Ref(instance) + {} + + DependentRef(const DependentRef& ref) + : Ref(ref.Get()) + {} +}; + + +class StringParam; + +template<> +class TypedObject : public ObjectBase, jstring> +{ + using Base = ObjectBase, jstring>; + +public: + using Param = const StringParam&; + + explicit TypedObject(const Context& ctx) : Base(ctx) {} + size_t Length() const { - MOZ_ASSERT(Base::mInstance); - JNIEnv* const env = GetEnvForThread(); - const size_t ret = env->GetArrayLength(JNIType(Base::mInstance)); + const size_t ret = Base::Env()->GetStringLength(Base::Instance()); + MOZ_CATCH_JNI_EXCEPTION(Base::Env()); + return ret; + } + + nsString ToString() const + { + const jchar* const str = Base::Env()->GetStringChars( + Base::Instance(), nullptr); + const jsize len = Base::Env()->GetStringLength(Base::Instance()); + + nsString result(reinterpret_cast(str), len); + Base::Env()->ReleaseStringChars(Base::Instance(), str); + return result; + } + + nsCString ToCString() const + { + return NS_ConvertUTF16toUTF8(ToString()); + } + + // Convert jstring to a nsString. + operator nsString() const + { + return ToString(); + } + + // Convert jstring to a nsCString. + operator nsCString() const + { + return ToCString(); + } +}; + +// Define a custom parameter type for String, +// which accepts both String::Ref and nsAString/nsACString +class StringParam : public String::Ref +{ + using Ref = String::Ref; + +private: + // Not null if we should delete ref on destruction. + JNIEnv* const mEnv; + + static jstring GetString(JNIEnv* env, const nsAString& str) + { + const jstring result = env->NewString( + reinterpret_cast(str.BeginReading()), + str.Length()); MOZ_CATCH_JNI_EXCEPTION(env); + return result; + } + +public: + MOZ_IMPLICIT StringParam(decltype(nullptr)) + : Ref(nullptr) + , mEnv(nullptr) + {} + + MOZ_IMPLICIT StringParam(const Ref& ref) + : Ref(ref.Get()) + , mEnv(nullptr) + {} + + MOZ_IMPLICIT StringParam(const nsAString& str, JNIEnv* env = Ref::FindEnv()) + : Ref(GetString(env, str)) + , mEnv(env) + {} + + MOZ_IMPLICIT StringParam(const char16_t* str, JNIEnv* env = Ref::FindEnv()) + : Ref(GetString(env, nsDependentString(str))) + , mEnv(env) + {} + + MOZ_IMPLICIT StringParam(const nsACString& str, JNIEnv* env = Ref::FindEnv()) + : Ref(GetString(env, NS_ConvertUTF8toUTF16(str))) + , mEnv(env) + {} + + MOZ_IMPLICIT StringParam(const char* str, JNIEnv* env = Ref::FindEnv()) + : Ref(GetString(env, NS_ConvertUTF8toUTF16(str))) + , mEnv(env) + {} + + ~StringParam() + { + if (mEnv) { + mEnv->DeleteLocalRef(Get()); + } + } + + operator String::LocalRef() const + { + // We can't return our existing ref because the returned + // LocalRef could be freed first, so we need a new local ref. + return String::LocalRef(mEnv ? mEnv : Ref::FindEnv(), *this); + } +}; + + +namespace detail { + template struct TypeAdapter; +} + +// Ref specialization for arrays. +template +class ArrayRefBase : public ObjectBase, JNIType> +{ + using Base = ObjectBase, JNIType>; + +public: + explicit ArrayRefBase(const Context, JNIType>& ctx) + : Base(ctx) + {} + + size_t Length() const + { + const size_t ret = Base::Env()->GetArrayLength(Base::Instance()); + MOZ_CATCH_JNI_EXCEPTION(Base::Env()); return ret; } ElementType GetElement(size_t index) const { - MOZ_ASSERT(Base::mInstance); - JNIEnv* const env = GetEnvForThread(); ElementType ret; - (env->*detail::TypeAdapter::GetArray)( - JNIType(Base::mInstance), jsize(index), 1, &ret); - MOZ_CATCH_JNI_EXCEPTION(env); + (Base::Env()->*detail::TypeAdapter::GetArray)( + Base::Instance(), jsize(index), 1, &ret); + MOZ_CATCH_JNI_EXCEPTION(Base::Env()); return ret; } nsTArray GetElements() const { - MOZ_ASSERT(Base::mInstance); static_assert(sizeof(ElementType) == sizeof(typename detail::TypeAdapter::JNIType), "Size of native type must match size of JNI type"); - JNIEnv* const env = GetEnvForThread(); - const jsize len = size_t(env->GetArrayLength( - JNIType(Base::mInstance))); + const jsize len = size_t(Base::Env()->GetArrayLength(Base::Instance())); nsTArray array((size_t(len))); array.SetLength(size_t(len)); - (env->*detail::TypeAdapter::GetArray)( - JNIType(Base::mInstance), 0, len, array.Elements()); + (Base::Env()->*detail::TypeAdapter::GetArray)( + Base::Instance(), 0, len, array.Elements()); return array; } @@ -609,84 +754,63 @@ public: } }; -#define DEFINE_PRIMITIVE_ARRAY_REF(Type, JNIType, ElementType) \ +#define DEFINE_PRIMITIVE_ARRAY_REF(JNIType, ElementType) \ template<> \ - class Ref : public ArrayRefBase \ + class TypedObject : public ArrayRefBase \ { \ - friend class RefBase; \ - friend class detail::TypeAdapter>; \ - \ - typedef ArrayRefBase Base; \ - \ - protected: \ - Ref(jobject instance) : Base(instance) {} \ - \ - Ref(const Ref& ref) : Base(ref.mInstance) {} \ - \ public: \ - MOZ_IMPLICIT Ref(decltype(nullptr)) : Base(nullptr) {} \ + explicit TypedObject(const Context& ctx) \ + : ArrayRefBase(ctx) \ + {} \ } -DEFINE_PRIMITIVE_ARRAY_REF(BooleanArray, jbooleanArray, bool); -DEFINE_PRIMITIVE_ARRAY_REF(ByteArray, jbyteArray, int8_t); -DEFINE_PRIMITIVE_ARRAY_REF(CharArray, jcharArray, char16_t); -DEFINE_PRIMITIVE_ARRAY_REF(ShortArray, jshortArray, int16_t); -DEFINE_PRIMITIVE_ARRAY_REF(IntArray, jintArray, int32_t); -DEFINE_PRIMITIVE_ARRAY_REF(LongArray, jlongArray, int64_t); -DEFINE_PRIMITIVE_ARRAY_REF(FloatArray, jfloatArray, float); -DEFINE_PRIMITIVE_ARRAY_REF(DoubleArray, jdoubleArray, double); +DEFINE_PRIMITIVE_ARRAY_REF(jbooleanArray, bool); +DEFINE_PRIMITIVE_ARRAY_REF(jbyteArray, int8_t); +DEFINE_PRIMITIVE_ARRAY_REF(jcharArray, char16_t); +DEFINE_PRIMITIVE_ARRAY_REF(jshortArray, int16_t); +DEFINE_PRIMITIVE_ARRAY_REF(jintArray, int32_t); +DEFINE_PRIMITIVE_ARRAY_REF(jlongArray, int64_t); +DEFINE_PRIMITIVE_ARRAY_REF(jfloatArray, float); +DEFINE_PRIMITIVE_ARRAY_REF(jdoubleArray, double); #undef DEFINE_PRIMITIVE_ARRAY_REF -// Ref specialization for jobjectArray. + template<> -class Ref : public RefBase +class TypedObject + : public ObjectBase, jobjectArray> { - friend class RefBase; - friend class detail::TypeAdapter>; - - typedef RefBase Base; - -protected: - Ref(jobject instance) : Base(instance) {} - - Ref(const Ref& ref) : Base(ref.mInstance) {} + using Base = ObjectBase, jobjectArray>; public: - MOZ_IMPLICIT Ref(decltype(nullptr)) : Base(nullptr) {} + explicit TypedObject(const Context& ctx) : Base(ctx) {} size_t Length() const { - MOZ_ASSERT(Base::mInstance); - JNIEnv* const env = GetEnvForThread(); - const size_t ret = env->GetArrayLength(jobjectArray(Base::mInstance)); - MOZ_CATCH_JNI_EXCEPTION(env); + const size_t ret = Base::Env()->GetArrayLength(Base::Instance()); + MOZ_CATCH_JNI_EXCEPTION(Base::Env()); return ret; } Object::LocalRef GetElement(size_t index) const { - MOZ_ASSERT(ObjectArray::mInstance); - JNIEnv* const env = GetEnvForThread(); - auto ret = Object::LocalRef::Adopt(env, env->GetObjectArrayElement( - jobjectArray(ObjectArray::mInstance), jsize(index))); - MOZ_CATCH_JNI_EXCEPTION(env); + auto ret = Object::LocalRef::Adopt( + Base::Env(), Base::Env()->GetObjectArrayElement( + Base::Instance(), jsize(index))); + MOZ_CATCH_JNI_EXCEPTION(Base::Env()); return ret; } nsTArray GetElements() const { - MOZ_ASSERT(ObjectArray::mInstance); - JNIEnv* const env = GetEnvForThread(); - const jsize len = size_t(env->GetArrayLength( - jarray(ObjectArray::mInstance))); + const jsize len = size_t(Base::Env()->GetArrayLength(Base::Instance())); nsTArray array((size_t(len))); for (jsize i = 0; i < len; i++) { array.AppendElement(Object::LocalRef::Adopt( - env, env->GetObjectArrayElement( - jobjectArray(ObjectArray::mInstance), i))); - MOZ_CATCH_JNI_EXCEPTION(env); + Base::Env(), Base::Env()->GetObjectArrayElement( + Base::Instance(), i))); + MOZ_CATCH_JNI_EXCEPTION(Base::Env()); } return array; } @@ -703,121 +827,9 @@ public: void SetElement(size_t index, Object::Param element) const { - MOZ_ASSERT(ObjectArray::mInstance); - JNIEnv* const env = GetEnvForThread(); - env->SetObjectArrayElement(jobjectArray(ObjectArray::mInstance), - jsize(index), element.Get()); - MOZ_CATCH_JNI_EXCEPTION(env); - } -}; - - -// Ref specialization for jstring. -template<> -class Ref : public RefBase -{ - friend class RefBase; - friend struct detail::TypeAdapter>; - - typedef RefBase Base; - -protected: - Ref(jobject instance) : Base(instance) {} - - Ref(const Ref& ref) : Base(ref.mInstance) {} - -public: - MOZ_IMPLICIT Ref(decltype(nullptr)) : Base(nullptr) {} - - // Get the length of the jstring. - size_t Length() const - { - JNIEnv* const env = GetEnvForThread(); - return env->GetStringLength(Get()); - } - - // Convert jstring to a nsString. - operator nsString() const - { - MOZ_ASSERT(String::mInstance); - - JNIEnv* const env = GetEnvForThread(); - const jchar* const str = env->GetStringChars(Get(), nullptr); - const jsize len = env->GetStringLength(Get()); - - nsString result(reinterpret_cast(str), len); - env->ReleaseStringChars(Get(), str); - return result; - } - - // Convert jstring to a nsCString. - operator nsCString() const - { - return NS_ConvertUTF16toUTF8(operator nsString()); - } -}; - - -// Define a custom parameter type for String, -// which accepts both String::Ref and nsAString/nsACString -class ParamImpl::Type : public Ref -{ -private: - // Not null if we should delete ref on destruction. - JNIEnv* const mEnv; - - static jstring GetString(JNIEnv* env, const nsAString& str) - { - const jstring result = env->NewString( - reinterpret_cast(str.BeginReading()), - str.Length()); - MOZ_CATCH_JNI_EXCEPTION(env); - return result; - } - -public: - MOZ_IMPLICIT Type(decltype(nullptr)) - : Ref(nullptr) - , mEnv(nullptr) - {} - - MOZ_IMPLICIT Type(const String::Ref& ref) - : Ref(ref.Get()) - , mEnv(nullptr) - {} - - MOZ_IMPLICIT Type(const nsAString& str, JNIEnv* env = GetEnvForThread()) - : Ref(GetString(env, str)) - , mEnv(env) - {} - - MOZ_IMPLICIT Type(const char16_t* str, JNIEnv* env = GetEnvForThread()) - : Ref(GetString(env, nsDependentString(str))) - , mEnv(env) - {} - - MOZ_IMPLICIT Type(const nsACString& str, JNIEnv* env = GetEnvForThread()) - : Ref(GetString(env, NS_ConvertUTF8toUTF16(str))) - , mEnv(env) - {} - - MOZ_IMPLICIT Type(const char* str, JNIEnv* env = GetEnvForThread()) - : Ref(GetString(env, NS_ConvertUTF8toUTF16(str))) - , mEnv(env) - {} - - ~Type() - { - if (mEnv) { - mEnv->DeleteLocalRef(Get()); - } - } - - operator String::LocalRef() const - { - // We can't return our existing ref because the returned - // LocalRef could be freed first, so we need a new local ref. - return String::LocalRef(mEnv ? mEnv : GetEnvForThread(), *this); + Base::Env()->SetObjectArrayElement( + Base::Instance(), jsize(index), element.Get()); + MOZ_CATCH_JNI_EXCEPTION(Base::Env()); } }; diff --git a/widget/android/jni/Types.h b/widget/android/jni/Types.h index 1b5c8bc4648b..10fb5702599e 100644 --- a/widget/android/jni/Types.h +++ b/widget/android/jni/Types.h @@ -27,7 +27,7 @@ template struct TypeAdapter; // TypeAdapter> applies when jobject is a return value. template struct TypeAdapter> { - typedef decltype(Ref(nullptr).Get()) JNIType; + using JNIType = typename Cls::Ref::JNIType; static constexpr auto Call = &JNIEnv::CallObjectMethodA; static constexpr auto StaticCall = &JNIEnv::CallStaticObjectMethodA; @@ -37,7 +37,7 @@ template struct TypeAdapter> { // Declare instance as jobject because JNI methods return // jobject even if the return value is really jstring, etc. static LocalRef ToNative(JNIEnv* env, jobject instance) { - return LocalRef::Adopt(env, instance); + return LocalRef::Adopt(env, JNIType(instance)); } static JNIType FromNative(JNIEnv*, LocalRef&& instance) { @@ -64,29 +64,29 @@ template constexpr jobject // TypeAdapter> applies when jobject is a parameter value. -template struct TypeAdapter> { - typedef decltype(Ref(nullptr).Get()) JNIType; +template struct TypeAdapter> { + using JNIType = typename Ref::JNIType; static constexpr auto Set = &JNIEnv::SetObjectField; static constexpr auto StaticSet = &JNIEnv::SetStaticObjectField; - static Ref ToNative(JNIEnv* env, JNIType instance) { - return Ref::From(instance); + static DependentRef ToNative(JNIEnv* env, JNIType instance) { + return DependentRef(instance); } - static JNIType FromNative(JNIEnv*, const Ref& instance) { + static JNIType FromNative(JNIEnv*, const Ref& instance) { return instance.Get(); } }; -template constexpr void - (JNIEnv::*TypeAdapter>::Set)(jobject, jfieldID, jobject); -template constexpr void - (JNIEnv::*TypeAdapter>::StaticSet)(jclass, jfieldID, jobject); +template constexpr void + (JNIEnv::*TypeAdapter>::Set)(jobject, jfieldID, jobject); +template constexpr void + (JNIEnv::*TypeAdapter>::StaticSet)(jclass, jfieldID, jobject); // jstring has its own Param type. -template<> struct TypeAdapter> +template<> struct TypeAdapter : public TypeAdapter {}; @@ -98,7 +98,7 @@ template struct TypeAdapter #define DEFINE_PRIMITIVE_TYPE_ADAPTER(NativeType, JNIType, JNIName) \ \ template<> struct TypeAdapter { \ - typedef JNIType JNI##Type; \ + using JNI##Type = JNIType; \ \ static constexpr auto Call = &JNIEnv::Call ## JNIName ## MethodA; \ static constexpr auto StaticCall = &JNIEnv::CallStatic ## JNIName ## MethodA; \ diff --git a/widget/android/jni/Utils.cpp b/widget/android/jni/Utils.cpp index fa696736d6a8..035a17195a11 100644 --- a/widget/android/jni/Utils.cpp +++ b/widget/android/jni/Utils.cpp @@ -47,19 +47,19 @@ DEFINE_PRIMITIVE_TYPE_ADAPTER(double, jdouble, Double, MOZ_JNICALL_ABI); } // namespace detail -constexpr char Object::name[]; -template<> const char TypedObject::name[] = "java/lang/String"; -template<> const char TypedObject::name[] = "java/lang/Class"; -template<> const char TypedObject::name[] = "java/lang/Throwable"; -template<> const char TypedObject::name[] = "[Z"; -template<> const char TypedObject::name[] = "[B"; -template<> const char TypedObject::name[] = "[C"; -template<> const char TypedObject::name[] = "[S"; -template<> const char TypedObject::name[] = "[I"; -template<> const char TypedObject::name[] = "[J"; -template<> const char TypedObject::name[] = "[F"; -template<> const char TypedObject::name[] = "[D"; -template<> const char TypedObject::name[] = "[Ljava/lang/Object;"; +template<> const char Context::name[] = "java/lang/Object"; +template<> const char Context, jstring>::name[] = "java/lang/String"; +template<> const char Context, jclass>::name[] = "java/lang/Class"; +template<> const char Context, jthrowable>::name[] = "java/lang/Throwable"; +template<> const char Context, jbooleanArray>::name[] = "[Z"; +template<> const char Context, jbyteArray>::name[] = "[B"; +template<> const char Context, jcharArray>::name[] = "[C"; +template<> const char Context, jshortArray>::name[] = "[S"; +template<> const char Context, jintArray>::name[] = "[I"; +template<> const char Context, jlongArray>::name[] = "[J"; +template<> const char Context, jfloatArray>::name[] = "[F"; +template<> const char Context, jdoubleArray>::name[] = "[D"; +template<> const char Context, jobjectArray>::name[] = "[Ljava/lang/Object;"; JNIEnv* sGeckoThreadEnv; @@ -128,8 +128,7 @@ bool ThrowException(JNIEnv *aEnv, const char *aClass, { MOZ_ASSERT(aEnv, "Invalid thread JNI env"); - ClassObject::LocalRef cls = - ClassObject::LocalRef::Adopt(aEnv->FindClass(aClass)); + Class::LocalRef cls = Class::LocalRef::Adopt(aEnv->FindClass(aClass)); MOZ_ASSERT(cls, "Cannot find exception class"); return !aEnv->ThrowNew(cls.Get(), aMessage); @@ -158,7 +157,7 @@ bool HandleUncaughtException(JNIEnv* aEnv) if (stack) { // GeckoAppShell wants us to annotate and trigger the crash reporter. CrashReporter::AnnotateCrashReport( - NS_LITERAL_CSTRING("AuxiliaryJavaStack"), nsCString(stack)); + NS_LITERAL_CSTRING("AuxiliaryJavaStack"), stack->ToCString()); } #endif // MOZ_CRASHREPORTER @@ -205,5 +204,10 @@ void SetNativeHandle(JNIEnv* env, jobject instance, uintptr_t handle) static_cast(handle)); } +jclass GetClassGlobalRef(JNIEnv* aEnv, const char* aClassName) +{ + return AndroidBridge::GetClassGlobalRef(aEnv, aClassName); +} + } // jni } // mozilla diff --git a/widget/android/jni/Utils.h b/widget/android/jni/Utils.h index 1e8c0d44b785..fe5ffab25a69 100644 --- a/widget/android/jni/Utils.h +++ b/widget/android/jni/Utils.h @@ -66,6 +66,8 @@ uintptr_t GetNativeHandle(JNIEnv* env, jobject instance); void SetNativeHandle(JNIEnv* env, jobject instance, uintptr_t handle); +jclass GetClassGlobalRef(JNIEnv* aEnv, const char* aClassName); + } // jni } // mozilla