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

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

Powered by Google App Engine
This is Rietveld 408576698