gin_java_method_invocation_helper.cc revision 116680a4aac90f2aa7413d9095a592090648e557
1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file. 4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/android/java/gin_java_method_invocation_helper.h" 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <unistd.h> 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/android/event_log.h" 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/android/jni_android.h" 11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/float_util.h" 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/android/java/gin_java_script_to_java_types_coercion.h" 13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/android/java/java_method.h" 14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/android/java/jni_helper.h" 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/common/android/gin_java_bridge_value.h" 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "third_party/WebKit/public/platform/WebString.h" 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using base::android::AttachCurrentThread; 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using base::android::ScopedJavaLocalRef; 21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace content { 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace { 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// See frameworks/base/core/java/android/webkit/EventLogTags.logtags 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const int kObjectGetClassInvocationAttemptLogTag = 70151; 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// This is an intermediate solution until we fix http://crbug.com/391492. 30116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstd::string ConvertJavaStringToUTF8(JNIEnv* env, jstring str) { 31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const jchar* chars = env->GetStringChars(str, NULL); 32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(chars); 33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blink::WebString utf16(chars, env->GetStringLength(str)); 34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch env->ReleaseStringChars(str, chars); 35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return utf16.utf8(); 36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)GinJavaMethodInvocationHelper::GinJavaMethodInvocationHelper( 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<ObjectDelegate> object, 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& method_name, 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::ListValue& arguments) 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : object_(object.Pass()), 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) method_name_(method_name), 46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch arguments_(arguments.DeepCopy()), 47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch invocation_error_(kGinJavaBridgeNoError) { 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)GinJavaMethodInvocationHelper::~GinJavaMethodInvocationHelper() {} 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void GinJavaMethodInvocationHelper::Init(DispatcherDelegate* dispatcher) { 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Build on the UI thread a map of object_id -> WeakRef for Java objects from 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // |arguments_|. Then we can use this map on the background thread without 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // accessing |dispatcher|. 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) BuildObjectRefsFromListValue(dispatcher, arguments_.get()); 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// As V8ValueConverter has finite recursion depth when serializing 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// JavaScript values, we don't bother about having a recursion threshold here. 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void GinJavaMethodInvocationHelper::BuildObjectRefsFromListValue( 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DispatcherDelegate* dispatcher, 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::Value* list_value) { 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(list_value->IsType(base::Value::TYPE_LIST)); 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::ListValue* list; 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) list_value->GetAsList(&list); 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (base::ListValue::const_iterator iter = list->begin(); 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) iter != list->end(); 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ++iter) { 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (AppendObjectRef(dispatcher, *iter)) 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) continue; 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if ((*iter)->IsType(base::Value::TYPE_LIST)) { 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) BuildObjectRefsFromListValue(dispatcher, *iter); 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else if ((*iter)->IsType(base::Value::TYPE_DICTIONARY)) { 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) BuildObjectRefsFromDictionaryValue(dispatcher, *iter); 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void GinJavaMethodInvocationHelper::BuildObjectRefsFromDictionaryValue( 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DispatcherDelegate* dispatcher, 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::Value* dict_value) { 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(dict_value->IsType(base::Value::TYPE_DICTIONARY)); 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::DictionaryValue* dict; 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dict_value->GetAsDictionary(&dict); 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (base::DictionaryValue::Iterator iter(*dict); 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) !iter.IsAtEnd(); 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) iter.Advance()) { 89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (AppendObjectRef(dispatcher, &iter.value())) 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) continue; 91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (iter.value().IsType(base::Value::TYPE_LIST)) { 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) BuildObjectRefsFromListValue(dispatcher, &iter.value()); 93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else if (iter.value().IsType(base::Value::TYPE_DICTIONARY)) { 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) BuildObjectRefsFromDictionaryValue(dispatcher, &iter.value()); 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool GinJavaMethodInvocationHelper::AppendObjectRef( 100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DispatcherDelegate* dispatcher, 101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::Value* raw_value) { 102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!GinJavaBridgeValue::ContainsGinJavaBridgeValue(raw_value)) 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<const GinJavaBridgeValue> value( 105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GinJavaBridgeValue::FromValue(raw_value)); 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!value->IsType(GinJavaBridgeValue::TYPE_OBJECT_ID)) 107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GinJavaBoundObject::ObjectID object_id; 109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (value->GetAsObjectID(&object_id)) { 110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ObjectRefs::iterator iter = object_refs_.find(object_id); 111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (iter == object_refs_.end()) { 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) JavaObjectWeakGlobalRef object_ref( 113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dispatcher->GetObjectWeakRef(object_id)); 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!object_ref.is_empty()) { 115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) object_refs_.insert(std::make_pair(object_id, object_ref)); 116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void GinJavaMethodInvocationHelper::Invoke() { 123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) JNIEnv* env = AttachCurrentThread(); 124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const JavaMethod* method = 125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) object_->FindMethod(method_name_, arguments_->GetSize()); 126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!method) { 127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SetInvocationError(kGinJavaBridgeMethodNotFound); 128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (object_->IsObjectGetClassMethod(method)) { 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::android::EventLogWriteInt(kObjectGetClassInvocationAttemptLogTag, 133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) getuid()); 134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SetInvocationError(kGinJavaBridgeAccessToObjectGetClassIsBlocked); 135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ScopedJavaLocalRef<jobject> obj; 1396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ScopedJavaLocalRef<jclass> cls; 1406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (method->is_static()) { 1416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) cls = object_->GetLocalClassRef(env); 1426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } else { 1436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) obj = object_->GetLocalRef(env); 1446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (obj.is_null() && cls.is_null()) { 146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SetInvocationError(kGinJavaBridgeObjectIsGone); 1476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return; 1486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GinJavaBridgeError coercion_error = kGinJavaBridgeNoError; 151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<jvalue> parameters(method->num_parameters()); 152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (size_t i = 0; i < method->num_parameters(); ++i) { 153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::Value* argument; 154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) arguments_->Get(i, &argument); 155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch parameters[i] = CoerceJavaScriptValueToJavaValue(env, 156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch argument, 157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch method->parameter_type(i), 158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch true, 159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch object_refs_, 160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &coercion_error); 161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (coercion_error == kGinJavaBridgeNoError) { 164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (method->is_static()) { 165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch InvokeMethod( 166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NULL, cls.obj(), method->return_type(), method->id(), ¶meters[0]); 167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch InvokeMethod( 169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch obj.obj(), NULL, method->return_type(), method->id(), ¶meters[0]); 170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 1716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } else { 172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SetInvocationError(coercion_error); 1736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Now that we're done with the jvalue, release any local references created 176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // by CoerceJavaScriptValueToJavaValue(). 177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (size_t i = 0; i < method->num_parameters(); ++i) { 178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ReleaseJavaValueIfRequired(env, ¶meters[i], method->parameter_type(i)); 179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 182116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid GinJavaMethodInvocationHelper::SetInvocationError( 183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GinJavaBridgeError error) { 184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) holds_primitive_result_ = true; 185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) primitive_result_.reset(new base::ListValue()); 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch invocation_error_ = error; 187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void GinJavaMethodInvocationHelper::SetPrimitiveResult( 190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::ListValue& result_wrapper) { 191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) holds_primitive_result_ = true; 192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) primitive_result_.reset(result_wrapper.DeepCopy()); 193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void GinJavaMethodInvocationHelper::SetObjectResult( 196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::android::JavaRef<jobject>& object, 197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::android::JavaRef<jclass>& safe_annotation_clazz) { 198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) holds_primitive_result_ = false; 199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) object_result_.Reset(object); 200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) safe_annotation_clazz_.Reset(safe_annotation_clazz); 201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool GinJavaMethodInvocationHelper::HoldsPrimitiveResult() { 204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return holds_primitive_result_; 205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const base::ListValue& GinJavaMethodInvocationHelper::GetPrimitiveResult() { 208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return *primitive_result_.get(); 209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const base::android::JavaRef<jobject>& 212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)GinJavaMethodInvocationHelper::GetObjectResult() { 213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return object_result_; 214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const base::android::JavaRef<jclass>& 217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)GinJavaMethodInvocationHelper::GetSafeAnnotationClass() { 218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return safe_annotation_clazz_; 219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 221116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst GinJavaBridgeError GinJavaMethodInvocationHelper::GetInvocationError() { 222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return invocation_error_; 223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void GinJavaMethodInvocationHelper::InvokeMethod(jobject object, 2266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) jclass clazz, 227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const JavaType& return_type, 228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jmethodID id, 229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jvalue* parameters) { 2306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) DCHECK(object || clazz); 231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) JNIEnv* env = AttachCurrentThread(); 232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::ListValue result_wrapper; 233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (return_type.type) { 234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeBoolean: 235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result_wrapper.AppendBoolean( 2366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) object ? env->CallBooleanMethodA(object, id, parameters) 2376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) : env->CallStaticBooleanMethodA(clazz, id, parameters)); 238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeByte: 240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result_wrapper.AppendInteger( 2416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) object ? env->CallByteMethodA(object, id, parameters) 2426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) : env->CallStaticByteMethodA(clazz, id, parameters)); 243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeChar: 245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result_wrapper.AppendInteger( 2466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) object ? env->CallCharMethodA(object, id, parameters) 2476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) : env->CallStaticCharMethodA(clazz, id, parameters)); 248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeShort: 250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result_wrapper.AppendInteger( 2516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) object ? env->CallShortMethodA(object, id, parameters) 2526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) : env->CallStaticShortMethodA(clazz, id, parameters)); 253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeInt: 255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result_wrapper.AppendInteger( 2566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) object ? env->CallIntMethodA(object, id, parameters) 2576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) : env->CallStaticIntMethodA(clazz, id, parameters)); 258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeLong: 260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result_wrapper.AppendDouble( 2616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) object ? env->CallLongMethodA(object, id, parameters) 2626d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) : env->CallStaticLongMethodA(clazz, id, parameters)); 263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeFloat: { 2656d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) float result = object 2666d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ? env->CallFloatMethodA(object, id, parameters) 2676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) : env->CallStaticFloatMethodA(clazz, id, parameters); 268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (base::IsFinite(result)) { 269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result_wrapper.AppendDouble(result); 270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else { 271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result_wrapper.Append( 272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GinJavaBridgeValue::CreateNonFiniteValue(result).release()); 273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeDouble: { 2776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) double result = object 2786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ? env->CallDoubleMethodA(object, id, parameters) 2796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) : env->CallStaticDoubleMethodA(clazz, id, parameters); 280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (base::IsFinite(result)) { 281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result_wrapper.AppendDouble(result); 282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else { 283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result_wrapper.Append( 284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GinJavaBridgeValue::CreateNonFiniteValue(result).release()); 285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeVoid: 2896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (object) 2906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) env->CallVoidMethodA(object, id, parameters); 2916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) else 2926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) env->CallStaticVoidMethodA(clazz, id, parameters); 293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result_wrapper.Append( 294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GinJavaBridgeValue::CreateUndefinedValue().release()); 295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeArray: 297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to not call methods that 298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // return arrays. Spec requires calling the method and converting the 299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // result to a JavaScript array. 300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result_wrapper.Append( 301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GinJavaBridgeValue::CreateUndefinedValue().release()); 302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeString: { 304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jstring java_string = static_cast<jstring>( 3056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) object ? env->CallObjectMethodA(object, id, parameters) 3066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) : env->CallStaticObjectMethodA(clazz, id, parameters)); 307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // If an exception was raised, we must clear it before calling most JNI 308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // methods. ScopedJavaLocalRef is liable to make such calls, so we test 309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // first. 310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (base::android::ClearException(env)) { 311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SetInvocationError(kGinJavaBridgeJavaExceptionRaised); 312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedJavaLocalRef<jstring> scoped_java_string(env, java_string); 315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!scoped_java_string.obj()) { 316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to return undefined. 317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Spec requires returning a null string. 318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result_wrapper.Append( 319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GinJavaBridgeValue::CreateUndefinedValue().release()); 320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result_wrapper.AppendString( 323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ConvertJavaStringToUTF8(env, scoped_java_string.obj())); 324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeObject: { 327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // If an exception was raised, we must clear it before calling most JNI 328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // methods. ScopedJavaLocalRef is liable to make such calls, so we test 329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // first. 3306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) jobject java_object = 3316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) object ? env->CallObjectMethodA(object, id, parameters) 3326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) : env->CallStaticObjectMethodA(clazz, id, parameters); 333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (base::android::ClearException(env)) { 334116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SetInvocationError(kGinJavaBridgeJavaExceptionRaised); 335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedJavaLocalRef<jobject> scoped_java_object(env, java_object); 338f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!scoped_java_object.obj()) { 339f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result_wrapper.Append(base::Value::CreateNullValue()); 340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 342f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SetObjectResult(scoped_java_object, object_->GetSafeAnnotationClass()); 343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 344f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 345f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 346f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // This is for all cases except JavaType::TypeObject. 347f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!base::android::ClearException(env)) { 348f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SetPrimitiveResult(result_wrapper); 349f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else { 350116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SetInvocationError(kGinJavaBridgeJavaExceptionRaised); 351f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 352f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 353f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 354f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace content 355