diff options
Diffstat (limited to 'widget/android/jni/Refs.h')
-rw-r--r-- | widget/android/jni/Refs.h | 953 |
1 files changed, 0 insertions, 953 deletions
diff --git a/widget/android/jni/Refs.h b/widget/android/jni/Refs.h deleted file mode 100644 index 9f54ee5cd..000000000 --- a/widget/android/jni/Refs.h +++ /dev/null @@ -1,953 +0,0 @@ -#ifndef mozilla_jni_Refs_h__ -#define mozilla_jni_Refs_h__ - -#include <jni.h> - -#include "mozilla/Move.h" -#include "mozilla/jni/Utils.h" - -#include "nsError.h" // for nsresult -#include "nsString.h" -#include "nsTArray.h" - -namespace mozilla { -namespace jni { - -// Wrapped object reference (e.g. jobject, jclass, etc...) -template<class Cls, typename JNIType> class Ref; -// Represents a calling context for JNI methods. -template<class Cls, typename JNIType> class Context; -// Wrapped local reference that inherits from Ref. -template<class Cls> class LocalRef; -// Wrapped global reference that inherits from Ref. -template<class Cls> class GlobalRef; -// Wrapped dangling reference that's owned by someone else. -template<class Cls> class DependentRef; - - -// Class to hold the native types of a method's arguments. -// For example, if a method has signature (ILjava/lang/String;)V, -// its arguments class would be jni::Args<int32_t, jni::String::Param> -template<typename...> -struct Args {}; - - -class Object; - -// Base class for Ref and its specializations. -template<class Cls, typename Type> -class Ref -{ - template<class C, typename T> friend class Ref; - - using Self = Ref<Cls, Type>; - 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<Cls, Type> - { - CopyableCtx(JNIEnv* env, Type instance) - : Context<Cls, Type>(env, instance) - {} - - CopyableCtx(const CopyableCtx& cls) - : Context<Cls, Type>(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: - static JNIEnv* FindEnv() - { - return Cls::callingThread == CallingThread::GECKO ? - GetGeckoThreadEnv() : GetEnvForThread(); - } - - 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<Cls, Type> From(JNIType obj) - { - return Ref<Cls, Type>(obj); - } - - // Construct a Ref form a generic object reference. - static Ref<Cls, Type> From(const Ref<Object, jobject>& obj) - { - return Ref<Cls, Type>(JNIType(obj.Get())); - } - - MOZ_IMPLICIT Ref(decltype(nullptr)) : mInstance(nullptr) {} - - // Get the raw JNI reference. - JNIType Get() const - { - return mInstance; - } - - bool operator==(const Ref& other) const - { - // Treat two references of the same object as being the same. - return mInstance == other.mInstance || JNI_FALSE != - FindEnv()->IsSameObject(mInstance, other.mInstance); - } - - bool operator!=(const Ref& other) const - { - return !operator==(other); - } - - bool operator==(decltype(nullptr)) const - { - return !mInstance; - } - - bool operator!=(decltype(nullptr)) const - { - return !!mInstance; - } - - CopyableCtx operator->() const - { - return CopyableCtx(FindEnv(), mInstance); - } - - // Any ref can be cast to an object ref. - operator Ref<Object, jobject>() const - { - return Ref<Object, jobject>(mInstance); - } - - // Null checking (e.g. !!ref) using the safe-bool idiom. - operator bool_type() const - { - return mInstance ? &Self::non_null_reference : nullptr; - } - - // We don't allow implicit conversion to jobject because that can lead - // to easy mistakes such as assigning a temporary LocalRef to a jobject, - // and using the jobject after the LocalRef has been freed. - - // We don't allow explicit conversion, to make outside code use Ref::Get. - // Using Ref::Get makes it very easy to see which code is using raw JNI - // types to make future refactoring easier. - - // operator JNIType() const = delete; -}; - - -// Represents a calling context for JNI methods. -template<class Cls, typename Type> -class Context : public Ref<Cls, Type> -{ - using Ref = jni::Ref<Cls, Type>; - - static jclass sClassRef; // global reference - -protected: - JNIEnv* const mEnv; - -public: - 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) { - const jclass cls = GetClassRef(mEnv, Cls::name); - sClassRef = jclass(mEnv->NewGlobalRef(cls)); - mEnv->DeleteLocalRef(cls); - } - 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<class Cls, typename Type = jobject> -class ObjectBase -{ -protected: - const jni::Context<Cls, Type>& mCtx; - - jclass ClassRef() const { return mCtx.ClassRef(); } - JNIEnv* Env() const { return mCtx.Env(); } - Type Instance() const { return mCtx.Get(); } - -public: - using Ref = jni::Ref<Cls, Type>; - using Context = jni::Context<Cls, Type>; - using LocalRef = jni::LocalRef<Cls>; - using GlobalRef = jni::GlobalRef<Cls>; - using Param = const Ref&; - - static const CallingThread callingThread = CallingThread::ANY; - static const char name[]; - - explicit ObjectBase(const Context& ctx) : mCtx(ctx) {} - - Cls* operator->() - { - return static_cast<Cls*>(this); - } -}; - -// Binding for a plain jobject. -class Object : public ObjectBase<Object, jobject> -{ -public: - explicit Object(const Context& ctx) : ObjectBase<Object, jobject>(ctx) {} -}; - -// Binding for a built-in object reference other than jobject. -template<typename T> -class TypedObject : public ObjectBase<TypedObject<T>, T> -{ -public: - explicit TypedObject(const Context<TypedObject<T>, T>& ctx) - : ObjectBase<TypedObject<T>, T>(ctx) - {} -}; - - -// Define bindings for built-in types. -using String = TypedObject<jstring>; -using Class = TypedObject<jclass>; -using Throwable = TypedObject<jthrowable>; - -using BooleanArray = TypedObject<jbooleanArray>; -using ByteArray = TypedObject<jbyteArray>; -using CharArray = TypedObject<jcharArray>; -using ShortArray = TypedObject<jshortArray>; -using IntArray = TypedObject<jintArray>; -using LongArray = TypedObject<jlongArray>; -using FloatArray = TypedObject<jfloatArray>; -using DoubleArray = TypedObject<jdoubleArray>; -using ObjectArray = TypedObject<jobjectArray>; - - -namespace detail { - -// See explanation in LocalRef. -template<class Cls> struct GenericObject { using Type = Object; }; -template<> struct GenericObject<Object> -{ - struct Type { - using Ref = jni::Ref<Type, jobject>; - using Context = jni::Context<Type, jobject>; - }; -}; -template<class Cls> struct GenericLocalRef -{ - template<class C> struct Type : jni::Object {}; -}; -template<> struct GenericLocalRef<Object> -{ - template<class C> using Type = jni::LocalRef<C>; -}; - -} // namespace - -template<class Cls> -class LocalRef : public Cls::Context -{ - template<class C> friend class LocalRef; - - using Ctx = typename Cls::Context; - using Ref = typename Cls::Ref; - using JNIType = typename Ref::JNIType; - - // In order to be able to convert LocalRef<Object> to LocalRef<Cls>, we - // need constructors and copy assignment operators that take in a - // LocalRef<Object> argument. However, if Cls *is* Object, we would have - // duplicated constructors and operators with LocalRef<Object> arguments. To - // avoid this conflict, we use GenericObject, which is defined as Object for - // LocalRef<non-Object> and defined as a dummy class for LocalRef<Object>. - using GenericObject = typename detail::GenericObject<Cls>::Type; - - // Similarly, GenericLocalRef is useed to convert LocalRef<Cls> to, - // LocalRef<Object>. It's defined as LocalRef<C> for Cls == Object, - // and defined as a dummy template class for Cls != Object. - template<class C> using GenericLocalRef - = typename detail::GenericLocalRef<Cls>::template Type<C>; - - static JNIType NewLocalRef(JNIEnv* env, JNIType obj) - { - return JNIType(obj ? env->NewLocalRef(obj) : nullptr); - } - - LocalRef(JNIEnv* env, JNIType instance) : Ctx(env, instance) {} - - LocalRef& swap(LocalRef& other) - { - auto instance = other.mInstance; - other.mInstance = Ctx::mInstance; - Ctx::mInstance = instance; - return *this; - } - -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(JNIType instance) - { - return LocalRef(Ref::FindEnv(), instance); - } - - static LocalRef Adopt(JNIEnv* env, JNIType instance) - { - return LocalRef(env, instance); - } - - // Copy constructor. - LocalRef(const LocalRef<Cls>& ref) - : Ctx(ref.mEnv, NewLocalRef(ref.mEnv, ref.mInstance)) - {} - - // Move constructor. - LocalRef(LocalRef<Cls>&& ref) - : Ctx(ref.mEnv, ref.mInstance) - { - ref.mInstance = nullptr; - } - - 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) - : Ctx(Ref::FindEnv(), nullptr) - { - Ctx::mInstance = NewLocalRef(Ctx::mEnv, ref.Get()); - } - - LocalRef(JNIEnv* env, const Ref& ref) - : Ctx(env, NewLocalRef(env, ref.Get())) - {} - - // Move a LocalRef<Object> into a LocalRef<Cls> without - // creating/deleting local references. - MOZ_IMPLICIT LocalRef(LocalRef<GenericObject>&& ref) - : Ctx(ref.mEnv, JNIType(ref.mInstance)) - { - ref.mInstance = nullptr; - } - - template<class C> - MOZ_IMPLICIT LocalRef(GenericLocalRef<C>&& ref) - : Ctx(ref.mEnv, ref.mInstance) - { - ref.mInstance = nullptr; - } - - // Implicitly converts nullptr to LocalRef. - MOZ_IMPLICIT LocalRef(decltype(nullptr)) - : Ctx(Ref::FindEnv(), nullptr) - {} - - ~LocalRef() - { - if (Ctx::mInstance) { - Ctx::mEnv->DeleteLocalRef(Ctx::mInstance); - Ctx::mInstance = nullptr; - } - } - - // 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. - typename Ref::JNIType Forget() - { - const auto obj = Ctx::Get(); - Ctx::mInstance = nullptr; - return obj; - } - - LocalRef<Cls>& operator=(LocalRef<Cls> ref) - { - return swap(ref); - } - - LocalRef<Cls>& operator=(const Ref& ref) - { - LocalRef<Cls> newRef(Ctx::mEnv, ref); - return swap(newRef); - } - - LocalRef<Cls>& operator=(LocalRef<GenericObject>&& ref) - { - LocalRef<Cls> newRef(mozilla::Move(ref)); - return swap(newRef); - } - - template<class C> - LocalRef<Cls>& operator=(GenericLocalRef<C>&& ref) - { - LocalRef<Cls> newRef(mozilla::Move(ref)); - return swap(newRef); - } - - LocalRef<Cls>& operator=(decltype(nullptr)) - { - LocalRef<Cls> newRef(Ctx::mEnv, nullptr); - return swap(newRef); - } -}; - - -template<class Cls> -class GlobalRef : public Cls::Ref -{ - using Ref = typename Cls::Ref; - using JNIType = typename Ref::JNIType; - - static JNIType NewGlobalRef(JNIEnv* env, JNIType instance) - { - return JNIType(instance ? env->NewGlobalRef(instance) : nullptr); - } - - GlobalRef& swap(GlobalRef& other) - { - auto instance = other.mInstance; - other.mInstance = Ref::mInstance; - Ref::mInstance = instance; - return *this; - } - -public: - GlobalRef() - : Ref(nullptr) - {} - - // Copy constructor - GlobalRef(const GlobalRef& ref) - : Ref(NewGlobalRef(GetEnvForThread(), ref.mInstance)) - {} - - // Move constructor - GlobalRef(GlobalRef&& ref) - : Ref(ref.mInstance) - { - ref.mInstance = nullptr; - } - - MOZ_IMPLICIT GlobalRef(const Ref& ref) - : Ref(NewGlobalRef(GetEnvForThread(), ref.Get())) - {} - - GlobalRef(JNIEnv* env, const Ref& ref) - : Ref(NewGlobalRef(env, ref.Get())) - {} - - MOZ_IMPLICIT GlobalRef(const LocalRef<Cls>& ref) - : Ref(NewGlobalRef(ref.Env(), ref.Get())) - {} - - // Implicitly converts nullptr to GlobalRef. - MOZ_IMPLICIT GlobalRef(decltype(nullptr)) - : Ref(nullptr) - {} - - ~GlobalRef() - { - if (Ref::mInstance) { - Clear(GetEnvForThread()); - } - } - - // 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. - typename Ref::JNIType Forget() - { - const auto obj = Ref::Get(); - Ref::mInstance = nullptr; - return obj; - } - - void Clear(JNIEnv* env) - { - if (Ref::mInstance) { - env->DeleteGlobalRef(Ref::mInstance); - Ref::mInstance = nullptr; - } - } - - GlobalRef<Cls>& operator=(GlobalRef<Cls> ref) - { - return swap(ref); - } - - GlobalRef<Cls>& operator=(const Ref& ref) - { - GlobalRef<Cls> newRef(ref); - return swap(newRef); - } - - GlobalRef<Cls>& operator=(const LocalRef<Cls>& ref) - { - GlobalRef<Cls> newRef(ref); - return swap(newRef); - } - - GlobalRef<Cls>& operator=(decltype(nullptr)) - { - GlobalRef<Cls> newRef(nullptr); - return swap(newRef); - } -}; - - -template<class Cls> -class DependentRef : public Cls::Ref -{ - 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<jstring> : public ObjectBase<TypedObject<jstring>, jstring> -{ - using Base = ObjectBase<TypedObject<jstring>, jstring>; - -public: - using Param = const StringParam&; - - explicit TypedObject(const Context& ctx) : Base(ctx) {} - - size_t Length() const - { - 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<const char16_t*>(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<const jchar*>(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(StringParam&& other) - : Ref(other.Get()) - , mEnv(other.mEnv) - { - other.mInstance = nullptr; - } - - ~StringParam() - { - if (mEnv && Get()) { - 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<typename T> struct TypeAdapter; -} - -// Ref specialization for arrays. -template<typename JNIType, class ElementType> -class ArrayRefBase : public ObjectBase<TypedObject<JNIType>, JNIType> -{ - using Base = ObjectBase<TypedObject<JNIType>, JNIType>; - -public: - explicit ArrayRefBase(const Context<TypedObject<JNIType>, JNIType>& ctx) - : Base(ctx) - {} - - static typename Base::LocalRef New(const ElementType* data, size_t length) { - using JNIElemType = typename detail::TypeAdapter<ElementType>::JNIType; - static_assert(sizeof(ElementType) == sizeof(JNIElemType), - "Size of native type must match size of JNI type"); - JNIEnv* const jenv = mozilla::jni::GetEnvForThread(); - auto result = - (jenv->*detail::TypeAdapter<ElementType>::NewArray)(length); - MOZ_CATCH_JNI_EXCEPTION(jenv); - (jenv->*detail::TypeAdapter<ElementType>::SetArray)( - result, jsize(0), length, - reinterpret_cast<const JNIElemType*>(data)); - MOZ_CATCH_JNI_EXCEPTION(jenv); - return Base::LocalRef::Adopt(jenv, result); - } - - 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 - { - using JNIElemType = typename detail::TypeAdapter<ElementType>::JNIType; - static_assert(sizeof(ElementType) == sizeof(JNIElemType), - "Size of native type must match size of JNI type"); - - ElementType ret; - (Base::Env()->*detail::TypeAdapter<ElementType>::GetArray)( - Base::Instance(), jsize(index), 1, - reinterpret_cast<JNIElemType*>(&ret)); - MOZ_CATCH_JNI_EXCEPTION(Base::Env()); - return ret; - } - - nsTArray<ElementType> GetElements() const - { - using JNIElemType = typename detail::TypeAdapter<ElementType>::JNIType; - static_assert(sizeof(ElementType) == sizeof(JNIElemType), - "Size of native type must match size of JNI type"); - - const jsize len = size_t(Base::Env()->GetArrayLength(Base::Instance())); - - nsTArray<ElementType> array((size_t(len))); - array.SetLength(size_t(len)); - (Base::Env()->*detail::TypeAdapter<ElementType>::GetArray)( - Base::Instance(), 0, len, - reinterpret_cast<JNIElemType*>(array.Elements())); - return array; - } - - ElementType operator[](size_t index) const - { - return GetElement(index); - } - - operator nsTArray<ElementType>() const - { - return GetElements(); - } -}; - -#define DEFINE_PRIMITIVE_ARRAY_REF(JNIType, ElementType) \ - template<> \ - class TypedObject<JNIType> : public ArrayRefBase<JNIType, ElementType> \ - { \ - public: \ - explicit TypedObject(const Context& ctx) \ - : ArrayRefBase<JNIType, ElementType>(ctx) \ - {} \ - } - -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 - - -class ByteBuffer : public ObjectBase<ByteBuffer, jobject> -{ -public: - explicit ByteBuffer(const Context& ctx) - : ObjectBase<ByteBuffer, jobject>(ctx) - {} - - static LocalRef New(void* data, size_t capacity) - { - JNIEnv* const env = GetEnvForThread(); - const auto ret = LocalRef::Adopt( - env, env->NewDirectByteBuffer(data, jlong(capacity))); - MOZ_CATCH_JNI_EXCEPTION(env); - return ret; - } - - void* Address() - { - void* const ret = Env()->GetDirectBufferAddress(Instance()); - MOZ_CATCH_JNI_EXCEPTION(Env()); - return ret; - } - - size_t Capacity() - { - const size_t ret = size_t(Env()->GetDirectBufferCapacity(Instance())); - MOZ_CATCH_JNI_EXCEPTION(Env()); - return ret; - } -}; - - -template<> -class TypedObject<jobjectArray> - : public ObjectBase<TypedObject<jobjectArray>, jobjectArray> -{ - using Base = ObjectBase<TypedObject<jobjectArray>, jobjectArray>; - -public: - explicit TypedObject(const Context& ctx) : Base(ctx) {} - - size_t Length() const - { - const size_t ret = Base::Env()->GetArrayLength(Base::Instance()); - MOZ_CATCH_JNI_EXCEPTION(Base::Env()); - return ret; - } - - Object::LocalRef GetElement(size_t index) const - { - auto ret = Object::LocalRef::Adopt( - Base::Env(), Base::Env()->GetObjectArrayElement( - Base::Instance(), jsize(index))); - MOZ_CATCH_JNI_EXCEPTION(Base::Env()); - return ret; - } - - nsTArray<Object::LocalRef> GetElements() const - { - const jsize len = size_t(Base::Env()->GetArrayLength(Base::Instance())); - - nsTArray<Object::LocalRef> array((size_t(len))); - for (jsize i = 0; i < len; i++) { - array.AppendElement(Object::LocalRef::Adopt( - Base::Env(), Base::Env()->GetObjectArrayElement( - Base::Instance(), i))); - MOZ_CATCH_JNI_EXCEPTION(Base::Env()); - } - return array; - } - - Object::LocalRef operator[](size_t index) const - { - return GetElement(index); - } - - operator nsTArray<Object::LocalRef>() const - { - return GetElements(); - } - - void SetElement(size_t index, Object::Param element) const - { - Base::Env()->SetObjectArrayElement( - Base::Instance(), jsize(index), element.Get()); - MOZ_CATCH_JNI_EXCEPTION(Base::Env()); - } -}; - - -// Support conversion from LocalRef<T>* to LocalRef<Object>*: -// LocalRef<Foo> foo; -// Foo::GetFoo(&foo); // error because parameter type is LocalRef<Object>*. -// Foo::GetFoo(ReturnTo(&foo)); // OK because ReturnTo converts the argument. -template<class Cls> -class ReturnToLocal -{ -private: - LocalRef<Cls>* const localRef; - LocalRef<Object> objRef; - -public: - explicit ReturnToLocal(LocalRef<Cls>* ref) : localRef(ref) {} - operator LocalRef<Object>*() { return &objRef; } - - ~ReturnToLocal() - { - if (objRef) { - *localRef = mozilla::Move(objRef); - } - } -}; - -template<class Cls> -ReturnToLocal<Cls> ReturnTo(LocalRef<Cls>* ref) -{ - return ReturnToLocal<Cls>(ref); -} - - -// Support conversion from GlobalRef<T>* to LocalRef<Object/T>*: -// GlobalRef<Foo> foo; -// Foo::GetFoo(&foo); // error because parameter type is LocalRef<Foo>*. -// Foo::GetFoo(ReturnTo(&foo)); // OK because ReturnTo converts the argument. -template<class Cls> -class ReturnToGlobal -{ -private: - GlobalRef<Cls>* const globalRef; - LocalRef<Object> objRef; - LocalRef<Cls> clsRef; - -public: - explicit ReturnToGlobal(GlobalRef<Cls>* ref) : globalRef(ref) {} - operator LocalRef<Object>*() { return &objRef; } - operator LocalRef<Cls>*() { return &clsRef; } - - ~ReturnToGlobal() - { - if (objRef) { - *globalRef = (clsRef = mozilla::Move(objRef)); - } else if (clsRef) { - *globalRef = clsRef; - } - } -}; - -template<class Cls> -ReturnToGlobal<Cls> ReturnTo(GlobalRef<Cls>* ref) -{ - return ReturnToGlobal<Cls>(ref); -} - -} // namespace jni -} // namespace mozilla - -#endif // mozilla_jni_Refs_h__ |