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/child/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()),
70 template_cache_(isolate
) {
73 GinJavaBridgeObject::~GinJavaBridgeObject() {
75 dispatcher_
->OnGinJavaBridgeObjectDeleted(object_id_
);
78 gin::ObjectTemplateBuilder
GinJavaBridgeObject::GetObjectTemplateBuilder(
79 v8::Isolate
* isolate
) {
80 return gin::Wrappable
<GinJavaBridgeObject
>::GetObjectTemplateBuilder(isolate
)
81 .AddNamedPropertyInterceptor();
84 v8::Local
<v8::Value
> GinJavaBridgeObject::GetNamedProperty(
86 const std::string
& property
) {
87 std::map
<std::string
, bool>::iterator method_pos
=
88 known_methods_
.find(property
);
89 if (method_pos
== known_methods_
.end()) {
91 return v8::Local
<v8::Value
>();
93 known_methods_
[property
] = dispatcher_
->HasJavaMethod(object_id_
, property
);
95 if (known_methods_
[property
])
96 return GetFunctionTemplate(isolate
, property
)->GetFunction();
98 return v8::Local
<v8::Value
>();
101 std::vector
<std::string
> GinJavaBridgeObject::EnumerateNamedProperties(
102 v8::Isolate
* isolate
) {
103 std::set
<std::string
> method_names
;
105 dispatcher_
->GetJavaMethods(object_id_
, &method_names
);
106 return std::vector
<std::string
> (method_names
.begin(), method_names
.end());
109 v8::Local
<v8::FunctionTemplate
> GinJavaBridgeObject::GetFunctionTemplate(
110 v8::Isolate
* isolate
,
111 const std::string
& name
) {
112 v8::Local
<v8::FunctionTemplate
> function_template
= template_cache_
.Get(name
);
113 if (!function_template
.IsEmpty())
114 return function_template
;
115 function_template
= gin::CreateFunctionTemplate(
116 isolate
, base::Bind(&GinJavaBridgeObject::InvokeMethod
,
117 base::Unretained(this), name
));
118 template_cache_
.Set(name
, function_template
);
119 return function_template
;
122 v8::Handle
<v8::Value
> GinJavaBridgeObject::InvokeMethod(
123 const std::string
& name
,
124 gin::Arguments
* args
) {
126 args
->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8(
127 args
->isolate(), kMethodInvocationErrorMessage
)));
128 return v8::Undefined(args
->isolate());
131 base::ListValue arguments
;
133 v8::HandleScope
handle_scope(args
->isolate());
134 v8::Handle
<v8::Context
> context
= args
->isolate()->GetCurrentContext();
135 v8::Handle
<v8::Value
> val
;
136 while (args
->GetNext(&val
)) {
137 scoped_ptr
<base::Value
> arg(converter_
->FromV8Value(val
, context
));
139 arguments
.Append(arg
.release());
141 arguments
.Append(base::Value::CreateNullValue());
146 GinJavaBridgeError error
;
147 scoped_ptr
<base::Value
> result
= dispatcher_
->InvokeJavaMethod(
148 object_id_
, name
, arguments
, &error
);
150 args
->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8(
151 args
->isolate(), GinJavaBridgeErrorToString(error
))));
152 return v8::Undefined(args
->isolate());
154 if (!result
->IsType(base::Value::TYPE_BINARY
)) {
155 return converter_
->ToV8Value(result
.get(),
156 args
->isolate()->GetCurrentContext());
159 scoped_ptr
<const GinJavaBridgeValue
> gin_value
=
160 GinJavaBridgeValue::FromValue(result
.get());
161 if (gin_value
->IsType(GinJavaBridgeValue::TYPE_OBJECT_ID
)) {
162 GinJavaBridgeObject
* result
= NULL
;
163 GinJavaBridgeDispatcher::ObjectID object_id
;
164 if (gin_value
->GetAsObjectID(&object_id
)) {
165 result
= dispatcher_
->GetObject(object_id
);
168 gin::Handle
<GinJavaBridgeObject
> controller
=
169 gin::CreateHandle(args
->isolate(), result
);
170 if (controller
.IsEmpty())
171 return v8::Undefined(args
->isolate());
172 return controller
.ToV8();
174 } else if (gin_value
->IsType(GinJavaBridgeValue::TYPE_NONFINITE
)) {
176 gin_value
->GetAsNonFinite(&float_value
);
177 return v8::Number::New(args
->isolate(), float_value
);
179 return v8::Undefined(args
->isolate());
182 gin::WrapperInfo
GinJavaBridgeObject::kWrapperInfo
= {gin::kEmbedderNativeGin
};
184 } // namespace content