Chromium Code Reviews| Index: content/browser/renderer_host/java/java_bound_object.cc |
| diff --git a/content/browser/renderer_host/java/java_bound_object.cc b/content/browser/renderer_host/java/java_bound_object.cc |
| index ca2eb1a257322ca47b0883cbf507cb05ab9bc45a..f82588dee3c457ecbee4d1d1f0104216eda70995 100644 |
| --- a/content/browser/renderer_host/java/java_bound_object.cc |
| +++ b/content/browser/renderer_host/java/java_bound_object.cc |
| @@ -34,12 +34,19 @@ namespace { |
| const char kJavaLangClass[] = "java/lang/Class"; |
| const char kJavaLangObject[] = "java/lang/Object"; |
| +const char kJavaLangReflectMethod[] = "java/lang/reflect/Method"; |
| const char kGetClass[] = "getClass"; |
| +const char kGetDeclaredMethods[] = "getDeclaredMethods"; |
| const char kGetMethods[] = "getMethods"; |
| +const char kGetModifiers[] = "getModifiers"; |
| +const char kReturningInteger[] = "()I"; |
| const char kReturningJavaLangClass[] = "()Ljava/lang/Class;"; |
| const char kReturningJavaLangReflectMethodArray[] = |
| "()[Ljava/lang/reflect/Method;"; |
| +// This constant represents the value at java.lang.reflect.Modifier.PUBLIC. |
| +const int kJavaPublicModifier = 1; |
| + |
| // Our special NPObject type. We extend an NPObject with a pointer to a |
| // JavaBoundObject. We also add static methods for each of the NPObject |
| // callbacks, which are registered by our NPClass. These methods simply |
| @@ -120,7 +127,8 @@ bool JavaNPObject::GetProperty(NPObject* np_object, |
| // NPVariant. Note that this method does not do any type coercion. The Java |
| // return value is simply converted to the corresponding NPAPI type. |
| bool CallJNIMethod(jobject object, const JavaType& return_type, jmethodID id, |
| - jvalue* parameters, NPVariant* result) { |
| + jvalue* parameters, NPVariant* result, |
| + bool allow_inherited_methods) { |
| JNIEnv* env = AttachCurrentThread(); |
| switch (return_type.type) { |
| case JavaType::TypeBoolean: |
| @@ -201,7 +209,9 @@ bool CallJNIMethod(jobject object, const JavaType& return_type, jmethodID id, |
| NULL_TO_NPVARIANT(*result); |
| break; |
| } |
| - OBJECT_TO_NPVARIANT(JavaBoundObject::Create(scoped_java_object), *result); |
| + OBJECT_TO_NPVARIANT(JavaBoundObject::Create(scoped_java_object, |
| + allow_inherited_methods), |
| + *result); |
| break; |
| } |
| } |
| @@ -717,7 +727,8 @@ jvalue CoerceJavaScriptValueToJavaValue(const NPVariant& variant, |
| } // namespace |
| -NPObject* JavaBoundObject::Create(const JavaRef<jobject>& object) { |
| +NPObject* JavaBoundObject::Create(const JavaRef<jobject>& object, |
| + bool allow_inherited_methods) { |
| // The first argument (a plugin's instance handle) is passed through to the |
| // allocate function directly, and we don't use it, so it's ok to be 0. |
| // The object is created with a ref count of one. |
| @@ -725,12 +736,15 @@ NPObject* JavaBoundObject::Create(const JavaRef<jobject>& object) { |
| &JavaNPObject::kNPClass)); |
| // The NPObject takes ownership of the JavaBoundObject. |
| reinterpret_cast<JavaNPObject*>(np_object)->bound_object = |
| - new JavaBoundObject(object); |
| + new JavaBoundObject(object, allow_inherited_methods); |
| return np_object; |
| } |
| -JavaBoundObject::JavaBoundObject(const JavaRef<jobject>& object) |
| - : java_object_(object) { |
| +JavaBoundObject::JavaBoundObject(const JavaRef<jobject>& object, |
| + bool allow_inherited_methods) |
| + : java_object_(object), |
| + are_methods_set_up_(false), |
| + allow_inherited_methods_(allow_inherited_methods) { |
| // We don't do anything with our Java object when first created. We do it all |
| // lazily when a method is first invoked. |
| } |
| @@ -783,7 +797,8 @@ bool JavaBoundObject::Invoke(const std::string& name, const NPVariant* args, |
| // Call |
| bool ok = CallJNIMethod(java_object_.obj(), method->return_type(), |
| - method->id(), ¶meters[0], result); |
| + method->id(), ¶meters[0], result, |
| + allow_inherited_methods_); |
| // Now that we're done with the jvalue, release any local references created |
| // by CoerceJavaScriptValueToJavaValue(). |
| @@ -796,9 +811,9 @@ bool JavaBoundObject::Invoke(const std::string& name, const NPVariant* args, |
| } |
| void JavaBoundObject::EnsureMethodsAreSetUp() const { |
| - if (!methods_.empty()) { |
| + if (are_methods_set_up_) |
| return; |
| - } |
| + are_methods_set_up_ = true; |
| JNIEnv* env = AttachCurrentThread(); |
| ScopedJavaLocalRef<jclass> clazz(env, static_cast<jclass>( |
| @@ -807,19 +822,40 @@ void JavaBoundObject::EnsureMethodsAreSetUp() const { |
| kJavaLangObject, |
| kGetClass, |
| kReturningJavaLangClass)))); |
| + |
| + const char* get_method = allow_inherited_methods_ ? |
| + kGetMethods : kGetDeclaredMethods; |
| + |
| ScopedJavaLocalRef<jobjectArray> methods(env, static_cast<jobjectArray>( |
| env->CallObjectMethod(clazz.obj(), GetMethodIDFromClassName( |
| env, |
| kJavaLangClass, |
| - kGetMethods, |
| + get_method, |
| kReturningJavaLangReflectMethodArray)))); |
| + |
| size_t num_methods = env->GetArrayLength(methods.obj()); |
| - DCHECK(num_methods) << "Java objects always have public methods"; |
| + if (num_methods <= 0) |
| + return; |
| + |
| for (size_t i = 0; i < num_methods; ++i) { |
| ScopedJavaLocalRef<jobject> java_method( |
| env, |
| env->GetObjectArrayElement(methods.obj(), i)); |
| - JavaMethod* method = new JavaMethod(java_method); |
| - methods_.insert(std::make_pair(method->name(), method)); |
| + |
| + bool is_method_allowed = true; |
| + if (!allow_inherited_methods_) { |
| + jint modifiers = env->CallIntMethod(java_method.obj(), |
| + GetMethodIDFromClassName( |
| + env, |
| + kJavaLangReflectMethod, |
| + kGetModifiers, |
| + kReturningInteger)); |
|
joth
2012/07/18 17:28:39
after the fact -- just noticed this is non-standar
|
| + is_method_allowed &= (modifiers & kJavaPublicModifier); |
| + } |
| + |
| + if (is_method_allowed) { |
| + JavaMethod* method = new JavaMethod(java_method); |
| + methods_.insert(std::make_pair(method->name(), method)); |
| + } |
| } |
| } |