/platform/external/webkit/WebCore/bridge/jni/jsc/JNIBridgeJSC.cpp

https://github.com/aharish/totoro-gb-opensource-update2 · C++ · 451 lines · 349 code · 68 blank · 34 comment · 30 complexity · f4ee2fa6438c739a0a104b5ba205897f MD5 · raw file

  1. /*
  2. * Copyright (C) 2003, 2004, 2005, 2007, 2009 Apple Inc. All rights reserved.
  3. * Copyright 2010, The Android Open Source Project
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
  15. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  17. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
  18. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  19. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  20. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  21. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  22. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include "config.h"
  27. #include "JNIBridgeJSC.h"
  28. #if ENABLE(MAC_JAVA_BRIDGE)
  29. #include "JNIUtilityPrivate.h"
  30. #include "runtime_array.h"
  31. #include "runtime_object.h"
  32. #include <runtime/Error.h>
  33. #ifdef NDEBUG
  34. #define JS_LOG(formatAndArgs...) ((void)0)
  35. #else
  36. #define JS_LOG(formatAndArgs...) { \
  37. fprintf(stderr, "%s:%d -- %s: ", __FILE__, __LINE__, __FUNCTION__); \
  38. fprintf(stderr, formatAndArgs); \
  39. }
  40. #endif
  41. using namespace JSC;
  42. using namespace JSC::Bindings;
  43. JavaField::JavaField(JNIEnv* env, jobject aField)
  44. {
  45. // Get field type name
  46. jstring fieldTypeName = 0;
  47. if (jobject fieldType = callJNIMethod_jobject(aField, "getType", "()Ljava/lang/Class;"))
  48. fieldTypeName = static_cast<jstring>(callJNIMethod_jobject(fieldType, "getName", "()Ljava/lang/String;"));
  49. if (!fieldTypeName)
  50. fieldTypeName = env->NewStringUTF("<Unknown>");
  51. m_type = JavaString(env, fieldTypeName);
  52. m_JNIType = JNITypeFromClassName(m_type.UTF8String());
  53. // Get field name
  54. jstring fieldName = static_cast<jstring>(callJNIMethod_jobject(aField, "getName", "()Ljava/lang/String;"));
  55. if (!fieldName)
  56. fieldName = env->NewStringUTF("<Unknown>");
  57. m_name = JavaString(env, fieldName);
  58. m_field = new JObjectWrapper(aField);
  59. }
  60. JSValue JavaArray::convertJObjectToArray(ExecState* exec, jobject anObject, const char* type, PassRefPtr<RootObject> rootObject)
  61. {
  62. if (type[0] != '[')
  63. return jsUndefined();
  64. return new (exec) RuntimeArray(exec, new JavaArray(anObject, type, rootObject));
  65. }
  66. jvalue JavaField::dispatchValueFromInstance(ExecState* exec, const JavaInstance* instance, const char* name, const char* sig, JNIType returnType) const
  67. {
  68. jobject jinstance = instance->javaInstance();
  69. jobject fieldJInstance = m_field->m_instance;
  70. JNIEnv* env = getJNIEnv();
  71. jvalue result;
  72. memset(&result, 0, sizeof(jvalue));
  73. jclass cls = env->GetObjectClass(fieldJInstance);
  74. if (cls) {
  75. jmethodID mid = env->GetMethodID(cls, name, sig);
  76. if (mid) {
  77. RootObject* rootObject = instance->rootObject();
  78. if (rootObject && rootObject->nativeHandle()) {
  79. JSValue exceptionDescription;
  80. jvalue args[1];
  81. args[0].l = jinstance;
  82. dispatchJNICall(exec, rootObject->nativeHandle(), fieldJInstance, false, returnType, mid, args, result, 0, exceptionDescription);
  83. if (exceptionDescription)
  84. throwError(exec, GeneralError, exceptionDescription.toString(exec));
  85. }
  86. }
  87. }
  88. return result;
  89. }
  90. JSValue JavaField::valueFromInstance(ExecState* exec, const Instance* i) const
  91. {
  92. const JavaInstance* instance = static_cast<const JavaInstance*>(i);
  93. JSValue jsresult = jsUndefined();
  94. switch (m_JNIType) {
  95. case array_type:
  96. case object_type:
  97. {
  98. jvalue result = dispatchValueFromInstance(exec, instance, "get", "(Ljava/lang/Object;)Ljava/lang/Object;", object_type);
  99. jobject anObject = result.l;
  100. const char* arrayType = type();
  101. if (arrayType[0] == '[')
  102. jsresult = JavaArray::convertJObjectToArray(exec, anObject, arrayType, instance->rootObject());
  103. else if (anObject)
  104. jsresult = JavaInstance::create(anObject, instance->rootObject())->createRuntimeObject(exec);
  105. }
  106. break;
  107. case boolean_type:
  108. jsresult = jsBoolean(dispatchValueFromInstance(exec, instance, "getBoolean", "(Ljava/lang/Object;)Z", boolean_type).z);
  109. break;
  110. case byte_type:
  111. case char_type:
  112. case short_type:
  113. case int_type:
  114. {
  115. jint value;
  116. jvalue result = dispatchValueFromInstance(exec, instance, "getInt", "(Ljava/lang/Object;)I", int_type);
  117. value = result.i;
  118. jsresult = jsNumber(exec, static_cast<int>(value));
  119. }
  120. break;
  121. case long_type:
  122. case float_type:
  123. case double_type:
  124. {
  125. jdouble value;
  126. jvalue result = dispatchValueFromInstance(exec, instance, "getDouble", "(Ljava/lang/Object;)D", double_type);
  127. value = result.i;
  128. jsresult = jsNumber(exec, static_cast<double>(value));
  129. }
  130. break;
  131. default:
  132. break;
  133. }
  134. JS_LOG("getting %s = %s\n", UString(name()).UTF8String().c_str(), jsresult.toString(exec).ascii());
  135. return jsresult;
  136. }
  137. void JavaField::dispatchSetValueToInstance(ExecState* exec, const JavaInstance* instance, jvalue javaValue, const char* name, const char* sig) const
  138. {
  139. jobject jinstance = instance->javaInstance();
  140. jobject fieldJInstance = m_field->m_instance;
  141. JNIEnv* env = getJNIEnv();
  142. jclass cls = env->GetObjectClass(fieldJInstance);
  143. if (cls) {
  144. jmethodID mid = env->GetMethodID(cls, name, sig);
  145. if (mid) {
  146. RootObject* rootObject = instance->rootObject();
  147. if (rootObject && rootObject->nativeHandle()) {
  148. JSValue exceptionDescription;
  149. jvalue args[2];
  150. jvalue result;
  151. args[0].l = jinstance;
  152. args[1] = javaValue;
  153. dispatchJNICall(exec, rootObject->nativeHandle(), fieldJInstance, false, void_type, mid, args, result, 0, exceptionDescription);
  154. if (exceptionDescription)
  155. throwError(exec, GeneralError, exceptionDescription.toString(exec));
  156. }
  157. }
  158. }
  159. }
  160. void JavaField::setValueToInstance(ExecState* exec, const Instance* i, JSValue aValue) const
  161. {
  162. const JavaInstance* instance = static_cast<const JavaInstance*>(i);
  163. jvalue javaValue = convertValueToJValue(exec, aValue, m_JNIType, type());
  164. JS_LOG("setting value %s to %s\n", UString(name()).UTF8String().c_str(), aValue.toString(exec).ascii());
  165. switch (m_JNIType) {
  166. case array_type:
  167. case object_type:
  168. {
  169. dispatchSetValueToInstance(exec, instance, javaValue, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V");
  170. }
  171. break;
  172. case boolean_type:
  173. {
  174. dispatchSetValueToInstance(exec, instance, javaValue, "setBoolean", "(Ljava/lang/Object;Z)V");
  175. }
  176. break;
  177. case byte_type:
  178. {
  179. dispatchSetValueToInstance(exec, instance, javaValue, "setByte", "(Ljava/lang/Object;B)V");
  180. }
  181. break;
  182. case char_type:
  183. {
  184. dispatchSetValueToInstance(exec, instance, javaValue, "setChar", "(Ljava/lang/Object;C)V");
  185. }
  186. break;
  187. case short_type:
  188. {
  189. dispatchSetValueToInstance(exec, instance, javaValue, "setShort", "(Ljava/lang/Object;S)V");
  190. }
  191. break;
  192. case int_type:
  193. {
  194. dispatchSetValueToInstance(exec, instance, javaValue, "setInt", "(Ljava/lang/Object;I)V");
  195. }
  196. break;
  197. case long_type:
  198. {
  199. dispatchSetValueToInstance(exec, instance, javaValue, "setLong", "(Ljava/lang/Object;J)V");
  200. }
  201. break;
  202. case float_type:
  203. {
  204. dispatchSetValueToInstance(exec, instance, javaValue, "setFloat", "(Ljava/lang/Object;F)V");
  205. }
  206. break;
  207. case double_type:
  208. {
  209. dispatchSetValueToInstance(exec, instance, javaValue, "setDouble", "(Ljava/lang/Object;D)V");
  210. }
  211. break;
  212. default:
  213. break;
  214. }
  215. }
  216. JavaArray::JavaArray(jobject array, const char* type, PassRefPtr<RootObject> rootObject)
  217. : Array(rootObject)
  218. {
  219. m_array = new JObjectWrapper(array);
  220. // Java array are fixed length, so we can cache length.
  221. JNIEnv* env = getJNIEnv();
  222. m_length = env->GetArrayLength(static_cast<jarray>(m_array->m_instance));
  223. m_type = strdup(type);
  224. m_rootObject = rootObject;
  225. }
  226. JavaArray::~JavaArray()
  227. {
  228. free(const_cast<char*>(m_type));
  229. }
  230. RootObject* JavaArray::rootObject() const
  231. {
  232. return m_rootObject && m_rootObject->isValid() ? m_rootObject.get() : 0;
  233. }
  234. void JavaArray::setValueAt(ExecState* exec, unsigned index, JSValue aValue) const
  235. {
  236. JNIEnv* env = getJNIEnv();
  237. char* javaClassName = 0;
  238. JNIType arrayType = JNITypeFromPrimitiveType(m_type[1]);
  239. if (m_type[1] == 'L') {
  240. // The type of the array will be something like:
  241. // "[Ljava.lang.string;". This is guaranteed, so no need
  242. // for extra sanity checks.
  243. javaClassName = strdup(&m_type[2]);
  244. javaClassName[strchr(javaClassName, ';')-javaClassName] = 0;
  245. }
  246. jvalue aJValue = convertValueToJValue(exec, aValue, arrayType, javaClassName);
  247. switch (arrayType) {
  248. case object_type:
  249. {
  250. env->SetObjectArrayElement(static_cast<jobjectArray>(javaArray()), index, aJValue.l);
  251. break;
  252. }
  253. case boolean_type:
  254. {
  255. env->SetBooleanArrayRegion(static_cast<jbooleanArray>(javaArray()), index, 1, &aJValue.z);
  256. break;
  257. }
  258. case byte_type:
  259. {
  260. env->SetByteArrayRegion(static_cast<jbyteArray>(javaArray()), index, 1, &aJValue.b);
  261. break;
  262. }
  263. case char_type:
  264. {
  265. env->SetCharArrayRegion(static_cast<jcharArray>(javaArray()), index, 1, &aJValue.c);
  266. break;
  267. }
  268. case short_type:
  269. {
  270. env->SetShortArrayRegion(static_cast<jshortArray>(javaArray()), index, 1, &aJValue.s);
  271. break;
  272. }
  273. case int_type:
  274. {
  275. env->SetIntArrayRegion(static_cast<jintArray>(javaArray()), index, 1, &aJValue.i);
  276. break;
  277. }
  278. case long_type:
  279. {
  280. env->SetLongArrayRegion(static_cast<jlongArray>(javaArray()), index, 1, &aJValue.j);
  281. }
  282. case float_type:
  283. {
  284. env->SetFloatArrayRegion(static_cast<jfloatArray>(javaArray()), index, 1, &aJValue.f);
  285. break;
  286. }
  287. case double_type:
  288. {
  289. env->SetDoubleArrayRegion(static_cast<jdoubleArray>(javaArray()), index, 1, &aJValue.d);
  290. break;
  291. }
  292. default:
  293. break;
  294. }
  295. if (javaClassName)
  296. free(const_cast<char*>(javaClassName));
  297. }
  298. JSValue JavaArray::valueAt(ExecState* exec, unsigned index) const
  299. {
  300. JNIEnv* env = getJNIEnv();
  301. JNIType arrayType = JNITypeFromPrimitiveType(m_type[1]);
  302. switch (arrayType) {
  303. case object_type:
  304. {
  305. jobjectArray objectArray = static_cast<jobjectArray>(javaArray());
  306. jobject anObject;
  307. anObject = env->GetObjectArrayElement(objectArray, index);
  308. // No object?
  309. if (!anObject)
  310. return jsNull();
  311. // Nested array?
  312. if (m_type[1] == '[')
  313. return JavaArray::convertJObjectToArray(exec, anObject, m_type + 1, rootObject());
  314. // or array of other object type?
  315. return JavaInstance::create(anObject, rootObject())->createRuntimeObject(exec);
  316. }
  317. case boolean_type:
  318. {
  319. jbooleanArray booleanArray = static_cast<jbooleanArray>(javaArray());
  320. jboolean aBoolean;
  321. env->GetBooleanArrayRegion(booleanArray, index, 1, &aBoolean);
  322. return jsBoolean(aBoolean);
  323. }
  324. case byte_type:
  325. {
  326. jbyteArray byteArray = static_cast<jbyteArray>(javaArray());
  327. jbyte aByte;
  328. env->GetByteArrayRegion(byteArray, index, 1, &aByte);
  329. return jsNumber(exec, aByte);
  330. }
  331. case char_type:
  332. {
  333. jcharArray charArray = static_cast<jcharArray>(javaArray());
  334. jchar aChar;
  335. env->GetCharArrayRegion(charArray, index, 1, &aChar);
  336. return jsNumber(exec, aChar);
  337. break;
  338. }
  339. case short_type:
  340. {
  341. jshortArray shortArray = static_cast<jshortArray>(javaArray());
  342. jshort aShort;
  343. env->GetShortArrayRegion(shortArray, index, 1, &aShort);
  344. return jsNumber(exec, aShort);
  345. }
  346. case int_type:
  347. {
  348. jintArray intArray = static_cast<jintArray>(javaArray());
  349. jint anInt;
  350. env->GetIntArrayRegion(intArray, index, 1, &anInt);
  351. return jsNumber(exec, anInt);
  352. }
  353. case long_type:
  354. {
  355. jlongArray longArray = static_cast<jlongArray>(javaArray());
  356. jlong aLong;
  357. env->GetLongArrayRegion(longArray, index, 1, &aLong);
  358. return jsNumber(exec, aLong);
  359. }
  360. case float_type:
  361. {
  362. jfloatArray floatArray = static_cast<jfloatArray>(javaArray());
  363. jfloat aFloat;
  364. env->GetFloatArrayRegion(floatArray, index, 1, &aFloat);
  365. return jsNumber(exec, aFloat);
  366. }
  367. case double_type:
  368. {
  369. jdoubleArray doubleArray = static_cast<jdoubleArray>(javaArray());
  370. jdouble aDouble;
  371. env->GetDoubleArrayRegion(doubleArray, index, 1, &aDouble);
  372. return jsNumber(exec, aDouble);
  373. }
  374. default:
  375. break;
  376. }
  377. return jsUndefined();
  378. }
  379. unsigned int JavaArray::getLength() const
  380. {
  381. return m_length;
  382. }
  383. #endif // ENABLE(MAC_JAVA_BRIDGE)