17fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian/* 278023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block * Copyright 2010, The Android Open Source Project 37fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian * 47fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian * Redistribution and use in source and binary forms, with or without 57fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian * modification, are permitted provided that the following conditions 67fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian * are met: 778023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block * * Redistributions of source code must retain the above copyright 87fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian * notice, this list of conditions and the following disclaimer. 978023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block * * Redistributions in binary form must reproduce the above copyright 107fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian * notice, this list of conditions and the following disclaimer in the 117fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian * documentation and/or other materials provided with the distribution. 127fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian * 1378023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 147fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 157fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1678023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 177fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 187fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 197fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 207fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 217fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 227fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2378023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 247fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian */ 257fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian 267fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian#include "config.h" 272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "JavaClassJobjectV8.h" 2820ab751acc0d49d74648373f701f3d0c4ff187c0Steve Block 2981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#if ENABLE(JAVA_BRIDGE) 3081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "JavaFieldJobjectV8.h" 322bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "JavaMethodJobject.h" 3381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 347fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qianusing namespace JSC::Bindings; 357fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian 36f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun#if PLATFORM(ANDROID) 37f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurunconst char kJavaScriptInterfaceAnnotation[] = "android/webkit/JavascriptInterface"; 38f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurunconst char kIsAnnotationPresent[] = "isAnnotationPresent"; 39f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurunconst char kGetMethods[] = "getMethods"; 40f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun 41f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurunstatic jclass safeAnnotationClazz = NULL; 42f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun 43f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim GurunJavaClassJobject::JavaClassJobject(jobject anInstance, bool requireAnnotation) 44f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun : m_requireAnnotation(requireAnnotation) 45f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun#else 462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochJavaClassJobject::JavaClassJobject(jobject anInstance) 47f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun#endif 487fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian{ 497fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian jobject aClass = callJNIMethod<jobject>(anInstance, "getClass", "()Ljava/lang/Class;"); 5078023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block 517fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian if (!aClass) { 522bde8e466a4451c7319e3a072d118917957d6554Steve Block LOG_ERROR("unable to call getClass on instance %p", anInstance); 537fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian return; 547fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian } 5578023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block 5678023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block JNIEnv* env = getJNIEnv(); 577fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian 587fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian // Get the fields 5909e3a0d3e5e0725e32330137c505146270a2fc84Steve Block jarray fields = static_cast<jarray>(callJNIMethod<jobject>(aClass, "getFields", "()[Ljava/lang/reflect/Field;")); 6078023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block int numFields = env->GetArrayLength(fields); 612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch for (int i = 0; i < numFields; i++) { 6209e3a0d3e5e0725e32330137c505146270a2fc84Steve Block jobject aJField = env->GetObjectArrayElement(static_cast<jobjectArray>(fields), i); 632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch JavaField* aField = new JavaFieldJobject(env, aJField); // deleted in the JavaClass destructor 642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch m_fields.set(aField->name(), aField); 657fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian env->DeleteLocalRef(aJField); 667fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian } 677fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian 687fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian // Get the methods 6909e3a0d3e5e0725e32330137c505146270a2fc84Steve Block jarray methods = static_cast<jarray>(callJNIMethod<jobject>(aClass, "getMethods", "()[Ljava/lang/reflect/Method;")); 707fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian int numMethods = env->GetArrayLength(methods); 71f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun#if PLATFORM(ANDROID) 72f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun jmethodID isAnnotationPresentMethodID = getAnnotationMethodID(env); 73f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun if (!isAnnotationPresentMethodID) { 74f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun LOG_ERROR("unable to find method %s on instance %p", kIsAnnotationPresent, anInstance); 75f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun return; 76f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun } 77f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun#endif 782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch for (int i = 0; i < numMethods; i++) { 7909e3a0d3e5e0725e32330137c505146270a2fc84Steve Block jobject aJMethod = env->GetObjectArrayElement(static_cast<jobjectArray>(methods), i); 80f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun#if PLATFORM(ANDROID) 81f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun if (jsAccessAllowed(env, isAnnotationPresentMethodID, aJMethod)) { 82f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun#endif 83f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun JavaMethod* aMethod = new JavaMethodJobject(env, aJMethod); // deleted in the JavaClass destructor 84f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun MethodList* methodList = m_methods.get(aMethod->name()); 85f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun if (!methodList) { 86f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun methodList = new MethodList(); 87f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun m_methods.set(aMethod->name(), methodList); 88f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun } 89f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun methodList->append(aMethod); 90f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun#if PLATFORM(ANDROID) 917fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian } 92f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun#endif 937fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian env->DeleteLocalRef(aJMethod); 9478023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block } 957fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian env->DeleteLocalRef(fields); 967fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian env->DeleteLocalRef(methods); 977fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian env->DeleteLocalRef(aClass); 987fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian} 997fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian 1002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochJavaClassJobject::~JavaClassJobject() 10178023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block{ 10278023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block deleteAllValues(m_fields); 10378023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block m_fields.clear(); 1047fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian 10578023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block MethodListMap::const_iterator end = m_methods.end(); 10678023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block for (MethodListMap::const_iterator it = m_methods.begin(); it != end; ++it) { 1077fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian const MethodList* methodList = it->second; 1087fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian deleteAllValues(*methodList); 1097fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian delete methodList; 1107fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian } 11178023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block m_methods.clear(); 1127fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian} 1137fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian 114f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun#if PLATFORM(ANDROID) 115f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurunbool JavaClassJobject::jsAccessAllowed(JNIEnv* env, jmethodID mid, jobject aJMethod) 116f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun{ 117f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun if (!m_requireAnnotation) 118f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun return true; 119f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun bool accessAllowed = env->CallBooleanMethod(aJMethod, mid, safeAnnotationClazz); 120f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun if (env->ExceptionCheck()) { 121f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun env->ExceptionDescribe(); 122f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun env->ExceptionClear(); 123f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun return false; 124f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun } 125f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun return accessAllowed; 126f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun} 127f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun 128f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim GurunjmethodID JavaClassJobject::getAnnotationMethodID(JNIEnv* env) 129f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun{ 130f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun jclass methodClass = env->FindClass("java/lang/reflect/Method"); 131f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun jmethodID mid = 0; 132f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun if (methodClass) 133f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun mid = env->GetMethodID(methodClass, kIsAnnotationPresent, "(Ljava/lang/Class;)Z"); 134f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun if (!methodClass || !mid) { 135f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun env->ExceptionDescribe(); 136f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun env->ExceptionClear(); 137f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun } 138f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun env->DeleteLocalRef(methodClass); 139f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun return mid; 140f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun} 141f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun 142f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurunbool JavaClassJobject::RegisterJavaClassJobject(JNIEnv* env) { 143f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun safeAnnotationClazz = reinterpret_cast<jclass>(env->NewGlobalRef(env->FindClass(kJavaScriptInterfaceAnnotation))); 144f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun if (!safeAnnotationClazz) { 145f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun LOG_ERROR("failed to register %s", kJavaScriptInterfaceAnnotation); 146f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun return false; 147f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun } 148f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun return true; 149f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun} 150f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun#endif 151f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3Selim Gurun 1522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochMethodList JavaClassJobject::methodsNamed(const char* name) const 1537fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian{ 15478023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block MethodList* methodList = m_methods.get(name); 15578023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block 1567fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian if (methodList) 1577fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian return *methodList; 1587fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian return MethodList(); 1597fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian} 1607fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian 1612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochJavaField* JavaClassJobject::fieldNamed(const char* name) const 1627fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian{ 16378023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block return m_fields.get(name); 1647fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian} 16581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 16681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#endif // ENABLE(JAVA_BRIDGE) 167