diff options
Diffstat (limited to 'Source/WebCore')
6 files changed, 120 insertions, 9 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 |