/WebCore/bridge/jni/jsc/JNIUtilityPrivate.cpp

http://github.com/CyanogenMod/android_external_webkit · C++ · 293 lines · 220 code · 35 blank · 38 comment · 29 complexity · 79e49dbf3d5ca935d74cc404c31e4f78 MD5 · raw file

  1. /*
  2. * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
  3. * Copyright 2009, 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. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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 "JNIUtilityPrivate.h"
  28. #if ENABLE(MAC_JAVA_BRIDGE)
  29. #include "JNIBridgeJSC.h"
  30. #include "runtime_array.h"
  31. #include "runtime_object.h"
  32. #include <runtime/JSArray.h>
  33. #include <runtime/JSLock.h>
  34. namespace JSC {
  35. namespace Bindings {
  36. static jobject convertArrayInstanceToJavaArray(ExecState* exec, JSArray* jsArray, const char* javaClassName)
  37. {
  38. JNIEnv* env = getJNIEnv();
  39. // As JS Arrays can contain a mixture of objects, assume we can convert to
  40. // the requested Java Array type requested, unless the array type is some object array
  41. // other than a string.
  42. unsigned length = jsArray->length();
  43. jobjectArray jarray = 0;
  44. // Build the correct array type
  45. switch (JNITypeFromPrimitiveType(javaClassName[1])) {
  46. case object_type:
  47. {
  48. // Only support string object types
  49. if (!strcmp("[Ljava.lang.String;", javaClassName)) {
  50. jarray = (jobjectArray)env->NewObjectArray(length,
  51. env->FindClass("java/lang/String"),
  52. env->NewStringUTF(""));
  53. for (unsigned i = 0; i < length; i++) {
  54. JSValue item = jsArray->get(exec, i);
  55. UString stringValue = item.toString(exec);
  56. env->SetObjectArrayElement(jarray, i,
  57. env->functions->NewString(env, (const jchar *)stringValue.data(), stringValue.size()));
  58. }
  59. }
  60. break;
  61. }
  62. case boolean_type:
  63. {
  64. jarray = (jobjectArray)env->NewBooleanArray(length);
  65. for (unsigned i = 0; i < length; i++) {
  66. JSValue item = jsArray->get(exec, i);
  67. jboolean value = (jboolean)item.toNumber(exec);
  68. env->SetBooleanArrayRegion((jbooleanArray)jarray, (jsize)i, (jsize)1, &value);
  69. }
  70. break;
  71. }
  72. case byte_type:
  73. {
  74. jarray = (jobjectArray)env->NewByteArray(length);
  75. for (unsigned i = 0; i < length; i++) {
  76. JSValue item = jsArray->get(exec, i);
  77. jbyte value = (jbyte)item.toNumber(exec);
  78. env->SetByteArrayRegion((jbyteArray)jarray, (jsize)i, (jsize)1, &value);
  79. }
  80. break;
  81. }
  82. case char_type:
  83. {
  84. jarray = (jobjectArray)env->NewCharArray(length);
  85. for (unsigned i = 0; i < length; i++) {
  86. JSValue item = jsArray->get(exec, i);
  87. UString stringValue = item.toString(exec);
  88. jchar value = 0;
  89. if (stringValue.size() > 0)
  90. value = ((const jchar*)stringValue.data())[0];
  91. env->SetCharArrayRegion((jcharArray)jarray, (jsize)i, (jsize)1, &value);
  92. }
  93. break;
  94. }
  95. case short_type:
  96. {
  97. jarray = (jobjectArray)env->NewShortArray(length);
  98. for (unsigned i = 0; i < length; i++) {
  99. JSValue item = jsArray->get(exec, i);
  100. jshort value = (jshort)item.toNumber(exec);
  101. env->SetShortArrayRegion((jshortArray)jarray, (jsize)i, (jsize)1, &value);
  102. }
  103. break;
  104. }
  105. case int_type:
  106. {
  107. jarray = (jobjectArray)env->NewIntArray(length);
  108. for (unsigned i = 0; i < length; i++) {
  109. JSValue item = jsArray->get(exec, i);
  110. jint value = (jint)item.toNumber(exec);
  111. env->SetIntArrayRegion((jintArray)jarray, (jsize)i, (jsize)1, &value);
  112. }
  113. break;
  114. }
  115. case long_type:
  116. {
  117. jarray = (jobjectArray)env->NewLongArray(length);
  118. for (unsigned i = 0; i < length; i++) {
  119. JSValue item = jsArray->get(exec, i);
  120. jlong value = (jlong)item.toNumber(exec);
  121. env->SetLongArrayRegion((jlongArray)jarray, (jsize)i, (jsize)1, &value);
  122. }
  123. break;
  124. }
  125. case float_type:
  126. {
  127. jarray = (jobjectArray)env->NewFloatArray(length);
  128. for (unsigned i = 0; i < length; i++) {
  129. JSValue item = jsArray->get(exec, i);
  130. jfloat value = (jfloat)item.toNumber(exec);
  131. env->SetFloatArrayRegion((jfloatArray)jarray, (jsize)i, (jsize)1, &value);
  132. }
  133. break;
  134. }
  135. case double_type:
  136. {
  137. jarray = (jobjectArray)env->NewDoubleArray(length);
  138. for (unsigned i = 0; i < length; i++) {
  139. JSValue item = jsArray->get(exec, i);
  140. jdouble value = (jdouble)item.toNumber(exec);
  141. env->SetDoubleArrayRegion((jdoubleArray)jarray, (jsize)i, (jsize)1, &value);
  142. }
  143. break;
  144. }
  145. case array_type: // don't handle embedded arrays
  146. case void_type: // Don't expect arrays of void objects
  147. case invalid_type: // Array of unknown objects
  148. break;
  149. }
  150. // if it was not one of the cases handled, then null is returned
  151. return jarray;
  152. }
  153. jvalue convertValueToJValue(ExecState* exec, JSValue value, JNIType jniType, const char* javaClassName)
  154. {
  155. JSLock lock(SilenceAssertionsOnly);
  156. jvalue result;
  157. switch (jniType) {
  158. case array_type:
  159. case object_type:
  160. {
  161. result.l = (jobject)0;
  162. // First see if we have a Java instance.
  163. if (value.isObject()) {
  164. JSObject* objectImp = asObject(value);
  165. if (objectImp->classInfo() == &RuntimeObjectImp::s_info) {
  166. RuntimeObjectImp* imp = static_cast<RuntimeObjectImp*>(objectImp);
  167. JavaInstance* instance = static_cast<JavaInstance*>(imp->getInternalInstance());
  168. if (instance)
  169. result.l = instance->javaInstance();
  170. } else if (objectImp->classInfo() == &RuntimeArray::s_info) {
  171. // Input is a JavaScript Array that was originally created from a Java Array
  172. RuntimeArray* imp = static_cast<RuntimeArray*>(objectImp);
  173. JavaArray* array = static_cast<JavaArray*>(imp->getConcreteArray());
  174. result.l = array->javaArray();
  175. } else if (objectImp->classInfo() == &JSArray::info) {
  176. // Input is a Javascript Array. We need to create it to a Java Array.
  177. result.l = convertArrayInstanceToJavaArray(exec, asArray(value), javaClassName);
  178. }
  179. }
  180. // Now convert value to a string if the target type is a java.lang.string, and we're not
  181. // converting from a Null.
  182. if (!result.l && !strcmp(javaClassName, "java.lang.String")) {
  183. #ifdef CONVERT_NULL_TO_EMPTY_STRING
  184. if (value->isNull()) {
  185. JNIEnv* env = getJNIEnv();
  186. jchar buf[2];
  187. jobject javaString = env->functions->NewString(env, buf, 0);
  188. result.l = javaString;
  189. } else
  190. #else
  191. if (!value.isNull())
  192. #endif
  193. {
  194. UString stringValue = value.toString(exec);
  195. JNIEnv* env = getJNIEnv();
  196. jobject javaString = env->functions->NewString(env, (const jchar *)stringValue.data(), stringValue.size());
  197. result.l = javaString;
  198. }
  199. } else if (!result.l)
  200. // ANDROID
  201. memset(&result, 0, sizeof(jvalue)); // Handle it the same as a void case
  202. }
  203. break;
  204. case boolean_type:
  205. {
  206. result.z = (jboolean)value.toNumber(exec);
  207. }
  208. break;
  209. case byte_type:
  210. {
  211. result.b = (jbyte)value.toNumber(exec);
  212. }
  213. break;
  214. case char_type:
  215. {
  216. result.c = (jchar)value.toNumber(exec);
  217. }
  218. break;
  219. case short_type:
  220. {
  221. result.s = (jshort)value.toNumber(exec);
  222. }
  223. break;
  224. case int_type:
  225. {
  226. result.i = (jint)value.toNumber(exec);
  227. }
  228. break;
  229. case long_type:
  230. {
  231. result.j = (jlong)value.toNumber(exec);
  232. }
  233. break;
  234. case float_type:
  235. {
  236. result.f = (jfloat)value.toNumber(exec);
  237. }
  238. break;
  239. case double_type:
  240. {
  241. result.d = (jdouble)value.toNumber(exec);
  242. }
  243. break;
  244. break;
  245. case invalid_type:
  246. default:
  247. case void_type:
  248. {
  249. // ANDROID
  250. memset(&result, 0, sizeof(jvalue));
  251. }
  252. break;
  253. }
  254. return result;
  255. }
  256. } // end of namespace Bindings
  257. } // end of namespace JSC
  258. #endif // ENABLE(MAC_JAVA_BRIDGE)