summaryrefslogtreecommitdiffstats
path: root/widget/android/jni/Natives.h
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2020-02-20 11:22:40 -0500
committerMatt A. Tobin <email@mattatobin.com>2020-02-20 11:22:40 -0500
commit18e74277b30891033c95cac58d8a9d53b1cdb646 (patch)
treeaa77d2f31d7f099e545644e4bef02ba0f7f4052a /widget/android/jni/Natives.h
parent178382e4cea9a093506ecc752b04793bd98b8ed5 (diff)
downloadUXP-18e74277b30891033c95cac58d8a9d53b1cdb646.tar
UXP-18e74277b30891033c95cac58d8a9d53b1cdb646.tar.gz
UXP-18e74277b30891033c95cac58d8a9d53b1cdb646.tar.lz
UXP-18e74277b30891033c95cac58d8a9d53b1cdb646.tar.xz
UXP-18e74277b30891033c95cac58d8a9d53b1cdb646.zip
Issue #1053 - Remove Android Widget Toolkit specific files
Diffstat (limited to 'widget/android/jni/Natives.h')
-rw-r--r--widget/android/jni/Natives.h707
1 files changed, 0 insertions, 707 deletions
diff --git a/widget/android/jni/Natives.h b/widget/android/jni/Natives.h
deleted file mode 100644
index 511d96a87..000000000
--- a/widget/android/jni/Natives.h
+++ /dev/null
@@ -1,707 +0,0 @@
-#ifndef mozilla_jni_Natives_h__
-#define mozilla_jni_Natives_h__
-
-#include <jni.h>
-
-#include "mozilla/IndexSequence.h"
-#include "mozilla/Move.h"
-#include "mozilla/Tuple.h"
-#include "mozilla/TypeTraits.h"
-#include "mozilla/UniquePtr.h"
-#include "mozilla/WeakPtr.h"
-#include "mozilla/Unused.h"
-#include "mozilla/jni/Accessors.h"
-#include "mozilla/jni/Refs.h"
-#include "mozilla/jni/Types.h"
-#include "mozilla/jni/Utils.h"
-
-namespace mozilla {
-namespace jni {
-
-/**
- * C++ classes implementing instance (non-static) native methods can choose
- * from one of two ownership models, when associating a C++ object with a Java
- * instance.
- *
- * * If the C++ class inherits from mozilla::SupportsWeakPtr, weak pointers
- * will be used. The Java instance will store and own the pointer to a
- * WeakPtr object. The C++ class itself is otherwise not owned or directly
- * referenced. To attach a Java instance to a C++ instance, pass in a pointer
- * to the C++ class (i.e. MyClass*).
- *
- * class MyClass : public SupportsWeakPtr<MyClass>
- * , public MyJavaClass::Natives<MyClass>
- * {
- * // ...
- *
- * public:
- * MOZ_DECLARE_WEAKREFERENCE_TYPENAME(MyClass)
- * using MyJavaClass::Natives<MyClass>::Dispose;
- *
- * void AttachTo(const MyJavaClass::LocalRef& instance)
- * {
- * MyJavaClass::Natives<MyClass>::AttachInstance(instance, this);
- *
- * // "instance" does NOT own "this", so the C++ object
- * // lifetime is separate from the Java object lifetime.
- * }
- * };
- *
- * * If the C++ class doesn't inherit from mozilla::SupportsWeakPtr, the Java
- * instance will store and own a pointer to the C++ object itself. This
- * pointer must not be stored or deleted elsewhere. To attach a Java instance
- * to a C++ instance, pass in a reference to a UniquePtr of the C++ class
- * (i.e. UniquePtr<MyClass>).
- *
- * class MyClass : public MyJavaClass::Natives<MyClass>
- * {
- * // ...
- *
- * public:
- * using MyJavaClass::Natives<MyClass>::Dispose;
- *
- * static void AttachTo(const MyJavaClass::LocalRef& instance)
- * {
- * MyJavaClass::Natives<MyClass>::AttachInstance(
- * instance, mozilla::MakeUnique<MyClass>());
- *
- * // "instance" owns the newly created C++ object, so the C++
- * // object is destroyed as soon as instance.dispose() is called.
- * }
- * };
- */
-
-namespace detail {
-
-inline uintptr_t CheckNativeHandle(JNIEnv* env, uintptr_t handle)
-{
- if (!handle) {
- if (!env->ExceptionCheck()) {
- ThrowException(env, "java/lang/NullPointerException",
- "Null native pointer");
- }
- return 0;
- }
- return handle;
-}
-
-template<class Impl, bool UseWeakPtr = mozilla::IsBaseOf<
- SupportsWeakPtr<Impl>, Impl>::value /* = false */>
-struct NativePtr
-{
- static Impl* Get(JNIEnv* env, jobject instance)
- {
- return reinterpret_cast<Impl*>(CheckNativeHandle(
- env, GetNativeHandle(env, instance)));
- }
-
- template<class LocalRef>
- static Impl* Get(const LocalRef& instance)
- {
- return Get(instance.Env(), instance.Get());
- }
-
- template<class LocalRef>
- static void Set(const LocalRef& instance, UniquePtr<Impl>&& ptr)
- {
- Clear(instance);
- SetNativeHandle(instance.Env(), instance.Get(),
- reinterpret_cast<uintptr_t>(ptr.release()));
- MOZ_CATCH_JNI_EXCEPTION(instance.Env());
- }
-
- template<class LocalRef>
- static void Clear(const LocalRef& instance)
- {
- UniquePtr<Impl> ptr(reinterpret_cast<Impl*>(
- GetNativeHandle(instance.Env(), instance.Get())));
- MOZ_CATCH_JNI_EXCEPTION(instance.Env());
-
- if (ptr) {
- SetNativeHandle(instance.Env(), instance.Get(), 0);
- MOZ_CATCH_JNI_EXCEPTION(instance.Env());
- }
- }
-};
-
-template<class Impl>
-struct NativePtr<Impl, /* UseWeakPtr = */ true>
-{
- static Impl* Get(JNIEnv* env, jobject instance)
- {
- const auto ptr = reinterpret_cast<WeakPtr<Impl>*>(
- CheckNativeHandle(env, GetNativeHandle(env, instance)));
- if (!ptr) {
- return nullptr;
- }
-
- Impl* const impl = *ptr;
- if (!impl) {
- ThrowException(env, "java/lang/NullPointerException",
- "Native object already released");
- }
- return impl;
- }
-
- template<class LocalRef>
- static Impl* Get(const LocalRef& instance)
- {
- return Get(instance.Env(), instance.Get());
- }
-
- template<class LocalRef>
- static void Set(const LocalRef& instance, Impl* ptr)
- {
- Clear(instance);
- SetNativeHandle(instance.Env(), instance.Get(),
- reinterpret_cast<uintptr_t>(new WeakPtr<Impl>(ptr)));
- MOZ_CATCH_JNI_EXCEPTION(instance.Env());
- }
-
- template<class LocalRef>
- static void Clear(const LocalRef& instance)
- {
- const auto ptr = reinterpret_cast<WeakPtr<Impl>*>(
- GetNativeHandle(instance.Env(), instance.Get()));
- MOZ_CATCH_JNI_EXCEPTION(instance.Env());
-
- if (ptr) {
- SetNativeHandle(instance.Env(), instance.Get(), 0);
- MOZ_CATCH_JNI_EXCEPTION(instance.Env());
- delete ptr;
- }
- }
-};
-
-} // namespace detail
-
-using namespace detail;
-
-/**
- * For JNI native methods that are dispatched to a proxy, i.e. using
- * @WrapForJNI(dispatchTo = "proxy"), the implementing C++ class must provide a
- * OnNativeCall member. Subsequently, every native call is automatically
- * wrapped in a functor object, and the object is passed to OnNativeCall. The
- * OnNativeCall implementation can choose to invoke the call, save it, dispatch
- * it to a different thread, etc. Each copy of functor may only be invoked
- * once.
- *
- * class MyClass : public MyJavaClass::Natives<MyClass>
- * {
- * // ...
- *
- * template<class Functor>
- * class ProxyRunnable final : public Runnable
- * {
- * Functor mCall;
- * public:
- * ProxyRunnable(Functor&& call) : mCall(mozilla::Move(call)) {}
- * virtual void run() override { mCall(); }
- * };
- *
- * public:
- * template<class Functor>
- * static void OnNativeCall(Functor&& call)
- * {
- * RunOnAnotherThread(new ProxyRunnable(mozilla::Move(call)));
- * }
- * };
- */
-
-namespace detail {
-
-// ProxyArg is used to handle JNI ref arguments for proxies. Because a proxied
-// call may happen outside of the original JNI native call, we must save all
-// JNI ref arguments as global refs to avoid the arguments going out of scope.
-template<typename T>
-struct ProxyArg
-{
- static_assert(mozilla::IsPod<T>::value, "T must be primitive type");
-
- // Primitive types can be saved by value.
- typedef T Type;
- typedef typename TypeAdapter<T>::JNIType JNIType;
-
- static void Clear(JNIEnv* env, Type&) {}
-
- static Type From(JNIEnv* env, JNIType val)
- {
- return TypeAdapter<T>::ToNative(env, val);
- }
-};
-
-template<class C, typename T>
-struct ProxyArg<Ref<C, T>>
-{
- // Ref types need to be saved by global ref.
- typedef typename C::GlobalRef Type;
- typedef typename TypeAdapter<Ref<C, T>>::JNIType JNIType;
-
- static void Clear(JNIEnv* env, Type& ref) { ref.Clear(env); }
-
- static Type From(JNIEnv* env, JNIType val)
- {
- return Type(env, C::Ref::From(val));
- }
-};
-
-template<typename C> struct ProxyArg<const C&> : ProxyArg<C> {};
-template<> struct ProxyArg<StringParam> : ProxyArg<String::Ref> {};
-template<class C> struct ProxyArg<LocalRef<C>> : ProxyArg<typename C::Ref> {};
-
-// ProxyNativeCall implements the functor object that is passed to OnNativeCall
-template<class Impl, class Owner, bool IsStatic,
- bool HasThisArg /* has instance/class local ref in the call */,
- typename... Args>
-class ProxyNativeCall : public AbstractCall
-{
- // "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<IsStatic,
- Class, Owner>::Type ThisArgClass;
- typedef typename mozilla::Conditional<IsStatic,
- jclass, jobject>::Type ThisArgJNIType;
-
- // Type signature of the destination C++ function, which matches the
- // Method template parameter in NativeStubImpl::Wrap.
- typedef typename mozilla::Conditional<IsStatic,
- typename mozilla::Conditional<HasThisArg,
- void (*) (const Class::LocalRef&, Args...),
- void (*) (Args...)>::Type,
- typename mozilla::Conditional<HasThisArg,
- void (Impl::*) (const typename Owner::LocalRef&, Args...),
- void (Impl::*) (Args...)>::Type>::Type NativeCallType;
-
- // Destination C++ function.
- NativeCallType mNativeCall;
- // Saved this arg.
- typename ThisArgClass::GlobalRef mThisArg;
- // Saved arguments.
- mozilla::Tuple<typename ProxyArg<Args>::Type...> mArgs;
-
- // We cannot use IsStatic and HasThisArg directly (without going through
- // extra hoops) because GCC complains about invalid overloads, so we use
- // another pair of template parameters, Static and ThisArg.
-
- template<bool Static, bool ThisArg, size_t... Indices>
- typename mozilla::EnableIf<Static && ThisArg, void>::Type
- Call(const Class::LocalRef& cls,
- mozilla::IndexSequence<Indices...>) const
- {
- (*mNativeCall)(cls, mozilla::Get<Indices>(mArgs)...);
- }
-
- template<bool Static, bool ThisArg, size_t... Indices>
- typename mozilla::EnableIf<Static && !ThisArg, void>::Type
- Call(const Class::LocalRef& cls,
- mozilla::IndexSequence<Indices...>) const
- {
- (*mNativeCall)(mozilla::Get<Indices>(mArgs)...);
- }
-
- template<bool Static, bool ThisArg, size_t... Indices>
- typename mozilla::EnableIf<!Static && ThisArg, void>::Type
- Call(const typename Owner::LocalRef& inst,
- mozilla::IndexSequence<Indices...>) const
- {
- Impl* const impl = NativePtr<Impl>::Get(inst);
- MOZ_CATCH_JNI_EXCEPTION(inst.Env());
- (impl->*mNativeCall)(inst, mozilla::Get<Indices>(mArgs)...);
- }
-
- template<bool Static, bool ThisArg, size_t... Indices>
- typename mozilla::EnableIf<!Static && !ThisArg, void>::Type
- Call(const typename Owner::LocalRef& inst,
- mozilla::IndexSequence<Indices...>) const
- {
- Impl* const impl = NativePtr<Impl>::Get(inst);
- MOZ_CATCH_JNI_EXCEPTION(inst.Env());
- (impl->*mNativeCall)(mozilla::Get<Indices>(mArgs)...);
- }
-
- template<size_t... Indices>
- void Clear(JNIEnv* env, mozilla::IndexSequence<Indices...>)
- {
- int dummy[] = {
- (ProxyArg<Args>::Clear(env, Get<Indices>(mArgs)), 0)...
- };
- mozilla::Unused << dummy;
- }
-
-public:
- // The class that implements the call target.
- typedef Impl TargetClass;
- typedef typename ThisArgClass::Param ThisArgType;
-
- static const bool isStatic = IsStatic;
-
- ProxyNativeCall(ThisArgJNIType thisArg,
- NativeCallType nativeCall,
- JNIEnv* env,
- typename ProxyArg<Args>::JNIType... args)
- : mNativeCall(nativeCall)
- , mThisArg(env, ThisArgClass::Ref::From(thisArg))
- , mArgs(ProxyArg<Args>::From(env, args)...)
- {}
-
- ProxyNativeCall(ProxyNativeCall&&) = default;
- ProxyNativeCall(const ProxyNativeCall&) = default;
-
- // Get class ref for static calls or object ref for instance calls.
- typename ThisArgClass::Param GetThisArg() const { return mThisArg; }
-
- // Return if target is the given function pointer / pointer-to-member.
- // Because we can only compare pointers of the same type, we use a
- // templated overload that is chosen only if given a different type of
- // pointer than our target pointer type.
- bool IsTarget(NativeCallType call) const { return call == mNativeCall; }
- template<typename T> bool IsTarget(T&&) const { return false; }
-
- // Redirect the call to another function / class member with the same
- // signature as the original target. Crash if given a wrong signature.
- void SetTarget(NativeCallType call) { mNativeCall = call; }
- template<typename T> void SetTarget(T&&) const { MOZ_CRASH(); }
-
- void operator()() override
- {
- JNIEnv* const env = GetEnvForThread();
- typename ThisArgClass::LocalRef thisArg(env, mThisArg);
- Call<IsStatic, HasThisArg>(
- thisArg, typename IndexSequenceFor<Args...>::Type());
-
- // Clear all saved global refs. We do this after the call is invoked,
- // and not inside the destructor because we already have a JNIEnv here,
- // so it's more efficient to clear out the saved args here. The
- // downside is that the call can only be invoked once.
- Clear(env, typename IndexSequenceFor<Args...>::Type());
- mThisArg.Clear(env);
- }
-};
-
-template<class Impl, bool HasThisArg, typename... Args>
-struct Dispatcher
-{
- template<class Traits, bool IsStatic = Traits::isStatic,
- typename... ProxyArgs>
- static typename EnableIf<
- Traits::dispatchTarget == DispatchTarget::PROXY, void>::Type
- Run(ProxyArgs&&... args)
- {
- Impl::OnNativeCall(ProxyNativeCall<
- Impl, typename Traits::Owner, IsStatic,
- HasThisArg, Args...>(Forward<ProxyArgs>(args)...));
- }
-
- template<class Traits, bool IsStatic = Traits::isStatic,
- typename ThisArg, typename... ProxyArgs>
- static typename EnableIf<
- Traits::dispatchTarget == DispatchTarget::GECKO, void>::Type
- Run(ThisArg thisArg, ProxyArgs&&... args)
- {
- // For a static method, do not forward the "this arg" (i.e. the class
- // local ref) if the implementation does not request it. This saves us
- // a pair of calls to add/delete global ref.
- DispatchToGeckoThread(MakeUnique<ProxyNativeCall<
- Impl, typename Traits::Owner, IsStatic, HasThisArg,
- Args...>>(HasThisArg || !IsStatic ? thisArg : nullptr,
- Forward<ProxyArgs>(args)...));
- }
-
- template<class Traits, bool IsStatic = false, typename... ProxyArgs>
- static typename EnableIf<
- Traits::dispatchTarget == DispatchTarget::CURRENT, void>::Type
- Run(ProxyArgs&&... args) {}
-};
-
-} // namespace detail
-
-// Wrapper methods that convert arguments from the JNI types to the native
-// types, e.g. from jobject to jni::Object::Ref. For instance methods, the
-// wrapper methods also convert calls to calls on objects.
-//
-// We need specialization for static/non-static because the two have different
-// signatures (jobject vs jclass and Impl::*Method vs *Method).
-// We need specialization for return type, because void return type requires
-// us to not deal with the return value.
-
-// Bug 1207642 - Work around Dalvik bug by realigning stack on JNI entry
-#ifdef __i386__
-#define MOZ_JNICALL JNICALL __attribute__((force_align_arg_pointer))
-#else
-#define MOZ_JNICALL JNICALL
-#endif
-
-template<class Traits, class Impl, class Args = typename Traits::Args>
-class NativeStub;
-
-template<class Traits, class Impl, typename... Args>
-class NativeStub<Traits, Impl, jni::Args<Args...>>
-{
- using Owner = typename Traits::Owner;
- using ReturnType = typename Traits::ReturnType;
-
- static constexpr bool isStatic = Traits::isStatic;
- static constexpr bool isVoid = mozilla::IsVoid<ReturnType>::value;
-
- struct VoidType { using JNIType = void; };
- using ReturnJNIType = typename Conditional<
- isVoid, VoidType, TypeAdapter<ReturnType>>::Type::JNIType;
-
- using ReturnTypeForNonVoidInstance = typename Conditional<
- !isStatic && !isVoid, ReturnType, VoidType>::Type;
- using ReturnTypeForVoidInstance = typename Conditional<
- !isStatic && isVoid, ReturnType, VoidType&>::Type;
- using ReturnTypeForNonVoidStatic = typename Conditional<
- isStatic && !isVoid, ReturnType, VoidType>::Type;
- using ReturnTypeForVoidStatic = typename Conditional<
- isStatic && isVoid, ReturnType, VoidType&>::Type;
-
- static_assert(Traits::dispatchTarget == DispatchTarget::CURRENT || isVoid,
- "Dispatched calls must have void return type");
-
-public:
- // Non-void instance method
- template<ReturnTypeForNonVoidInstance (Impl::*Method) (Args...)>
- static MOZ_JNICALL ReturnJNIType
- Wrap(JNIEnv* env, jobject instance,
- typename TypeAdapter<Args>::JNIType... args)
- {
- MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
-
- Impl* const impl = NativePtr<Impl>::Get(env, instance);
- if (!impl) {
- // There is a pending JNI exception at this point.
- return ReturnJNIType();
- }
- return TypeAdapter<ReturnType>::FromNative(env,
- (impl->*Method)(TypeAdapter<Args>::ToNative(env, args)...));
- }
-
- // Non-void instance method with instance reference
- template<ReturnTypeForNonVoidInstance (Impl::*Method)
- (const typename Owner::LocalRef&, Args...)>
- static MOZ_JNICALL ReturnJNIType
- Wrap(JNIEnv* env, jobject instance,
- typename TypeAdapter<Args>::JNIType... args)
- {
- MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
-
- Impl* const impl = NativePtr<Impl>::Get(env, instance);
- if (!impl) {
- // There is a pending JNI exception at this point.
- return ReturnJNIType();
- }
- auto self = Owner::LocalRef::Adopt(env, instance);
- const auto res = TypeAdapter<ReturnType>::FromNative(env,
- (impl->*Method)(self, TypeAdapter<Args>::ToNative(env, args)...));
- self.Forget();
- return res;
- }
-
- // Void instance method
- template<ReturnTypeForVoidInstance (Impl::*Method) (Args...)>
- static MOZ_JNICALL void
- Wrap(JNIEnv* env, jobject instance,
- typename TypeAdapter<Args>::JNIType... args)
- {
- MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
-
- if (Traits::dispatchTarget != DispatchTarget::CURRENT) {
- Dispatcher<Impl, /* HasThisArg */ false, Args...>::
- template Run<Traits>(instance, Method, env, args...);
- return;
- }
-
- Impl* const impl = NativePtr<Impl>::Get(env, instance);
- if (!impl) {
- // There is a pending JNI exception at this point.
- return;
- }
- (impl->*Method)(TypeAdapter<Args>::ToNative(env, args)...);
- }
-
- // Void instance method with instance reference
- template<ReturnTypeForVoidInstance (Impl::*Method)
- (const typename Owner::LocalRef&, Args...)>
- static MOZ_JNICALL void
- Wrap(JNIEnv* env, jobject instance,
- typename TypeAdapter<Args>::JNIType... args)
- {
- MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
-
- if (Traits::dispatchTarget != DispatchTarget::CURRENT) {
- Dispatcher<Impl, /* HasThisArg */ true, Args...>::
- template Run<Traits>(instance, Method, env, args...);
- return;
- }
-
- Impl* const impl = NativePtr<Impl>::Get(env, instance);
- if (!impl) {
- // There is a pending JNI exception at this point.
- return;
- }
- auto self = Owner::LocalRef::Adopt(env, instance);
- (impl->*Method)(self, TypeAdapter<Args>::ToNative(env, args)...);
- self.Forget();
- }
-
- // Overload for DisposeNative
- template<ReturnTypeForVoidInstance (*DisposeNative)
- (const typename Owner::LocalRef&)>
- static MOZ_JNICALL void
- Wrap(JNIEnv* env, jobject instance)
- {
- MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
-
- if (Traits::dispatchTarget != DispatchTarget::CURRENT) {
- using LocalRef = typename Owner::LocalRef;
- Dispatcher<Impl, /* HasThisArg */ false, const LocalRef&>::
- template Run<Traits, /* IsStatic */ true>(
- /* ThisArg */ nullptr, DisposeNative, env, instance);
- return;
- }
-
- auto self = Owner::LocalRef::Adopt(env, instance);
- (Impl::DisposeNative)(self);
- self.Forget();
- }
-
- // Non-void static method
- template<ReturnTypeForNonVoidStatic (*Method) (Args...)>
- static MOZ_JNICALL ReturnJNIType
- Wrap(JNIEnv* env, jclass, typename TypeAdapter<Args>::JNIType... args)
- {
- MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
-
- return TypeAdapter<ReturnType>::FromNative(env,
- (*Method)(TypeAdapter<Args>::ToNative(env, args)...));
- }
-
- // Non-void static method with class reference
- template<ReturnTypeForNonVoidStatic (*Method)
- (const Class::LocalRef&, Args...)>
- static MOZ_JNICALL ReturnJNIType
- Wrap(JNIEnv* env, jclass cls, typename TypeAdapter<Args>::JNIType... args)
- {
- MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
-
- auto clazz = Class::LocalRef::Adopt(env, cls);
- const auto res = TypeAdapter<ReturnType>::FromNative(env,
- (*Method)(clazz, TypeAdapter<Args>::ToNative(env, args)...));
- clazz.Forget();
- return res;
- }
-
- // Void static method
- template<ReturnTypeForVoidStatic (*Method) (Args...)>
- static MOZ_JNICALL void
- Wrap(JNIEnv* env, jclass cls, typename TypeAdapter<Args>::JNIType... args)
- {
- MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
-
- if (Traits::dispatchTarget != DispatchTarget::CURRENT) {
- Dispatcher<Impl, /* HasThisArg */ false, Args...>::
- template Run<Traits>(cls, Method, env, args...);
- return;
- }
-
- (*Method)(TypeAdapter<Args>::ToNative(env, args)...);
- }
-
- // Void static method with class reference
- template<ReturnTypeForVoidStatic (*Method)
- (const Class::LocalRef&, Args...)>
- static MOZ_JNICALL void
- Wrap(JNIEnv* env, jclass cls, typename TypeAdapter<Args>::JNIType... args)
- {
- MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
-
- if (Traits::dispatchTarget != DispatchTarget::CURRENT) {
- Dispatcher<Impl, /* HasThisArg */ true, Args...>::
- template Run<Traits>(cls, Method, env, args...);
- return;
- }
-
- auto clazz = Class::LocalRef::Adopt(env, cls);
- (*Method)(clazz, TypeAdapter<Args>::ToNative(env, args)...);
- clazz.Forget();
- }
-};
-
-// Generate a JNINativeMethod from a native
-// method's traits class and a wrapped stub.
-template<class Traits, typename Ret, typename... Args>
-constexpr JNINativeMethod MakeNativeMethod(MOZ_JNICALL Ret (*stub)(JNIEnv*, Args...))
-{
- return {
- Traits::name,
- Traits::signature,
- reinterpret_cast<void*>(stub)
- };
-}
-
-// Class inherited by implementing class.
-template<class Cls, class Impl>
-class NativeImpl
-{
- typedef typename Cls::template Natives<Impl> Natives;
-
- static bool sInited;
-
-public:
- static void Init() {
- if (sInited) {
- return;
- }
- 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;
- }
-
-protected:
-
- // Associate a C++ instance with a Java instance.
- static void AttachNative(const typename Cls::LocalRef& instance,
- SupportsWeakPtr<Impl>* ptr)
- {
- static_assert(mozilla::IsBaseOf<SupportsWeakPtr<Impl>, Impl>::value,
- "Attach with UniquePtr&& when not using WeakPtr");
- return NativePtr<Impl>::Set(instance, static_cast<Impl*>(ptr));
- }
-
- static void AttachNative(const typename Cls::LocalRef& instance,
- UniquePtr<Impl>&& ptr)
- {
- static_assert(!mozilla::IsBaseOf<SupportsWeakPtr<Impl>, Impl>::value,
- "Attach with SupportsWeakPtr* when using WeakPtr");
- return NativePtr<Impl>::Set(instance, mozilla::Move(ptr));
- }
-
- // Get the C++ instance associated with a Java instance.
- // There is always a pending exception if the return value is nullptr.
- static Impl* GetNative(const typename Cls::LocalRef& instance) {
- return NativePtr<Impl>::Get(instance);
- }
-
- static void DisposeNative(const typename Cls::LocalRef& instance) {
- NativePtr<Impl>::Clear(instance);
- }
-
- NativeImpl() {
- // Initialize on creation if not already initialized.
- Init();
- }
-};
-
-// Define static member.
-template<class C, class I>
-bool NativeImpl<C, I>::sInited;
-
-} // namespace jni
-} // namespace mozilla
-
-#endif // mozilla_jni_Natives_h__