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