OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "content/renderer/java/gin_java_bridge_object.h" | |
6 | |
7 #include "base/strings/utf_string_conversions.h" | |
8 #include "content/common/android/gin_java_bridge_value.h" | |
9 #include "content/public/renderer/v8_value_converter.h" | |
10 #include "content/renderer/java/gin_java_bridge_value_converter.h" | |
11 #include "gin/function_template.h" | |
12 #include "third_party/WebKit/public/web/WebFrame.h" | |
13 #include "third_party/WebKit/public/web/WebKit.h" | |
14 | |
15 namespace content { | |
16 | |
17 namespace { | |
18 | |
19 const char kMethodInvocationErrorMessage[] = | |
20 "Java bridge method invocation error"; | |
21 | |
22 } // namespace | |
23 | |
24 | |
25 // static | |
26 GinJavaBridgeObject* GinJavaBridgeObject::Inject( | |
27 blink::WebFrame* frame, | |
28 const base::WeakPtr<GinJavaBridgeDispatcher>& dispatcher, | |
29 const std::string& object_name, | |
30 GinJavaBridgeDispatcher::ObjectID object_id) { | |
31 GinJavaBridgeObject* result = new GinJavaBridgeObject( | |
32 blink::mainThreadIsolate(), dispatcher, object_id); | |
33 if (InjectExisting(frame, result, object_name)) { | |
34 return result; | |
35 } else { | |
36 delete result; | |
37 return NULL; | |
38 } | |
39 } | |
40 | |
41 // static | |
42 GinJavaBridgeObject* GinJavaBridgeObject::InjectAnonymous( | |
43 const base::WeakPtr<GinJavaBridgeDispatcher>& dispatcher, | |
44 GinJavaBridgeDispatcher::ObjectID object_id) { | |
45 return new GinJavaBridgeObject( | |
46 blink::mainThreadIsolate(), dispatcher, object_id); | |
47 } | |
48 | |
49 // static | |
50 bool GinJavaBridgeObject::InjectExisting(blink::WebFrame* frame, | |
51 GinJavaBridgeObject* object, | |
52 const std::string& object_name) { | |
53 v8::Isolate* isolate = blink::mainThreadIsolate(); | |
54 v8::HandleScope handle_scope(isolate); | |
55 v8::Handle<v8::Context> context = frame->mainWorldScriptContext(); | |
56 if (context.IsEmpty()) | |
57 return false; | |
58 | |
59 v8::Context::Scope context_scope(context); | |
60 v8::Handle<v8::Object> global = context->Global(); | |
61 gin::Handle<GinJavaBridgeObject> controller = | |
62 gin::CreateHandle(isolate, object); | |
jochen (gone - plz use gerrit)
2014/05/05 10:55:49
CreateHandle will delete object if it fails to cre
mnaganov (inactive)
2014/05/06 10:54:15
Thanks for pointing this out! I missed that fact t
| |
63 if (controller.IsEmpty()) | |
64 return false; | |
65 | |
66 global->Set(gin::StringToV8(isolate, object_name), controller.ToV8()); | |
67 return true; | |
68 } | |
69 | |
70 GinJavaBridgeObject::GinJavaBridgeObject( | |
71 v8::Isolate* isolate, | |
72 const base::WeakPtr<GinJavaBridgeDispatcher>& dispatcher, | |
73 GinJavaBridgeDispatcher::ObjectID object_id) | |
74 : gin::NamedPropertyInterceptor(isolate, this), | |
75 dispatcher_(dispatcher), | |
76 object_id_(object_id), | |
77 converter_(new GinJavaBridgeValueConverter()) { | |
78 } | |
79 | |
80 GinJavaBridgeObject::~GinJavaBridgeObject() { | |
81 if (dispatcher_) | |
82 dispatcher_->OnGinJavaBridgeObjectDeleted(object_id_); | |
83 } | |
84 | |
85 gin::ObjectTemplateBuilder GinJavaBridgeObject::GetObjectTemplateBuilder( | |
86 v8::Isolate* isolate) { | |
87 return gin::Wrappable<GinJavaBridgeObject>::GetObjectTemplateBuilder(isolate) | |
88 .AddNamedPropertyInterceptor(); | |
89 } | |
90 | |
91 v8::Local<v8::Value> GinJavaBridgeObject::GetNamedProperty( | |
92 v8::Isolate* isolate, | |
93 const std::string& property) { | |
94 if (dispatcher_ && dispatcher_->HasJavaMethod(object_id_, property)) { | |
95 return gin::CreateFunctionTemplate( | |
96 isolate, | |
97 base::Bind(&GinJavaBridgeObject::InvokeMethod, | |
98 base::Unretained(this), | |
99 property))->GetFunction(); | |
100 } else { | |
101 return v8::Local<v8::Value>(); | |
102 } | |
103 } | |
104 | |
105 std::vector<std::string> GinJavaBridgeObject::EnumerateNamedProperties( | |
106 v8::Isolate* isolate) { | |
107 std::set<std::string> method_names; | |
108 if (dispatcher_) { | |
109 dispatcher_->GetJavaMethods(object_id_, &method_names); | |
jochen (gone - plz use gerrit)
2014/05/05 10:55:49
nit. no { }
mnaganov (inactive)
2014/05/06 10:54:15
Done.
| |
110 } | |
111 return std::vector<std::string> (method_names.begin(), method_names.end()); | |
112 } | |
113 | |
114 v8::Handle<v8::Value> GinJavaBridgeObject::InvokeMethod( | |
115 const std::string& name, | |
116 gin::Arguments* args) { | |
117 if (!dispatcher_) { | |
118 args->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8( | |
119 args->isolate(), kMethodInvocationErrorMessage))); | |
120 return v8::Undefined(args->isolate()); | |
121 } | |
122 | |
123 base::ListValue arguments; | |
124 { | |
125 v8::HandleScope handle_scope(args->isolate()); | |
126 v8::Handle<v8::Context> context = args->isolate()->GetCurrentContext(); | |
127 v8::Handle<v8::Value> val; | |
128 while (args->GetNext(&val)) { | |
129 scoped_ptr<base::Value> arg(converter_->FromV8Value(val, context)); | |
130 if (arg.get()) { | |
131 arguments.Append(arg.release()); | |
132 } else { | |
133 arguments.Append(base::Value::CreateNullValue()); | |
134 } | |
135 } | |
136 } | |
137 | |
138 scoped_ptr<base::Value> result = | |
139 dispatcher_->InvokeJavaMethod(object_id_, name, arguments); | |
140 if (!result.get()) { | |
141 args->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8( | |
142 args->isolate(), kMethodInvocationErrorMessage))); | |
143 return v8::Undefined(args->isolate()); | |
144 } | |
145 if (!result->IsType(base::Value::TYPE_BINARY)) { | |
146 return converter_->ToV8Value(result.get(), | |
147 args->isolate()->GetCurrentContext()); | |
148 } | |
149 | |
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); | |
157 } | |
158 if (result) { | |
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(); | |
164 } | |
165 } else if (gin_value->IsType(GinJavaBridgeValue::TYPE_NONFINITE)) { | |
166 float float_value; | |
167 gin_value->GetAsNonFinite(&float_value); | |
168 return v8::Number::New(args->isolate(), float_value); | |
169 } | |
170 return v8::Undefined(args->isolate()); | |
171 } | |
172 | |
173 gin::WrapperInfo GinJavaBridgeObject::kWrapperInfo = {gin::kEmbedderNativeGin}; | |
174 | |
175 } // namespace content | |
OLD | NEW |