summaryrefslogtreecommitdiffstats
path: root/widget/android/jni/Types.h
diff options
context:
space:
mode:
Diffstat (limited to 'widget/android/jni/Types.h')
-rw-r--r--widget/android/jni/Types.h123
1 files changed, 123 insertions, 0 deletions
diff --git a/widget/android/jni/Types.h b/widget/android/jni/Types.h
new file mode 100644
index 0000000000..1fe5fa4400
--- /dev/null
+++ b/widget/android/jni/Types.h
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_jni_Types_h__
+#define mozilla_jni_Types_h__
+
+#include <jni.h>
+
+#include "mozilla/jni/Refs.h"
+#include "mozilla/jni/TypeAdapter.h"
+
+namespace mozilla {
+namespace jni {
+namespace detail {
+
+// TypeAdapter specializations are the interfaces between native/C++ types such
+// as int32_t and JNI types such as jint. The template parameter T is the native
+// type, and each TypeAdapter specialization can have the following members:
+//
+// * Call: JNIEnv member pointer for making a method call that returns T.
+// * StaticCall: JNIEnv member pointer for making a static call that returns T.
+// * Get: JNIEnv member pointer for getting a field of type T.
+// * StaticGet: JNIEnv member pointer for getting a static field of type T.
+// * Set: JNIEnv member pointer for setting a field of type T.
+// * StaticGet: JNIEnv member pointer for setting a static field of type T.
+// * ToNative: static function that converts the JNI type to the native type.
+// * FromNative: static function that converts the native type to the JNI type.
+
+// TypeAdapter<LocalRef<Cls>> applies when jobject is a return value.
+template <class Cls>
+struct TypeAdapter<LocalRef<Cls>> {
+ using JNIType = typename Cls::Ref::JNIType;
+
+ static constexpr auto Call = &JNIEnv::CallObjectMethodA;
+ static constexpr auto StaticCall = &JNIEnv::CallStaticObjectMethodA;
+ static constexpr auto Get = &JNIEnv::GetObjectField;
+ static constexpr auto StaticGet = &JNIEnv::GetStaticObjectField;
+
+ // Declare instance as jobject because JNI methods return
+ // jobject even if the return value is really jstring, etc.
+ static LocalRef<Cls> ToNative(JNIEnv* env, jobject instance) {
+ return LocalRef<Cls>::Adopt(env, JNIType(instance));
+ }
+
+ static JNIType FromNative(JNIEnv*, LocalRef<Cls>&& instance) {
+ return instance.Forget();
+ }
+};
+
+// clang is picky about function types, including attributes that modify the
+// calling convention, lining up. GCC appears to be somewhat less so.
+#ifdef __clang__
+# define MOZ_JNICALL_ABI JNICALL
+#else
+# define MOZ_JNICALL_ABI
+#endif
+
+// NDK r18 made jvalue* method parameters const. We detect the change directly
+// instead of using ndk-version.h in order to remain compatible with r15 for
+// now, which doesn't include those headers.
+class CallArgs {
+ static const jvalue* test(void (JNIEnv::*)(jobject, jmethodID,
+ const jvalue*));
+ static jvalue* test(void (JNIEnv::*)(jobject, jmethodID, jvalue*));
+
+ public:
+ using JValueType = decltype(test(&JNIEnv::CallVoidMethodA));
+};
+
+template <class Cls>
+constexpr jobject (JNIEnv::*TypeAdapter<LocalRef<Cls>>::Call)(
+ jobject, jmethodID, CallArgs::JValueType) MOZ_JNICALL_ABI;
+template <class Cls>
+constexpr jobject (JNIEnv::*TypeAdapter<LocalRef<Cls>>::StaticCall)(
+ jclass, jmethodID, CallArgs::JValueType) MOZ_JNICALL_ABI;
+template <class Cls>
+constexpr jobject (JNIEnv::*TypeAdapter<LocalRef<Cls>>::Get)(jobject, jfieldID);
+template <class Cls>
+constexpr jobject (JNIEnv::*TypeAdapter<LocalRef<Cls>>::StaticGet)(jclass,
+ jfieldID);
+
+// TypeAdapter<Ref<Cls>> applies when jobject is a parameter value.
+template <class Cls, typename T>
+struct TypeAdapter<Ref<Cls, T>> {
+ using JNIType = typename Ref<Cls, T>::JNIType;
+
+ static constexpr auto Set = &JNIEnv::SetObjectField;
+ static constexpr auto StaticSet = &JNIEnv::SetStaticObjectField;
+
+ static DependentRef<Cls> ToNative(JNIEnv* env, JNIType instance) {
+ return DependentRef<Cls>(instance);
+ }
+
+ static JNIType FromNative(JNIEnv*, const Ref<Cls, T>& instance) {
+ return instance.Get();
+ }
+};
+
+template <class Cls, typename T>
+constexpr void (JNIEnv::*TypeAdapter<Ref<Cls, T>>::Set)(jobject, jfieldID,
+ jobject);
+template <class Cls, typename T>
+constexpr void (JNIEnv::*TypeAdapter<Ref<Cls, T>>::StaticSet)(jclass, jfieldID,
+ jobject);
+
+// jstring has its own Param type.
+template <>
+struct TypeAdapter<StringParam> : public TypeAdapter<String::Ref> {};
+
+template <class Cls>
+struct TypeAdapter<const Cls&> : public TypeAdapter<Cls> {};
+
+} // namespace detail
+
+using namespace detail;
+
+} // namespace jni
+} // namespace mozilla
+
+#endif // mozilla_jni_Types_h__