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