// Copyright 2015 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/renderer/java/gin_java_function_invocation_helper.h" #include "content/common/android/gin_java_bridge_errors.h" #include "content/common/android/gin_java_bridge_value.h" #include "content/public/child/v8_value_converter.h" #include "content/renderer/java/gin_java_bridge_object.h" #include "content/renderer/java/gin_java_bridge_value_converter.h" namespace content { namespace { const char kMethodInvocationAsConstructorDisallowed[] = "Java bridge method can't be invoked as a constructor"; const char kMethodInvocationOnNonInjectedObjectDisallowed[] = "Java bridge method can't be invoked on a non-injected object"; const char kMethodInvocationErrorMessage[] = "Java bridge method invocation error"; } // namespace GinJavaFunctionInvocationHelper::GinJavaFunctionInvocationHelper( const std::string& method_name, const base::WeakPtr& dispatcher) : method_name_(method_name), dispatcher_(dispatcher), converter_(new GinJavaBridgeValueConverter()) { } GinJavaFunctionInvocationHelper::~GinJavaFunctionInvocationHelper() { } v8::Local GinJavaFunctionInvocationHelper::Invoke( gin::Arguments* args) { if (!dispatcher_) { args->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8( args->isolate(), kMethodInvocationErrorMessage))); return v8::Undefined(args->isolate()); } if (args->IsConstructCall()) { args->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8( args->isolate(), kMethodInvocationAsConstructorDisallowed))); return v8::Undefined(args->isolate()); } content::GinJavaBridgeObject* object = NULL; if (!args->GetHolder(&object) || !object) { args->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8( args->isolate(), kMethodInvocationOnNonInjectedObjectDisallowed))); return v8::Undefined(args->isolate()); } base::ListValue arguments; { v8::HandleScope handle_scope(args->isolate()); v8::Local context = args->isolate()->GetCurrentContext(); v8::Local val; while (args->GetNext(&val)) { scoped_ptr arg(converter_->FromV8Value(val, context)); if (arg.get()) { arguments.Append(arg.release()); } else { arguments.Append(base::Value::CreateNullValue()); } } } GinJavaBridgeError error; scoped_ptr result = dispatcher_->InvokeJavaMethod( object->object_id(), method_name_, arguments, &error); if (!result.get()) { args->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8( args->isolate(), GinJavaBridgeErrorToString(error)))); return v8::Undefined(args->isolate()); } if (!result->IsType(base::Value::TYPE_BINARY)) { return converter_->ToV8Value(result.get(), args->isolate()->GetCurrentContext()); } scoped_ptr gin_value = GinJavaBridgeValue::FromValue(result.get()); if (gin_value->IsType(GinJavaBridgeValue::TYPE_OBJECT_ID)) { GinJavaBridgeObject* result = NULL; GinJavaBridgeDispatcher::ObjectID object_id; if (gin_value->GetAsObjectID(&object_id)) { result = dispatcher_->GetObject(object_id); } if (result) { gin::Handle controller = gin::CreateHandle(args->isolate(), result); if (controller.IsEmpty()) return v8::Undefined(args->isolate()); return controller.ToV8(); } } else if (gin_value->IsType(GinJavaBridgeValue::TYPE_NONFINITE)) { float float_value; gin_value->GetAsNonFinite(&float_value); return v8::Number::New(args->isolate(), float_value); } return v8::Undefined(args->isolate()); } } // namespace content