1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/java/gin_java_bridge_object.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "content/common/android/gin_java_bridge_errors.h"
9 #include "content/common/android/gin_java_bridge_value.h"
10 #include "content/public/renderer/v8_value_converter.h"
11 #include "content/renderer/java/gin_java_bridge_value_converter.h"
12 #include "gin/function_template.h"
13 #include "third_party/WebKit/public/web/WebFrame.h"
14 #include "third_party/WebKit/public/web/WebKit.h"
20 const char kMethodInvocationErrorMessage
[] =
21 "Java bridge method invocation error";
27 GinJavaBridgeObject
* GinJavaBridgeObject::InjectNamed(
28 blink::WebFrame
* frame
,
29 const base::WeakPtr
<GinJavaBridgeDispatcher
>& dispatcher
,
30 const std::string
& object_name
,
31 GinJavaBridgeDispatcher::ObjectID object_id
) {
32 v8::Isolate
* isolate
= blink::mainThreadIsolate();
33 v8::HandleScope
handle_scope(isolate
);
34 v8::Handle
<v8::Context
> context
= frame
->mainWorldScriptContext();
35 if (context
.IsEmpty())
38 GinJavaBridgeObject
* object
=
39 new GinJavaBridgeObject(isolate
, dispatcher
, object_id
);
41 v8::Context::Scope
context_scope(context
);
42 v8::Handle
<v8::Object
> global
= context
->Global();
43 gin::Handle
<GinJavaBridgeObject
> controller
=
44 gin::CreateHandle(isolate
, object
);
45 // WrappableBase instance deletes itself in case of a wrapper
46 // creation failure, thus there is no need to delete |object|.
47 if (controller
.IsEmpty())
50 global
->Set(gin::StringToV8(isolate
, object_name
), controller
.ToV8());
55 GinJavaBridgeObject
* GinJavaBridgeObject::InjectAnonymous(
56 const base::WeakPtr
<GinJavaBridgeDispatcher
>& dispatcher
,
57 GinJavaBridgeDispatcher::ObjectID object_id
) {
58 return new GinJavaBridgeObject(
59 blink::mainThreadIsolate(), dispatcher
, object_id
);
62 GinJavaBridgeObject::GinJavaBridgeObject(
64 const base::WeakPtr
<GinJavaBridgeDispatcher
>& dispatcher
,
65 GinJavaBridgeDispatcher::ObjectID object_id
)
66 : gin::NamedPropertyInterceptor(isolate
, this),
67 dispatcher_(dispatcher
),
68 object_id_(object_id
),
69 converter_(new GinJavaBridgeValueConverter()) {
72 GinJavaBridgeObject::~GinJavaBridgeObject() {
74 dispatcher_
->OnGinJavaBridgeObjectDeleted(object_id_
);
77 gin::ObjectTemplateBuilder
GinJavaBridgeObject::GetObjectTemplateBuilder(
78 v8::Isolate
* isolate
) {
79 return gin::Wrappable
<GinJavaBridgeObject
>::GetObjectTemplateBuilder(isolate
)
80 .AddNamedPropertyInterceptor();
83 v8::Local
<v8::Value
> GinJavaBridgeObject::GetNamedProperty(
85 const std::string
& property
) {
86 std::map
<std::string
, bool>::iterator method_pos
=
87 known_methods_
.find(property
);
88 if (method_pos
== known_methods_
.end()) {
90 return v8::Local
<v8::Value
>();
92 known_methods_
[property
] = dispatcher_
->HasJavaMethod(object_id_
, property
);
94 if (known_methods_
[property
]) {
95 return gin::CreateFunctionTemplate(
97 base::Bind(&GinJavaBridgeObject::InvokeMethod
,
98 base::Unretained(this),
99 property
))->GetFunction();
101 return v8::Local
<v8::Value
>();
105 std::vector
<std::string
> GinJavaBridgeObject::EnumerateNamedProperties(
106 v8::Isolate
* isolate
) {
107 std::set
<std::string
> method_names
;
109 dispatcher_
->GetJavaMethods(object_id_
, &method_names
);
110 return std::vector
<std::string
> (method_names
.begin(), method_names
.end());
113 v8::Handle
<v8::Value
> GinJavaBridgeObject::InvokeMethod(
114 const std::string
& name
,
115 gin::Arguments
* args
) {
117 args
->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8(
118 args
->isolate(), kMethodInvocationErrorMessage
)));
119 return v8::Undefined(args
->isolate());
122 base::ListValue arguments
;
124 v8::HandleScope
handle_scope(args
->isolate());
125 v8::Handle
<v8::Context
> context
= args
->isolate()->GetCurrentContext();
126 v8::Handle
<v8::Value
> val
;
127 while (args
->GetNext(&val
)) {
128 scoped_ptr
<base::Value
> arg(converter_
->FromV8Value(val
, context
));
130 arguments
.Append(arg
.release());
132 arguments
.Append(base::Value::CreateNullValue());
137 GinJavaBridgeError error
;
138 scoped_ptr
<base::Value
> result
= dispatcher_
->InvokeJavaMethod(
139 object_id_
, name
, arguments
, &error
);
141 args
->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8(
142 args
->isolate(), GinJavaBridgeErrorToString(error
))));
143 return v8::Undefined(args
->isolate());
145 if (!result
->IsType(base::Value::TYPE_BINARY
)) {
146 return converter_
->ToV8Value(result
.get(),
147 args
->isolate()->GetCurrentContext());
150 scoped_ptr
<const GinJavaBridgeValue
> gin_value
=
151 GinJavaBridgeValue::FromValue(result
.get());
152 if (gin_value
->IsType(GinJavaBridgeValue::TYPE_OBJECT_ID
)) {
153 GinJavaBridgeObject
* result
= NULL
;
154 GinJavaBridgeDispatcher::ObjectID object_id
;
155 if (gin_value
->GetAsObjectID(&object_id
)) {
156 result
= dispatcher_
->GetObject(object_id
);
159 gin::Handle
<GinJavaBridgeObject
> controller
=
160 gin::CreateHandle(args
->isolate(), result
);
161 if (controller
.IsEmpty())
162 return v8::Undefined(args
->isolate());
163 return controller
.ToV8();
165 } else if (gin_value
->IsType(GinJavaBridgeValue::TYPE_NONFINITE
)) {
167 gin_value
->GetAsNonFinite(&float_value
);
168 return v8::Number::New(args
->isolate(), float_value
);
170 return v8::Undefined(args
->isolate());
173 gin::WrapperInfo
GinJavaBridgeObject::kWrapperInfo
= {gin::kEmbedderNativeGin
};
175 } // namespace content