1b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian/*
209e3a0d3e5e0725e32330137c505146270a2fc84Steve Block * Copyright 2010, The Android Open Source Project
3b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian *
4b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian * Redistribution and use in source and binary forms, with or without
5b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian * modification, are permitted provided that the following conditions
6b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian * are met:
7b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian *  * Redistributions of source code must retain the above copyright
8b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian *    notice, this list of conditions and the following disclaimer.
9b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian *  * Redistributions in binary form must reproduce the above copyright
10b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian *    notice, this list of conditions and the following disclaimer in the
11b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian *    documentation and/or other materials provided with the distribution.
12b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian *
13b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1609e3a0d3e5e0725e32330137c505146270a2fc84Steve Block * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian */
25b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian
26b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian
27b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian#include "config.h"
2854dec9637e20bfba1857f3d54df3c43ce94ff97bSteve Block#include "JavaNPObjectV8.h"
2920ab751acc0d49d74648373f701f3d0c4ff187c0Steve Block
3081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#if ENABLE(JAVA_BRIDGE)
3181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
3209e3a0d3e5e0725e32330137c505146270a2fc84Steve Block#include "JNIUtilityPrivate.h"
3378023b8120c8cd0aba398f04bf5aacb8d3fd05c7Steve Block#include "JavaClassV8.h"
3481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#include "JavaFieldV8.h"
3540c8c4abfc2d689e4aa21c5dfab61ce45e45b38bSteve Block#include "JavaInstanceV8.h"
362bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "JavaMethod.h"
372bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "JavaValueV8.h"
38b999781071d8167a543e0e48ad25d51178d713d1Steve Block#include "npruntime_impl.h"
397fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian
4054dec9637e20bfba1857f3d54df3c43ce94ff97bSteve Blocknamespace JSC {
4154dec9637e20bfba1857f3d54df3c43ce94ff97bSteve Block
4254dec9637e20bfba1857f3d54df3c43ce94ff97bSteve Blocknamespace Bindings {
4354dec9637e20bfba1857f3d54df3c43ce94ff97bSteve Block
44b2318f335c407832166c7568f3e50afedad5b9dbFeng Qianstatic NPObject* AllocJavaNPObject(NPP, NPClass*)
45b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian{
4654dec9637e20bfba1857f3d54df3c43ce94ff97bSteve Block    JavaNPObject* obj = static_cast<JavaNPObject*>(malloc(sizeof(JavaNPObject)));
4754dec9637e20bfba1857f3d54df3c43ce94ff97bSteve Block    if (!obj)
48e8f342c7034cddf274ba5b9e18c51dd3e29c7db9Feng Qian        return 0;
49e72218e36405a28fa142afc38ef1fff50797cc45Steve Block    memset(obj, 0, sizeof(JavaNPObject));
50e8f342c7034cddf274ba5b9e18c51dd3e29c7db9Feng Qian    return reinterpret_cast<NPObject*>(obj);
51b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian}
52b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian
53b2318f335c407832166c7568f3e50afedad5b9dbFeng Qianstatic void FreeJavaNPObject(NPObject* npobj)
54b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian{
55b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian    JavaNPObject* obj = reinterpret_cast<JavaNPObject*>(npobj);
5609e3a0d3e5e0725e32330137c505146270a2fc84Steve Block    obj->m_instance = 0; // free does not call the destructor
57b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian    free(obj);
58b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian}
597fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian
60b2318f335c407832166c7568f3e50afedad5b9dbFeng Qianstatic NPClass JavaNPObjectClass = {
617fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian    NP_CLASS_STRUCT_VERSION,
6209e3a0d3e5e0725e32330137c505146270a2fc84Steve Block    AllocJavaNPObject, // allocate,
6309e3a0d3e5e0725e32330137c505146270a2fc84Steve Block    FreeJavaNPObject, // free,
6409e3a0d3e5e0725e32330137c505146270a2fc84Steve Block    0, // invalidate
6509e3a0d3e5e0725e32330137c505146270a2fc84Steve Block    JavaNPObjectHasMethod,
6609e3a0d3e5e0725e32330137c505146270a2fc84Steve Block    JavaNPObjectInvoke,
6709e3a0d3e5e0725e32330137c505146270a2fc84Steve Block    0, // invokeDefault,
6809e3a0d3e5e0725e32330137c505146270a2fc84Steve Block    JavaNPObjectHasProperty,
6909e3a0d3e5e0725e32330137c505146270a2fc84Steve Block    JavaNPObjectGetProperty,
7009e3a0d3e5e0725e32330137c505146270a2fc84Steve Block    0, // setProperty
7109e3a0d3e5e0725e32330137c505146270a2fc84Steve Block    0, // removeProperty
7209e3a0d3e5e0725e32330137c505146270a2fc84Steve Block    0, // enumerate
7309e3a0d3e5e0725e32330137c505146270a2fc84Steve Block    0 // construct
747fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian};
757fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian
7649a6d4f2c272010e14806805cb2ca55e6fe8a782Steve BlockNPObject* JavaInstanceToNPObject(JavaInstance* instance)
7709e3a0d3e5e0725e32330137c505146270a2fc84Steve Block{
78ab4f4d6e9dcd2465524619737cd0bbd7386fa14eBen Murdoch    JavaNPObject* object = reinterpret_cast<JavaNPObject*>(_NPN_CreateObject(0, &JavaNPObjectClass));
7954dec9637e20bfba1857f3d54df3c43ce94ff97bSteve Block    object->m_instance = instance;
80b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian    return reinterpret_cast<NPObject*>(object);
817fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian}
827fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian
83b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian// Returns null if obj is not a wrapper of JavaInstance
8409e3a0d3e5e0725e32330137c505146270a2fc84Steve BlockJavaInstance* ExtractJavaInstance(NPObject* obj)
8509e3a0d3e5e0725e32330137c505146270a2fc84Steve Block{
8609e3a0d3e5e0725e32330137c505146270a2fc84Steve Block    if (obj->_class == &JavaNPObjectClass)
8754dec9637e20bfba1857f3d54df3c43ce94ff97bSteve Block        return reinterpret_cast<JavaNPObject*>(obj)->m_instance.get();
88b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian    return 0;
897fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian}
907fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian
9109e3a0d3e5e0725e32330137c505146270a2fc84Steve Blockbool JavaNPObjectHasMethod(NPObject* obj, NPIdentifier identifier)
9209e3a0d3e5e0725e32330137c505146270a2fc84Steve Block{
93b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian    JavaInstance* instance = ExtractJavaInstance(obj);
9454dec9637e20bfba1857f3d54df3c43ce94ff97bSteve Block    if (!instance)
95b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian        return false;
9602a23642eaae7e2fdd441eddffd2c085fbee3b49Ben Murdoch    NPUTF8* name = _NPN_UTF8FromIdentifier(identifier);
9754dec9637e20bfba1857f3d54df3c43ce94ff97bSteve Block    if (!name)
98b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian        return false;
99b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian
10088d4517612dafdcaff7a98f2a68ff071e2734ea6Steve Block    instance->begin();
101b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian    bool result = (instance->getClass()->methodsNamed(name).size() > 0);
10288d4517612dafdcaff7a98f2a68ff071e2734ea6Steve Block    instance->end();
1037fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian
104b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian    // TODO: use NPN_MemFree
105b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian    free(name);
106b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian
107b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian    return result;
1087fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian}
1097fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian
11009e3a0d3e5e0725e32330137c505146270a2fc84Steve Blockbool JavaNPObjectInvoke(NPObject* obj, NPIdentifier identifier, const NPVariant* args, uint32_t argCount, NPVariant* result)
11109e3a0d3e5e0725e32330137c505146270a2fc84Steve Block{
112b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian    JavaInstance* instance = ExtractJavaInstance(obj);
11354dec9637e20bfba1857f3d54df3c43ce94ff97bSteve Block    if (!instance)
114b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian        return false;
11502a23642eaae7e2fdd441eddffd2c085fbee3b49Ben Murdoch    NPUTF8* name = _NPN_UTF8FromIdentifier(identifier);
11654dec9637e20bfba1857f3d54df3c43ce94ff97bSteve Block    if (!name)
117b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian        return false;
118b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian
11988d4517612dafdcaff7a98f2a68ff071e2734ea6Steve Block    instance->begin();
120b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian
1212bde8e466a4451c7319e3a072d118917957d6554Steve Block    MethodList methodList = instance->getClass()->methodsNamed(name);
122b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian    // TODO: use NPN_MemFree
123b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian    free(name);
1242bde8e466a4451c7319e3a072d118917957d6554Steve Block
1252bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Try to find a good match for the overloaded method. The
1262bde8e466a4451c7319e3a072d118917957d6554Steve Block    // fundamental problem is that JavaScript doesn't have the
1272bde8e466a4451c7319e3a072d118917957d6554Steve Block    // notion of method overloading and Java does. We could
1282bde8e466a4451c7319e3a072d118917957d6554Steve Block    // get a bit more sophisticated and attempt to do some
1292bde8e466a4451c7319e3a072d118917957d6554Steve Block    // type checking as well as checking the number of parameters.
1302bde8e466a4451c7319e3a072d118917957d6554Steve Block    size_t numMethods = methodList.size();
1312bde8e466a4451c7319e3a072d118917957d6554Steve Block    JavaMethod* aMethod;
1322bde8e466a4451c7319e3a072d118917957d6554Steve Block    JavaMethod* jMethod = 0;
1332bde8e466a4451c7319e3a072d118917957d6554Steve Block    for (size_t methodIndex = 0; methodIndex < numMethods; methodIndex++) {
1342bde8e466a4451c7319e3a072d118917957d6554Steve Block        aMethod = methodList[methodIndex];
1352bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (aMethod->numParameters() == static_cast<int>(argCount)) {
1362bde8e466a4451c7319e3a072d118917957d6554Steve Block            jMethod = aMethod;
1372bde8e466a4451c7319e3a072d118917957d6554Steve Block            break;
1382bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
1392bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
1401b90d74d66fbb55d40e5e87a84423acd81ab062aSteve Block    if (!jMethod) {
1411b90d74d66fbb55d40e5e87a84423acd81ab062aSteve Block        instance->end();
1422bde8e466a4451c7319e3a072d118917957d6554Steve Block        return false;
1431b90d74d66fbb55d40e5e87a84423acd81ab062aSteve Block    }
1442bde8e466a4451c7319e3a072d118917957d6554Steve Block
1452bde8e466a4451c7319e3a072d118917957d6554Steve Block    JavaValue* jArgs = new JavaValue[argCount];
1462bde8e466a4451c7319e3a072d118917957d6554Steve Block    for (unsigned int i = 0; i < argCount; i++)
1472bde8e466a4451c7319e3a072d118917957d6554Steve Block        jArgs[i] = convertNPVariantToJavaValue(args[i], jMethod->parameterAt(i));
1482bde8e466a4451c7319e3a072d118917957d6554Steve Block
149cb3fc20cd59c3956ace2b6b9966da170b92b9162Steve Block// ANDROID
150cb3fc20cd59c3956ace2b6b9966da170b92b9162Steve Block    bool exceptionOccurred;
151cb3fc20cd59c3956ace2b6b9966da170b92b9162Steve Block    JavaValue jResult = instance->invokeMethod(jMethod, jArgs, exceptionOccurred);
1522bde8e466a4451c7319e3a072d118917957d6554Steve Block    instance->end();
1532bde8e466a4451c7319e3a072d118917957d6554Steve Block    delete[] jArgs;
1542bde8e466a4451c7319e3a072d118917957d6554Steve Block
155cb3fc20cd59c3956ace2b6b9966da170b92b9162Steve Block    if (exceptionOccurred)
156cb3fc20cd59c3956ace2b6b9966da170b92b9162Steve Block        return false;
157cb3fc20cd59c3956ace2b6b9966da170b92b9162Steve Block// END ANDROID
158cb3fc20cd59c3956ace2b6b9966da170b92b9162Steve Block
1592bde8e466a4451c7319e3a072d118917957d6554Steve Block    VOID_TO_NPVARIANT(*result);
1602bde8e466a4451c7319e3a072d118917957d6554Steve Block    convertJavaValueToNPVariant(jResult, result);
1612bde8e466a4451c7319e3a072d118917957d6554Steve Block    return true;
1627fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian}
1637fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian
16409e3a0d3e5e0725e32330137c505146270a2fc84Steve Blockbool JavaNPObjectHasProperty(NPObject* obj, NPIdentifier identifier)
16509e3a0d3e5e0725e32330137c505146270a2fc84Steve Block{
166b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian    JavaInstance* instance = ExtractJavaInstance(obj);
16754dec9637e20bfba1857f3d54df3c43ce94ff97bSteve Block    if (!instance)
168b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian        return false;
16902a23642eaae7e2fdd441eddffd2c085fbee3b49Ben Murdoch    NPUTF8* name = _NPN_UTF8FromIdentifier(identifier);
17054dec9637e20bfba1857f3d54df3c43ce94ff97bSteve Block    if (!name)
171b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian        return false;
17288d4517612dafdcaff7a98f2a68ff071e2734ea6Steve Block    instance->begin();
17354dec9637e20bfba1857f3d54df3c43ce94ff97bSteve Block    bool result = instance->getClass()->fieldNamed(name);
17488d4517612dafdcaff7a98f2a68ff071e2734ea6Steve Block    instance->end();
175b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian    free(name);
176b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian    return result;
1777fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian}
1787fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian
17909e3a0d3e5e0725e32330137c505146270a2fc84Steve Blockbool JavaNPObjectGetProperty(NPObject* obj, NPIdentifier identifier, NPVariant* result)
18009e3a0d3e5e0725e32330137c505146270a2fc84Steve Block{
181b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian    VOID_TO_NPVARIANT(*result);
182b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian    JavaInstance* instance = ExtractJavaInstance(obj);
18354dec9637e20bfba1857f3d54df3c43ce94ff97bSteve Block    if (!instance)
184b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian        return false;
18502a23642eaae7e2fdd441eddffd2c085fbee3b49Ben Murdoch    NPUTF8* name = _NPN_UTF8FromIdentifier(identifier);
18654dec9637e20bfba1857f3d54df3c43ce94ff97bSteve Block    if (!name)
187b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian        return false;
1887fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian
18988d4517612dafdcaff7a98f2a68ff071e2734ea6Steve Block    instance->begin();
190b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian    JavaField* field = instance->getClass()->fieldNamed(name);
19109e3a0d3e5e0725e32330137c505146270a2fc84Steve Block    free(name); // TODO: use NPN_MemFree
1921b90d74d66fbb55d40e5e87a84423acd81ab062aSteve Block    if (!field) {
1931b90d74d66fbb55d40e5e87a84423acd81ab062aSteve Block        instance->end();
194b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian        return false;
1951b90d74d66fbb55d40e5e87a84423acd81ab062aSteve Block    }
196b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian
1972d44f555f1b58dea94258c21592a95e78fe5bc21Steve Block#if PLATFORM(ANDROID)
198ee6ca70ca284d2333863f121123b1812043deb33Ben Murdoch    // JSC does not seem to support returning object properties so we emulate that
199ee6ca70ca284d2333863f121123b1812043deb33Ben Murdoch    // behaviour here.
2009c8e65377a8462e90abc85e3d888365f7fecf9e3Steve Block    JavaValue value;
201ee6ca70ca284d2333863f121123b1812043deb33Ben Murdoch#else
2022bde8e466a4451c7319e3a072d118917957d6554Steve Block    JavaValue value = instance->getField(field);
2039c8e65377a8462e90abc85e3d888365f7fecf9e3Steve Block#endif // PLATFORM(ANDROID)
2042bde8e466a4451c7319e3a072d118917957d6554Steve Block    instance->end();
2052bde8e466a4451c7319e3a072d118917957d6554Steve Block
2062bde8e466a4451c7319e3a072d118917957d6554Steve Block    convertJavaValueToNPVariant(value, result);
207b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian
208b2318f335c407832166c7568f3e50afedad5b9dbFeng Qian    return true;
2097fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian}
2107fa30a60f66c19c8e6fb91ef799bca4d8d6f57f2Feng Qian
21109e3a0d3e5e0725e32330137c505146270a2fc84Steve Block} // namespace Bindings
21254dec9637e20bfba1857f3d54df3c43ce94ff97bSteve Block
21309e3a0d3e5e0725e32330137c505146270a2fc84Steve Block} // namespace JSC
21481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
21581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#endif // ENABLE(JAVA_BRIDGE)
216