// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.h"

#include <unistd.h>

#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "content/common/android/gin_java_bridge_value.h"

using base::android::ConvertUTF8ToJavaString;

namespace content {

namespace {

const char kJavaLangString[] = "java/lang/String";
const char kUndefined[] = "undefined";

double RoundDoubleTowardsZero(const double& x) {
  if (std::isnan(x)) {
    return 0.0;
  }
  return x > 0.0 ? floor(x) : ceil(x);
}

// Rounds to jlong using Java's type conversion rules.
jlong RoundDoubleToLong(const double& x) {
  double intermediate = RoundDoubleTowardsZero(x);
  // The int64 limits can not be converted exactly to double values, so we
  // compare to custom constants. kint64max is 2^63 - 1, but the spacing
  // between double values in the the range 2^62 to 2^63 is 2^10. The cast is
  // required to silence a spurious gcc warning for integer overflow.
  const int64 kLimit = (GG_INT64_C(1) << 63) - static_cast<uint64>(1 << 10);
  DCHECK(kLimit > 0);
  const double kLargestDoubleLessThanInt64Max = kLimit;
  const double kSmallestDoubleGreaterThanInt64Min = -kLimit;
  if (intermediate > kLargestDoubleLessThanInt64Max) {
    return kint64max;
  }
  if (intermediate < kSmallestDoubleGreaterThanInt64Min) {
    return kint64min;
  }
  return static_cast<jlong>(intermediate);
}

// Rounds to jint using Java's type conversion rules.
jint RoundDoubleToInt(const double& x) {
  double intermediate = RoundDoubleTowardsZero(x);
  // The int32 limits cast exactly to double values.
  intermediate = std::min(intermediate, static_cast<double>(kint32max));
  intermediate = std::max(intermediate, static_cast<double>(kint32min));
  return static_cast<jint>(intermediate);
}

jvalue CoerceJavaScriptIntegerToJavaValue(JNIEnv* env,
                                          const base::Value* value,
                                          const JavaType& target_type,
                                          bool coerce_to_string) {
  // See http://jdk6.java.net/plugin2/liveconnect/#JS_NUMBER_VALUES.

  // For conversion to numeric types, we need to replicate Java's type
  // conversion rules. This requires that for integer values, we simply discard
  // all but the lowest n buts, where n is the number of bits in the target
  // type.
  jvalue result;
  int int_value;
  value->GetAsInteger(&int_value);
  switch (target_type.type) {
    case JavaType::TypeByte:
      result.b = static_cast<jbyte>(int_value);
      break;
    case JavaType::TypeChar:
      result.c = static_cast<jchar>(int_value);
      break;
    case JavaType::TypeShort:
      result.s = static_cast<jshort>(int_value);
      break;
    case JavaType::TypeInt:
      result.i = int_value;
      break;
    case JavaType::TypeLong:
      result.j = int_value;
      break;
    case JavaType::TypeFloat:
      result.f = int_value;
      break;
    case JavaType::TypeDouble:
      result.d = int_value;
      break;
    case JavaType::TypeObject:
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to null. Spec
      // requires handling object equivalents of primitive types.
      result.l = NULL;
      break;
    case JavaType::TypeString:
      result.l = coerce_to_string
                     ? ConvertUTF8ToJavaString(
                           env, base::Int64ToString(int_value)).Release()
                     : NULL;
      break;
    case JavaType::TypeBoolean:
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to false. Spec
      // requires converting to false for 0 or NaN, true otherwise.
      result.z = JNI_FALSE;
      break;
    case JavaType::TypeArray:
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to null. Spec
      // requires raising a JavaScript exception.
      result.l = NULL;
      break;
    case JavaType::TypeVoid:
      // Conversion to void must never happen.
      NOTREACHED();
      break;
  }
  return result;
}

jvalue CoerceJavaScriptDoubleToJavaValue(JNIEnv* env,
                                         double double_value,
                                         const JavaType& target_type,
                                         bool coerce_to_string) {
  // See http://jdk6.java.net/plugin2/liveconnect/#JS_NUMBER_VALUES.
  // For conversion to numeric types, we need to replicate Java's type
  // conversion rules.
  jvalue result;
  switch (target_type.type) {
    case JavaType::TypeByte:
      result.b = static_cast<jbyte>(RoundDoubleToInt(double_value));
      break;
    case JavaType::TypeChar:
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert double to 0.
      // Spec requires converting doubles similarly to how we convert doubles to
      // other numeric types.
      result.c = 0;
      break;
    case JavaType::TypeShort:
      result.s = static_cast<jshort>(RoundDoubleToInt(double_value));
      break;
    case JavaType::TypeInt:
      result.i = RoundDoubleToInt(double_value);
      break;
    case JavaType::TypeLong:
      result.j = RoundDoubleToLong(double_value);
      break;
    case JavaType::TypeFloat:
      result.f = static_cast<jfloat>(double_value);
      break;
    case JavaType::TypeDouble:
      result.d = double_value;
      break;
    case JavaType::TypeObject:
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to null. Spec
      // requires handling object equivalents of primitive types.
      result.l = NULL;
      break;
    case JavaType::TypeString:
      result.l =
          coerce_to_string
              ? ConvertUTF8ToJavaString(
                    env, base::StringPrintf("%.6lg", double_value)).Release()
              : NULL;
      break;
    case JavaType::TypeBoolean:
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to false. Spec
      // requires converting to false for 0 or NaN, true otherwise.
      result.z = JNI_FALSE;
      break;
    case JavaType::TypeArray:
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to null. Spec
      // requires raising a JavaScript exception.
      result.l = NULL;
      break;
    case JavaType::TypeVoid:
      // Conversion to void must never happen.
      NOTREACHED();
      break;
  }
  return result;
}

jvalue CoerceJavaScriptBooleanToJavaValue(JNIEnv* env,
                                          const base::Value* value,
                                          const JavaType& target_type,
                                          bool coerce_to_string) {
  // See http://jdk6.java.net/plugin2/liveconnect/#JS_BOOLEAN_VALUES.
  bool boolean_value;
  value->GetAsBoolean(&boolean_value);
  jvalue result;
  switch (target_type.type) {
    case JavaType::TypeBoolean:
      result.z = boolean_value ? JNI_TRUE : JNI_FALSE;
      break;
    case JavaType::TypeObject:
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
      // requires handling java.lang.Boolean and java.lang.Object.
      result.l = NULL;
      break;
    case JavaType::TypeString:
      result.l = coerce_to_string
                     ? ConvertUTF8ToJavaString(
                           env, boolean_value ? "true" : "false").Release()
                     : NULL;
      break;
    case JavaType::TypeByte:
    case JavaType::TypeChar:
    case JavaType::TypeShort:
    case JavaType::TypeInt:
    case JavaType::TypeLong:
    case JavaType::TypeFloat:
    case JavaType::TypeDouble: {
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec
      // requires converting to 0 or 1.
      jvalue null_value = {0};
      result = null_value;
      break;
    }
    case JavaType::TypeArray:
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
      // requires raising a JavaScript exception.
      result.l = NULL;
      break;
    case JavaType::TypeVoid:
      // Conversion to void must never happen.
      NOTREACHED();
      break;
  }
  return result;
}

jvalue CoerceJavaScriptStringToJavaValue(JNIEnv* env,
                                         const base::Value* value,
                                         const JavaType& target_type) {
  // See http://jdk6.java.net/plugin2/liveconnect/#JS_STRING_VALUES.
  jvalue result;
  switch (target_type.type) {
    case JavaType::TypeString: {
      std::string string_result;
      value->GetAsString(&string_result);
      result.l = ConvertUTF8ToJavaString(env, string_result).Release();
      break;
    }
    case JavaType::TypeObject:
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
      // requires handling java.lang.Object.
      result.l = NULL;
      break;
    case JavaType::TypeByte:
    case JavaType::TypeShort:
    case JavaType::TypeInt:
    case JavaType::TypeLong:
    case JavaType::TypeFloat:
    case JavaType::TypeDouble: {
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec
      // requires using valueOf() method of corresponding object type.
      jvalue null_value = {0};
      result = null_value;
      break;
    }
    case JavaType::TypeChar:
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec
      // requires using java.lang.Short.decode().
      result.c = 0;
      break;
    case JavaType::TypeBoolean:
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to false. Spec
      // requires converting the empty string to false, otherwise true.
      result.z = JNI_FALSE;
      break;
    case JavaType::TypeArray:
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
      // requires raising a JavaScript exception.
      result.l = NULL;
      break;
    case JavaType::TypeVoid:
      // Conversion to void must never happen.
      NOTREACHED();
      break;
  }
  return result;
}

// Note that this only handles primitive types and strings.
jobject CreateJavaArray(JNIEnv* env, const JavaType& type, jsize length) {
  switch (type.type) {
    case JavaType::TypeBoolean:
      return env->NewBooleanArray(length);
    case JavaType::TypeByte:
      return env->NewByteArray(length);
    case JavaType::TypeChar:
      return env->NewCharArray(length);
    case JavaType::TypeShort:
      return env->NewShortArray(length);
    case JavaType::TypeInt:
      return env->NewIntArray(length);
    case JavaType::TypeLong:
      return env->NewLongArray(length);
    case JavaType::TypeFloat:
      return env->NewFloatArray(length);
    case JavaType::TypeDouble:
      return env->NewDoubleArray(length);
    case JavaType::TypeString: {
      base::android::ScopedJavaLocalRef<jclass> clazz(
          base::android::GetClass(env, kJavaLangString));
      return env->NewObjectArray(length, clazz.obj(), NULL);
    }
    case JavaType::TypeVoid:
      // Conversion to void must never happen.
    case JavaType::TypeArray:
    case JavaType::TypeObject:
      // Not handled.
      NOTREACHED();
  }
  return NULL;
}

// Sets the specified element of the supplied array to the value of the
// supplied jvalue. Requires that the type of the array matches that of the
// jvalue. Handles only primitive types and strings. Note that in the case of a
// string, the array takes a new reference to the string object.
void SetArrayElement(JNIEnv* env,
                     jobject array,
                     const JavaType& type,
                     jsize index,
                     const jvalue& value) {
  switch (type.type) {
    case JavaType::TypeBoolean:
      env->SetBooleanArrayRegion(static_cast<jbooleanArray>(array), index, 1,
                                 &value.z);
      break;
    case JavaType::TypeByte:
      env->SetByteArrayRegion(static_cast<jbyteArray>(array), index, 1,
                              &value.b);
      break;
    case JavaType::TypeChar:
      env->SetCharArrayRegion(static_cast<jcharArray>(array), index, 1,
                              &value.c);
      break;
    case JavaType::TypeShort:
      env->SetShortArrayRegion(static_cast<jshortArray>(array), index, 1,
                               &value.s);
      break;
    case JavaType::TypeInt:
      env->SetIntArrayRegion(static_cast<jintArray>(array), index, 1,
                             &value.i);
      break;
    case JavaType::TypeLong:
      env->SetLongArrayRegion(static_cast<jlongArray>(array), index, 1,
                              &value.j);
      break;
    case JavaType::TypeFloat:
      env->SetFloatArrayRegion(static_cast<jfloatArray>(array), index, 1,
                               &value.f);
      break;
    case JavaType::TypeDouble:
      env->SetDoubleArrayRegion(static_cast<jdoubleArray>(array), index, 1,
                                &value.d);
      break;
    case JavaType::TypeString:
      env->SetObjectArrayElement(static_cast<jobjectArray>(array), index,
                                 value.l);
      break;
    case JavaType::TypeVoid:
      // Conversion to void must never happen.
    case JavaType::TypeArray:
    case JavaType::TypeObject:
      // Not handled.
      NOTREACHED();
  }
  base::android::CheckException(env);
}

jvalue CoerceJavaScriptNullOrUndefinedToJavaValue(JNIEnv* env,
                                                  const base::Value* value,
                                                  const JavaType& target_type,
                                                  bool coerce_to_string) {
  bool is_undefined = false;
  scoped_ptr<const GinJavaBridgeValue> gin_value;
  if (GinJavaBridgeValue::ContainsGinJavaBridgeValue(value)) {
    gin_value = GinJavaBridgeValue::FromValue(value);
    if (gin_value->IsType(GinJavaBridgeValue::TYPE_UNDEFINED)) {
      is_undefined = true;
    }
  }
  jvalue result;
  switch (target_type.type) {
    case JavaType::TypeObject:
      result.l = NULL;
      break;
    case JavaType::TypeString:
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert undefined to
      // "undefined". Spec requires converting undefined to NULL.
      result.l = (coerce_to_string && is_undefined)
                     ? ConvertUTF8ToJavaString(env, kUndefined).Release()
                     : NULL;
      break;
    case JavaType::TypeByte:
    case JavaType::TypeChar:
    case JavaType::TypeShort:
    case JavaType::TypeInt:
    case JavaType::TypeLong:
    case JavaType::TypeFloat:
    case JavaType::TypeDouble: {
      jvalue null_value = {0};
      result = null_value;
      break;
    }
    case JavaType::TypeBoolean:
      result.z = JNI_FALSE;
      break;
    case JavaType::TypeArray:
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
      // requires raising a JavaScript exception.
      result.l = NULL;
      break;
    case JavaType::TypeVoid:
      // Conversion to void must never happen.
      NOTREACHED();
      break;
  }
  return result;
}

jobject CoerceJavaScriptListToArray(JNIEnv* env,
                                    const base::Value* value,
                                    const JavaType& target_type,
                                    const ObjectRefs& object_refs) {
  DCHECK_EQ(JavaType::TypeArray, target_type.type);
  const JavaType& target_inner_type = *target_type.inner_type.get();
  // LIVECONNECT_COMPLIANCE: Existing behavior is to return null for
  // multi-dimensional arrays. Spec requires handling multi-demensional arrays.
  if (target_inner_type.type == JavaType::TypeArray) {
    return NULL;
  }

  // LIVECONNECT_COMPLIANCE: Existing behavior is to return null for object
  // arrays. Spec requires handling object arrays.
  if (target_inner_type.type == JavaType::TypeObject) {
    return NULL;
  }

  const base::ListValue* list_value;
  value->GetAsList(&list_value);
  // Create the Java array.
  jsize length = static_cast<jsize>(list_value->GetSize());
  jobject result = CreateJavaArray(env, target_inner_type, length);
  if (!result) {
    return NULL;
  }
  scoped_ptr<base::Value> null_value(base::Value::CreateNullValue());
  for (jsize i = 0; i < length; ++i) {
    const base::Value* value_element = null_value.get();
    list_value->Get(i, &value_element);
    jvalue element = CoerceJavaScriptValueToJavaValue(
        env, value_element, target_inner_type, false, object_refs);
    SetArrayElement(env, result, target_inner_type, i, element);
    // CoerceJavaScriptValueToJavaValue() creates new local references to
    // strings, objects and arrays. Of these, only strings can occur here.
    // SetArrayElement() causes the array to take its own reference to the
    // string, so we can now release the local reference.
    DCHECK_NE(JavaType::TypeObject, target_inner_type.type);
    DCHECK_NE(JavaType::TypeArray, target_inner_type.type);
    ReleaseJavaValueIfRequired(env, &element, target_inner_type);
  }

  return result;
}

jobject CoerceJavaScriptDictionaryToArray(JNIEnv* env,
                                          const base::Value* value,
                                          const JavaType& target_type,
                                          const ObjectRefs& object_refs) {
  DCHECK_EQ(JavaType::TypeArray, target_type.type);

  const JavaType& target_inner_type = *target_type.inner_type.get();
  // LIVECONNECT_COMPLIANCE: Existing behavior is to return null for
  // multi-dimensional arrays. Spec requires handling multi-demensional arrays.
  if (target_inner_type.type == JavaType::TypeArray) {
    return NULL;
  }

  // LIVECONNECT_COMPLIANCE: Existing behavior is to return null for object
  // arrays. Spec requires handling object arrays.
  if (target_inner_type.type == JavaType::TypeObject) {
    return NULL;
  }

  const base::DictionaryValue* dictionary_value;
  value->GetAsDictionary(&dictionary_value);
  const base::Value* length_value;
  // If the object does not have a length property, return null.
  if (!dictionary_value->Get("length", &length_value)) {
    return NULL;
  }

  // If the length property does not have numeric type, or is outside the valid
  // range for a Java array length, return null.
  jsize length = -1;
  if (length_value->IsType(base::Value::TYPE_INTEGER)) {
    int int_length;
    length_value->GetAsInteger(&int_length);
    if (int_length >= 0 && int_length <= kint32max) {
      length = static_cast<jsize>(int_length);
    }
  } else if (length_value->IsType(base::Value::TYPE_DOUBLE)) {
    double double_length;
    length_value->GetAsDouble(&double_length);
    if (double_length >= 0.0 && double_length <= kint32max) {
      length = static_cast<jsize>(double_length);
    }
  }
  if (length == -1) {
    return NULL;
  }

  jobject result = CreateJavaArray(env, target_inner_type, length);
  if (!result) {
    return NULL;
  }
  scoped_ptr<base::Value> null_value(base::Value::CreateNullValue());
  for (jsize i = 0; i < length; ++i) {
    const std::string key(base::IntToString(i));
    const base::Value* value_element = null_value.get();
    if (dictionary_value->HasKey(key)) {
      dictionary_value->Get(key, &value_element);
    }
    jvalue element = CoerceJavaScriptValueToJavaValue(
        env, value_element, target_inner_type, false, object_refs);
    SetArrayElement(env, result, target_inner_type, i, element);
    // CoerceJavaScriptValueToJavaValue() creates new local references to
    // strings, objects and arrays. Of these, only strings can occur here.
    // SetArrayElement() causes the array to take its own reference to the
    // string, so we can now release the local reference.
    DCHECK_NE(JavaType::TypeObject, target_inner_type.type);
    DCHECK_NE(JavaType::TypeArray, target_inner_type.type);
    ReleaseJavaValueIfRequired(env, &element, target_inner_type);
  }

  return result;
}

jvalue CoerceJavaScriptObjectToJavaValue(JNIEnv* env,
                                         const base::Value* value,
                                         const JavaType& target_type,
                                         bool coerce_to_string,
                                         const ObjectRefs& object_refs) {
  // This covers both JavaScript objects (including arrays) and Java objects.
  // See http://jdk6.java.net/plugin2/liveconnect/#JS_OTHER_OBJECTS,
  // http://jdk6.java.net/plugin2/liveconnect/#JS_ARRAY_VALUES and
  // http://jdk6.java.net/plugin2/liveconnect/#JS_JAVA_OBJECTS
  jvalue result;
  switch (target_type.type) {
    case JavaType::TypeObject: {
      if (GinJavaBridgeValue::ContainsGinJavaBridgeValue(value)) {
        scoped_ptr<const GinJavaBridgeValue> gin_value(
            GinJavaBridgeValue::FromValue(value));
        DCHECK(gin_value);
        DCHECK(gin_value->IsType(GinJavaBridgeValue::TYPE_OBJECT_ID));
        base::android::ScopedJavaLocalRef<jobject> obj;
        GinJavaBoundObject::ObjectID object_id;
        if (gin_value->GetAsObjectID(&object_id)) {
          ObjectRefs::const_iterator iter = object_refs.find(object_id);
          if (iter != object_refs.end()) {
            obj.Reset(iter->second.get(env));
          }
        }
        result.l = obj.Release();
      } else {
        // LIVECONNECT_COMPLIANCE: Existing behavior is to pass null. Spec
        // requires converting if the target type is
        // netscape.javascript.JSObject, otherwise raising a JavaScript
        // exception.
        result.l = NULL;
      }
      break;
    }
    case JavaType::TypeString:
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to
      // "undefined". Spec requires calling toString() on the Java object.
      result.l = coerce_to_string
                     ? ConvertUTF8ToJavaString(env, kUndefined).Release()
                     : NULL;
      break;
    case JavaType::TypeByte:
    case JavaType::TypeShort:
    case JavaType::TypeInt:
    case JavaType::TypeLong:
    case JavaType::TypeFloat:
    case JavaType::TypeDouble:
    case JavaType::TypeChar: {
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec
      // requires raising a JavaScript exception.
      jvalue null_value = {0};
      result = null_value;
      break;
    }
    case JavaType::TypeBoolean:
      // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to false. Spec
      // requires raising a JavaScript exception.
      result.z = JNI_FALSE;
      break;
    case JavaType::TypeArray:
      if (value->IsType(base::Value::TYPE_DICTIONARY)) {
        result.l = CoerceJavaScriptDictionaryToArray(
            env, value, target_type, object_refs);
      } else if (value->IsType(base::Value::TYPE_LIST)) {
        result.l =
            CoerceJavaScriptListToArray(env, value, target_type, object_refs);
      } else {
        result.l = NULL;
      }
      break;
    case JavaType::TypeVoid:
      // Conversion to void must never happen.
      NOTREACHED();
      break;
  }
  return result;
}

jvalue CoerceGinJavaBridgeValueToJavaValue(JNIEnv* env,
                                           const base::Value* value,
                                           const JavaType& target_type,
                                           bool coerce_to_string,
                                           const ObjectRefs& object_refs) {
  DCHECK(GinJavaBridgeValue::ContainsGinJavaBridgeValue(value));
  scoped_ptr<const GinJavaBridgeValue> gin_value(
      GinJavaBridgeValue::FromValue(value));
  switch (gin_value->GetType()) {
    case GinJavaBridgeValue::TYPE_UNDEFINED:
      return CoerceJavaScriptNullOrUndefinedToJavaValue(
          env, value, target_type, coerce_to_string);
    case GinJavaBridgeValue::TYPE_NONFINITE: {
      float float_value;
      gin_value->GetAsNonFinite(&float_value);
      return CoerceJavaScriptDoubleToJavaValue(
          env, float_value, target_type, coerce_to_string);
    }
    case GinJavaBridgeValue::TYPE_OBJECT_ID:
      return CoerceJavaScriptObjectToJavaValue(
          env, value, target_type, coerce_to_string, object_refs);
    default:
      NOTREACHED();
  }
  return jvalue();
}

}  // namespace


void ReleaseJavaValueIfRequired(JNIEnv* env,
                                jvalue* value,
                                const JavaType& type) {
  if (type.type == JavaType::TypeString || type.type == JavaType::TypeObject ||
      type.type == JavaType::TypeArray) {
    env->DeleteLocalRef(value->l);
    value->l = NULL;
  }
}

jvalue CoerceJavaScriptValueToJavaValue(JNIEnv* env,
                                        const base::Value* value,
                                        const JavaType& target_type,
                                        bool coerce_to_string,
                                        const ObjectRefs& object_refs) {
  // Note that in all these conversions, the relevant field of the jvalue must
  // always be explicitly set, as jvalue does not initialize its fields.

  switch (value->GetType()) {
    case base::Value::TYPE_INTEGER:
      return CoerceJavaScriptIntegerToJavaValue(
          env, value, target_type, coerce_to_string);
    case base::Value::TYPE_DOUBLE: {
      double double_value;
      value->GetAsDouble(&double_value);
      return CoerceJavaScriptDoubleToJavaValue(
          env, double_value, target_type, coerce_to_string);
    }
    case base::Value::TYPE_BOOLEAN:
      return CoerceJavaScriptBooleanToJavaValue(
          env, value, target_type, coerce_to_string);
    case base::Value::TYPE_STRING:
      return CoerceJavaScriptStringToJavaValue(env, value, target_type);
    case base::Value::TYPE_DICTIONARY:
    case base::Value::TYPE_LIST:
      return CoerceJavaScriptObjectToJavaValue(
          env, value, target_type, coerce_to_string, object_refs);
    case base::Value::TYPE_NULL:
      return CoerceJavaScriptNullOrUndefinedToJavaValue(
          env, value, target_type, coerce_to_string);
    case base::Value::TYPE_BINARY:
      return CoerceGinJavaBridgeValueToJavaValue(
          env, value, target_type, coerce_to_string, object_refs);
  }
  NOTREACHED();
  return jvalue();
}

}  // namespace content
