diff options
Diffstat (limited to 'widget/android/jni/Utils.cpp')
-rw-r--r-- | widget/android/jni/Utils.cpp | 291 |
1 files changed, 0 insertions, 291 deletions
diff --git a/widget/android/jni/Utils.cpp b/widget/android/jni/Utils.cpp deleted file mode 100644 index 919588851..000000000 --- a/widget/android/jni/Utils.cpp +++ /dev/null @@ -1,291 +0,0 @@ -#include "Utils.h" -#include "Types.h" - -#include <android/log.h> -#include <pthread.h> - -#include "mozilla/Assertions.h" - -#include "GeneratedJNIWrappers.h" -#include "nsAppShell.h" - -namespace mozilla { -namespace jni { - -namespace detail { - -#define DEFINE_PRIMITIVE_TYPE_ADAPTER(NativeType, JNIType, JNIName, ABIName) \ - \ - constexpr JNIType (JNIEnv::*TypeAdapter<NativeType>::Call) \ - (jobject, jmethodID, jvalue*) MOZ_JNICALL_ABI; \ - constexpr JNIType (JNIEnv::*TypeAdapter<NativeType>::StaticCall) \ - (jclass, jmethodID, jvalue*) MOZ_JNICALL_ABI; \ - constexpr JNIType (JNIEnv::*TypeAdapter<NativeType>::Get) \ - (jobject, jfieldID) ABIName; \ - constexpr JNIType (JNIEnv::*TypeAdapter<NativeType>::StaticGet) \ - (jclass, jfieldID) ABIName; \ - constexpr void (JNIEnv::*TypeAdapter<NativeType>::Set) \ - (jobject, jfieldID, JNIType) ABIName; \ - constexpr void (JNIEnv::*TypeAdapter<NativeType>::StaticSet) \ - (jclass, jfieldID, JNIType) ABIName; \ - constexpr void (JNIEnv::*TypeAdapter<NativeType>::GetArray) \ - (JNIType ## Array, jsize, jsize, JNIType*) - -DEFINE_PRIMITIVE_TYPE_ADAPTER(bool, jboolean, Boolean, /*nothing*/); -DEFINE_PRIMITIVE_TYPE_ADAPTER(int8_t, jbyte, Byte, /*nothing*/); -DEFINE_PRIMITIVE_TYPE_ADAPTER(char16_t, jchar, Char, /*nothing*/); -DEFINE_PRIMITIVE_TYPE_ADAPTER(int16_t, jshort, Short, /*nothing*/); -DEFINE_PRIMITIVE_TYPE_ADAPTER(int32_t, jint, Int, /*nothing*/); -DEFINE_PRIMITIVE_TYPE_ADAPTER(int64_t, jlong, Long, /*nothing*/); -DEFINE_PRIMITIVE_TYPE_ADAPTER(float, jfloat, Float, MOZ_JNICALL_ABI); -DEFINE_PRIMITIVE_TYPE_ADAPTER(double, jdouble, Double, MOZ_JNICALL_ABI); - -#undef DEFINE_PRIMITIVE_TYPE_ADAPTER - -} // namespace detail - -template<> const char ObjectBase<Object, jobject>::name[] = "java/lang/Object"; -template<> const char ObjectBase<TypedObject<jstring>, jstring>::name[] = "java/lang/String"; -template<> const char ObjectBase<TypedObject<jclass>, jclass>::name[] = "java/lang/Class"; -template<> const char ObjectBase<TypedObject<jthrowable>, jthrowable>::name[] = "java/lang/Throwable"; -template<> const char ObjectBase<TypedObject<jbooleanArray>, jbooleanArray>::name[] = "[Z"; -template<> const char ObjectBase<TypedObject<jbyteArray>, jbyteArray>::name[] = "[B"; -template<> const char ObjectBase<TypedObject<jcharArray>, jcharArray>::name[] = "[C"; -template<> const char ObjectBase<TypedObject<jshortArray>, jshortArray>::name[] = "[S"; -template<> const char ObjectBase<TypedObject<jintArray>, jintArray>::name[] = "[I"; -template<> const char ObjectBase<TypedObject<jlongArray>, jlongArray>::name[] = "[J"; -template<> const char ObjectBase<TypedObject<jfloatArray>, jfloatArray>::name[] = "[F"; -template<> const char ObjectBase<TypedObject<jdoubleArray>, jdoubleArray>::name[] = "[D"; -template<> const char ObjectBase<TypedObject<jobjectArray>, jobjectArray>::name[] = "[Ljava/lang/Object;"; -template<> const char ObjectBase<ByteBuffer, jobject>::name[] = "java/nio/ByteBuffer"; - - -JNIEnv* sGeckoThreadEnv; - -namespace { - -JavaVM* sJavaVM; -pthread_key_t sThreadEnvKey; -jclass sOOMErrorClass; -jobject sClassLoader; -jmethodID sClassLoaderLoadClass; -bool sIsFennec; - -void UnregisterThreadEnv(void* env) -{ - if (!env) { - // We were never attached. - return; - } - // The thread may have already been detached. In that case, it's still - // okay to call DetachCurrentThread(); it'll simply return an error. - // However, we must not access | env | because it may be invalid. - MOZ_ASSERT(sJavaVM); - sJavaVM->DetachCurrentThread(); -} - -} // namespace - -void SetGeckoThreadEnv(JNIEnv* aEnv) -{ - MOZ_ASSERT(aEnv); - MOZ_ASSERT(!sGeckoThreadEnv || sGeckoThreadEnv == aEnv); - - if (!sGeckoThreadEnv - && pthread_key_create(&sThreadEnvKey, UnregisterThreadEnv)) { - MOZ_CRASH("Failed to initialize required TLS"); - } - - sGeckoThreadEnv = aEnv; - MOZ_ALWAYS_TRUE(!pthread_setspecific(sThreadEnvKey, aEnv)); - - MOZ_ALWAYS_TRUE(!aEnv->GetJavaVM(&sJavaVM)); - MOZ_ASSERT(sJavaVM); - - sOOMErrorClass = Class::GlobalRef(Class::LocalRef::Adopt( - aEnv->FindClass("java/lang/OutOfMemoryError"))).Forget(); - aEnv->ExceptionClear(); - - sClassLoader = Object::GlobalRef(java::GeckoThread::ClsLoader()).Forget(); - sClassLoaderLoadClass = aEnv->GetMethodID( - Class::LocalRef::Adopt(aEnv->GetObjectClass(sClassLoader)).Get(), - "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); - MOZ_ASSERT(sClassLoader && sClassLoaderLoadClass); - - auto geckoAppClass = Class::LocalRef::Adopt( - aEnv->FindClass("org/mozilla/gecko/GeckoApp")); - aEnv->ExceptionClear(); - sIsFennec = !!geckoAppClass; -} - -JNIEnv* GetEnvForThread() -{ - MOZ_ASSERT(sGeckoThreadEnv); - - JNIEnv* env = static_cast<JNIEnv*>(pthread_getspecific(sThreadEnvKey)); - if (env) { - return env; - } - - // We don't have a saved JNIEnv, so try to get one. - // AttachCurrentThread() does the same thing as GetEnv() when a thread is - // already attached, so we don't have to call GetEnv() at all. - if (!sJavaVM->AttachCurrentThread(&env, nullptr)) { - MOZ_ASSERT(env); - MOZ_ALWAYS_TRUE(!pthread_setspecific(sThreadEnvKey, env)); - return env; - } - - MOZ_CRASH("Failed to get JNIEnv for thread"); - return nullptr; // unreachable -} - -bool ThrowException(JNIEnv *aEnv, const char *aClass, - const char *aMessage) -{ - MOZ_ASSERT(aEnv, "Invalid thread JNI env"); - - Class::LocalRef cls = Class::LocalRef::Adopt(aEnv->FindClass(aClass)); - MOZ_ASSERT(cls, "Cannot find exception class"); - - return !aEnv->ThrowNew(cls.Get(), aMessage); -} - -bool HandleUncaughtException(JNIEnv* aEnv) -{ - MOZ_ASSERT(aEnv, "Invalid thread JNI env"); - - if (!aEnv->ExceptionCheck()) { - return false; - } - -#ifdef MOZ_CHECK_JNI - aEnv->ExceptionDescribe(); -#endif - - Throwable::LocalRef e = - Throwable::LocalRef::Adopt(aEnv, aEnv->ExceptionOccurred()); - MOZ_ASSERT(e); - aEnv->ExceptionClear(); - - String::LocalRef stack = java::GeckoAppShell::GetExceptionStackTrace(e); - if (stack && ReportException(aEnv, e.Get(), stack.Get())) { - return true; - } - - aEnv->ExceptionClear(); - java::GeckoAppShell::HandleUncaughtException(e); - - if (NS_WARN_IF(aEnv->ExceptionCheck())) { - aEnv->ExceptionDescribe(); - aEnv->ExceptionClear(); - } - - return true; -} - -bool ReportException(JNIEnv* aEnv, jthrowable aExc, jstring aStack) -{ - bool result = true; - - if (sOOMErrorClass && aEnv->IsInstanceOf(aExc, sOOMErrorClass)) { - NS_ABORT_OOM(0); // Unknown OOM size - } - return result; -} - -namespace { - -jclass sJNIObjectClass; -jfieldID sJNIObjectHandleField; - -bool EnsureJNIObject(JNIEnv* env, jobject instance) { - if (!sJNIObjectClass) { - sJNIObjectClass = Class::GlobalRef(Class::LocalRef::Adopt(GetClassRef( - env, "org/mozilla/gecko/mozglue/JNIObject"))).Forget(); - - sJNIObjectHandleField = env->GetFieldID( - 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)); -} - -jclass GetClassRef(JNIEnv* aEnv, const char* aClassName) -{ - // First try the default class loader. - auto classRef = Class::LocalRef::Adopt(aEnv, aEnv->FindClass(aClassName)); - - if (!classRef && sClassLoader) { - // If the default class loader failed but we have an app class loader, try that. - // Clear the pending exception from failed FindClass call above. - aEnv->ExceptionClear(); - classRef = Class::LocalRef::Adopt(aEnv, jclass( - aEnv->CallObjectMethod(sClassLoader, sClassLoaderLoadClass, - StringParam(aClassName, aEnv).Get()))); - } - - if (classRef) { - return classRef.Forget(); - } - - __android_log_print( - ANDROID_LOG_ERROR, "Gecko", - ">>> FATAL JNI ERROR! FindClass(className=\"%s\") failed. " - "Did ProGuard optimize away something it shouldn't have?", - aClassName); - aEnv->ExceptionDescribe(); - MOZ_CRASH("Cannot find JNI class"); - return nullptr; -} - -void DispatchToGeckoThread(UniquePtr<AbstractCall>&& aCall) -{ - class AbstractCallEvent : public nsAppShell::Event - { - UniquePtr<AbstractCall> mCall; - - public: - AbstractCallEvent(UniquePtr<AbstractCall>&& aCall) - : mCall(Move(aCall)) - {} - - void Run() override - { - (*mCall)(); - } - }; - - nsAppShell::PostEvent(MakeUnique<AbstractCallEvent>(Move(aCall))); -} - -bool IsFennec() -{ - return sIsFennec; -} - -} // jni -} // mozilla |