diff options
Diffstat (limited to 'widget/android/jni/Natives.h')
-rw-r--r-- | widget/android/jni/Natives.h | 707 |
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__ |