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

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

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

Powered by Google App Engine
This is Rietveld 408576698