Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(84)

Side by Side Diff: content/browser/renderer_host/java/gin_java_method_invocation_helper.cc

Issue 323403007: [Android] Java Bridge with Gin: implement Java bound object (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/renderer_host/java/gin_java_method_invocation_helper.h " 5 #include "content/browser/renderer_host/java/gin_java_method_invocation_helper.h "
6 6
7 #include <unistd.h> 7 #include <unistd.h>
8 8
9 #include "base/android/event_log.h" 9 #include "base/android/event_log.h"
10 #include "base/android/jni_android.h" 10 #include "base/android/jni_android.h"
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 if (!object_ref.is_empty()) { 111 if (!object_ref.is_empty()) {
112 object_refs_.insert(std::make_pair(object_id, object_ref)); 112 object_refs_.insert(std::make_pair(object_id, object_ref));
113 } 113 }
114 } 114 }
115 } 115 }
116 return true; 116 return true;
117 } 117 }
118 118
119 void GinJavaMethodInvocationHelper::Invoke() { 119 void GinJavaMethodInvocationHelper::Invoke() {
120 JNIEnv* env = AttachCurrentThread(); 120 JNIEnv* env = AttachCurrentThread();
121 ScopedJavaLocalRef<jobject> obj(object_->GetLocalRef(env));
122 if (obj.is_null()) {
123 SetInvocationFailure(kObjectIsGone);
124 return;
125 }
126 const JavaMethod* method = 121 const JavaMethod* method =
127 object_->FindMethod(method_name_, arguments_->GetSize()); 122 object_->FindMethod(method_name_, arguments_->GetSize());
128 if (!method) { 123 if (!method) {
129 SetInvocationFailure(kMethodNotFound); 124 SetInvocationFailure(kMethodNotFound);
130 return; 125 return;
131 } 126 }
132 127
133 if (object_->IsObjectGetClassMethod(method)) { 128 if (object_->IsObjectGetClassMethod(method)) {
134 base::android::EventLogWriteInt(kObjectGetClassInvocationAttemptLogTag, 129 base::android::EventLogWriteInt(kObjectGetClassInvocationAttemptLogTag,
135 getuid()); 130 getuid());
136 SetInvocationFailure(kAccessToObjectGetClassIsBlocked); 131 SetInvocationFailure(kAccessToObjectGetClassIsBlocked);
137 return; 132 return;
138 } 133 }
139 134
135 ScopedJavaLocalRef<jobject> obj;
136 ScopedJavaLocalRef<jclass> cls;
137 if (method->is_static()) {
138 cls = object_->GetLocalClassRef(env);
139 } else {
140 obj = object_->GetLocalRef(env);
141 }
142 if (obj.is_null() && cls.is_null()) {
143 SetInvocationFailure(kObjectIsGone);
144 return;
145 }
146
140 std::vector<jvalue> parameters(method->num_parameters()); 147 std::vector<jvalue> parameters(method->num_parameters());
141 for (size_t i = 0; i < method->num_parameters(); ++i) { 148 for (size_t i = 0; i < method->num_parameters(); ++i) {
142 const base::Value* argument; 149 const base::Value* argument;
143 arguments_->Get(i, &argument); 150 arguments_->Get(i, &argument);
144 parameters[i] = CoerceJavaScriptValueToJavaValue( 151 parameters[i] = CoerceJavaScriptValueToJavaValue(
145 env, argument, method->parameter_type(i), true, object_refs_); 152 env, argument, method->parameter_type(i), true, object_refs_);
146 } 153 }
147 InvokeMethod(obj.obj(), method->return_type(), method->id(), &parameters[0]); 154 if (method->is_static()) {
155 InvokeMethod(
156 NULL, cls.obj(), method->return_type(), method->id(), &parameters[0]);
157 } else {
158 InvokeMethod(
159 obj.obj(), NULL, method->return_type(), method->id(), &parameters[0]);
160 }
148 161
149 // Now that we're done with the jvalue, release any local references created 162 // Now that we're done with the jvalue, release any local references created
150 // by CoerceJavaScriptValueToJavaValue(). 163 // by CoerceJavaScriptValueToJavaValue().
151 for (size_t i = 0; i < method->num_parameters(); ++i) { 164 for (size_t i = 0; i < method->num_parameters(); ++i) {
152 ReleaseJavaValueIfRequired(env, &parameters[i], method->parameter_type(i)); 165 ReleaseJavaValueIfRequired(env, &parameters[i], method->parameter_type(i));
153 } 166 }
154 } 167 }
155 168
156 void GinJavaMethodInvocationHelper::SetInvocationFailure( 169 void GinJavaMethodInvocationHelper::SetInvocationFailure(
157 const char* error_message) { 170 const char* error_message) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 const base::android::JavaRef<jclass>& 203 const base::android::JavaRef<jclass>&
191 GinJavaMethodInvocationHelper::GetSafeAnnotationClass() { 204 GinJavaMethodInvocationHelper::GetSafeAnnotationClass() {
192 return safe_annotation_clazz_; 205 return safe_annotation_clazz_;
193 } 206 }
194 207
195 const std::string& GinJavaMethodInvocationHelper::GetErrorMessage() { 208 const std::string& GinJavaMethodInvocationHelper::GetErrorMessage() {
196 return error_message_; 209 return error_message_;
197 } 210 }
198 211
199 void GinJavaMethodInvocationHelper::InvokeMethod(jobject object, 212 void GinJavaMethodInvocationHelper::InvokeMethod(jobject object,
213 jclass clazz,
200 const JavaType& return_type, 214 const JavaType& return_type,
201 jmethodID id, 215 jmethodID id,
202 jvalue* parameters) { 216 jvalue* parameters) {
217 DCHECK(object || clazz);
203 JNIEnv* env = AttachCurrentThread(); 218 JNIEnv* env = AttachCurrentThread();
204 base::ListValue result_wrapper; 219 base::ListValue result_wrapper;
205 switch (return_type.type) { 220 switch (return_type.type) {
206 case JavaType::TypeBoolean: 221 case JavaType::TypeBoolean:
207 result_wrapper.AppendBoolean( 222 result_wrapper.AppendBoolean(
208 env->CallBooleanMethodA(object, id, parameters)); 223 object ? env->CallBooleanMethodA(object, id, parameters)
224 : env->CallStaticBooleanMethodA(clazz, id, parameters));
209 break; 225 break;
210 case JavaType::TypeByte: 226 case JavaType::TypeByte:
211 result_wrapper.AppendInteger( 227 result_wrapper.AppendInteger(
212 env->CallByteMethodA(object, id, parameters)); 228 object ? env->CallByteMethodA(object, id, parameters)
229 : env->CallStaticByteMethodA(clazz, id, parameters));
213 break; 230 break;
214 case JavaType::TypeChar: 231 case JavaType::TypeChar:
215 result_wrapper.AppendInteger( 232 result_wrapper.AppendInteger(
216 env->CallCharMethodA(object, id, parameters)); 233 object ? env->CallCharMethodA(object, id, parameters)
234 : env->CallStaticCharMethodA(clazz, id, parameters));
217 break; 235 break;
218 case JavaType::TypeShort: 236 case JavaType::TypeShort:
219 result_wrapper.AppendInteger( 237 result_wrapper.AppendInteger(
220 env->CallShortMethodA(object, id, parameters)); 238 object ? env->CallShortMethodA(object, id, parameters)
239 : env->CallStaticShortMethodA(clazz, id, parameters));
221 break; 240 break;
222 case JavaType::TypeInt: 241 case JavaType::TypeInt:
223 result_wrapper.AppendInteger( 242 result_wrapper.AppendInteger(
224 env->CallIntMethodA(object, id, parameters)); 243 object ? env->CallIntMethodA(object, id, parameters)
244 : env->CallStaticIntMethodA(clazz, id, parameters));
225 break; 245 break;
226 case JavaType::TypeLong: 246 case JavaType::TypeLong:
227 result_wrapper.AppendDouble( 247 result_wrapper.AppendDouble(
228 env->CallLongMethodA(object, id, parameters)); 248 object ? env->CallLongMethodA(object, id, parameters)
249 : env->CallStaticLongMethodA(clazz, id, parameters));
229 break; 250 break;
230 case JavaType::TypeFloat: { 251 case JavaType::TypeFloat: {
231 float result = env->CallFloatMethodA(object, id, parameters); 252 float result = object
253 ? env->CallFloatMethodA(object, id, parameters)
254 : env->CallStaticFloatMethodA(clazz, id, parameters);
232 if (base::IsFinite(result)) { 255 if (base::IsFinite(result)) {
233 result_wrapper.AppendDouble(result); 256 result_wrapper.AppendDouble(result);
234 } else { 257 } else {
235 result_wrapper.Append( 258 result_wrapper.Append(
236 GinJavaBridgeValue::CreateNonFiniteValue(result).release()); 259 GinJavaBridgeValue::CreateNonFiniteValue(result).release());
237 } 260 }
238 break; 261 break;
239 } 262 }
240 case JavaType::TypeDouble: { 263 case JavaType::TypeDouble: {
241 double result = env->CallDoubleMethodA(object, id, parameters); 264 double result = object
265 ? env->CallDoubleMethodA(object, id, parameters)
266 : env->CallStaticDoubleMethodA(clazz, id, parameters);
242 if (base::IsFinite(result)) { 267 if (base::IsFinite(result)) {
243 result_wrapper.AppendDouble(result); 268 result_wrapper.AppendDouble(result);
244 } else { 269 } else {
245 result_wrapper.Append( 270 result_wrapper.Append(
246 GinJavaBridgeValue::CreateNonFiniteValue(result).release()); 271 GinJavaBridgeValue::CreateNonFiniteValue(result).release());
247 } 272 }
248 break; 273 break;
249 } 274 }
250 case JavaType::TypeVoid: 275 case JavaType::TypeVoid:
251 env->CallVoidMethodA(object, id, parameters); 276 if (object)
277 env->CallVoidMethodA(object, id, parameters);
278 else
279 env->CallStaticVoidMethodA(clazz, id, parameters);
252 result_wrapper.Append( 280 result_wrapper.Append(
253 GinJavaBridgeValue::CreateUndefinedValue().release()); 281 GinJavaBridgeValue::CreateUndefinedValue().release());
254 break; 282 break;
255 case JavaType::TypeArray: 283 case JavaType::TypeArray:
256 // LIVECONNECT_COMPLIANCE: Existing behavior is to not call methods that 284 // LIVECONNECT_COMPLIANCE: Existing behavior is to not call methods that
257 // return arrays. Spec requires calling the method and converting the 285 // return arrays. Spec requires calling the method and converting the
258 // result to a JavaScript array. 286 // result to a JavaScript array.
259 result_wrapper.Append( 287 result_wrapper.Append(
260 GinJavaBridgeValue::CreateUndefinedValue().release()); 288 GinJavaBridgeValue::CreateUndefinedValue().release());
261 break; 289 break;
262 case JavaType::TypeString: { 290 case JavaType::TypeString: {
263 jstring java_string = static_cast<jstring>( 291 jstring java_string = static_cast<jstring>(
264 env->CallObjectMethodA(object, id, parameters)); 292 object ? env->CallObjectMethodA(object, id, parameters)
293 : env->CallStaticObjectMethodA(clazz, id, parameters));
265 // If an exception was raised, we must clear it before calling most JNI 294 // If an exception was raised, we must clear it before calling most JNI
266 // methods. ScopedJavaLocalRef is liable to make such calls, so we test 295 // methods. ScopedJavaLocalRef is liable to make such calls, so we test
267 // first. 296 // first.
268 if (base::android::ClearException(env)) { 297 if (base::android::ClearException(env)) {
269 SetInvocationFailure(kJavaExceptionRaised); 298 SetInvocationFailure(kJavaExceptionRaised);
270 return; 299 return;
271 } 300 }
272 ScopedJavaLocalRef<jstring> scoped_java_string(env, java_string); 301 ScopedJavaLocalRef<jstring> scoped_java_string(env, java_string);
273 if (!scoped_java_string.obj()) { 302 if (!scoped_java_string.obj()) {
274 // LIVECONNECT_COMPLIANCE: Existing behavior is to return undefined. 303 // LIVECONNECT_COMPLIANCE: Existing behavior is to return undefined.
275 // Spec requires returning a null string. 304 // Spec requires returning a null string.
276 result_wrapper.Append( 305 result_wrapper.Append(
277 GinJavaBridgeValue::CreateUndefinedValue().release()); 306 GinJavaBridgeValue::CreateUndefinedValue().release());
278 break; 307 break;
279 } 308 }
280 result_wrapper.AppendString( 309 result_wrapper.AppendString(
281 base::android::ConvertJavaStringToUTF8(scoped_java_string)); 310 base::android::ConvertJavaStringToUTF8(scoped_java_string));
282 break; 311 break;
283 } 312 }
284 case JavaType::TypeObject: { 313 case JavaType::TypeObject: {
285 // If an exception was raised, we must clear it before calling most JNI 314 // If an exception was raised, we must clear it before calling most JNI
286 // methods. ScopedJavaLocalRef is liable to make such calls, so we test 315 // methods. ScopedJavaLocalRef is liable to make such calls, so we test
287 // first. 316 // first.
288 jobject java_object = env->CallObjectMethodA(object, id, parameters); 317 jobject java_object =
318 object ? env->CallObjectMethodA(object, id, parameters)
319 : env->CallStaticObjectMethodA(clazz, id, parameters);
289 if (base::android::ClearException(env)) { 320 if (base::android::ClearException(env)) {
290 SetInvocationFailure(kJavaExceptionRaised); 321 SetInvocationFailure(kJavaExceptionRaised);
291 return; 322 return;
292 } 323 }
293 ScopedJavaLocalRef<jobject> scoped_java_object(env, java_object); 324 ScopedJavaLocalRef<jobject> scoped_java_object(env, java_object);
294 if (!scoped_java_object.obj()) { 325 if (!scoped_java_object.obj()) {
295 result_wrapper.Append(base::Value::CreateNullValue()); 326 result_wrapper.Append(base::Value::CreateNullValue());
296 break; 327 break;
297 } 328 }
298 SetObjectResult(scoped_java_object, object_->GetSafeAnnotationClass()); 329 SetObjectResult(scoped_java_object, object_->GetSafeAnnotationClass());
299 return; 330 return;
300 } 331 }
301 } 332 }
302 // This is for all cases except JavaType::TypeObject. 333 // This is for all cases except JavaType::TypeObject.
303 if (!base::android::ClearException(env)) { 334 if (!base::android::ClearException(env)) {
304 SetPrimitiveResult(result_wrapper); 335 SetPrimitiveResult(result_wrapper);
305 } else { 336 } else {
306 SetInvocationFailure(kJavaExceptionRaised); 337 SetInvocationFailure(kJavaExceptionRaised);
307 } 338 }
308 } 339 }
309 340
310 } // namespace content 341 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698