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

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: Fixed nits 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) {
M-A Ruel 2011/11/11 13:31:13 Is this function hot? If so, a switch case on the
Steve Block 2011/11/11 16:05:20 No, it's not hot, as it's only used when setting u
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;
M-A Ruel 2011/11/11 13:31:13 Everywhere, move all globals to top of file.
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 = java_method_.env();
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 JavaMethod::~JavaMethod() {
155 }
156
157 std::string JavaMethod::name() const {
M-A Ruel 2011/11/11 13:31:13 Functions like that can be inline.
Steve Block 2011/11/11 16:05:20 Done.
158 return name_;
159 }
160
161 size_t JavaMethod::num_parameters() const {
162 const_cast<JavaMethod*>(this)->EnsureNumParametersIsSetUp();
163 return num_parameters_;
164 }
165
166 JavaType::Type JavaMethod::parameter_type(size_t index) const {
167 const_cast<JavaMethod*>(this)->EnsureTypesAndIDAreSetUp();
168 return parameter_types_[index];
169 }
170
171 JavaType::Type JavaMethod::return_type() const {
172 const_cast<JavaMethod*>(this)->EnsureTypesAndIDAreSetUp();
173 return return_type_;
174 }
175
176 jmethodID JavaMethod::id() const {
177 const_cast<JavaMethod*>(this)->EnsureTypesAndIDAreSetUp();
178 return id_;
179 }
180
181 void JavaMethod::EnsureNumParametersIsSetUp() {
182 if (have_calculated_num_parameters_) {
183 return;
184 }
185 have_calculated_num_parameters_ = true;
186
187 // The number of parameters will be used frequently when determining
188 // whether to call this method. We don't get the ID etc until actually
189 // required.
190 JNIEnv* env = java_method_.env();
191 ScopedJavaLocalRef<jarray> parameters(env, static_cast<jarray>(
192 env->CallObjectMethod(java_method_.obj(),
193 GetMethodGetParameterTypesID())));
194 num_parameters_ = env->GetArrayLength(parameters.obj());
195 }
196
197 void JavaMethod::EnsureTypesAndIDAreSetUp() {
198 if (id_) {
199 return;
200 }
201
202 // Get the parameters
203 JNIEnv* env = java_method_.env();
204 ScopedJavaLocalRef<jobjectArray> parameters(env, static_cast<jobjectArray>(
205 env->CallObjectMethod(java_method_.obj(),
206 GetMethodGetParameterTypesID())));
207 // Usually, this will already have been called.
208 EnsureNumParametersIsSetUp();
209 DCHECK_EQ(num_parameters_,
210 static_cast<size_t>(env->GetArrayLength(parameters.obj())));
211
212 // Java gives us the argument type using an extended version of the 'binary
213 // name'. See
214 // http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Class.html#getNa me().
215 // If we build the signature now, there's no need to store the binary name
216 // of the arguments. We just store the simple type.
217 std::string signature("(");
218
219 // Form the signature and record the parameter types.
220 parameter_types_.resize(num_parameters_);
221 for (size_t i = 0; i < num_parameters_; ++i) {
222 ScopedJavaLocalRef<jobject> parameter(env, env->GetObjectArrayElement(
223 parameters.obj(), i));
224 ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>(
225 env->CallObjectMethod(parameter.obj(), GetClassGetNameID())));
226 std::string name_utf8 = ConvertJavaStringToUTF8(env, name.obj());
227 signature += BinaryNameToJNIName(name_utf8, &parameter_types_[i]);
228 }
229 signature += ")";
230
231 // Get the return type
232 ScopedJavaLocalRef<jclass> clazz(env, static_cast<jclass>(
233 env->CallObjectMethod(java_method_.obj(), GetMethodGetReturnTypeID())));
234 ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>(
235 env->CallObjectMethod(clazz.obj(), GetClassGetNameID())));
236 signature += BinaryNameToJNIName(ConvertJavaStringToUTF8(env, name.obj()),
237 &return_type_);
238
239 // Get the ID for this method.
240 ScopedJavaLocalRef<jclass> declaring_class(env, static_cast<jclass>(
241 env->CallObjectMethod(java_method_.obj(),
242 GetMethodGetDeclaringClassID())));
243 id_ = base::android::GetMethodID(env, declaring_class.obj(), name_.c_str(),
244 signature.c_str());
245
246 java_method_.Reset();
247 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698