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

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

Issue 8509019: Add JavaBoundObject (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Moved new files to java/ Created 9 years, 1 month 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/browser/renderer_host/java/java_method.h"
6
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h"
9 #include "base/string_util.h" // For ReplaceSubstringsAfterOffset
10
11 using base::android::AttachCurrentThread;
12 using base::android::ConvertJavaStringToUTF8;
13 using base::android::GetMethodIDFromClassName;
14 using base::android::ScopedJavaLocalRef;
15
16 namespace {
17
18 // Java's reflection API represents types as a string using an extended 'binary
19 // name'. This converts to an enum which we store in place of the binary name
20 // for simplicity.
21 JavaType::Type BinaryNameToType(const std::string& binary_name) {
22 if (binary_name == "boolean") {
23 return JavaType::TypeBoolean;
24 } else if (binary_name == "byte") {
25 return JavaType::TypeByte;
26 } else if (binary_name == "char") {
27 return JavaType::TypeChar;
28 } else if (binary_name == "short") {
29 return JavaType::TypeShort;
30 } else if (binary_name == "int") {
31 return JavaType::TypeInt;
32 } else if (binary_name == "long") {
33 return JavaType::TypeLong;
34 } else if (binary_name == "float") {
35 return JavaType::TypeFloat;
36 } else if (binary_name == "double") {
37 return JavaType::TypeDouble;
38 } else if (binary_name == "void") {
39 return JavaType::TypeVoid;
40 } else if (binary_name[0] == '[') {
41 return JavaType::TypeArray;
42 } else if (binary_name == "java.lang.String") {
43 return JavaType::TypeString;
44 }
45 return JavaType::TypeObject;
46 }
47
48 std::string BinaryNameToJNIName(const std::string& binary_name,
49 JavaType::Type* type) {
50 DCHECK(type);
51 *type = BinaryNameToType(binary_name);
52 switch (*type) {
53 case JavaType::TypeBoolean:
54 return "Z";
55 case JavaType::TypeByte:
56 return "B";
57 case JavaType::TypeChar:
58 return "C";
59 case JavaType::TypeShort:
60 return "S";
61 case JavaType::TypeInt:
62 return "I";
63 case JavaType::TypeLong:
64 return "J";
65 case JavaType::TypeFloat:
66 return "F";
67 case JavaType::TypeDouble:
68 return "D";
69 case JavaType::TypeVoid:
70 return "V";
71 case JavaType::TypeArray:
72 return "[";
73 default:
74 DCHECK (*type == JavaType::TypeString || *type == JavaType::TypeObject);
75 std::string jni_name = "L" + binary_name + ";";
76 ReplaceSubstringsAfterOffset(&jni_name, 0, ".", "/");
77 return jni_name;
78 }
79 }
80
81 static jmethodID g_method_get_parameter_types_id = NULL;
82 jmethodID GetMethodGetParameterTypesID() {
83 if (!g_method_get_parameter_types_id) {
84 g_method_get_parameter_types_id = GetMethodIDFromClassName(
85 AttachCurrentThread(),
86 "java/lang/reflect/Method",
87 "getParameterTypes",
88 "()[Ljava/lang/Class;");
89 }
90 return g_method_get_parameter_types_id;
91 }
92
93 static jmethodID g_method_get_name_id = NULL;
94 jmethodID GetMethodGetNameID() {
95 if (!g_method_get_name_id) {
96 g_method_get_name_id = GetMethodIDFromClassName(AttachCurrentThread(),
97 "java/lang/reflect/Method",
98 "getName",
99 "()Ljava/lang/String;");
100 }
101 return g_method_get_name_id;
102 }
103
104 static jmethodID g_method_get_return_type_id = NULL;
105 jmethodID GetMethodGetReturnTypeID() {
106 if (!g_method_get_return_type_id) {
107 g_method_get_return_type_id = GetMethodIDFromClassName(
108 AttachCurrentThread(),
109 "java/lang/reflect/Method",
110 "getReturnType",
111 "()Ljava/lang/Class;");
112 }
113 return g_method_get_return_type_id;
114 }
115
116 static jmethodID g_method_get_declaring_class_id = NULL;
117 jmethodID GetMethodGetDeclaringClassID() {
118 if (!g_method_get_declaring_class_id) {
119 g_method_get_declaring_class_id = GetMethodIDFromClassName(
120 AttachCurrentThread(),
121 "java/lang/reflect/Method",
122 "getDeclaringClass",
123 "()Ljava/lang/Class;");
124 }
125 return g_method_get_declaring_class_id;
126 }
127
128 static jmethodID g_class_get_name_id = NULL;
129 jmethodID GetClassGetNameID() {
130 if (!g_class_get_name_id) {
131 g_class_get_name_id = GetMethodIDFromClassName(AttachCurrentThread(),
132 "java/lang/Class",
133 "getName",
134 "()Ljava/lang/String;");
135 }
136 return g_class_get_name_id;
137 }
138
139 } // namespace
140
141 JavaMethod::JavaMethod(const base::android::JavaRef<jobject>& method)
142 : java_method_(method),
143 have_calculated_num_parameters_(false),
144 id_(NULL) {
145 JNIEnv* env = AttachCurrentThread();
joth 2011/11/11 11:40:38 again can use java_method_.env() rather than numer
Steve Block 2011/11/11 12:22:53 Done.
146 // On construction, we do nothing except get the name. Everything else is
147 // done lazily.
148 ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>(
149 env->CallObjectMethod(java_method_.obj(),
150 GetMethodGetNameID())));
151 name_ = ConvertJavaStringToUTF8(env, name.obj());
152 }
153
154 std::string JavaMethod::name() const {
155 return name_;
156 }
157
158 size_t JavaMethod::num_parameters() const {
159 const_cast<JavaMethod*>(this)->EnsureNumParametersIsSetUp();
160 return num_parameters_;
161 }
162
163 JavaType::Type JavaMethod::parameter_type(size_t index) const {
164 const_cast<JavaMethod*>(this)->EnsureTypesAndIDAreSetUp();
165 return parameter_types_[index];
166 }
167
168 JavaType::Type JavaMethod::return_type() const {
169 const_cast<JavaMethod*>(this)->EnsureTypesAndIDAreSetUp();
170 return return_type_;
171 }
172
173 jmethodID JavaMethod::id() const {
174 const_cast<JavaMethod*>(this)->EnsureTypesAndIDAreSetUp();
175 return id_;
176 }
177
178 void JavaMethod::EnsureNumParametersIsSetUp() {
179 if (have_calculated_num_parameters_) {
180 return;
181 }
182 have_calculated_num_parameters_ = true;
183
184 // The number of parameters will be used frequently when determining
185 // whether to call this method. We don't get the ID etc until actually
186 // required.
187 JNIEnv* env = AttachCurrentThread();
188 ScopedJavaLocalRef<jarray> parameters(env, static_cast<jarray>(
189 env->CallObjectMethod(java_method_.obj(),
190 GetMethodGetParameterTypesID())));
191 num_parameters_ = env->GetArrayLength(parameters.obj());
192 }
193
194 void JavaMethod::EnsureTypesAndIDAreSetUp() {
195 if (id_) {
196 return;
197 }
198
199 // Get the parameters
200 JNIEnv* env = AttachCurrentThread();
201 ScopedJavaLocalRef<jobjectArray> parameters(env, static_cast<jobjectArray>(
202 env->CallObjectMethod(java_method_.obj(),
203 GetMethodGetParameterTypesID())));
204 // Usually, this will already have been called.
205 EnsureNumParametersIsSetUp();
206 DCHECK_EQ(num_parameters_,
207 static_cast<size_t>(env->GetArrayLength(parameters.obj())));
208
209 // Java gives us the argument type using an extended version of the 'binary
210 // name'. See
211 // http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Class.html#getNa me().
212 // If we build the signature now, there's no need to store the binary name
213 // of the arguments. We just store the simple type.
214 std::string signature("(");
215
216 // Form the signature and record the parameter types.
217 parameter_types_.resize(num_parameters_);
218 for (size_t i = 0; i < num_parameters_; ++i) {
219 ScopedJavaLocalRef<jobject> parameter(env, env->GetObjectArrayElement(
220 parameters.obj(), i));
221 ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>(
222 env->CallObjectMethod(parameter.obj(), GetClassGetNameID())));
223 std::string name_utf8 = ConvertJavaStringToUTF8(env, name.obj());
224 signature += BinaryNameToJNIName(name_utf8, &parameter_types_[i]);
225 }
226 signature += ")";
227
228 // Get the return type
229 ScopedJavaLocalRef<jclass> clazz(env, static_cast<jclass>(
230 env->CallObjectMethod(java_method_.obj(), GetMethodGetReturnTypeID())));
231 ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>(
232 env->CallObjectMethod(clazz.obj(), GetClassGetNameID())));
233 signature += BinaryNameToJNIName(ConvertJavaStringToUTF8(env, name.obj()),
234 &return_type_);
235
236 // Get the ID for this method.
237 ScopedJavaLocalRef<jclass> declaring_class(env, static_cast<jclass>(
238 env->CallObjectMethod(java_method_.obj(),
239 GetMethodGetDeclaringClassID())));
240 id_ = base::android::GetMethodID(env, declaring_class.obj(), name_.c_str(),
241 signature.c_str());
242
243 java_method_.Reset();
244 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698