1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
// Copyright 2015 The Chromium Authors
// 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 <utility>
#include "base/strings/strcat.h"
#include "base/values.h"
#include "content/common/android/gin_java_bridge_errors.h"
#include "content/common/android/gin_java_bridge_value.h"
#include "content/public/renderer/v8_value_converter.h"
#include "content/renderer/java/gin_java_bridge_object.h"
#include "content/renderer/java/gin_java_bridge_value_converter.h"
#include "v8/include/v8-exception.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<GinJavaBridgeDispatcher>& dispatcher)
: method_name_(method_name),
dispatcher_(dispatcher),
converter_(new GinJavaBridgeValueConverter()) {}
GinJavaFunctionInvocationHelper::~GinJavaFunctionInvocationHelper() {
}
v8::Local<v8::Value> GinJavaFunctionInvocationHelper::Invoke(
gin::Arguments* args) {
if (!dispatcher_) {
args->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8(
args->isolate(), base::StrCat({"Error invoking ", method_name_, ": ",
kMethodInvocationErrorMessage}))));
return v8::Undefined(args->isolate());
}
if (args->IsConstructCall()) {
args->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8(
args->isolate(),
base::StrCat({"Error invoking ", method_name_, ": ",
kMethodInvocationAsConstructorDisallowed}))));
return v8::Undefined(args->isolate());
}
content::GinJavaBridgeObject* object = nullptr;
if (!args->GetHolder(&object) || !object) {
args->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8(
args->isolate(),
base::StrCat({"Error invoking ", method_name_, ": ",
kMethodInvocationOnNonInjectedObjectDisallowed}))));
return v8::Undefined(args->isolate());
}
base::Value::List arguments;
{
v8::HandleScope handle_scope(args->isolate());
v8::Local<v8::Context> context = args->isolate()->GetCurrentContext();
v8::Local<v8::Value> val;
while (args->GetNext(&val)) {
std::unique_ptr<base::Value> arg(converter_->FromV8Value(val, context));
if (arg) {
arguments.Append(base::Value::FromUniquePtrValue(std::move(arg)));
} else {
arguments.Append(base::Value());
}
}
}
mojom::GinJavaBridgeError error =
mojom::GinJavaBridgeError::kGinJavaBridgeNoError;
std::unique_ptr<base::Value> result;
if (auto* remote = object->GetRemote()) {
base::Value::List result_wrapper;
if (remote->InvokeMethod(method_name_, std::move(arguments), &error,
&result_wrapper)) {
if (!result_wrapper.empty()) {
result = base::Value::ToUniquePtrValue(result_wrapper[0].Clone());
}
} else {
error = mojom::GinJavaBridgeError::kGinJavaBridgeObjectIsGone;
}
}
if (!result.get()) {
args->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8(
args->isolate(), base::StrCat({"Error invoking ", method_name_, ": ",
GinJavaBridgeErrorToString(error)}))));
return v8::Undefined(args->isolate());
}
if (!result->is_blob()) {
return converter_->ToV8Value(result.get(),
args->isolate()->GetCurrentContext());
}
std::unique_ptr<const GinJavaBridgeValue> gin_value =
GinJavaBridgeValue::FromValue(result.get());
if (gin_value->IsType(GinJavaBridgeValue::TYPE_OBJECT_ID)) {
GinJavaBridgeObject* object_result = NULL;
GinJavaBridgeDispatcher::ObjectID object_id;
if (gin_value->GetAsObjectID(&object_id)) {
object_result = dispatcher_->GetObject(object_id);
}
if (object_result) {
gin::Handle<GinJavaBridgeObject> controller =
gin::CreateHandle(args->isolate(), object_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
|