Add a direct ownership model where the Java object owns the corresponding C++ object directly, in addition to the WeakPtr model where the Java object owns a WeakPtr to the C++ object. The WeakPtr model is chosen when the implementing C++ class inherits from SupportsWeakPtr. Otherwise, the direct ownership model is chosen. Under the direct ownership model, a UniquePtr object must be used to attach the containing C++ object to a Java object, to ensure ownership is passed on to the Java object.
130 lines
4.0 KiB
C++
130 lines
4.0 KiB
C++
#include "Utils.h"
|
|
#include "Types.h"
|
|
|
|
#include "mozilla/Assertions.h"
|
|
|
|
#include "AndroidBridge.h"
|
|
#include "GeneratedJNIWrappers.h"
|
|
|
|
namespace mozilla {
|
|
namespace jni {
|
|
|
|
namespace detail {
|
|
|
|
#define DEFINE_PRIMITIVE_TYPE_ADAPTER(NativeType, JNIType, JNIName) \
|
|
\
|
|
constexpr JNIType (JNIEnv::*TypeAdapter<NativeType>::Call) \
|
|
(jobject, jmethodID, jvalue*); \
|
|
constexpr JNIType (JNIEnv::*TypeAdapter<NativeType>::StaticCall) \
|
|
(jclass, jmethodID, jvalue*); \
|
|
constexpr JNIType (JNIEnv::*TypeAdapter<NativeType>::Get) \
|
|
(jobject, jfieldID); \
|
|
constexpr JNIType (JNIEnv::*TypeAdapter<NativeType>::StaticGet) \
|
|
(jclass, jfieldID); \
|
|
constexpr void (JNIEnv::*TypeAdapter<NativeType>::Set) \
|
|
(jobject, jfieldID, JNIType); \
|
|
constexpr void (JNIEnv::*TypeAdapter<NativeType>::StaticSet) \
|
|
(jclass, jfieldID, JNIType)
|
|
|
|
DEFINE_PRIMITIVE_TYPE_ADAPTER(bool, jboolean, Boolean);
|
|
DEFINE_PRIMITIVE_TYPE_ADAPTER(int8_t, jbyte, Byte);
|
|
DEFINE_PRIMITIVE_TYPE_ADAPTER(char16_t, jchar, Char);
|
|
DEFINE_PRIMITIVE_TYPE_ADAPTER(int16_t, jshort, Short);
|
|
DEFINE_PRIMITIVE_TYPE_ADAPTER(int32_t, jint, Int);
|
|
DEFINE_PRIMITIVE_TYPE_ADAPTER(int64_t, jlong, Long);
|
|
DEFINE_PRIMITIVE_TYPE_ADAPTER(float, jfloat, Float);
|
|
DEFINE_PRIMITIVE_TYPE_ADAPTER(double, jdouble, Double);
|
|
|
|
#undef DEFINE_PRIMITIVE_TYPE_ADAPTER
|
|
|
|
} // namespace detail
|
|
|
|
constexpr char Object::name[];
|
|
template<> const char TypedObject<jstring>::name[] = "java/lang/String";
|
|
template<> const char TypedObject<jclass>::name[] = "java/lang/Class";
|
|
template<> const char TypedObject<jthrowable>::name[] = "java/lang/Throwable";
|
|
template<> const char TypedObject<jbooleanArray>::name[] = "[Z";
|
|
template<> const char TypedObject<jbyteArray>::name[] = "[B";
|
|
template<> const char TypedObject<jcharArray>::name[] = "[C";
|
|
template<> const char TypedObject<jshortArray>::name[] = "[S";
|
|
template<> const char TypedObject<jintArray>::name[] = "[I";
|
|
template<> const char TypedObject<jlongArray>::name[] = "[J";
|
|
template<> const char TypedObject<jfloatArray>::name[] = "[F";
|
|
template<> const char TypedObject<jdoubleArray>::name[] = "[D";
|
|
template<> const char TypedObject<jobjectArray>::name[] = "[Ljava/lang/Object;";
|
|
|
|
|
|
bool ThrowException(JNIEnv *aEnv, const char *aClass,
|
|
const char *aMessage)
|
|
{
|
|
MOZ_ASSERT(aEnv, "Invalid thread JNI env");
|
|
|
|
ClassObject::LocalRef cls =
|
|
ClassObject::LocalRef::Adopt(aEnv->FindClass(aClass));
|
|
MOZ_ASSERT(cls, "Cannot find exception class");
|
|
|
|
return !aEnv->ThrowNew(cls.Get(), aMessage);
|
|
}
|
|
|
|
void HandleUncaughtException(JNIEnv *aEnv)
|
|
{
|
|
MOZ_ASSERT(aEnv, "Invalid thread JNI env");
|
|
|
|
if (!aEnv->ExceptionCheck()) {
|
|
return;
|
|
}
|
|
|
|
Throwable::LocalRef e =
|
|
Throwable::LocalRef::Adopt(aEnv->ExceptionOccurred());
|
|
MOZ_ASSERT(e);
|
|
|
|
aEnv->ExceptionClear();
|
|
widget::GeckoAppShell::HandleUncaughtException(nullptr, e);
|
|
|
|
// Should be dead by now...
|
|
MOZ_CRASH("Failed to handle uncaught exception");
|
|
}
|
|
|
|
namespace {
|
|
|
|
jclass sJNIObjectClass;
|
|
jfieldID sJNIObjectHandleField;
|
|
|
|
bool EnsureJNIObject(JNIEnv* env, jobject instance) {
|
|
if (!sJNIObjectClass) {
|
|
sJNIObjectClass = AndroidBridge::GetClassGlobalRef(
|
|
env, "org/mozilla/gecko/mozglue/JNIObject");
|
|
|
|
sJNIObjectHandleField = AndroidBridge::GetFieldID(
|
|
env, sJNIObjectClass, "mHandle", "J");
|
|
}
|
|
|
|
MOZ_ASSERT(env->IsInstanceOf(instance, sJNIObjectClass));
|
|
return true;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
uintptr_t GetNativeHandle(JNIEnv* env, jobject instance)
|
|
{
|
|
if (!EnsureJNIObject(env, instance)) {
|
|
return 0;
|
|
}
|
|
|
|
return static_cast<uintptr_t>(
|
|
env->GetLongField(instance, sJNIObjectHandleField));
|
|
}
|
|
|
|
void SetNativeHandle(JNIEnv* env, jobject instance, uintptr_t handle)
|
|
{
|
|
if (!EnsureJNIObject(env, instance)) {
|
|
return;
|
|
}
|
|
|
|
env->SetLongField(instance, sJNIObjectHandleField,
|
|
static_cast<jlong>(handle));
|
|
}
|
|
|
|
} // jni
|
|
} // mozilla
|