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

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

Issue 10830173: JavaBridge should use Annotation (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add new line before private Created 8 years, 4 months 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/renderer_host/java/java_bound_object.h" 5 #include "content/browser/renderer_host/java/java_bound_object.h"
6 6
7 #include "base/android/jni_android.h" 7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h" 8 #include "base/android/jni_string.h"
9 #include "base/memory/singleton.h" 9 #include "base/memory/singleton.h"
10 #include "base/string_number_conversions.h" 10 #include "base/string_number_conversions.h"
(...skipping 17 matching lines...) Expand all
28 28
29 // Note that in some cases, we differ from from the spec in order to maintain 29 // Note that in some cases, we differ from from the spec in order to maintain
30 // existing behavior. These areas are marked LIVECONNECT_COMPLIANCE. We may 30 // existing behavior. These areas are marked LIVECONNECT_COMPLIANCE. We may
31 // revisit this decision in the future. 31 // revisit this decision in the future.
32 32
33 namespace { 33 namespace {
34 34
35 const char kJavaLangClass[] = "java/lang/Class"; 35 const char kJavaLangClass[] = "java/lang/Class";
36 const char kJavaLangObject[] = "java/lang/Object"; 36 const char kJavaLangObject[] = "java/lang/Object";
37 const char kJavaLangReflectMethod[] = "java/lang/reflect/Method"; 37 const char kJavaLangReflectMethod[] = "java/lang/reflect/Method";
38 // TODO(dtrainor): Parameterize this so that WebView and Chrome for Android can
39 // use different annotations.
40 const char kJavaScriptInterfaceAnnotation[] =
41 "org/chromium/content/browser/JavascriptInterface";
38 const char kGetClass[] = "getClass"; 42 const char kGetClass[] = "getClass";
39 const char kGetDeclaredMethods[] = "getDeclaredMethods";
40 const char kGetMethods[] = "getMethods"; 43 const char kGetMethods[] = "getMethods";
41 const char kGetModifiers[] = "getModifiers"; 44 const char kIsAnnotationPresent[] = "isAnnotationPresent";
42 const char kReturningInteger[] = "()I";
43 const char kReturningJavaLangClass[] = "()Ljava/lang/Class;"; 45 const char kReturningJavaLangClass[] = "()Ljava/lang/Class;";
44 const char kReturningJavaLangReflectMethodArray[] = 46 const char kReturningJavaLangReflectMethodArray[] =
45 "()[Ljava/lang/reflect/Method;"; 47 "()[Ljava/lang/reflect/Method;";
48 const char kTakesJavaLangClassReturningBoolean[] = "(Ljava/lang/Class;)Z";
46 49
47 // This constant represents the value at java.lang.reflect.Modifier.PUBLIC. 50 jclass g_safe_annotation_clazz = NULL;
48 const int kJavaPublicModifier = 1;
49 51
50 // Our special NPObject type. We extend an NPObject with a pointer to a 52 // Our special NPObject type. We extend an NPObject with a pointer to a
51 // JavaBoundObject. We also add static methods for each of the NPObject 53 // JavaBoundObject. We also add static methods for each of the NPObject
52 // callbacks, which are registered by our NPClass. These methods simply 54 // callbacks, which are registered by our NPClass. These methods simply
53 // delegate to the private implementation methods of JavaBoundObject. 55 // delegate to the private implementation methods of JavaBoundObject.
54 struct JavaNPObject : public NPObject { 56 struct JavaNPObject : public NPObject {
55 JavaBoundObject* bound_object; 57 JavaBoundObject* bound_object;
56 58
57 static const NPClass kNPClass; 59 static const NPClass kNPClass;
58 60
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 return false; 123 return false;
122 } 124 }
123 125
124 // Calls a Java method through JNI. If the Java method raises an uncaught 126 // Calls a Java method through JNI. If the Java method raises an uncaught
125 // exception, it is cleared and this method returns false. Otherwise, this 127 // exception, it is cleared and this method returns false. Otherwise, this
126 // method returns true and the Java method's return value is provided as an 128 // method returns true and the Java method's return value is provided as an
127 // NPVariant. Note that this method does not do any type coercion. The Java 129 // NPVariant. Note that this method does not do any type coercion. The Java
128 // return value is simply converted to the corresponding NPAPI type. 130 // return value is simply converted to the corresponding NPAPI type.
129 bool CallJNIMethod(jobject object, const JavaType& return_type, jmethodID id, 131 bool CallJNIMethod(jobject object, const JavaType& return_type, jmethodID id,
130 jvalue* parameters, NPVariant* result, 132 jvalue* parameters, NPVariant* result,
131 bool allow_inherited_methods) { 133 bool require_annotation) {
132 JNIEnv* env = AttachCurrentThread(); 134 JNIEnv* env = AttachCurrentThread();
133 switch (return_type.type) { 135 switch (return_type.type) {
134 case JavaType::TypeBoolean: 136 case JavaType::TypeBoolean:
135 BOOLEAN_TO_NPVARIANT(env->CallBooleanMethodA(object, id, parameters), 137 BOOLEAN_TO_NPVARIANT(env->CallBooleanMethodA(object, id, parameters),
136 *result); 138 *result);
137 break; 139 break;
138 case JavaType::TypeByte: 140 case JavaType::TypeByte:
139 INT32_TO_NPVARIANT(env->CallByteMethodA(object, id, parameters), *result); 141 INT32_TO_NPVARIANT(env->CallByteMethodA(object, id, parameters), *result);
140 break; 142 break;
141 case JavaType::TypeChar: 143 case JavaType::TypeChar:
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 jobject java_object = env->CallObjectMethodA(object, id, parameters); 205 jobject java_object = env->CallObjectMethodA(object, id, parameters);
204 if (base::android::ClearException(env)) { 206 if (base::android::ClearException(env)) {
205 return false; 207 return false;
206 } 208 }
207 ScopedJavaLocalRef<jobject> scoped_java_object(env, java_object); 209 ScopedJavaLocalRef<jobject> scoped_java_object(env, java_object);
208 if (!scoped_java_object.obj()) { 210 if (!scoped_java_object.obj()) {
209 NULL_TO_NPVARIANT(*result); 211 NULL_TO_NPVARIANT(*result);
210 break; 212 break;
211 } 213 }
212 OBJECT_TO_NPVARIANT(JavaBoundObject::Create(scoped_java_object, 214 OBJECT_TO_NPVARIANT(JavaBoundObject::Create(scoped_java_object,
213 allow_inherited_methods), 215 require_annotation),
214 *result); 216 *result);
215 break; 217 break;
216 } 218 }
217 } 219 }
218 return !base::android::ClearException(env); 220 return !base::android::ClearException(env);
219 } 221 }
220 222
221 jvalue CoerceJavaScriptNumberToJavaValue(const NPVariant& variant, 223 jvalue CoerceJavaScriptNumberToJavaValue(const NPVariant& variant,
222 const JavaType& target_type, 224 const JavaType& target_type,
223 bool coerce_to_string) { 225 bool coerce_to_string) {
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after
719 case NPVariantType_Void: 721 case NPVariantType_Void:
720 return CoerceJavaScriptNullOrUndefinedToJavaValue(variant, target_type, 722 return CoerceJavaScriptNullOrUndefinedToJavaValue(variant, target_type,
721 coerce_to_string); 723 coerce_to_string);
722 } 724 }
723 NOTREACHED(); 725 NOTREACHED();
724 return jvalue(); 726 return jvalue();
725 } 727 }
726 728
727 } // namespace 729 } // namespace
728 730
729
730 NPObject* JavaBoundObject::Create(const JavaRef<jobject>& object, 731 NPObject* JavaBoundObject::Create(const JavaRef<jobject>& object,
731 bool allow_inherited_methods) { 732 bool require_annotation) {
732 // The first argument (a plugin's instance handle) is passed through to the 733 // The first argument (a plugin's instance handle) is passed through to the
733 // allocate function directly, and we don't use it, so it's ok to be 0. 734 // allocate function directly, and we don't use it, so it's ok to be 0.
734 // The object is created with a ref count of one. 735 // The object is created with a ref count of one.
735 NPObject* np_object = WebBindings::createObject(0, const_cast<NPClass*>( 736 NPObject* np_object = WebBindings::createObject(0, const_cast<NPClass*>(
736 &JavaNPObject::kNPClass)); 737 &JavaNPObject::kNPClass));
737 // The NPObject takes ownership of the JavaBoundObject. 738 // The NPObject takes ownership of the JavaBoundObject.
738 reinterpret_cast<JavaNPObject*>(np_object)->bound_object = 739 reinterpret_cast<JavaNPObject*>(np_object)->bound_object =
739 new JavaBoundObject(object, allow_inherited_methods); 740 new JavaBoundObject(object, require_annotation);
740 return np_object; 741 return np_object;
741 } 742 }
742 743
743 JavaBoundObject::JavaBoundObject(const JavaRef<jobject>& object, 744 JavaBoundObject::JavaBoundObject(const JavaRef<jobject>& object,
744 bool allow_inherited_methods) 745 bool require_annotation)
745 : java_object_(object), 746 : java_object_(object),
746 are_methods_set_up_(false), 747 are_methods_set_up_(false),
747 allow_inherited_methods_(allow_inherited_methods) { 748 require_annotation_(require_annotation) {
748 // We don't do anything with our Java object when first created. We do it all 749 // We don't do anything with our Java object when first created. We do it all
749 // lazily when a method is first invoked. 750 // lazily when a method is first invoked.
750 } 751 }
751 752
752 JavaBoundObject::~JavaBoundObject() { 753 JavaBoundObject::~JavaBoundObject() {
753 } 754 }
754 755
755 jobject JavaBoundObject::GetJavaObject(NPObject* object) { 756 jobject JavaBoundObject::GetJavaObject(NPObject* object) {
756 DCHECK_EQ(&JavaNPObject::kNPClass, object->_class); 757 DCHECK_EQ(&JavaNPObject::kNPClass, object->_class);
757 JavaBoundObject* jbo = reinterpret_cast<JavaNPObject*>(object)->bound_object; 758 JavaBoundObject* jbo = reinterpret_cast<JavaNPObject*>(object)->bound_object;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
791 std::vector<jvalue> parameters(arg_count); 792 std::vector<jvalue> parameters(arg_count);
792 for (size_t i = 0; i < arg_count; ++i) { 793 for (size_t i = 0; i < arg_count; ++i) {
793 parameters[i] = CoerceJavaScriptValueToJavaValue(args[i], 794 parameters[i] = CoerceJavaScriptValueToJavaValue(args[i],
794 method->parameter_type(i), 795 method->parameter_type(i),
795 true); 796 true);
796 } 797 }
797 798
798 // Call 799 // Call
799 bool ok = CallJNIMethod(java_object_.obj(), method->return_type(), 800 bool ok = CallJNIMethod(java_object_.obj(), method->return_type(),
800 method->id(), &parameters[0], result, 801 method->id(), &parameters[0], result,
801 allow_inherited_methods_); 802 require_annotation_);
802 803
803 // Now that we're done with the jvalue, release any local references created 804 // Now that we're done with the jvalue, release any local references created
804 // by CoerceJavaScriptValueToJavaValue(). 805 // by CoerceJavaScriptValueToJavaValue().
805 JNIEnv* env = AttachCurrentThread(); 806 JNIEnv* env = AttachCurrentThread();
806 for (size_t i = 0; i < arg_count; ++i) { 807 for (size_t i = 0; i < arg_count; ++i) {
807 ReleaseJavaValueIfRequired(env, &parameters[i], method->parameter_type(i)); 808 ReleaseJavaValueIfRequired(env, &parameters[i], method->parameter_type(i));
808 } 809 }
809 810
810 return ok; 811 return ok;
811 } 812 }
812 813
814 bool JavaBoundObject::RegisterJavaBoundObject(JNIEnv* env) {
815 g_safe_annotation_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
816 base::android::GetUnscopedClass(env, kJavaScriptInterfaceAnnotation)));
817 DCHECK(g_safe_annotation_clazz);
818
819 return true;
820 }
821
813 void JavaBoundObject::EnsureMethodsAreSetUp() const { 822 void JavaBoundObject::EnsureMethodsAreSetUp() const {
814 if (are_methods_set_up_) 823 if (are_methods_set_up_)
815 return; 824 return;
816 are_methods_set_up_ = true; 825 are_methods_set_up_ = true;
817 826
818 JNIEnv* env = AttachCurrentThread(); 827 JNIEnv* env = AttachCurrentThread();
819 ScopedJavaLocalRef<jclass> clazz(env, static_cast<jclass>( 828 ScopedJavaLocalRef<jclass> clazz(env, static_cast<jclass>(
820 env->CallObjectMethod(java_object_.obj(), GetMethodIDFromClassName( 829 env->CallObjectMethod(java_object_.obj(), GetMethodIDFromClassName(
821 env, 830 env,
822 kJavaLangObject, 831 kJavaLangObject,
823 kGetClass, 832 kGetClass,
824 kReturningJavaLangClass)))); 833 kReturningJavaLangClass))));
825 834
826 const char* get_method = allow_inherited_methods_ ?
827 kGetMethods : kGetDeclaredMethods;
828
829 ScopedJavaLocalRef<jobjectArray> methods(env, static_cast<jobjectArray>( 835 ScopedJavaLocalRef<jobjectArray> methods(env, static_cast<jobjectArray>(
830 env->CallObjectMethod(clazz.obj(), GetMethodIDFromClassName( 836 env->CallObjectMethod(clazz.obj(), GetMethodIDFromClassName(
831 env, 837 env,
832 kJavaLangClass, 838 kJavaLangClass,
833 get_method, 839 kGetMethods,
834 kReturningJavaLangReflectMethodArray)))); 840 kReturningJavaLangReflectMethodArray))));
835 841
836 size_t num_methods = env->GetArrayLength(methods.obj()); 842 size_t num_methods = env->GetArrayLength(methods.obj());
837 if (num_methods <= 0) 843 // Java objects always have public methods.
838 return; 844 DCHECK(num_methods);
839 845
840 for (size_t i = 0; i < num_methods; ++i) { 846 for (size_t i = 0; i < num_methods; ++i) {
841 ScopedJavaLocalRef<jobject> java_method( 847 ScopedJavaLocalRef<jobject> java_method(
842 env, 848 env,
843 env->GetObjectArrayElement(methods.obj(), i)); 849 env->GetObjectArrayElement(methods.obj(), i));
844 850
845 bool is_method_allowed = true; 851 if (require_annotation_) {
846 if (!allow_inherited_methods_) { 852 jboolean safe = env->CallBooleanMethod(java_method.obj(),
847 jint modifiers = env->CallIntMethod(java_method.obj(), 853 GetMethodIDFromClassName(
848 GetMethodIDFromClassName( 854 env,
849 env, 855 kJavaLangReflectMethod,
850 kJavaLangReflectMethod, 856 kIsAnnotationPresent,
851 kGetModifiers, 857 kTakesJavaLangClassReturningBoolean),
852 kReturningInteger)); 858 g_safe_annotation_clazz);
853 is_method_allowed &= (modifiers & kJavaPublicModifier); 859
860 if (!safe)
861 continue;
854 } 862 }
855 863
856 if (is_method_allowed) { 864 JavaMethod* method = new JavaMethod(java_method);
857 JavaMethod* method = new JavaMethod(java_method); 865 methods_.insert(std::make_pair(method->name(), method));
858 methods_.insert(std::make_pair(method->name(), method));
859 }
860 } 866 }
861 } 867 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698