diff options
author | Selim Gurun <sgurun@google.com> | 2012-09-04 16:31:02 -0700 |
---|---|---|
committer | Selim Gurun <sgurun@google.com> | 2012-09-10 16:39:35 -0700 |
commit | f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3 (patch) | |
tree | f0eaf8dc0c087e6961ef36fc9250bdda15ee17f5 | |
parent | 61df0147f508e20bd22fab568b7c8b3c405cfad5 (diff) | |
download | external_webkit-f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3.zip external_webkit-f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3.tar.gz external_webkit-f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3.tar.bz2 |
Control access to inherited methods of jsinterface objects
Bug: 7073422
Use a flag and annotation for allowing access to inherited methods of
jsinterface objects. When flag is false, no annotation is needed. When
flag is true, annotation is needed for allowing access to inherited methods.
Change-Id: I610119dc5410d8df1962fa9dbea09866f81d374c
-rw-r--r-- | Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp | 10 | ||||
-rw-r--r-- | Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.h | 4 | ||||
-rw-r--r-- | Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.cpp | 74 | ||||
-rw-r--r-- | Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.h | 16 | ||||
-rw-r--r-- | Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.cpp | 17 | ||||
-rw-r--r-- | Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.h | 8 | ||||
-rw-r--r-- | Source/WebKit/android/jni/WebCoreFrameBridge.cpp | 18 |
7 files changed, 131 insertions, 16 deletions
diff --git a/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp b/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp index 15b4bda..c6e0a6c 100644 --- a/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp +++ b/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp @@ -206,7 +206,7 @@ JavaValue convertNPVariantToJavaValue(NPVariant value, const String& javaClass) break; } - result.m_objectValue = adoptRef(new JavaInstanceJobject(javaArray)); + result.m_objectValue = adoptRef(new JavaInstanceJobject(javaArray, false)); env->DeleteLocalRef(javaArray); } break; @@ -421,7 +421,11 @@ void convertJavaValueToNPVariant(JavaValue value, NPVariant* result) } } +#if PLATFORM(ANDROID) +JavaValue jvalueToJavaValue(const jvalue& value, const JavaType& type, bool requireAnnotation) +#else JavaValue jvalueToJavaValue(const jvalue& value, const JavaType& type) +#endif { JavaValue result; result.m_type = type; @@ -429,7 +433,11 @@ JavaValue jvalueToJavaValue(const jvalue& value, const JavaType& type) case JavaTypeVoid: break; case JavaTypeObject: +#if PLATFORM(ANDROID) + result.m_objectValue = new JavaInstanceJobject(value.l, requireAnnotation); +#else result.m_objectValue = new JavaInstanceJobject(value.l); +#endif break; case JavaTypeString: { diff --git a/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.h b/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.h index 0282904..47ee45a 100644 --- a/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.h +++ b/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.h @@ -41,7 +41,11 @@ class JavaValue; JavaValue convertNPVariantToJavaValue(NPVariant, const String& javaClass); void convertJavaValueToNPVariant(JavaValue, NPVariant*); +#if PLATFORM(ANDROID) +JavaValue jvalueToJavaValue(const jvalue&, const JavaType&, bool requireAnnotation); +#else JavaValue jvalueToJavaValue(const jvalue&, const JavaType&); +#endif jvalue javaValueToJvalue(const JavaValue&); } // namespace Bindings diff --git a/Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.cpp b/Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.cpp index 40bfd63..669eb49 100644 --- a/Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.cpp +++ b/Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.cpp @@ -33,7 +33,18 @@ using namespace JSC::Bindings; +#if PLATFORM(ANDROID) +const char kJavaScriptInterfaceAnnotation[] = "android/webkit/JavascriptInterface"; +const char kIsAnnotationPresent[] = "isAnnotationPresent"; +const char kGetMethods[] = "getMethods"; + +static jclass safeAnnotationClazz = NULL; + +JavaClassJobject::JavaClassJobject(jobject anInstance, bool requireAnnotation) + : m_requireAnnotation(requireAnnotation) +#else JavaClassJobject::JavaClassJobject(jobject anInstance) +#endif { jobject aClass = callJNIMethod<jobject>(anInstance, "getClass", "()Ljava/lang/Class;"); @@ -57,15 +68,28 @@ JavaClassJobject::JavaClassJobject(jobject anInstance) // Get the methods jarray methods = static_cast<jarray>(callJNIMethod<jobject>(aClass, "getMethods", "()[Ljava/lang/reflect/Method;")); int numMethods = env->GetArrayLength(methods); +#if PLATFORM(ANDROID) + jmethodID isAnnotationPresentMethodID = getAnnotationMethodID(env); + if (!isAnnotationPresentMethodID) { + LOG_ERROR("unable to find method %s on instance %p", kIsAnnotationPresent, anInstance); + return; + } +#endif for (int i = 0; i < numMethods; i++) { jobject aJMethod = env->GetObjectArrayElement(static_cast<jobjectArray>(methods), i); - JavaMethod* aMethod = new JavaMethodJobject(env, aJMethod); // deleted in the JavaClass destructor - MethodList* methodList = m_methods.get(aMethod->name()); - if (!methodList) { - methodList = new MethodList(); - m_methods.set(aMethod->name(), methodList); +#if PLATFORM(ANDROID) + if (jsAccessAllowed(env, isAnnotationPresentMethodID, aJMethod)) { +#endif + JavaMethod* aMethod = new JavaMethodJobject(env, aJMethod); // deleted in the JavaClass destructor + MethodList* methodList = m_methods.get(aMethod->name()); + if (!methodList) { + methodList = new MethodList(); + m_methods.set(aMethod->name(), methodList); + } + methodList->append(aMethod); +#if PLATFORM(ANDROID) } - methodList->append(aMethod); +#endif env->DeleteLocalRef(aJMethod); } env->DeleteLocalRef(fields); @@ -87,6 +111,44 @@ JavaClassJobject::~JavaClassJobject() m_methods.clear(); } +#if PLATFORM(ANDROID) +bool JavaClassJobject::jsAccessAllowed(JNIEnv* env, jmethodID mid, jobject aJMethod) +{ + if (!m_requireAnnotation) + return true; + bool accessAllowed = env->CallBooleanMethod(aJMethod, mid, safeAnnotationClazz); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + env->ExceptionClear(); + return false; + } + return accessAllowed; +} + +jmethodID JavaClassJobject::getAnnotationMethodID(JNIEnv* env) +{ + jclass methodClass = env->FindClass("java/lang/reflect/Method"); + jmethodID mid = 0; + if (methodClass) + mid = env->GetMethodID(methodClass, kIsAnnotationPresent, "(Ljava/lang/Class;)Z"); + if (!methodClass || !mid) { + env->ExceptionDescribe(); + env->ExceptionClear(); + } + env->DeleteLocalRef(methodClass); + return mid; +} + +bool JavaClassJobject::RegisterJavaClassJobject(JNIEnv* env) { + safeAnnotationClazz = reinterpret_cast<jclass>(env->NewGlobalRef(env->FindClass(kJavaScriptInterfaceAnnotation))); + if (!safeAnnotationClazz) { + LOG_ERROR("failed to register %s", kJavaScriptInterfaceAnnotation); + return false; + } + return true; +} +#endif + MethodList JavaClassJobject::methodsNamed(const char* name) const { MethodList* methodList = m_methods.get(name); diff --git a/Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.h b/Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.h index d27ca97..e4035aa 100644 --- a/Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.h +++ b/Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.h @@ -37,17 +37,33 @@ namespace Bindings { class JavaClassJobject : public JavaClass { public: +#if PLATFORM(ANDROID) + JavaClassJobject(jobject, bool); +#else JavaClassJobject(jobject); +#endif virtual ~JavaClassJobject(); // JavaClass implementation virtual MethodList methodsNamed(const char* name) const; virtual JavaField* fieldNamed(const char* name) const; +#if PLATFORM(ANDROID) + static bool RegisterJavaClassJobject(JNIEnv* env); +#endif + private: +#if PLATFORM(ANDROID) + bool jsAccessAllowed(JNIEnv* env, jmethodID mid, jobject aJMethod); + jmethodID getAnnotationMethodID(JNIEnv* env); +#endif + typedef HashMap<WTF::String, MethodList*> MethodListMap; MethodListMap m_methods; FieldMap m_fields; +#if PLATFORM(ANDROID) + bool m_requireAnnotation; +#endif }; } // namespace Bindings diff --git a/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.cpp b/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.cpp index e7b854d..c97a67f 100644 --- a/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.cpp +++ b/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.cpp @@ -41,8 +41,15 @@ using namespace JSC::Bindings; +#if PLATFORM(ANDROID) +JavaInstanceJobject::JavaInstanceJobject(jobject instance, bool requireAnnotation) +#else JavaInstanceJobject::JavaInstanceJobject(jobject instance) +#endif : m_instance(new JobjectWrapper(instance)) +#if PLATFORM(ANDROID) + , m_requireAnnotation(requireAnnotation) +#endif { } @@ -61,7 +68,11 @@ void JavaInstanceJobject::end() JavaClass* JavaInstanceJobject::getClass() const { if (!m_class) +#if PLATFORM(ANDROID) + m_class = adoptPtr(new JavaClassJobject(javaInstance(), m_requireAnnotation)); +#else m_class = adoptPtr(new JavaClassJobject(javaInstance())); +#endif return m_class.get(); } @@ -86,7 +97,7 @@ JavaValue JavaInstanceJobject::invokeMethod(const JavaMethod* method, JavaValue* return JavaValue(); } - return jvalueToJavaValue(result, method->returnType()); + return jvalueToJavaValue(result, method->returnType(), m_requireAnnotation); // END ANDROID } @@ -113,7 +124,11 @@ JavaValue JavaInstanceJobject::getField(const JavaField* field) appendClassName(signature, field->typeClassName()); signature.append(';'); } +#if PLATFORM(ANDROID) + return jvalueToJavaValue(getJNIField(javaInstance(), field->type(), field->name().utf8().data(), signature.toString().utf8().data()), field->type(), m_requireAnnotation); +#else return jvalueToJavaValue(getJNIField(javaInstance(), field->type(), field->name().utf8().data(), signature.toString().utf8().data()), field->type()); +#endif } #endif // ENABLE(JAVA_BRIDGE) diff --git a/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.h b/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.h index 255c190..77dcf28 100644 --- a/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.h +++ b/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.h @@ -48,8 +48,11 @@ namespace Bindings { class JavaInstanceJobject : public JavaInstance { public: +#if PLATFORM(ANDROID) + JavaInstanceJobject(jobject instance, bool requireAnnotation); +#else JavaInstanceJobject(jobject instance); - +#endif // JavaInstance implementation virtual JavaClass* getClass() const; // ANDROID @@ -64,6 +67,9 @@ public: protected: RefPtr<JobjectWrapper> m_instance; mutable OwnPtr<JavaClass> m_class; +#if PLATFORM(ANDROID) + bool m_requireAnnotation; +#endif }; } // namespace Bindings diff --git a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp index 61ffd29..ecda831 100644 --- a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp +++ b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp @@ -61,6 +61,7 @@ #include "IconDatabase.h" #include "Image.h" #include "InspectorClientAndroid.h" +#include "JavaClassJobjectV8.h" #include "JavaNPObjectV8.h" #include "JavaInstanceJobjectV8.h" #include "KURL.h" @@ -1504,14 +1505,14 @@ static jobject StringByEvaluatingJavaScriptFromString(JNIEnv *env, jobject obj, // and virtualEnd and swap the weak reference for the real object. class WeakJavaInstance : public JavaInstanceJobject { public: - static PassRefPtr<WeakJavaInstance> create(jobject obj) + static PassRefPtr<WeakJavaInstance> create(jobject obj, bool requireAnnotation) { - return adoptRef(new WeakJavaInstance(obj)); + return adoptRef(new WeakJavaInstance(obj, requireAnnotation)); } private: - WeakJavaInstance(jobject instance) - : JavaInstanceJobject(instance) + WeakJavaInstance(jobject instance, bool requireAnnotation) + : JavaInstanceJobject(instance, requireAnnotation) , m_beginEndDepth(0) { JNIEnv* env = getJNIEnv(); @@ -1568,7 +1569,7 @@ private: }; static void AddJavascriptInterface(JNIEnv *env, jobject obj, jint nativeFramePointer, - jobject javascriptObj, jstring interfaceName) + jobject javascriptObj, jstring interfaceName, jboolean requireAnnotation) { WebCore::Frame* pFrame = 0; if (nativeFramePointer == 0) @@ -1582,7 +1583,8 @@ static void AddJavascriptInterface(JNIEnv *env, jobject obj, jint nativeFramePoi ALOGV("::WebCore:: addJSInterface: %p", pFrame); if (pFrame) { - RefPtr<JavaInstance> addedObject = WeakJavaInstance::create(javascriptObj); + RefPtr<JavaInstance> addedObject = WeakJavaInstance::create(javascriptObj, + requireAnnotation); const char* name = getCharactersFromJStringInEnv(env, interfaceName); // Pass ownership of the added object to bindToWindowObject. NPObject* npObject = JavaInstanceToNPObject(addedObject.get()); @@ -1950,7 +1952,7 @@ static JNINativeMethod gBrowserFrameNativeMethods[] = { (void*) Reload }, { "nativeGoBackOrForward", "(I)V", (void*) GoBackOrForward }, - { "nativeAddJavascriptInterface", "(ILjava/lang/Object;Ljava/lang/String;)V", + { "nativeAddJavascriptInterface", "(ILjava/lang/Object;Ljava/lang/String;Z)V", (void*) AddJavascriptInterface }, { "stringByEvaluatingJavaScriptFromString", "(Ljava/lang/String;)Ljava/lang/String;", @@ -1985,6 +1987,8 @@ static JNINativeMethod gBrowserFrameNativeMethods[] = { int registerWebFrame(JNIEnv* env) { + JavaClassJobject::RegisterJavaClassJobject(env); + jclass clazz = env->FindClass("android/webkit/BrowserFrame"); ALOG_ASSERT(clazz, "Cannot find BrowserFrame"); gFrameField = env->GetFieldID(clazz, "mNativeFrame", "I"); |