OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "android_webview/native/callback_jni_bridge.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "base/android/scoped_java_ref.h" | |
10 #include "base/bind.h" | |
11 #include "base/threading/thread_checker.h" | |
12 #include "jni/CallbackJNIBridge_jni.h" | |
13 | |
14 using base::Callback; | |
15 using base::android::AttachCurrentThread; | |
16 using base::android::ScopedJavaLocalRef; | |
17 using base::android::ScopedJavaGlobalRef; | |
18 | |
19 namespace android_webview { | |
20 | |
21 namespace { | |
22 | |
23 // A bit of template magic lets us select the right JNI invoke and create | |
24 // method depending on the type of arguments being processed. | |
25 template<typename T> | |
26 struct JNISelector { | |
27 }; | |
28 | |
29 template<> | |
30 struct JNISelector<int> { | |
31 static void Invoke(JNIEnv* env, jobject obj, jint value) { | |
32 Java_JavaCallbackInt_invoke(env, obj, value); | |
33 } | |
34 | |
35 static ScopedJavaLocalRef<jobject> create(JNIEnv* env, jint callbackPtr) { | |
36 return Java_NativeCallbackInt_create(env, callbackPtr); | |
37 } | |
38 }; | |
39 | |
40 template<> | |
41 struct JNISelector<long> { | |
42 static void Invoke(JNIEnv* env, jobject obj, jlong value) { | |
43 Java_JavaCallbackLong_invoke(env, obj, value); | |
44 } | |
45 | |
46 static ScopedJavaLocalRef<jobject> create(JNIEnv* env, jint callbackPtr) { | |
47 return Java_NativeCallbackLong_create(env, callbackPtr); | |
48 } | |
49 }; | |
50 | |
51 template<> | |
52 struct JNISelector<bool> { | |
53 static void Invoke(JNIEnv* env, jobject obj, jboolean value) { | |
54 Java_JavaCallbackBoolean_invoke(env, obj, value); | |
55 } | |
56 | |
57 static ScopedJavaLocalRef<jobject> create(JNIEnv* env, jint callbackPtr) { | |
58 return Java_NativeCallbackBoolean_create(env, callbackPtr); | |
59 } | |
60 }; | |
61 | |
62 template<> | |
63 struct JNISelector<ScopedJavaLocalRef<jobject> > { | |
64 static void Invoke(JNIEnv* env, | |
65 jobject obj, | |
66 const ScopedJavaLocalRef<jobject>& value) { | |
67 Java_JavaCallback_invoke(env, obj, value.obj()); | |
68 } | |
69 | |
70 static ScopedJavaLocalRef<jobject> create(JNIEnv* env, jint callbackPtr) { | |
71 return Java_NativeCallback_create(env, callbackPtr); | |
72 } | |
73 }; | |
74 | |
75 // This wraps a Java-side ValueCallback instance. | |
76 template<typename T> | |
77 class JavaCallback { | |
78 public: | |
79 JavaCallback(JNIEnv* env, | |
80 const ScopedJavaLocalRef<jobject>& jvalue_callback) { | |
81 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
| |
82 } | |
83 | |
84 void onReceiveValue(T value) { | |
85 DCHECK(!jvalue_callback_.is_null()); | |
86 DCHECK(thread_checker_.CalledOnValidThread()); | |
87 | |
88 if (!jvalue_callback_.is_null()) { | |
89 JNIEnv* env = AttachCurrentThread(); | |
90 JNISelector<T>::Invoke(env, jvalue_callback_.obj(), value); | |
91 jvalue_callback_.Reset(); | |
92 } | |
93 } | |
94 | |
95 private: | |
96 ScopedJavaGlobalRef<jobject> jvalue_callback_; | |
97 base::ThreadChecker thread_checker_; | |
98 }; | |
99 | |
100 template <typename T> | |
101 static Callback<void(T)> FromJavaCallbackTemplate( | |
102 JNIEnv* env, | |
103 const ScopedJavaLocalRef<jobject>& jvalue_callback) { | |
104 JavaCallback<T>* value_callback = new JavaCallback<T>(env, jvalue_callback); | |
105 return base::Bind(&JavaCallback<T>::onReceiveValue, | |
106 base::Owned(value_callback)); | |
107 } | |
108 | |
109 } // namespace | |
110 | |
111 Callback<void(int)> CallbackJNIBridge::FromJavaCallbackInt( | |
112 JNIEnv* env, | |
113 const ScopedJavaLocalRef<jobject>& jvalue_callback) { | |
114 return FromJavaCallbackTemplate<int>(env, jvalue_callback); | |
115 } | |
116 | |
117 Callback<void(long)> CallbackJNIBridge::FromJavaCallbackLong( | |
118 JNIEnv* env, | |
119 const ScopedJavaLocalRef<jobject>& jvalue_callback) { | |
120 return FromJavaCallbackTemplate<long>(env, jvalue_callback); | |
121 } | |
122 | |
123 Callback<void(bool)> CallbackJNIBridge::FromJavaCallbackBool( | |
124 JNIEnv* env, | |
125 const ScopedJavaLocalRef<jobject>& jvalue_callback) { | |
126 return FromJavaCallbackTemplate<bool>(env, jvalue_callback); | |
127 } | |
128 | |
129 base::Callback<void(ScopedJavaLocalRef<jobject>)> | |
130 CallbackJNIBridge::FromJavaCallbackObj( | |
131 JNIEnv* env, | |
132 const ScopedJavaLocalRef<jobject>& jvalue_callback) { | |
133 return FromJavaCallbackTemplate<ScopedJavaLocalRef<jobject> >( | |
134 env, jvalue_callback); | |
135 } | |
136 | |
137 namespace { | |
138 | |
139 template <typename T> | |
140 ScopedJavaLocalRef<jobject> ToJavaCallbackTemplate( | |
141 JNIEnv* env, | |
142 const base::Callback<void(T)>& callback) { | |
143 Callback<void(T)>* native_callback = new Callback<void(T)>(callback); | |
144 ScopedJavaLocalRef<jobject> jvalue_callback = Java_NativeCallbackInt_create( | |
145 env, reinterpret_cast<int>(native_callback)); | |
146 | |
147 return jvalue_callback; | |
148 } | |
149 | |
150 } // namespace | |
151 | |
152 ScopedJavaLocalRef<jobject> CallbackJNIBridge::ToJavaCallbackInt( | |
153 JNIEnv* env, | |
154 const Callback<void(int)>& callback) { | |
155 return ToJavaCallbackTemplate(env, callback); | |
156 } | |
157 | |
158 ScopedJavaLocalRef<jobject> CallbackJNIBridge::ToJavaCallbackLong( | |
159 JNIEnv* env, | |
160 const Callback<void(long)>& callback) { | |
161 return ToJavaCallbackTemplate(env, callback); | |
162 } | |
163 | |
164 ScopedJavaLocalRef<jobject> CallbackJNIBridge::ToJavaCallbackBool( | |
165 JNIEnv* env, | |
166 const Callback<void(bool)>& callback) { | |
167 return ToJavaCallbackTemplate(env, callback); | |
168 } | |
169 | |
170 ScopedJavaLocalRef<jobject> CallbackJNIBridge::ToJavaCallbackObj( | |
171 JNIEnv* env, | |
172 const base::Callback<void(ScopedJavaLocalRef<jobject>)>& callback) { | |
173 Callback<void(ScopedJavaLocalRef<jobject>)>* native_callback = | |
174 new Callback<void(ScopedJavaLocalRef<jobject>)>(callback); | |
175 ScopedJavaLocalRef<jobject> jvalue_callback = | |
176 Java_NativeCallback_create( | |
177 env, reinterpret_cast<int>(native_callback)); | |
178 | |
179 return jvalue_callback; | |
180 } | |
181 | |
182 // static methods ------------------------------------------------------------- | |
183 namespace { | |
184 | |
185 template <typename T> | |
186 void DestroyTemplate(JNIEnv* env, jclass clazz, jint callbackPtr) { | |
187 Callback<void(T)>* native_callback = | |
188 reinterpret_cast<Callback<void(T)>*>(callbackPtr); | |
189 delete native_callback; | |
190 } | |
191 | |
192 template <typename T, typename JT> | |
193 static void InvokeTemplate(JNIEnv* env, | |
194 jclass clazz, | |
195 jint callbackPtr, | |
196 JT value) { | |
197 Callback<void(T)>* native_callback = | |
198 reinterpret_cast<Callback<void(T)>*>(callbackPtr); | |
199 native_callback->Run(value); | |
200 } | |
201 | |
202 } // namespace | |
203 | |
204 static void DestroyInt(JNIEnv* env, jclass clazz, jint callbackPtr) { | |
205 DestroyTemplate<int>(env, clazz, callbackPtr); | |
206 } | |
207 | |
208 static void InvokeInt(JNIEnv* env, jclass clazz, jint callbackPtr, jint value) { | |
209 InvokeTemplate<int, jint>(env, clazz, callbackPtr, value); | |
210 } | |
211 | |
212 static void DestroyLong(JNIEnv* env, jclass clazz, jint callbackPtr) { | |
213 DestroyTemplate<long>(env, clazz, callbackPtr); | |
214 } | |
215 | |
216 static void InvokeLong(JNIEnv* env, | |
217 jclass clazz, | |
218 jint callbackPtr, | |
219 jlong value) { | |
220 InvokeTemplate<long, jlong>(env, clazz, callbackPtr, value); | |
221 } | |
222 | |
223 static void DestroyBoolean(JNIEnv* env, jclass clazz, jint callbackPtr) { | |
224 DestroyTemplate<bool>(env, clazz, callbackPtr); | |
225 } | |
226 | |
227 static void InvokeBoolean(JNIEnv* env, | |
228 jclass clazz, | |
229 jint callbackPtr, | |
230 jboolean value) { | |
231 InvokeTemplate<bool, jboolean>(env, clazz, callbackPtr, value); | |
232 } | |
233 | |
234 static void DestroyObj(JNIEnv* env, jclass clazz, jint callbackPtr) { | |
235 DestroyTemplate<ScopedJavaLocalRef<jobject> >(env, clazz, callbackPtr); | |
236 } | |
237 | |
238 static void InvokeObj(JNIEnv* env, | |
239 jclass clazz, | |
240 jint callbackPtr, | |
241 jobject value) { | |
242 ScopedJavaLocalRef<jobject> jvalue(env, value); | |
243 InvokeTemplate<ScopedJavaLocalRef<jobject>, | |
244 const ScopedJavaLocalRef<jobject>&>(env, | |
245 clazz, | |
246 callbackPtr, | |
247 jvalue); | |
248 } | |
249 | |
250 bool RegisterCallbackJNIBridge(JNIEnv* env) { | |
251 return RegisterNativesImpl(env); | |
252 } | |
253 | |
254 } // namespace android_webview | |
OLD | NEW |