Chromium Code Reviews| Index: android_webview/native/callback_jni_bridge.cc |
| diff --git a/android_webview/native/callback_jni_bridge.cc b/android_webview/native/callback_jni_bridge.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..f0e79b53ab3560f34c75f4de38d8715bd9664fe6 |
| --- /dev/null |
| +++ b/android_webview/native/callback_jni_bridge.cc |
| @@ -0,0 +1,254 @@ |
| +// Copyright 2013 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "android_webview/native/callback_jni_bridge.h" |
| + |
| +#include <vector> |
| + |
| +#include "base/android/scoped_java_ref.h" |
| +#include "base/bind.h" |
| +#include "base/threading/thread_checker.h" |
| +#include "jni/CallbackJNIBridge_jni.h" |
| + |
| +using base::Callback; |
| +using base::android::AttachCurrentThread; |
| +using base::android::ScopedJavaLocalRef; |
| +using base::android::ScopedJavaGlobalRef; |
| + |
| +namespace android_webview { |
| + |
| +namespace { |
| + |
| +// A bit of template magic lets us select the right JNI invoke and create |
| +// method depending on the type of arguments being processed. |
| +template<typename T> |
| +struct JNISelector { |
| +}; |
| + |
| +template<> |
| +struct JNISelector<int> { |
| + static void Invoke(JNIEnv* env, jobject obj, jint value) { |
| + Java_JavaCallbackInt_invoke(env, obj, value); |
| + } |
| + |
| + static ScopedJavaLocalRef<jobject> create(JNIEnv* env, jint callbackPtr) { |
| + return Java_NativeCallbackInt_create(env, callbackPtr); |
| + } |
| +}; |
| + |
| +template<> |
| +struct JNISelector<long> { |
| + static void Invoke(JNIEnv* env, jobject obj, jlong value) { |
| + Java_JavaCallbackLong_invoke(env, obj, value); |
| + } |
| + |
| + static ScopedJavaLocalRef<jobject> create(JNIEnv* env, jint callbackPtr) { |
| + return Java_NativeCallbackLong_create(env, callbackPtr); |
| + } |
| +}; |
| + |
| +template<> |
| +struct JNISelector<bool> { |
| + static void Invoke(JNIEnv* env, jobject obj, jboolean value) { |
| + Java_JavaCallbackBoolean_invoke(env, obj, value); |
| + } |
| + |
| + static ScopedJavaLocalRef<jobject> create(JNIEnv* env, jint callbackPtr) { |
| + return Java_NativeCallbackBoolean_create(env, callbackPtr); |
| + } |
| +}; |
| + |
| +template<> |
| +struct JNISelector<ScopedJavaLocalRef<jobject> > { |
| + static void Invoke(JNIEnv* env, |
| + jobject obj, |
| + const ScopedJavaLocalRef<jobject>& value) { |
| + Java_JavaCallback_invoke(env, obj, value.obj()); |
| + } |
| + |
| + static ScopedJavaLocalRef<jobject> create(JNIEnv* env, jint callbackPtr) { |
| + return Java_NativeCallback_create(env, callbackPtr); |
| + } |
| +}; |
| + |
| +// This wraps a Java-side ValueCallback instance. |
| +template<typename T> |
| +class JavaCallback { |
| + public: |
| + JavaCallback(JNIEnv* env, |
| + const ScopedJavaLocalRef<jobject>& jvalue_callback) { |
| + jvalue_callback_.Reset(env, jvalue_callback.obj()); |
|
mkosiba (inactive)
2013/02/25 23:43:44
I think I'll add a DCHECK here to see if jvalue_ca
|
| + } |
| + |
| + void onReceiveValue(T value) { |
| + DCHECK(!jvalue_callback_.is_null()); |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| + if (!jvalue_callback_.is_null()) { |
| + JNIEnv* env = AttachCurrentThread(); |
| + JNISelector<T>::Invoke(env, jvalue_callback_.obj(), value); |
| + jvalue_callback_.Reset(); |
| + } |
| + } |
| + |
| + private: |
| + ScopedJavaGlobalRef<jobject> jvalue_callback_; |
| + base::ThreadChecker thread_checker_; |
| +}; |
| + |
| +template <typename T> |
| +static Callback<void(T)> FromJavaCallbackTemplate( |
| + JNIEnv* env, |
| + const ScopedJavaLocalRef<jobject>& jvalue_callback) { |
| + JavaCallback<T>* value_callback = new JavaCallback<T>(env, jvalue_callback); |
| + return base::Bind(&JavaCallback<T>::onReceiveValue, |
| + base::Owned(value_callback)); |
| +} |
| + |
| +} // namespace |
| + |
| +Callback<void(int)> CallbackJNIBridge::FromJavaCallbackInt( |
| + JNIEnv* env, |
| + const ScopedJavaLocalRef<jobject>& jvalue_callback) { |
| + return FromJavaCallbackTemplate<int>(env, jvalue_callback); |
| +} |
| + |
| +Callback<void(long)> CallbackJNIBridge::FromJavaCallbackLong( |
| + JNIEnv* env, |
| + const ScopedJavaLocalRef<jobject>& jvalue_callback) { |
| + return FromJavaCallbackTemplate<long>(env, jvalue_callback); |
| +} |
| + |
| +Callback<void(bool)> CallbackJNIBridge::FromJavaCallbackBool( |
| + JNIEnv* env, |
| + const ScopedJavaLocalRef<jobject>& jvalue_callback) { |
| + return FromJavaCallbackTemplate<bool>(env, jvalue_callback); |
| +} |
| + |
| +base::Callback<void(ScopedJavaLocalRef<jobject>)> |
| +CallbackJNIBridge::FromJavaCallbackObj( |
| + JNIEnv* env, |
| + const ScopedJavaLocalRef<jobject>& jvalue_callback) { |
| + return FromJavaCallbackTemplate<ScopedJavaLocalRef<jobject> >( |
| + env, jvalue_callback); |
| +} |
| + |
| +namespace { |
| + |
| +template <typename T> |
| +ScopedJavaLocalRef<jobject> ToJavaCallbackTemplate( |
| + JNIEnv* env, |
| + const base::Callback<void(T)>& callback) { |
| + Callback<void(T)>* native_callback = new Callback<void(T)>(callback); |
| + ScopedJavaLocalRef<jobject> jvalue_callback = Java_NativeCallbackInt_create( |
| + env, reinterpret_cast<int>(native_callback)); |
| + |
| + return jvalue_callback; |
| +} |
| + |
| +} // namespace |
| + |
| +ScopedJavaLocalRef<jobject> CallbackJNIBridge::ToJavaCallbackInt( |
| + JNIEnv* env, |
| + const Callback<void(int)>& callback) { |
| + return ToJavaCallbackTemplate(env, callback); |
| +} |
| + |
| +ScopedJavaLocalRef<jobject> CallbackJNIBridge::ToJavaCallbackLong( |
| + JNIEnv* env, |
| + const Callback<void(long)>& callback) { |
| + return ToJavaCallbackTemplate(env, callback); |
| +} |
| + |
| +ScopedJavaLocalRef<jobject> CallbackJNIBridge::ToJavaCallbackBool( |
| + JNIEnv* env, |
| + const Callback<void(bool)>& callback) { |
| + return ToJavaCallbackTemplate(env, callback); |
| +} |
| + |
| +ScopedJavaLocalRef<jobject> CallbackJNIBridge::ToJavaCallbackObj( |
| + JNIEnv* env, |
| + const base::Callback<void(ScopedJavaLocalRef<jobject>)>& callback) { |
| + Callback<void(ScopedJavaLocalRef<jobject>)>* native_callback = |
| + new Callback<void(ScopedJavaLocalRef<jobject>)>(callback); |
| + ScopedJavaLocalRef<jobject> jvalue_callback = |
| + Java_NativeCallback_create( |
| + env, reinterpret_cast<int>(native_callback)); |
| + |
| + return jvalue_callback; |
| +} |
| + |
| +// static methods ------------------------------------------------------------- |
| +namespace { |
| + |
| +template <typename T> |
| +void DestroyTemplate(JNIEnv* env, jclass clazz, jint callbackPtr) { |
| + Callback<void(T)>* native_callback = |
| + reinterpret_cast<Callback<void(T)>*>(callbackPtr); |
| + delete native_callback; |
| +} |
| + |
| +template <typename T, typename JT> |
| +static void InvokeTemplate(JNIEnv* env, |
| + jclass clazz, |
| + jint callbackPtr, |
| + JT value) { |
| + Callback<void(T)>* native_callback = |
| + reinterpret_cast<Callback<void(T)>*>(callbackPtr); |
| + native_callback->Run(value); |
| +} |
| + |
| +} // namespace |
| + |
| +static void DestroyInt(JNIEnv* env, jclass clazz, jint callbackPtr) { |
| + DestroyTemplate<int>(env, clazz, callbackPtr); |
| +} |
| + |
| +static void InvokeInt(JNIEnv* env, jclass clazz, jint callbackPtr, jint value) { |
| + InvokeTemplate<int, jint>(env, clazz, callbackPtr, value); |
| +} |
| + |
| +static void DestroyLong(JNIEnv* env, jclass clazz, jint callbackPtr) { |
| + DestroyTemplate<long>(env, clazz, callbackPtr); |
| +} |
| + |
| +static void InvokeLong(JNIEnv* env, |
| + jclass clazz, |
| + jint callbackPtr, |
| + jlong value) { |
| + InvokeTemplate<long, jlong>(env, clazz, callbackPtr, value); |
| +} |
| + |
| +static void DestroyBoolean(JNIEnv* env, jclass clazz, jint callbackPtr) { |
| + DestroyTemplate<bool>(env, clazz, callbackPtr); |
| +} |
| + |
| +static void InvokeBoolean(JNIEnv* env, |
| + jclass clazz, |
| + jint callbackPtr, |
| + jboolean value) { |
| + InvokeTemplate<bool, jboolean>(env, clazz, callbackPtr, value); |
| +} |
| + |
| +static void DestroyObj(JNIEnv* env, jclass clazz, jint callbackPtr) { |
| + DestroyTemplate<ScopedJavaLocalRef<jobject> >(env, clazz, callbackPtr); |
| +} |
| + |
| +static void InvokeObj(JNIEnv* env, |
| + jclass clazz, |
| + jint callbackPtr, |
| + jobject value) { |
| + ScopedJavaLocalRef<jobject> jvalue(env, value); |
| + InvokeTemplate<ScopedJavaLocalRef<jobject>, |
| + const ScopedJavaLocalRef<jobject>&>(env, |
| + clazz, |
| + callbackPtr, |
| + jvalue); |
| +} |
| + |
| +bool RegisterCallbackJNIBridge(JNIEnv* env) { |
| + return RegisterNativesImpl(env); |
| +} |
| + |
| +} // namespace android_webview |