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::GetMethodID; | |
15 using base::android::GetStaticMethodID; | |
14 using base::android::MethodID; | 16 using base::android::MethodID; |
15 using base::android::ScopedJavaLocalRef; | 17 using base::android::ScopedJavaLocalRef; |
16 | 18 |
17 namespace { | 19 namespace { |
18 | 20 |
19 // Java's reflection API represents types as a string using an extended 'binary | 21 // Java's reflection API represents types as a string using an extended 'binary |
20 // name'. This converts to an enum which we store in place of the binary name | 22 // name'. This converts to an enum which we store in place of the binary name |
21 // for simplicity. | 23 // for simplicity. |
22 JavaType::Type BinaryNameToType(const std::string& binary_name) { | 24 JavaType::Type BinaryNameToType(const std::string& binary_name) { |
23 if (binary_name == "boolean") { | 25 if (binary_name == "boolean") { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
72 case JavaType::TypeArray: | 74 case JavaType::TypeArray: |
73 return "["; | 75 return "["; |
74 default: | 76 default: |
75 DCHECK (*type == JavaType::TypeString || *type == JavaType::TypeObject); | 77 DCHECK (*type == JavaType::TypeString || *type == JavaType::TypeObject); |
76 std::string jni_name = "L" + binary_name + ";"; | 78 std::string jni_name = "L" + binary_name + ";"; |
77 ReplaceSubstringsAfterOffset(&jni_name, 0, ".", "/"); | 79 ReplaceSubstringsAfterOffset(&jni_name, 0, ".", "/"); |
78 return jni_name; | 80 return jni_name; |
79 } | 81 } |
80 } | 82 } |
81 | 83 |
82 class MethodGetParameterTypesID : public MethodID { | 84 class MethodGetParameterTypesID : public MethodID { |
joth
2011/11/29 11:24:36
aside: I never noticed MethodID get added in the l
Steve Block
2011/11/29 16:54:00
Personally I prefer a simple static too, but I thi
| |
83 public: | 85 public: |
84 static MethodGetParameterTypesID* GetInstance() { | 86 static MethodGetParameterTypesID* GetInstance() { |
85 return Singleton<MethodGetParameterTypesID>::get(); | 87 return Singleton<MethodGetParameterTypesID>::get(); |
86 } | 88 } |
87 private: | 89 private: |
88 friend struct DefaultSingletonTraits<MethodGetParameterTypesID>; | 90 friend struct DefaultSingletonTraits<MethodGetParameterTypesID>; |
89 MethodGetParameterTypesID() | 91 MethodGetParameterTypesID() |
90 : MethodID(AttachCurrentThread(), "java/lang/reflect/Method", | 92 : MethodID(AttachCurrentThread(), "java/lang/reflect/Method", |
91 "getParameterTypes", "()[Ljava/lang/Class;") { | 93 "getParameterTypes", "()[Ljava/lang/Class;") { |
92 } | 94 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
128 } | 130 } |
129 private: | 131 private: |
130 friend struct DefaultSingletonTraits<MethodGetDeclaringClassID>; | 132 friend struct DefaultSingletonTraits<MethodGetDeclaringClassID>; |
131 MethodGetDeclaringClassID() | 133 MethodGetDeclaringClassID() |
132 : MethodID(AttachCurrentThread(), "java/lang/reflect/Method", | 134 : MethodID(AttachCurrentThread(), "java/lang/reflect/Method", |
133 "getDeclaringClass", "()Ljava/lang/Class;") { | 135 "getDeclaringClass", "()Ljava/lang/Class;") { |
134 } | 136 } |
135 DISALLOW_COPY_AND_ASSIGN(MethodGetDeclaringClassID); | 137 DISALLOW_COPY_AND_ASSIGN(MethodGetDeclaringClassID); |
136 }; | 138 }; |
137 | 139 |
140 class MethodGetModifiersID : public MethodID { | |
joth
2011/11/29 11:24:36
nit: I'd find all these easier to read if named li
Steve Block
2011/11/29 16:54:00
All of these are named <class><method>ID. I don't
| |
141 public: | |
142 static MethodGetModifiersID* GetInstance() { | |
143 return Singleton<MethodGetModifiersID>::get(); | |
144 } | |
145 private: | |
joth
2011/11/29 11:24:36
nit: we normally have a blank line before private:
Steve Block
2011/11/29 16:54:00
Done.
| |
146 friend struct DefaultSingletonTraits<MethodGetModifiersID>; | |
147 MethodGetModifiersID() | |
148 : MethodID(AttachCurrentThread(), "java/lang/reflect/Method", | |
149 "getModifiers", "()I") { | |
150 } | |
151 DISALLOW_COPY_AND_ASSIGN(MethodGetModifiersID); | |
152 }; | |
153 | |
138 class ClassGetNameID : public MethodID { | 154 class ClassGetNameID : public MethodID { |
joth
2011/11/29 11:24:36
add 'Method' in the name for consistency with the
Steve Block
2011/11/29 16:54:00
See above
| |
139 public: | 155 public: |
140 static ClassGetNameID* GetInstance() { | 156 static ClassGetNameID* GetInstance() { |
141 return Singleton<ClassGetNameID>::get(); | 157 return Singleton<ClassGetNameID>::get(); |
142 } | 158 } |
143 private: | 159 private: |
144 friend struct DefaultSingletonTraits<ClassGetNameID>; | 160 friend struct DefaultSingletonTraits<ClassGetNameID>; |
145 ClassGetNameID() | 161 ClassGetNameID() |
146 : MethodID(AttachCurrentThread(), "java/lang/Class", "getName", | 162 : MethodID(AttachCurrentThread(), "java/lang/Class", "getName", |
147 "()Ljava/lang/String;") { | 163 "()Ljava/lang/String;") { |
148 } | 164 } |
149 DISALLOW_COPY_AND_ASSIGN(ClassGetNameID); | 165 DISALLOW_COPY_AND_ASSIGN(ClassGetNameID); |
150 }; | 166 }; |
151 | 167 |
168 class ModifierIsStaticID { | |
169 public: | |
170 static ModifierIsStaticID* GetInstance() { | |
171 return Singleton<ModifierIsStaticID>::get(); | |
172 } | |
173 jclass clazz() { return clazz_.obj(); } | |
174 jmethodID id() { return id_; } | |
175 private: | |
176 friend struct DefaultSingletonTraits<ModifierIsStaticID>; | |
177 ModifierIsStaticID() { | |
178 JNIEnv* env = AttachCurrentThread(); | |
179 clazz_.Reset(env, env->FindClass("java/lang/reflect/Modifier")); | |
180 id_ = GetStaticMethodID(env, clazz_.obj(), "isStatic", "(I)Z"); | |
181 } | |
182 base::android::ScopedJavaGlobalRef<jclass> clazz_; | |
183 jmethodID id_; | |
184 DISALLOW_COPY_AND_ASSIGN(ModifierIsStaticID); | |
185 }; | |
186 | |
152 } // namespace | 187 } // namespace |
153 | 188 |
154 JavaMethod::JavaMethod(const base::android::JavaRef<jobject>& method) | 189 JavaMethod::JavaMethod(const base::android::JavaRef<jobject>& method) |
155 : java_method_(method), | 190 : java_method_(method), |
156 have_calculated_num_parameters_(false), | 191 have_calculated_num_parameters_(false), |
157 id_(NULL) { | 192 id_(NULL) { |
158 JNIEnv* env = java_method_.env(); | 193 JNIEnv* env = java_method_.env(); |
159 // On construction, we do nothing except get the name. Everything else is | 194 // On construction, we do nothing except get the name. Everything else is |
160 // done lazily. | 195 // done lazily. |
161 ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>( | 196 ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>( |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
240 | 275 |
241 // Get the return type | 276 // Get the return type |
242 ScopedJavaLocalRef<jclass> clazz(env, static_cast<jclass>( | 277 ScopedJavaLocalRef<jclass> clazz(env, static_cast<jclass>( |
243 env->CallObjectMethod(java_method_.obj(), | 278 env->CallObjectMethod(java_method_.obj(), |
244 MethodGetReturnTypeID::GetInstance()->id()))); | 279 MethodGetReturnTypeID::GetInstance()->id()))); |
245 ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>( | 280 ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>( |
246 env->CallObjectMethod(clazz.obj(), ClassGetNameID::GetInstance()->id()))); | 281 env->CallObjectMethod(clazz.obj(), ClassGetNameID::GetInstance()->id()))); |
247 signature += BinaryNameToJNIName(ConvertJavaStringToUTF8(env, name.obj()), | 282 signature += BinaryNameToJNIName(ConvertJavaStringToUTF8(env, name.obj()), |
248 &return_type_); | 283 &return_type_); |
249 | 284 |
285 // Determine whether the method is static. | |
286 jint modifiers = env->CallIntMethod( | |
287 java_method_.obj(), | |
288 MethodGetModifiersID::GetInstance()->id()); | |
289 bool is_static = env->CallStaticBooleanMethod( | |
290 ModifierIsStaticID::GetInstance()->clazz(), | |
291 ModifierIsStaticID::GetInstance()->id(), | |
292 modifiers); | |
293 | |
250 // Get the ID for this method. | 294 // Get the ID for this method. |
251 ScopedJavaLocalRef<jclass> declaring_class(env, static_cast<jclass>( | 295 ScopedJavaLocalRef<jclass> declaring_class(env, static_cast<jclass>( |
252 env->CallObjectMethod(java_method_.obj(), | 296 env->CallObjectMethod(java_method_.obj(), |
253 MethodGetDeclaringClassID::GetInstance()->id()))); | 297 MethodGetDeclaringClassID::GetInstance()->id()))); |
254 id_ = base::android::GetMethodID(env, declaring_class.obj(), name_.c_str(), | 298 id_ = is_static ? |
255 signature.c_str()); | 299 GetStaticMethodID(env, declaring_class.obj(), name_.c_str(), |
300 signature.c_str()) : | |
301 GetMethodID(env, declaring_class.obj(), name_.c_str(), | |
302 signature.c_str()); | |
256 | 303 |
257 java_method_.Reset(); | 304 java_method_.Reset(); |
258 } | 305 } |
OLD | NEW |