1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file. 4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/android/java/gin_java_script_to_java_types_coercion.h" 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <unistd.h> 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/android/jni_android.h" 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/android/jni_string.h" 11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/strings/stringprintf.h" 13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/common/android/gin_java_bridge_value.h" 15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "third_party/WebKit/public/platform/WebString.h" 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdochusing base::android::ScopedJavaLocalRef; 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace content { 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace { 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char kJavaLangString[] = "java/lang/String"; 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char kUndefined[] = "undefined"; 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// This is an intermediate solution until we fix http://crbug.com/391492. 27116680a4aac90f2aa7413d9095a592090648e557Ben Murdochjstring ConvertUTF8ToJString(JNIEnv* env, const std::string& string) { 28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::string16 utf16( 29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blink::WebString::fromUTF8(string.c_str(), string.size())); 30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return env->NewString(utf16.data(), utf16.length()); 31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)double RoundDoubleTowardsZero(const double& x) { 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (std::isnan(x)) { 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return 0.0; 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return x > 0.0 ? floor(x) : ceil(x); 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Rounds to jlong using Java's type conversion rules. 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)jlong RoundDoubleToLong(const double& x) { 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) double intermediate = RoundDoubleTowardsZero(x); 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // The int64 limits can not be converted exactly to double values, so we 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // compare to custom constants. kint64max is 2^63 - 1, but the spacing 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // between double values in the the range 2^62 to 2^63 is 2^10. The cast is 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // required to silence a spurious gcc warning for integer overflow. 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const int64 kLimit = (GG_INT64_C(1) << 63) - static_cast<uint64>(1 << 10); 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(kLimit > 0); 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const double kLargestDoubleLessThanInt64Max = kLimit; 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const double kSmallestDoubleGreaterThanInt64Min = -kLimit; 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (intermediate > kLargestDoubleLessThanInt64Max) { 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return kint64max; 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (intermediate < kSmallestDoubleGreaterThanInt64Min) { 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return kint64min; 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return static_cast<jlong>(intermediate); 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Rounds to jint using Java's type conversion rules. 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)jint RoundDoubleToInt(const double& x) { 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) double intermediate = RoundDoubleTowardsZero(x); 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // The int32 limits cast exactly to double values. 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) intermediate = std::min(intermediate, static_cast<double>(kint32max)); 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) intermediate = std::max(intermediate, static_cast<double>(kint32min)); 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return static_cast<jint>(intermediate); 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)jvalue CoerceJavaScriptIntegerToJavaValue(JNIEnv* env, 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::Value* value, 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const JavaType& target_type, 72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool coerce_to_string, 73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GinJavaBridgeError* error) { 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // See http://jdk6.java.net/plugin2/liveconnect/#JS_NUMBER_VALUES. 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // For conversion to numeric types, we need to replicate Java's type 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // conversion rules. This requires that for integer values, we simply discard 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // all but the lowest n buts, where n is the number of bits in the target 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // type. 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jvalue result; 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int int_value; 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->GetAsInteger(&int_value); 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (target_type.type) { 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeByte: 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.b = static_cast<jbyte>(int_value); 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeChar: 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.c = static_cast<jchar>(int_value); 89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeShort: 91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.s = static_cast<jshort>(int_value); 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeInt: 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.i = int_value; 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeLong: 97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.j = int_value; 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeFloat: 100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.f = int_value; 101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeDouble: 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.d = int_value; 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeObject: 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to null. Spec 107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // requires handling object equivalents of primitive types. 108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.l = NULL; 109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeString: 111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.l = coerce_to_string 112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ? ConvertUTF8ToJString(env, base::Int64ToString(int_value)) 113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : NULL; 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeBoolean: 116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to false. Spec 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // requires converting to false for 0 or NaN, true otherwise. 118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.z = JNI_FALSE; 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeArray: 121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to null. Spec 122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // requires raising a JavaScript exception. 123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.l = NULL; 124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeVoid: 126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Conversion to void must never happen. 127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NOTREACHED(); 128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return result; 131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)jvalue CoerceJavaScriptDoubleToJavaValue(JNIEnv* env, 134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) double double_value, 135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const JavaType& target_type, 136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool coerce_to_string, 137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GinJavaBridgeError* error) { 138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // See http://jdk6.java.net/plugin2/liveconnect/#JS_NUMBER_VALUES. 139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // For conversion to numeric types, we need to replicate Java's type 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // conversion rules. 141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jvalue result; 142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (target_type.type) { 143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeByte: 144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.b = static_cast<jbyte>(RoundDoubleToInt(double_value)); 145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeChar: 147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert double to 0. 148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Spec requires converting doubles similarly to how we convert doubles to 149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // other numeric types. 150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.c = 0; 151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeShort: 153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.s = static_cast<jshort>(RoundDoubleToInt(double_value)); 154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeInt: 156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.i = RoundDoubleToInt(double_value); 157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeLong: 159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.j = RoundDoubleToLong(double_value); 160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeFloat: 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.f = static_cast<jfloat>(double_value); 163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeDouble: 165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.d = double_value; 166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeObject: 168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to null. Spec 169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // requires handling object equivalents of primitive types. 170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.l = NULL; 171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeString: 173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result.l = coerce_to_string 174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ? ConvertUTF8ToJString( 175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch env, base::StringPrintf("%.6lg", double_value)) 176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : NULL; 177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeBoolean: 179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to false. Spec 180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // requires converting to false for 0 or NaN, true otherwise. 181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.z = JNI_FALSE; 182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeArray: 184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to null. Spec 185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // requires raising a JavaScript exception. 186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.l = NULL; 187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeVoid: 189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Conversion to void must never happen. 190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NOTREACHED(); 191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return result; 194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)jvalue CoerceJavaScriptBooleanToJavaValue(JNIEnv* env, 197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::Value* value, 198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const JavaType& target_type, 199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool coerce_to_string, 200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GinJavaBridgeError* error) { 201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // See http://jdk6.java.net/plugin2/liveconnect/#JS_BOOLEAN_VALUES. 202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool boolean_value; 203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->GetAsBoolean(&boolean_value); 204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jvalue result; 205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (target_type.type) { 206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeBoolean: 207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.z = boolean_value ? JNI_TRUE : JNI_FALSE; 208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeObject: 210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec 211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // requires handling java.lang.Boolean and java.lang.Object. 212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.l = NULL; 213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeString: 215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result.l = coerce_to_string ? ConvertUTF8ToJString( 216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch env, boolean_value ? "true" : "false") 217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : NULL; 218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeByte: 220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeChar: 221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeShort: 222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeInt: 223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeLong: 224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeFloat: 225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeDouble: { 226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec 227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // requires converting to 0 or 1. 228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jvalue null_value = {0}; 229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result = null_value; 230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeArray: 233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec 234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // requires raising a JavaScript exception. 235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.l = NULL; 236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeVoid: 238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Conversion to void must never happen. 239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NOTREACHED(); 240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return result; 243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)jvalue CoerceJavaScriptStringToJavaValue(JNIEnv* env, 246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::Value* value, 247116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const JavaType& target_type, 248116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GinJavaBridgeError* error) { 249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // See http://jdk6.java.net/plugin2/liveconnect/#JS_STRING_VALUES. 250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jvalue result; 251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (target_type.type) { 252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeString: { 253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string string_result; 254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->GetAsString(&string_result); 255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result.l = ConvertUTF8ToJString(env, string_result); 256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeObject: 259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec 260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // requires handling java.lang.Object. 261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.l = NULL; 262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeByte: 264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeShort: 265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeInt: 266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeLong: 267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeFloat: 268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeDouble: { 269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec 270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // requires using valueOf() method of corresponding object type. 271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jvalue null_value = {0}; 272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result = null_value; 273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeChar: 276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec 277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // requires using java.lang.Short.decode(). 278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.c = 0; 279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeBoolean: 281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to false. Spec 282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // requires converting the empty string to false, otherwise true. 283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.z = JNI_FALSE; 284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeArray: 286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec 287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // requires raising a JavaScript exception. 288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.l = NULL; 289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeVoid: 291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Conversion to void must never happen. 292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NOTREACHED(); 293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return result; 296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Note that this only handles primitive types and strings. 299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)jobject CreateJavaArray(JNIEnv* env, const JavaType& type, jsize length) { 300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (type.type) { 301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeBoolean: 302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return env->NewBooleanArray(length); 303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeByte: 304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return env->NewByteArray(length); 305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeChar: 306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return env->NewCharArray(length); 307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeShort: 308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return env->NewShortArray(length); 309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeInt: 310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return env->NewIntArray(length); 311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeLong: 312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return env->NewLongArray(length); 313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeFloat: 314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return env->NewFloatArray(length); 315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeDouble: 316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return env->NewDoubleArray(length); 317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeString: { 318116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ScopedJavaLocalRef<jclass> clazz( 319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::android::GetClass(env, kJavaLangString)); 320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return env->NewObjectArray(length, clazz.obj(), NULL); 321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeVoid: 323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Conversion to void must never happen. 324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeArray: 325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeObject: 326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Not handled. 327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NOTREACHED(); 328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return NULL; 330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 331f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Sets the specified element of the supplied array to the value of the 333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// supplied jvalue. Requires that the type of the array matches that of the 334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// jvalue. Handles only primitive types and strings. Note that in the case of a 335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// string, the array takes a new reference to the string object. 336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SetArrayElement(JNIEnv* env, 337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jobject array, 338f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const JavaType& type, 339f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jsize index, 340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const jvalue& value) { 341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (type.type) { 342f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeBoolean: 343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) env->SetBooleanArrayRegion(static_cast<jbooleanArray>(array), index, 1, 344f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &value.z); 345f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 346f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeByte: 347f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) env->SetByteArrayRegion(static_cast<jbyteArray>(array), index, 1, 348f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &value.b); 349f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 350f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeChar: 351f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) env->SetCharArrayRegion(static_cast<jcharArray>(array), index, 1, 352f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &value.c); 353f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 354f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeShort: 355f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) env->SetShortArrayRegion(static_cast<jshortArray>(array), index, 1, 356f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &value.s); 357f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 358f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeInt: 359f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) env->SetIntArrayRegion(static_cast<jintArray>(array), index, 1, 360f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &value.i); 361f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 362f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeLong: 363f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) env->SetLongArrayRegion(static_cast<jlongArray>(array), index, 1, 364f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &value.j); 365f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 366f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeFloat: 367f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) env->SetFloatArrayRegion(static_cast<jfloatArray>(array), index, 1, 368f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &value.f); 369f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 370f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeDouble: 371f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) env->SetDoubleArrayRegion(static_cast<jdoubleArray>(array), index, 1, 372f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &value.d); 373f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 374f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeString: 375f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) env->SetObjectArrayElement(static_cast<jobjectArray>(array), index, 376f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value.l); 377f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 378f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeVoid: 379f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Conversion to void must never happen. 380f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeArray: 381f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeObject: 382f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Not handled. 383f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NOTREACHED(); 384f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 385f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::android::CheckException(env); 386f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 387f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 388f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)jvalue CoerceJavaScriptNullOrUndefinedToJavaValue(JNIEnv* env, 389f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::Value* value, 390f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const JavaType& target_type, 391116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool coerce_to_string, 392116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GinJavaBridgeError* error) { 393f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool is_undefined = false; 394f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<const GinJavaBridgeValue> gin_value; 395f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (GinJavaBridgeValue::ContainsGinJavaBridgeValue(value)) { 396f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) gin_value = GinJavaBridgeValue::FromValue(value); 397f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (gin_value->IsType(GinJavaBridgeValue::TYPE_UNDEFINED)) { 398f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) is_undefined = true; 399f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 400f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 401f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jvalue result; 402f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (target_type.type) { 403f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeObject: 404f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.l = NULL; 405f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 406f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeString: 407f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert undefined to 408f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // "undefined". Spec requires converting undefined to NULL. 409f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.l = (coerce_to_string && is_undefined) 410116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ? ConvertUTF8ToJString(env, kUndefined) 411f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : NULL; 412f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 413f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeByte: 414f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeChar: 415f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeShort: 416f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeInt: 417f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeLong: 418f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeFloat: 419f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeDouble: { 420f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jvalue null_value = {0}; 421f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result = null_value; 422f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 423f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 424f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeBoolean: 425f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.z = JNI_FALSE; 426f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 427f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeArray: 428f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec 429f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // requires raising a JavaScript exception. 430f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.l = NULL; 431f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 432f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeVoid: 433f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Conversion to void must never happen. 434f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NOTREACHED(); 435f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 436f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 437f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return result; 438f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 439f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 440f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)jobject CoerceJavaScriptListToArray(JNIEnv* env, 441f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::Value* value, 442f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const JavaType& target_type, 443116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ObjectRefs& object_refs, 444116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GinJavaBridgeError* error) { 445f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_EQ(JavaType::TypeArray, target_type.type); 446f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const JavaType& target_inner_type = *target_type.inner_type.get(); 447f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to return null for 448f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // multi-dimensional arrays. Spec requires handling multi-demensional arrays. 449f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (target_inner_type.type == JavaType::TypeArray) { 450f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return NULL; 451f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 452f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 453f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to return null for object 454f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // arrays. Spec requires handling object arrays. 455f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (target_inner_type.type == JavaType::TypeObject) { 456f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return NULL; 457f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 458f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 459f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::ListValue* list_value; 460f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->GetAsList(&list_value); 461f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Create the Java array. 462f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jsize length = static_cast<jsize>(list_value->GetSize()); 463f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jobject result = CreateJavaArray(env, target_inner_type, length); 464f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!result) { 465f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return NULL; 466f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 467f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<base::Value> null_value(base::Value::CreateNullValue()); 468f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (jsize i = 0; i < length; ++i) { 469f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::Value* value_element = null_value.get(); 470f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) list_value->Get(i, &value_element); 471f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jvalue element = CoerceJavaScriptValueToJavaValue( 472116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch env, value_element, target_inner_type, false, object_refs, error); 473f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SetArrayElement(env, result, target_inner_type, i, element); 474f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // CoerceJavaScriptValueToJavaValue() creates new local references to 475f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // strings, objects and arrays. Of these, only strings can occur here. 476f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // SetArrayElement() causes the array to take its own reference to the 477f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // string, so we can now release the local reference. 478f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_NE(JavaType::TypeObject, target_inner_type.type); 479f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_NE(JavaType::TypeArray, target_inner_type.type); 480f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ReleaseJavaValueIfRequired(env, &element, target_inner_type); 481f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 482f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 483f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return result; 484f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 485f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 486f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)jobject CoerceJavaScriptDictionaryToArray(JNIEnv* env, 487f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::Value* value, 488f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const JavaType& target_type, 489116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ObjectRefs& object_refs, 490116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GinJavaBridgeError* error) { 491f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_EQ(JavaType::TypeArray, target_type.type); 492f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 493f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const JavaType& target_inner_type = *target_type.inner_type.get(); 494f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to return null for 495f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // multi-dimensional arrays. Spec requires handling multi-demensional arrays. 496f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (target_inner_type.type == JavaType::TypeArray) { 497f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return NULL; 498f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 499f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 500f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to return null for object 501f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // arrays. Spec requires handling object arrays. 502f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (target_inner_type.type == JavaType::TypeObject) { 503f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return NULL; 504f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 505f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 506f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::DictionaryValue* dictionary_value; 507f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->GetAsDictionary(&dictionary_value); 508f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::Value* length_value; 509f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // If the object does not have a length property, return null. 510f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!dictionary_value->Get("length", &length_value)) { 511f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return NULL; 512f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 513f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 514f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // If the length property does not have numeric type, or is outside the valid 515f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // range for a Java array length, return null. 516f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jsize length = -1; 517f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (length_value->IsType(base::Value::TYPE_INTEGER)) { 518f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int int_length; 519f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) length_value->GetAsInteger(&int_length); 520f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (int_length >= 0 && int_length <= kint32max) { 521f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) length = static_cast<jsize>(int_length); 522f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 523f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else if (length_value->IsType(base::Value::TYPE_DOUBLE)) { 524f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) double double_length; 525f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) length_value->GetAsDouble(&double_length); 526f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (double_length >= 0.0 && double_length <= kint32max) { 527f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) length = static_cast<jsize>(double_length); 528f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 529f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 530f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (length == -1) { 531f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return NULL; 532f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 533f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 534f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jobject result = CreateJavaArray(env, target_inner_type, length); 535f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!result) { 536f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return NULL; 537f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 538f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<base::Value> null_value(base::Value::CreateNullValue()); 539f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (jsize i = 0; i < length; ++i) { 540f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string key(base::IntToString(i)); 541f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::Value* value_element = null_value.get(); 542f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (dictionary_value->HasKey(key)) { 543f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dictionary_value->Get(key, &value_element); 544f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 545f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jvalue element = CoerceJavaScriptValueToJavaValue( 546116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch env, value_element, target_inner_type, false, object_refs, error); 547f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SetArrayElement(env, result, target_inner_type, i, element); 548f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // CoerceJavaScriptValueToJavaValue() creates new local references to 549f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // strings, objects and arrays. Of these, only strings can occur here. 550f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // SetArrayElement() causes the array to take its own reference to the 551f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // string, so we can now release the local reference. 552f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_NE(JavaType::TypeObject, target_inner_type.type); 553f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_NE(JavaType::TypeArray, target_inner_type.type); 554f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ReleaseJavaValueIfRequired(env, &element, target_inner_type); 555f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 556f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 557f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return result; 558f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 559f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 560116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Returns 'true' if it is possible to cast an object of class |src| to 561116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// an object of class |dst|. 562116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool CanAssignClassVariables(JNIEnv* env, 563116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ScopedJavaLocalRef<jclass>& dst, 564116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ScopedJavaLocalRef<jclass>& src) { 565116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (dst.is_null() || src.is_null()) 566116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 567116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return env->IsAssignableFrom(src.obj(), dst.obj()) == JNI_TRUE; 568116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 569116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 570116680a4aac90f2aa7413d9095a592090648e557Ben MurdochScopedJavaLocalRef<jclass> GetObjectClass( 571116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch JNIEnv* env, 572116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ScopedJavaLocalRef<jobject>& obj) { 573116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch jclass clazz = env->GetObjectClass(obj.obj()); 574116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return ScopedJavaLocalRef<jclass>(env, clazz); 575116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 576116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 577f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)jvalue CoerceJavaScriptObjectToJavaValue(JNIEnv* env, 578f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::Value* value, 579f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const JavaType& target_type, 580f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool coerce_to_string, 581116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ObjectRefs& object_refs, 582116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GinJavaBridgeError* error) { 583f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // This covers both JavaScript objects (including arrays) and Java objects. 584f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // See http://jdk6.java.net/plugin2/liveconnect/#JS_OTHER_OBJECTS, 585f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // http://jdk6.java.net/plugin2/liveconnect/#JS_ARRAY_VALUES and 586f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // http://jdk6.java.net/plugin2/liveconnect/#JS_JAVA_OBJECTS 587f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jvalue result; 588f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (target_type.type) { 589f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeObject: { 590f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (GinJavaBridgeValue::ContainsGinJavaBridgeValue(value)) { 591f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<const GinJavaBridgeValue> gin_value( 592f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GinJavaBridgeValue::FromValue(value)); 593f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(gin_value); 594f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(gin_value->IsType(GinJavaBridgeValue::TYPE_OBJECT_ID)); 595116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ScopedJavaLocalRef<jobject> obj; 596f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GinJavaBoundObject::ObjectID object_id; 597f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (gin_value->GetAsObjectID(&object_id)) { 598f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ObjectRefs::const_iterator iter = object_refs.find(object_id); 599f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (iter != object_refs.end()) { 600f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) obj.Reset(iter->second.get(env)); 601f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 602f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 603116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!target_type.class_jni_name.empty()); 604116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!obj.is_null()); 605116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (CanAssignClassVariables( 606116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch env, 607116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::android::GetClass(env, target_type.JNIName().c_str()), 608116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetObjectClass(env, obj))) { 609116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result.l = obj.Release(); 610116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 611116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result.l = NULL; 612116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *error = kGinJavaBridgeNonAssignableTypes; 613116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 614f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else { 615f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to pass null. Spec 616f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // requires converting if the target type is 617f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // netscape.javascript.JSObject, otherwise raising a JavaScript 618f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // exception. 619f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.l = NULL; 620f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 621f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 622f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 623f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeString: 624f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 625f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // "undefined". Spec requires calling toString() on the Java object. 626116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result.l = 627116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch coerce_to_string ? ConvertUTF8ToJString(env, kUndefined) : NULL; 628f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 629f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeByte: 630f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeShort: 631f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeInt: 632f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeLong: 633f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeFloat: 634f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeDouble: 635f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeChar: { 636f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec 637f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // requires raising a JavaScript exception. 638f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jvalue null_value = {0}; 639f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result = null_value; 640f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 641f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 642f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeBoolean: 643f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to false. Spec 644f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // requires raising a JavaScript exception. 645f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.z = JNI_FALSE; 646f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 647f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeArray: 648f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (value->IsType(base::Value::TYPE_DICTIONARY)) { 649f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.l = CoerceJavaScriptDictionaryToArray( 650116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch env, value, target_type, object_refs, error); 651f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else if (value->IsType(base::Value::TYPE_LIST)) { 652116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result.l = CoerceJavaScriptListToArray( 653116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch env, value, target_type, object_refs, error); 654f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else { 655f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.l = NULL; 656f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 657f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 658f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case JavaType::TypeVoid: 659f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Conversion to void must never happen. 660f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NOTREACHED(); 661f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 662f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 663f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return result; 664f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 665f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 666f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)jvalue CoerceGinJavaBridgeValueToJavaValue(JNIEnv* env, 667f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::Value* value, 668f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const JavaType& target_type, 669f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool coerce_to_string, 670116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ObjectRefs& object_refs, 671116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GinJavaBridgeError* error) { 672f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(GinJavaBridgeValue::ContainsGinJavaBridgeValue(value)); 673f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<const GinJavaBridgeValue> gin_value( 674f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GinJavaBridgeValue::FromValue(value)); 675f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (gin_value->GetType()) { 676f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case GinJavaBridgeValue::TYPE_UNDEFINED: 677f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return CoerceJavaScriptNullOrUndefinedToJavaValue( 678116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch env, value, target_type, coerce_to_string, error); 679f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case GinJavaBridgeValue::TYPE_NONFINITE: { 680f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) float float_value; 681f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) gin_value->GetAsNonFinite(&float_value); 682f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return CoerceJavaScriptDoubleToJavaValue( 683116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch env, float_value, target_type, coerce_to_string, error); 684f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 685f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case GinJavaBridgeValue::TYPE_OBJECT_ID: 686f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return CoerceJavaScriptObjectToJavaValue( 687116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch env, value, target_type, coerce_to_string, object_refs, error); 688f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) default: 689f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NOTREACHED(); 690f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 691f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return jvalue(); 692f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 693f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 694f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace 695f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 696f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 697f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ReleaseJavaValueIfRequired(JNIEnv* env, 698f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jvalue* value, 699f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const JavaType& type) { 700f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (type.type == JavaType::TypeString || type.type == JavaType::TypeObject || 701f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) type.type == JavaType::TypeArray) { 702f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) env->DeleteLocalRef(value->l); 703f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->l = NULL; 704f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 705f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 706f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 707f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)jvalue CoerceJavaScriptValueToJavaValue(JNIEnv* env, 708f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::Value* value, 709f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const JavaType& target_type, 710f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool coerce_to_string, 711116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ObjectRefs& object_refs, 712116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GinJavaBridgeError* error) { 713f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Note that in all these conversions, the relevant field of the jvalue must 714f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // always be explicitly set, as jvalue does not initialize its fields. 715f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 716f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (value->GetType()) { 717f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case base::Value::TYPE_INTEGER: 718f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return CoerceJavaScriptIntegerToJavaValue( 719116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch env, value, target_type, coerce_to_string, error); 720f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case base::Value::TYPE_DOUBLE: { 721f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) double double_value; 722f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->GetAsDouble(&double_value); 723f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return CoerceJavaScriptDoubleToJavaValue( 724116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch env, double_value, target_type, coerce_to_string, error); 725f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 726f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case base::Value::TYPE_BOOLEAN: 727f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return CoerceJavaScriptBooleanToJavaValue( 728116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch env, value, target_type, coerce_to_string, error); 729f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case base::Value::TYPE_STRING: 730116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return CoerceJavaScriptStringToJavaValue(env, value, target_type, error); 731f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case base::Value::TYPE_DICTIONARY: 732f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case base::Value::TYPE_LIST: 733f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return CoerceJavaScriptObjectToJavaValue( 734116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch env, value, target_type, coerce_to_string, object_refs, error); 735f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case base::Value::TYPE_NULL: 736f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return CoerceJavaScriptNullOrUndefinedToJavaValue( 737116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch env, value, target_type, coerce_to_string, error); 738f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case base::Value::TYPE_BINARY: 739f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return CoerceGinJavaBridgeValueToJavaValue( 740116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch env, value, target_type, coerce_to_string, object_refs, error); 741f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 742f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NOTREACHED(); 743f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return jvalue(); 744f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 745f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 746f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace content 747