OLD | NEW |
---|---|
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/numerics/safe_conversions.h" | 10 #include "base/numerics/safe_conversions.h" |
(...skipping 21 matching lines...) Expand all Loading... | |
32 // Note that in some cases, we differ from from the spec in order to maintain | 32 // Note that in some cases, we differ from from the spec in order to maintain |
33 // existing behavior. These areas are marked LIVECONNECT_COMPLIANCE. We may | 33 // existing behavior. These areas are marked LIVECONNECT_COMPLIANCE. We may |
34 // revisit this decision in the future. | 34 // revisit this decision in the future. |
35 | 35 |
36 namespace content { | 36 namespace content { |
37 namespace { | 37 namespace { |
38 | 38 |
39 const char kJavaLangClass[] = "java/lang/Class"; | 39 const char kJavaLangClass[] = "java/lang/Class"; |
40 const char kJavaLangObject[] = "java/lang/Object"; | 40 const char kJavaLangObject[] = "java/lang/Object"; |
41 const char kJavaLangReflectMethod[] = "java/lang/reflect/Method"; | 41 const char kJavaLangReflectMethod[] = "java/lang/reflect/Method"; |
42 const char kJavaLangSecurityExceptionClass[] = "java/lang/SecurityException"; | |
42 const char kGetClass[] = "getClass"; | 43 const char kGetClass[] = "getClass"; |
43 const char kGetMethods[] = "getMethods"; | 44 const char kGetMethods[] = "getMethods"; |
44 const char kIsAnnotationPresent[] = "isAnnotationPresent"; | 45 const char kIsAnnotationPresent[] = "isAnnotationPresent"; |
45 const char kReturningJavaLangClass[] = "()Ljava/lang/Class;"; | 46 const char kReturningJavaLangClass[] = "()Ljava/lang/Class;"; |
46 const char kReturningJavaLangReflectMethodArray[] = | 47 const char kReturningJavaLangReflectMethodArray[] = |
47 "()[Ljava/lang/reflect/Method;"; | 48 "()[Ljava/lang/reflect/Method;"; |
48 const char kTakesJavaLangClassReturningBoolean[] = "(Ljava/lang/Class;)Z"; | 49 const char kTakesJavaLangClassReturningBoolean[] = "(Ljava/lang/Class;)Z"; |
50 // This is an exception message, so no need to localize. | |
51 const char kAccessToObjectGetClassIsBlocked[] = | |
52 "Access to java.lang.Object.getClass is blocked"; | |
palmer
2014/04/03 21:53:58
Nit: As you think of more bad classes/methods to b
mnaganov (inactive)
2014/04/04 10:16:49
As I have explained in the bug, so far 'getClass'
| |
49 | 53 |
50 // Our special NPObject type. We extend an NPObject with a pointer to a | 54 // 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 | 55 // JavaBoundObject. We also add static methods for each of the NPObject |
52 // callbacks, which are registered by our NPClass. These methods simply | 56 // callbacks, which are registered by our NPClass. These methods simply |
53 // delegate to the private implementation methods of JavaBoundObject. | 57 // delegate to the private implementation methods of JavaBoundObject. |
54 struct JavaNPObject : public NPObject { | 58 struct JavaNPObject : public NPObject { |
55 JavaBoundObject* bound_object; | 59 JavaBoundObject* bound_object; |
56 | 60 |
57 static const NPClass kNPClass; | 61 static const NPClass kNPClass; |
58 | 62 |
(...skipping 754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
813 } | 817 } |
814 | 818 |
815 JavaBoundObject::JavaBoundObject( | 819 JavaBoundObject::JavaBoundObject( |
816 const JavaRef<jobject>& object, | 820 const JavaRef<jobject>& object, |
817 const JavaRef<jclass>& safe_annotation_clazz, | 821 const JavaRef<jclass>& safe_annotation_clazz, |
818 const base::WeakPtr<JavaBridgeDispatcherHostManager>& manager, | 822 const base::WeakPtr<JavaBridgeDispatcherHostManager>& manager, |
819 bool can_enumerate_methods) | 823 bool can_enumerate_methods) |
820 : java_object_(AttachCurrentThread(), object.obj()), | 824 : java_object_(AttachCurrentThread(), object.obj()), |
821 manager_(manager), | 825 manager_(manager), |
822 are_methods_set_up_(false), | 826 are_methods_set_up_(false), |
827 object_get_class_method_id_(NULL), | |
823 can_enumerate_methods_(can_enumerate_methods), | 828 can_enumerate_methods_(can_enumerate_methods), |
824 safe_annotation_clazz_(safe_annotation_clazz) { | 829 safe_annotation_clazz_(safe_annotation_clazz) { |
825 BrowserThread::PostTask( | 830 BrowserThread::PostTask( |
826 BrowserThread::UI, FROM_HERE, | 831 BrowserThread::UI, FROM_HERE, |
827 base::Bind(&JavaBridgeDispatcherHostManager::JavaBoundObjectCreated, | 832 base::Bind(&JavaBridgeDispatcherHostManager::JavaBoundObjectCreated, |
828 manager_, | 833 manager_, |
829 base::android::ScopedJavaGlobalRef<jobject>(object))); | 834 base::android::ScopedJavaGlobalRef<jobject>(object))); |
830 // Other than informing the JavaBridgeDispatcherHostManager that a java bound | 835 // Other than informing the JavaBridgeDispatcherHostManager that a java bound |
831 // object has been created (above), we don't do anything else with our Java | 836 // object has been created (above), we don't do anything else with our Java |
832 // object when first created. We do it all lazily when a method is first | 837 // object when first created. We do it all lazily when a method is first |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
889 } | 894 } |
890 | 895 |
891 // Coerce | 896 // Coerce |
892 std::vector<jvalue> parameters(arg_count); | 897 std::vector<jvalue> parameters(arg_count); |
893 for (size_t i = 0; i < arg_count; ++i) { | 898 for (size_t i = 0; i < arg_count; ++i) { |
894 parameters[i] = CoerceJavaScriptValueToJavaValue(args[i], | 899 parameters[i] = CoerceJavaScriptValueToJavaValue(args[i], |
895 method->parameter_type(i), | 900 method->parameter_type(i), |
896 true); | 901 true); |
897 } | 902 } |
898 | 903 |
899 ScopedJavaLocalRef<jobject> obj = java_object_.get(AttachCurrentThread()); | 904 JNIEnv* env = AttachCurrentThread(); |
905 ScopedJavaLocalRef<jobject> obj = java_object_.get(env); | |
906 | |
907 // Block access to java.lang.Object.getClass. | |
908 // As it is declared to be final, it is sufficient to compare methodIDs. | |
909 if (method->id() == object_get_class_method_id_) { | |
910 BrowserThread::PostTask( | |
911 BrowserThread::UI, FROM_HERE, | |
912 base::Bind(&JavaBoundObject::ThrowSecurityException, | |
913 kAccessToObjectGetClassIsBlocked)); | |
914 return false; | |
915 } | |
900 | 916 |
901 bool ok = false; | 917 bool ok = false; |
902 if (!obj.is_null()) { | 918 if (!obj.is_null()) { |
903 // Call | 919 // Call |
904 ok = CallJNIMethod(obj.obj(), method->return_type(), | 920 ok = CallJNIMethod(obj.obj(), method->return_type(), |
905 method->id(), ¶meters[0], result, | 921 method->id(), ¶meters[0], result, |
906 safe_annotation_clazz_, | 922 safe_annotation_clazz_, |
907 manager_, | 923 manager_, |
908 can_enumerate_methods_); | 924 can_enumerate_methods_); |
909 } | 925 } |
910 | 926 |
911 // Now that we're done with the jvalue, release any local references created | 927 // Now that we're done with the jvalue, release any local references created |
912 // by CoerceJavaScriptValueToJavaValue(). | 928 // by CoerceJavaScriptValueToJavaValue(). |
913 JNIEnv* env = AttachCurrentThread(); | |
914 for (size_t i = 0; i < arg_count; ++i) { | 929 for (size_t i = 0; i < arg_count; ++i) { |
915 ReleaseJavaValueIfRequired(env, ¶meters[i], method->parameter_type(i)); | 930 ReleaseJavaValueIfRequired(env, ¶meters[i], method->parameter_type(i)); |
916 } | 931 } |
917 | 932 |
918 return ok; | 933 return ok; |
919 } | 934 } |
920 | 935 |
921 void JavaBoundObject::EnsureMethodsAreSetUp() const { | 936 void JavaBoundObject::EnsureMethodsAreSetUp() const { |
922 if (are_methods_set_up_) | 937 if (are_methods_set_up_) |
923 return; | 938 return; |
924 are_methods_set_up_ = true; | 939 are_methods_set_up_ = true; |
925 | 940 |
926 JNIEnv* env = AttachCurrentThread(); | 941 JNIEnv* env = AttachCurrentThread(); |
942 | |
943 object_get_class_method_id_ = GetMethodIDFromClassName( | |
944 env, | |
945 kJavaLangObject, | |
946 kGetClass, | |
947 kReturningJavaLangClass); | |
948 | |
927 ScopedJavaLocalRef<jobject> obj = java_object_.get(env); | 949 ScopedJavaLocalRef<jobject> obj = java_object_.get(env); |
928 | 950 |
929 if (obj.is_null()) { | 951 if (obj.is_null()) { |
930 return; | 952 return; |
931 } | 953 } |
932 | 954 |
933 ScopedJavaLocalRef<jclass> clazz(env, static_cast<jclass>( | 955 ScopedJavaLocalRef<jclass> clazz(env, static_cast<jclass>( |
934 env->CallObjectMethod(obj.obj(), GetMethodIDFromClassName( | 956 env->CallObjectMethod(obj.obj(), object_get_class_method_id_))); |
935 env, | |
936 kJavaLangObject, | |
937 kGetClass, | |
938 kReturningJavaLangClass)))); | |
939 | 957 |
940 ScopedJavaLocalRef<jobjectArray> methods(env, static_cast<jobjectArray>( | 958 ScopedJavaLocalRef<jobjectArray> methods(env, static_cast<jobjectArray>( |
941 env->CallObjectMethod(clazz.obj(), GetMethodIDFromClassName( | 959 env->CallObjectMethod(clazz.obj(), GetMethodIDFromClassName( |
942 env, | 960 env, |
943 kJavaLangClass, | 961 kJavaLangClass, |
944 kGetMethods, | 962 kGetMethods, |
945 kReturningJavaLangReflectMethodArray)))); | 963 kReturningJavaLangReflectMethodArray)))); |
946 | 964 |
947 size_t num_methods = env->GetArrayLength(methods.obj()); | 965 size_t num_methods = env->GetArrayLength(methods.obj()); |
948 // Java objects always have public methods. | 966 // Java objects always have public methods. |
(...skipping 15 matching lines...) Expand all Loading... | |
964 | 982 |
965 if (!safe) | 983 if (!safe) |
966 continue; | 984 continue; |
967 } | 985 } |
968 | 986 |
969 JavaMethod* method = new JavaMethod(java_method); | 987 JavaMethod* method = new JavaMethod(java_method); |
970 methods_.insert(std::make_pair(method->name(), method)); | 988 methods_.insert(std::make_pair(method->name(), method)); |
971 } | 989 } |
972 } | 990 } |
973 | 991 |
992 // static | |
993 void JavaBoundObject::ThrowSecurityException(const char* message) { | |
994 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
995 JNIEnv* env = AttachCurrentThread(); | |
996 base::android::ScopedJavaLocalRef<jclass> clazz( | |
997 env, env->FindClass(kJavaLangSecurityExceptionClass)); | |
998 env->ThrowNew(clazz.obj(), message); | |
999 } | |
1000 | |
974 } // namespace content | 1001 } // namespace content |
OLD | NEW |