diff options
Diffstat (limited to 'Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.cpp')
-rw-r--r-- | Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.cpp | 74 |
1 files changed, 68 insertions, 6 deletions
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); |