| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/java_method.h" | 5 #include "content/browser/renderer_host/java/java_method.h" |
| 6 | 6 |
| 7 #include "base/android/jni_android.h" | 7 #include "base/android/jni_android.h" |
| 8 #include "base/android/jni_string.h" | 8 #include "base/android/jni_string.h" |
| 9 #include "base/memory/singleton.h" | 9 #include "base/memory/singleton.h" |
| 10 #include "base/string_util.h" // For ReplaceSubstringsAfterOffset | 10 #include "base/string_util.h" // For ReplaceSubstringsAfterOffset |
| 11 | 11 |
| 12 using base::android::AttachCurrentThread; | 12 using base::android::AttachCurrentThread; |
| 13 using base::android::ConvertJavaStringToUTF8; | 13 using base::android::ConvertJavaStringToUTF8; |
| 14 using base::android::MethodID; | 14 using base::android::GetMethodIDFromClassName; |
| 15 using base::android::ScopedJavaLocalRef; | 15 using base::android::ScopedJavaLocalRef; |
| 16 | 16 |
| 17 namespace { | 17 namespace { |
| 18 | 18 |
| 19 const char kGetName[] = "getName"; |
| 20 const char kGetDeclaringClass[] = "getDeclaringClass"; |
| 21 const char kGetParameterTypes[] = "getParameterTypes"; |
| 22 const char kGetReturnType[] = "getReturnType"; |
| 23 const char kJavaLangClass[] = "java/lang/Class"; |
| 24 const char kJavaLangReflectMethod[] = "java/lang/reflect/Method"; |
| 25 const char kReturningJavaLangClass[] = "()Ljava/lang/Class;"; |
| 26 const char kReturningJavaLangClassArray[] = "()[Ljava/lang/Class;"; |
| 27 const char kReturningJavaLangString[] = "()Ljava/lang/String;"; |
| 28 |
| 19 std::string BinaryNameToJNIName(const std::string& binary_name, | 29 std::string BinaryNameToJNIName(const std::string& binary_name, |
| 20 JavaType* type) { | 30 JavaType* type) { |
| 21 DCHECK(type); | 31 DCHECK(type); |
| 22 *type = JavaType::CreateFromBinaryName(binary_name); | 32 *type = JavaType::CreateFromBinaryName(binary_name); |
| 23 switch (type->type) { | 33 switch (type->type) { |
| 24 case JavaType::TypeBoolean: | 34 case JavaType::TypeBoolean: |
| 25 return "Z"; | 35 return "Z"; |
| 26 case JavaType::TypeByte: | 36 case JavaType::TypeByte: |
| 27 return "B"; | 37 return "B"; |
| 28 case JavaType::TypeChar: | 38 case JavaType::TypeChar: |
| (...skipping 14 matching lines...) Expand all Loading... |
| 43 return "["; | 53 return "["; |
| 44 default: | 54 default: |
| 45 DCHECK(type->type == JavaType::TypeString || | 55 DCHECK(type->type == JavaType::TypeString || |
| 46 type->type == JavaType::TypeObject); | 56 type->type == JavaType::TypeObject); |
| 47 std::string jni_name = "L" + binary_name + ";"; | 57 std::string jni_name = "L" + binary_name + ";"; |
| 48 ReplaceSubstringsAfterOffset(&jni_name, 0, ".", "/"); | 58 ReplaceSubstringsAfterOffset(&jni_name, 0, ".", "/"); |
| 49 return jni_name; | 59 return jni_name; |
| 50 } | 60 } |
| 51 } | 61 } |
| 52 | 62 |
| 53 class MethodGetParameterTypesID : public MethodID { | |
| 54 public: | |
| 55 static MethodGetParameterTypesID* GetInstance() { | |
| 56 return Singleton<MethodGetParameterTypesID>::get(); | |
| 57 } | |
| 58 private: | |
| 59 friend struct DefaultSingletonTraits<MethodGetParameterTypesID>; | |
| 60 MethodGetParameterTypesID() | |
| 61 : MethodID(AttachCurrentThread(), "java/lang/reflect/Method", | |
| 62 "getParameterTypes", "()[Ljava/lang/Class;") { | |
| 63 } | |
| 64 DISALLOW_COPY_AND_ASSIGN(MethodGetParameterTypesID); | |
| 65 }; | |
| 66 | |
| 67 class MethodGetNameID : public MethodID { | |
| 68 public: | |
| 69 static MethodGetNameID* GetInstance() { | |
| 70 return Singleton<MethodGetNameID>::get(); | |
| 71 } | |
| 72 private: | |
| 73 friend struct DefaultSingletonTraits<MethodGetNameID>; | |
| 74 MethodGetNameID() | |
| 75 : MethodID(AttachCurrentThread(), "java/lang/reflect/Method", | |
| 76 "getName", "()Ljava/lang/String;") { | |
| 77 } | |
| 78 DISALLOW_COPY_AND_ASSIGN(MethodGetNameID); | |
| 79 }; | |
| 80 | |
| 81 class MethodGetReturnTypeID : public MethodID { | |
| 82 public: | |
| 83 static MethodGetReturnTypeID* GetInstance() { | |
| 84 return Singleton<MethodGetReturnTypeID>::get(); | |
| 85 } | |
| 86 private: | |
| 87 friend struct DefaultSingletonTraits<MethodGetReturnTypeID>; | |
| 88 MethodGetReturnTypeID() | |
| 89 : MethodID(AttachCurrentThread(), "java/lang/reflect/Method", | |
| 90 "getReturnType", "()Ljava/lang/Class;") { | |
| 91 } | |
| 92 DISALLOW_COPY_AND_ASSIGN(MethodGetReturnTypeID); | |
| 93 }; | |
| 94 | |
| 95 class MethodGetDeclaringClassID : public MethodID { | |
| 96 public: | |
| 97 static MethodGetDeclaringClassID* GetInstance() { | |
| 98 return Singleton<MethodGetDeclaringClassID>::get(); | |
| 99 } | |
| 100 private: | |
| 101 friend struct DefaultSingletonTraits<MethodGetDeclaringClassID>; | |
| 102 MethodGetDeclaringClassID() | |
| 103 : MethodID(AttachCurrentThread(), "java/lang/reflect/Method", | |
| 104 "getDeclaringClass", "()Ljava/lang/Class;") { | |
| 105 } | |
| 106 DISALLOW_COPY_AND_ASSIGN(MethodGetDeclaringClassID); | |
| 107 }; | |
| 108 | |
| 109 class ClassGetNameID : public MethodID { | |
| 110 public: | |
| 111 static ClassGetNameID* GetInstance() { | |
| 112 return Singleton<ClassGetNameID>::get(); | |
| 113 } | |
| 114 private: | |
| 115 friend struct DefaultSingletonTraits<ClassGetNameID>; | |
| 116 ClassGetNameID() | |
| 117 : MethodID(AttachCurrentThread(), "java/lang/Class", "getName", | |
| 118 "()Ljava/lang/String;") { | |
| 119 } | |
| 120 DISALLOW_COPY_AND_ASSIGN(ClassGetNameID); | |
| 121 }; | |
| 122 | |
| 123 } // namespace | 63 } // namespace |
| 124 | 64 |
| 125 JavaMethod::JavaMethod(const base::android::JavaRef<jobject>& method) | 65 JavaMethod::JavaMethod(const base::android::JavaRef<jobject>& method) |
| 126 : java_method_(method), | 66 : java_method_(method), |
| 127 have_calculated_num_parameters_(false), | 67 have_calculated_num_parameters_(false), |
| 128 id_(NULL) { | 68 id_(NULL) { |
| 129 JNIEnv* env = java_method_.env(); | 69 JNIEnv* env = java_method_.env(); |
| 130 // On construction, we do nothing except get the name. Everything else is | 70 // On construction, we do nothing except get the name. Everything else is |
| 131 // done lazily. | 71 // done lazily. |
| 132 ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>( | 72 ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>( |
| 133 env->CallObjectMethod(java_method_.obj(), | 73 env->CallObjectMethod(java_method_.obj(), GetMethodIDFromClassName( |
| 134 MethodGetNameID::GetInstance()->id()))); | 74 env, |
| 75 kJavaLangReflectMethod, |
| 76 kGetName, |
| 77 kReturningJavaLangString)))); |
| 135 name_ = ConvertJavaStringToUTF8(env, name.obj()); | 78 name_ = ConvertJavaStringToUTF8(env, name.obj()); |
| 136 } | 79 } |
| 137 | 80 |
| 138 JavaMethod::~JavaMethod() { | 81 JavaMethod::~JavaMethod() { |
| 139 } | 82 } |
| 140 | 83 |
| 141 size_t JavaMethod::num_parameters() const { | 84 size_t JavaMethod::num_parameters() const { |
| 142 EnsureNumParametersIsSetUp(); | 85 EnsureNumParametersIsSetUp(); |
| 143 return num_parameters_; | 86 return num_parameters_; |
| 144 } | 87 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 162 if (have_calculated_num_parameters_) { | 105 if (have_calculated_num_parameters_) { |
| 163 return; | 106 return; |
| 164 } | 107 } |
| 165 have_calculated_num_parameters_ = true; | 108 have_calculated_num_parameters_ = true; |
| 166 | 109 |
| 167 // The number of parameters will be used frequently when determining | 110 // The number of parameters will be used frequently when determining |
| 168 // whether to call this method. We don't get the ID etc until actually | 111 // whether to call this method. We don't get the ID etc until actually |
| 169 // required. | 112 // required. |
| 170 JNIEnv* env = java_method_.env(); | 113 JNIEnv* env = java_method_.env(); |
| 171 ScopedJavaLocalRef<jarray> parameters(env, static_cast<jarray>( | 114 ScopedJavaLocalRef<jarray> parameters(env, static_cast<jarray>( |
| 172 env->CallObjectMethod(java_method_.obj(), | 115 env->CallObjectMethod(java_method_.obj(), GetMethodIDFromClassName( |
| 173 MethodGetParameterTypesID::GetInstance()->id()))); | 116 env, |
| 117 kJavaLangReflectMethod, |
| 118 kGetParameterTypes, |
| 119 kReturningJavaLangClassArray)))); |
| 174 num_parameters_ = env->GetArrayLength(parameters.obj()); | 120 num_parameters_ = env->GetArrayLength(parameters.obj()); |
| 175 } | 121 } |
| 176 | 122 |
| 177 void JavaMethod::EnsureTypesAndIDAreSetUp() const { | 123 void JavaMethod::EnsureTypesAndIDAreSetUp() const { |
| 178 if (id_) { | 124 if (id_) { |
| 179 return; | 125 return; |
| 180 } | 126 } |
| 181 | 127 |
| 182 // Get the parameters | 128 // Get the parameters |
| 183 JNIEnv* env = java_method_.env(); | 129 JNIEnv* env = java_method_.env(); |
| 184 ScopedJavaLocalRef<jobjectArray> parameters(env, static_cast<jobjectArray>( | 130 ScopedJavaLocalRef<jobjectArray> parameters(env, static_cast<jobjectArray>( |
| 185 env->CallObjectMethod(java_method_.obj(), | 131 env->CallObjectMethod(java_method_.obj(), GetMethodIDFromClassName( |
| 186 MethodGetParameterTypesID::GetInstance()->id()))); | 132 env, |
| 133 kJavaLangReflectMethod, |
| 134 kGetParameterTypes, |
| 135 kReturningJavaLangClassArray)))); |
| 187 // Usually, this will already have been called. | 136 // Usually, this will already have been called. |
| 188 EnsureNumParametersIsSetUp(); | 137 EnsureNumParametersIsSetUp(); |
| 189 DCHECK_EQ(num_parameters_, | 138 DCHECK_EQ(num_parameters_, |
| 190 static_cast<size_t>(env->GetArrayLength(parameters.obj()))); | 139 static_cast<size_t>(env->GetArrayLength(parameters.obj()))); |
| 191 | 140 |
| 192 // Java gives us the argument type using an extended version of the 'binary | 141 // Java gives us the argument type using an extended version of the 'binary |
| 193 // name'. See | 142 // name'. See |
| 194 // http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Class.html#getNa
me(). | 143 // http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Class.html#getNa
me(). |
| 195 // If we build the signature now, there's no need to store the binary name | 144 // If we build the signature now, there's no need to store the binary name |
| 196 // of the arguments. We just store the simple type. | 145 // of the arguments. We just store the simple type. |
| 197 std::string signature("("); | 146 std::string signature("("); |
| 198 | 147 |
| 199 // Form the signature and record the parameter types. | 148 // Form the signature and record the parameter types. |
| 200 parameter_types_.resize(num_parameters_); | 149 parameter_types_.resize(num_parameters_); |
| 201 for (size_t i = 0; i < num_parameters_; ++i) { | 150 for (size_t i = 0; i < num_parameters_; ++i) { |
| 202 ScopedJavaLocalRef<jobject> parameter(env, env->GetObjectArrayElement( | 151 ScopedJavaLocalRef<jobject> parameter(env, env->GetObjectArrayElement( |
| 203 parameters.obj(), i)); | 152 parameters.obj(), i)); |
| 204 ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>( | 153 ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>( |
| 205 env->CallObjectMethod(parameter.obj(), | 154 env->CallObjectMethod(parameter.obj(), GetMethodIDFromClassName( |
| 206 ClassGetNameID::GetInstance()->id()))); | 155 env, |
| 156 kJavaLangClass, |
| 157 kGetName, |
| 158 kReturningJavaLangString)))); |
| 207 std::string name_utf8 = ConvertJavaStringToUTF8(env, name.obj()); | 159 std::string name_utf8 = ConvertJavaStringToUTF8(env, name.obj()); |
| 208 signature += BinaryNameToJNIName(name_utf8, ¶meter_types_[i]); | 160 signature += BinaryNameToJNIName(name_utf8, ¶meter_types_[i]); |
| 209 } | 161 } |
| 210 signature += ")"; | 162 signature += ")"; |
| 211 | 163 |
| 212 // Get the return type | 164 // Get the return type |
| 213 ScopedJavaLocalRef<jclass> clazz(env, static_cast<jclass>( | 165 ScopedJavaLocalRef<jclass> clazz(env, static_cast<jclass>( |
| 214 env->CallObjectMethod(java_method_.obj(), | 166 env->CallObjectMethod(java_method_.obj(), GetMethodIDFromClassName( |
| 215 MethodGetReturnTypeID::GetInstance()->id()))); | 167 env, |
| 168 kJavaLangReflectMethod, |
| 169 kGetReturnType, |
| 170 kReturningJavaLangClass)))); |
| 216 ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>( | 171 ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>( |
| 217 env->CallObjectMethod(clazz.obj(), ClassGetNameID::GetInstance()->id()))); | 172 env->CallObjectMethod(clazz.obj(), GetMethodIDFromClassName( |
| 173 env, |
| 174 kJavaLangClass, |
| 175 kGetName, |
| 176 kReturningJavaLangString)))); |
| 218 signature += BinaryNameToJNIName(ConvertJavaStringToUTF8(env, name.obj()), | 177 signature += BinaryNameToJNIName(ConvertJavaStringToUTF8(env, name.obj()), |
| 219 &return_type_); | 178 &return_type_); |
| 220 | 179 |
| 221 // Get the ID for this method. | 180 // Get the ID for this method. |
| 222 ScopedJavaLocalRef<jclass> declaring_class(env, static_cast<jclass>( | 181 ScopedJavaLocalRef<jclass> declaring_class(env, static_cast<jclass>( |
| 223 env->CallObjectMethod(java_method_.obj(), | 182 env->CallObjectMethod(java_method_.obj(), GetMethodIDFromClassName( |
| 224 MethodGetDeclaringClassID::GetInstance()->id()))); | 183 env, |
| 184 kJavaLangReflectMethod, |
| 185 kGetDeclaringClass, |
| 186 kReturningJavaLangClass)))); |
| 225 id_ = base::android::GetMethodID(env, declaring_class.obj(), name_.c_str(), | 187 id_ = base::android::GetMethodID(env, declaring_class.obj(), name_.c_str(), |
| 226 signature.c_str()); | 188 signature.c_str()); |
| 227 | 189 |
| 228 java_method_.Reset(); | 190 java_method_.Reset(); |
| 229 } | 191 } |
| OLD | NEW |