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

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

Issue 345753003: [Android] Java Bridge with Gin: implement Java Bridge dispatcher (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use an enum for passing error codes Created 6 years, 5 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"
11 #include "base/android/jni_string.h" 11 #include "base/android/jni_string.h"
12 #include "base/float_util.h" 12 #include "base/float_util.h"
13 #include "content/browser/renderer_host/java/gin_java_script_to_java_types_coerc ion.h" 13 #include "content/browser/renderer_host/java/gin_java_script_to_java_types_coerc ion.h"
14 #include "content/browser/renderer_host/java/java_method.h" 14 #include "content/browser/renderer_host/java/java_method.h"
15 #include "content/browser/renderer_host/java/jni_helper.h" 15 #include "content/browser/renderer_host/java/jni_helper.h"
16 #include "content/common/android/gin_java_bridge_value.h" 16 #include "content/common/android/gin_java_bridge_value.h"
17 #include "content/public/browser/browser_thread.h" 17 #include "content/public/browser/browser_thread.h"
18 18
19 using base::android::AttachCurrentThread; 19 using base::android::AttachCurrentThread;
20 using base::android::ScopedJavaLocalRef; 20 using base::android::ScopedJavaLocalRef;
21 21
22 namespace content { 22 namespace content {
23 23
24 namespace { 24 namespace {
25 25
26 const char kObjectIsGone[] = "Java object is gone";
27 const char kMethodNotFound[] = "Method not found";
28 const char kAccessToObjectGetClassIsBlocked[] =
29 "Access to java.lang.Object.getClass is blocked";
30 const char kJavaExceptionRaised[] =
31 "Java exception has been raised during method invocation";
32
33 // See frameworks/base/core/java/android/webkit/EventLogTags.logtags 26 // See frameworks/base/core/java/android/webkit/EventLogTags.logtags
34 const int kObjectGetClassInvocationAttemptLogTag = 70151; 27 const int kObjectGetClassInvocationAttemptLogTag = 70151;
35 28
36 } // namespace 29 } // namespace
37 30
38 GinJavaMethodInvocationHelper::GinJavaMethodInvocationHelper( 31 GinJavaMethodInvocationHelper::GinJavaMethodInvocationHelper(
39 scoped_ptr<ObjectDelegate> object, 32 scoped_ptr<ObjectDelegate> object,
40 const std::string& method_name, 33 const std::string& method_name,
41 const base::ListValue& arguments) 34 const base::ListValue& arguments)
42 : object_(object.Pass()), 35 : object_(object.Pass()),
43 method_name_(method_name), 36 method_name_(method_name),
44 arguments_(arguments.DeepCopy()) { 37 arguments_(arguments.DeepCopy()),
38 invocation_error_(kGinJavaBridgeNoError) {
45 } 39 }
46 40
47 GinJavaMethodInvocationHelper::~GinJavaMethodInvocationHelper() {} 41 GinJavaMethodInvocationHelper::~GinJavaMethodInvocationHelper() {}
48 42
49 void GinJavaMethodInvocationHelper::Init(DispatcherDelegate* dispatcher) { 43 void GinJavaMethodInvocationHelper::Init(DispatcherDelegate* dispatcher) {
50 // Build on the UI thread a map of object_id -> WeakRef for Java objects from 44 // Build on the UI thread a map of object_id -> WeakRef for Java objects from
51 // |arguments_|. Then we can use this map on the background thread without 45 // |arguments_|. Then we can use this map on the background thread without
52 // accessing |dispatcher|. 46 // accessing |dispatcher|.
53 BuildObjectRefsFromListValue(dispatcher, arguments_.get()); 47 BuildObjectRefsFromListValue(dispatcher, arguments_.get());
54 } 48 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 } 108 }
115 } 109 }
116 return true; 110 return true;
117 } 111 }
118 112
119 void GinJavaMethodInvocationHelper::Invoke() { 113 void GinJavaMethodInvocationHelper::Invoke() {
120 JNIEnv* env = AttachCurrentThread(); 114 JNIEnv* env = AttachCurrentThread();
121 const JavaMethod* method = 115 const JavaMethod* method =
122 object_->FindMethod(method_name_, arguments_->GetSize()); 116 object_->FindMethod(method_name_, arguments_->GetSize());
123 if (!method) { 117 if (!method) {
124 SetInvocationFailure(kMethodNotFound); 118 SetInvocationError(kGinJavaBridgeMethodNotFound);
125 return; 119 return;
126 } 120 }
127 121
128 if (object_->IsObjectGetClassMethod(method)) { 122 if (object_->IsObjectGetClassMethod(method)) {
129 base::android::EventLogWriteInt(kObjectGetClassInvocationAttemptLogTag, 123 base::android::EventLogWriteInt(kObjectGetClassInvocationAttemptLogTag,
130 getuid()); 124 getuid());
131 SetInvocationFailure(kAccessToObjectGetClassIsBlocked); 125 SetInvocationError(kGinJavaBridgeAccessToObjectGetClassIsBlocked);
132 return; 126 return;
133 } 127 }
134 128
135 ScopedJavaLocalRef<jobject> obj; 129 ScopedJavaLocalRef<jobject> obj;
136 ScopedJavaLocalRef<jclass> cls; 130 ScopedJavaLocalRef<jclass> cls;
137 if (method->is_static()) { 131 if (method->is_static()) {
138 cls = object_->GetLocalClassRef(env); 132 cls = object_->GetLocalClassRef(env);
139 } else { 133 } else {
140 obj = object_->GetLocalRef(env); 134 obj = object_->GetLocalRef(env);
141 } 135 }
142 if (obj.is_null() && cls.is_null()) { 136 if (obj.is_null() && cls.is_null()) {
143 SetInvocationFailure(kObjectIsGone); 137 SetInvocationError(kGinJavaBridgeObjectIsGone);
144 return; 138 return;
145 } 139 }
146 140
147 std::vector<jvalue> parameters(method->num_parameters()); 141 std::vector<jvalue> parameters(method->num_parameters());
148 for (size_t i = 0; i < method->num_parameters(); ++i) { 142 for (size_t i = 0; i < method->num_parameters(); ++i) {
149 const base::Value* argument; 143 const base::Value* argument;
150 arguments_->Get(i, &argument); 144 arguments_->Get(i, &argument);
151 parameters[i] = CoerceJavaScriptValueToJavaValue( 145 parameters[i] = CoerceJavaScriptValueToJavaValue(
152 env, argument, method->parameter_type(i), true, object_refs_); 146 env, argument, method->parameter_type(i), true, object_refs_);
153 } 147 }
154 if (method->is_static()) { 148 if (method->is_static()) {
155 InvokeMethod( 149 InvokeMethod(
156 NULL, cls.obj(), method->return_type(), method->id(), &parameters[0]); 150 NULL, cls.obj(), method->return_type(), method->id(), &parameters[0]);
157 } else { 151 } else {
158 InvokeMethod( 152 InvokeMethod(
159 obj.obj(), NULL, method->return_type(), method->id(), &parameters[0]); 153 obj.obj(), NULL, method->return_type(), method->id(), &parameters[0]);
160 } 154 }
161 155
162 // Now that we're done with the jvalue, release any local references created 156 // Now that we're done with the jvalue, release any local references created
163 // by CoerceJavaScriptValueToJavaValue(). 157 // by CoerceJavaScriptValueToJavaValue().
164 for (size_t i = 0; i < method->num_parameters(); ++i) { 158 for (size_t i = 0; i < method->num_parameters(); ++i) {
165 ReleaseJavaValueIfRequired(env, &parameters[i], method->parameter_type(i)); 159 ReleaseJavaValueIfRequired(env, &parameters[i], method->parameter_type(i));
166 } 160 }
167 } 161 }
168 162
169 void GinJavaMethodInvocationHelper::SetInvocationFailure( 163 void GinJavaMethodInvocationHelper::SetInvocationError(
170 const char* error_message) { 164 GinJavaBridgeError error) {
171 holds_primitive_result_ = true; 165 holds_primitive_result_ = true;
172 primitive_result_.reset(new base::ListValue()); 166 primitive_result_.reset(new base::ListValue());
173 error_message_ = error_message; 167 invocation_error_ = error;
174 } 168 }
175 169
176 void GinJavaMethodInvocationHelper::SetPrimitiveResult( 170 void GinJavaMethodInvocationHelper::SetPrimitiveResult(
177 const base::ListValue& result_wrapper) { 171 const base::ListValue& result_wrapper) {
178 holds_primitive_result_ = true; 172 holds_primitive_result_ = true;
179 primitive_result_.reset(result_wrapper.DeepCopy()); 173 primitive_result_.reset(result_wrapper.DeepCopy());
180 } 174 }
181 175
182 void GinJavaMethodInvocationHelper::SetObjectResult( 176 void GinJavaMethodInvocationHelper::SetObjectResult(
183 const base::android::JavaRef<jobject>& object, 177 const base::android::JavaRef<jobject>& object,
(...skipping 14 matching lines...) Expand all
198 const base::android::JavaRef<jobject>& 192 const base::android::JavaRef<jobject>&
199 GinJavaMethodInvocationHelper::GetObjectResult() { 193 GinJavaMethodInvocationHelper::GetObjectResult() {
200 return object_result_; 194 return object_result_;
201 } 195 }
202 196
203 const base::android::JavaRef<jclass>& 197 const base::android::JavaRef<jclass>&
204 GinJavaMethodInvocationHelper::GetSafeAnnotationClass() { 198 GinJavaMethodInvocationHelper::GetSafeAnnotationClass() {
205 return safe_annotation_clazz_; 199 return safe_annotation_clazz_;
206 } 200 }
207 201
208 const std::string& GinJavaMethodInvocationHelper::GetErrorMessage() { 202 const GinJavaBridgeError GinJavaMethodInvocationHelper::GetInvocationError() {
209 return error_message_; 203 return invocation_error_;
210 } 204 }
211 205
212 void GinJavaMethodInvocationHelper::InvokeMethod(jobject object, 206 void GinJavaMethodInvocationHelper::InvokeMethod(jobject object,
213 jclass clazz, 207 jclass clazz,
214 const JavaType& return_type, 208 const JavaType& return_type,
215 jmethodID id, 209 jmethodID id,
216 jvalue* parameters) { 210 jvalue* parameters) {
217 DCHECK(object || clazz); 211 DCHECK(object || clazz);
218 JNIEnv* env = AttachCurrentThread(); 212 JNIEnv* env = AttachCurrentThread();
219 base::ListValue result_wrapper; 213 base::ListValue result_wrapper;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 GinJavaBridgeValue::CreateUndefinedValue().release()); 282 GinJavaBridgeValue::CreateUndefinedValue().release());
289 break; 283 break;
290 case JavaType::TypeString: { 284 case JavaType::TypeString: {
291 jstring java_string = static_cast<jstring>( 285 jstring java_string = static_cast<jstring>(
292 object ? env->CallObjectMethodA(object, id, parameters) 286 object ? env->CallObjectMethodA(object, id, parameters)
293 : env->CallStaticObjectMethodA(clazz, id, parameters)); 287 : env->CallStaticObjectMethodA(clazz, id, parameters));
294 // If an exception was raised, we must clear it before calling most JNI 288 // If an exception was raised, we must clear it before calling most JNI
295 // methods. ScopedJavaLocalRef is liable to make such calls, so we test 289 // methods. ScopedJavaLocalRef is liable to make such calls, so we test
296 // first. 290 // first.
297 if (base::android::ClearException(env)) { 291 if (base::android::ClearException(env)) {
298 SetInvocationFailure(kJavaExceptionRaised); 292 SetInvocationError(kGinJavaBridgeJavaExceptionRaised);
299 return; 293 return;
300 } 294 }
301 ScopedJavaLocalRef<jstring> scoped_java_string(env, java_string); 295 ScopedJavaLocalRef<jstring> scoped_java_string(env, java_string);
302 if (!scoped_java_string.obj()) { 296 if (!scoped_java_string.obj()) {
303 // LIVECONNECT_COMPLIANCE: Existing behavior is to return undefined. 297 // LIVECONNECT_COMPLIANCE: Existing behavior is to return undefined.
304 // Spec requires returning a null string. 298 // Spec requires returning a null string.
305 result_wrapper.Append( 299 result_wrapper.Append(
306 GinJavaBridgeValue::CreateUndefinedValue().release()); 300 GinJavaBridgeValue::CreateUndefinedValue().release());
307 break; 301 break;
308 } 302 }
309 result_wrapper.AppendString( 303 result_wrapper.AppendString(
310 base::android::ConvertJavaStringToUTF8(scoped_java_string)); 304 base::android::ConvertJavaStringToUTF8(scoped_java_string));
311 break; 305 break;
312 } 306 }
313 case JavaType::TypeObject: { 307 case JavaType::TypeObject: {
314 // If an exception was raised, we must clear it before calling most JNI 308 // If an exception was raised, we must clear it before calling most JNI
315 // methods. ScopedJavaLocalRef is liable to make such calls, so we test 309 // methods. ScopedJavaLocalRef is liable to make such calls, so we test
316 // first. 310 // first.
317 jobject java_object = 311 jobject java_object =
318 object ? env->CallObjectMethodA(object, id, parameters) 312 object ? env->CallObjectMethodA(object, id, parameters)
319 : env->CallStaticObjectMethodA(clazz, id, parameters); 313 : env->CallStaticObjectMethodA(clazz, id, parameters);
320 if (base::android::ClearException(env)) { 314 if (base::android::ClearException(env)) {
321 SetInvocationFailure(kJavaExceptionRaised); 315 SetInvocationError(kGinJavaBridgeJavaExceptionRaised);
322 return; 316 return;
323 } 317 }
324 ScopedJavaLocalRef<jobject> scoped_java_object(env, java_object); 318 ScopedJavaLocalRef<jobject> scoped_java_object(env, java_object);
325 if (!scoped_java_object.obj()) { 319 if (!scoped_java_object.obj()) {
326 result_wrapper.Append(base::Value::CreateNullValue()); 320 result_wrapper.Append(base::Value::CreateNullValue());
327 break; 321 break;
328 } 322 }
329 SetObjectResult(scoped_java_object, object_->GetSafeAnnotationClass()); 323 SetObjectResult(scoped_java_object, object_->GetSafeAnnotationClass());
330 return; 324 return;
331 } 325 }
332 } 326 }
333 // This is for all cases except JavaType::TypeObject. 327 // This is for all cases except JavaType::TypeObject.
334 if (!base::android::ClearException(env)) { 328 if (!base::android::ClearException(env)) {
335 SetPrimitiveResult(result_wrapper); 329 SetPrimitiveResult(result_wrapper);
336 } else { 330 } else {
337 SetInvocationFailure(kJavaExceptionRaised); 331 SetInvocationError(kGinJavaBridgeJavaExceptionRaised);
338 } 332 }
339 } 333 }
340 334
341 } // namespace content 335 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698