diff --git a/widget/android/PrefsHelper.h b/widget/android/PrefsHelper.h index 020bf5588ac..fa7a31cffb0 100644 --- a/widget/android/PrefsHelper.h +++ b/widget/android/PrefsHelper.h @@ -44,9 +44,8 @@ struct PrefsHelper namesPtrArray.AppendElement(nullptr); continue; } - namesPtrArray.AppendElement(namesStrArray.AppendElement( - nsString(jni::String::LocalRef( - mozilla::Move(namesRefArray[i]))))->Data()); + namesPtrArray.AppendElement(namesStrArray.AppendElement(nsString( + jni::String::Ref::From(namesRefArray[i])))->Data()); } nsIAndroidBrowserApp* browserApp = nullptr; diff --git a/widget/android/jni/Refs.h b/widget/android/jni/Refs.h index c713b8b6657..52469c4f8ce 100644 --- a/widget/android/jni/Refs.h +++ b/widget/android/jni/Refs.h @@ -548,6 +548,96 @@ public: }; +// Ref specialization for arrays. +template +class ArrayRefBase : public RefBase +{ + typedef RefBase Base; + +protected: + ArrayRefBase(jobject instance) : Base(instance) {} + + ArrayRefBase(const ArrayRefBase& ref) : Base(ref.mInstance) {} + +public: + size_t Length() const + { + MOZ_ASSERT(Base::mInstance); + JNIEnv* const env = GetEnvForThread(); + const size_t ret = env->GetArrayLength(JNIType(Base::mInstance)); + MOZ_CATCH_JNI_EXCEPTION(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); + 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))); + + nsTArray array((size_t(len))); + array.SetLength(size_t(len)); + (env->*detail::TypeAdapter::GetArray)( + JNIType(Base::mInstance), 0, len, array.Elements()); + return array; + } + + ElementType operator[](size_t index) const + { + return GetElement(index); + } + + operator nsTArray() const + { + return GetElements(); + } +}; + +#define DEFINE_PRIMITIVE_ARRAY_REF(Type, JNIType, ElementType) \ + template<> \ + class Ref : 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) {} \ + } + +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); + +#undef DEFINE_PRIMITIVE_ARRAY_REF + // Ref specialization for jobjectArray. template<> class Ref : public RefBase @@ -565,12 +655,11 @@ protected: public: MOZ_IMPLICIT Ref(decltype(nullptr)) : Base(nullptr) {} - // Get the length of the object array. size_t Length() const { - MOZ_ASSERT(ObjectArray::mInstance); + MOZ_ASSERT(Base::mInstance); JNIEnv* const env = GetEnvForThread(); - const size_t ret = env->GetArrayLength(jarray(ObjectArray::mInstance)); + const size_t ret = env->GetArrayLength(jobjectArray(Base::mInstance)); MOZ_CATCH_JNI_EXCEPTION(env); return ret; } @@ -602,6 +691,11 @@ public: return array; } + Object::LocalRef operator[](size_t index) const + { + return GetElement(index); + } + operator nsTArray() const { return GetElements(); diff --git a/widget/android/jni/Types.h b/widget/android/jni/Types.h index 2a647ed51ce..1b5c8bc4648 100644 --- a/widget/android/jni/Types.h +++ b/widget/android/jni/Types.h @@ -106,6 +106,7 @@ template struct TypeAdapter static constexpr auto StaticGet = &JNIEnv::GetStatic ## JNIName ## Field; \ static constexpr auto Set = &JNIEnv::Set ## JNIName ## Field; \ static constexpr auto StaticSet = &JNIEnv::SetStatic ## JNIName ## Field; \ + static constexpr auto GetArray = &JNIEnv::Get ## JNIName ## ArrayRegion; \ \ static JNIType FromNative(JNIEnv*, NativeType val) { \ return static_cast(val); \ diff --git a/widget/android/jni/Utils.cpp b/widget/android/jni/Utils.cpp index 0b0f57eb4ae..fa696736d6a 100644 --- a/widget/android/jni/Utils.cpp +++ b/widget/android/jni/Utils.cpp @@ -17,7 +17,7 @@ namespace jni { namespace detail { -#define DEFINE_PRIMITIVE_TYPE_ADAPTER(NativeType, JNIType, JNIName, ABIName) \ +#define DEFINE_PRIMITIVE_TYPE_ADAPTER(NativeType, JNIType, JNIName, ABIName) \ \ constexpr JNIType (JNIEnv::*TypeAdapter::Call) \ (jobject, jmethodID, jvalue*) MOZ_JNICALL_ABI; \ @@ -30,7 +30,9 @@ namespace detail { constexpr void (JNIEnv::*TypeAdapter::Set) \ (jobject, jfieldID, JNIType) ABIName; \ constexpr void (JNIEnv::*TypeAdapter::StaticSet) \ - (jclass, jfieldID, JNIType) ABIName + (jclass, jfieldID, JNIType) ABIName; \ + constexpr void (JNIEnv::*TypeAdapter::GetArray) \ + (JNIType ## Array, jsize, jsize, JNIType*) DEFINE_PRIMITIVE_TYPE_ADAPTER(bool, jboolean, Boolean, /*nothing*/); DEFINE_PRIMITIVE_TYPE_ADAPTER(int8_t, jbyte, Byte, /*nothing*/);