chromeos: dbus: add Bluetooth properties support
[chromium-blink-merge.git] / content / common / npobject_stub.cc
blobb6f28a7364dde306d90da199829d19a827775db5
1 // Copyright (c) 2011 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/common/npobject_stub.h"
7 #include "base/command_line.h"
8 #include "content/common/np_channel_base.h"
9 #include "content/common/npobject_util.h"
10 #include "content/common/plugin_messages.h"
11 #include "content/public/common/content_client.h"
12 #include "content/public/common/content_switches.h"
13 #include "third_party/npapi/bindings/npapi.h"
14 #include "third_party/npapi/bindings/npruntime.h"
15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h"
16 #include "webkit/plugins/npapi/plugin_constants_win.h"
17 #include "webkit/plugins/npapi/plugin_host.h"
19 using WebKit::WebBindings;
21 NPObjectStub::NPObjectStub(
22 NPObject* npobject,
23 NPChannelBase* channel,
24 int route_id,
25 gfx::NativeViewId containing_window,
26 const GURL& page_url)
27 : npobject_(npobject),
28 channel_(channel),
29 route_id_(route_id),
30 containing_window_(containing_window),
31 page_url_(page_url) {
32 channel_->AddMappingForNPObjectStub(route_id, npobject);
33 channel_->AddRoute(route_id, this, this);
35 // We retain the object just as PluginHost does if everything was in-process.
36 WebBindings::retainObject(npobject_);
39 NPObjectStub::~NPObjectStub() {
40 channel_->RemoveRoute(route_id_);
41 DCHECK(!npobject_);
44 void NPObjectStub::DeleteSoon() {
45 if (npobject_) {
46 channel_->RemoveMappingForNPObjectStub(route_id_, npobject_);
48 // We need to NULL npobject_ prior to calling releaseObject() to avoid
49 // problems with re-entrancy. See http://crbug.com/94179#c17 for more
50 // details on how this can happen.
51 NPObject* npobject = npobject_;
52 npobject_ = NULL;
54 WebBindings::releaseObject(npobject);
56 MessageLoop::current()->DeleteSoon(FROM_HERE, this);
60 bool NPObjectStub::Send(IPC::Message* msg) {
61 return channel_->Send(msg);
64 NPObject* NPObjectStub::GetUnderlyingNPObject() {
65 return npobject_;
68 IPC::Channel::Listener* NPObjectStub::GetChannelListener() {
69 return static_cast<IPC::Channel::Listener*>(this);
72 bool NPObjectStub::OnMessageReceived(const IPC::Message& msg) {
73 content::GetContentClient()->SetActiveURL(page_url_);
74 if (!npobject_) {
75 if (msg.is_sync()) {
76 // The object could be garbage because the frame has gone away, so
77 // just send an error reply to the caller.
78 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
79 reply->set_reply_error();
80 Send(reply);
83 return true;
86 bool handled = true;
87 IPC_BEGIN_MESSAGE_MAP(NPObjectStub, msg)
88 IPC_MESSAGE_HANDLER_DELAY_REPLY(NPObjectMsg_Release, OnRelease);
89 IPC_MESSAGE_HANDLER(NPObjectMsg_HasMethod, OnHasMethod);
90 IPC_MESSAGE_HANDLER_DELAY_REPLY(NPObjectMsg_Invoke, OnInvoke);
91 IPC_MESSAGE_HANDLER(NPObjectMsg_HasProperty, OnHasProperty);
92 IPC_MESSAGE_HANDLER(NPObjectMsg_GetProperty, OnGetProperty);
93 IPC_MESSAGE_HANDLER_DELAY_REPLY(NPObjectMsg_SetProperty, OnSetProperty);
94 IPC_MESSAGE_HANDLER(NPObjectMsg_RemoveProperty, OnRemoveProperty);
95 IPC_MESSAGE_HANDLER(NPObjectMsg_Invalidate, OnInvalidate);
96 IPC_MESSAGE_HANDLER(NPObjectMsg_Enumeration, OnEnumeration);
97 IPC_MESSAGE_HANDLER_DELAY_REPLY(NPObjectMsg_Construct, OnConstruct);
98 IPC_MESSAGE_HANDLER_DELAY_REPLY(NPObjectMsg_Evaluate, OnEvaluate);
99 IPC_MESSAGE_UNHANDLED(handled = false)
100 IPC_END_MESSAGE_MAP()
101 DCHECK(handled);
102 return handled;
105 void NPObjectStub::OnChannelError() {
106 DeleteSoon();
109 void NPObjectStub::OnRelease(IPC::Message* reply_msg) {
110 Send(reply_msg);
111 DeleteSoon();
114 void NPObjectStub::OnHasMethod(const NPIdentifier_Param& name,
115 bool* result) {
116 NPIdentifier id = CreateNPIdentifier(name);
117 // If we're in the plugin process, then the stub is holding onto an NPObject
118 // from the plugin, so all function calls on it need to go through the
119 // functions in NPClass. If we're in the renderer process, then we just call
120 // the NPN_ functions.
121 if (IsPluginProcess()) {
122 if (npobject_->_class->hasMethod) {
123 *result = npobject_->_class->hasMethod(npobject_, id);
124 } else {
125 *result = false;
127 } else {
128 *result = WebBindings::hasMethod(0, npobject_, id);
132 void NPObjectStub::OnInvoke(bool is_default,
133 const NPIdentifier_Param& method,
134 const std::vector<NPVariant_Param>& args,
135 IPC::Message* reply_msg) {
136 bool return_value = false;
137 NPVariant_Param result_param;
138 NPVariant result_var;
140 VOID_TO_NPVARIANT(result_var);
141 result_param.type = NPVARIANT_PARAM_VOID;
143 int arg_count = static_cast<int>(args.size());
144 NPVariant* args_var = new NPVariant[arg_count];
145 for (int i = 0; i < arg_count; ++i) {
146 if (!CreateNPVariant(
147 args[i], channel_, &(args_var[i]), containing_window_,
148 page_url_)) {
149 NPObjectMsg_Invoke::WriteReplyParams(reply_msg, result_param,
150 return_value);
151 channel_->Send(reply_msg);
152 delete[] args_var;
153 return;
157 if (is_default) {
158 if (IsPluginProcess()) {
159 if (npobject_->_class->invokeDefault) {
160 return_value = npobject_->_class->invokeDefault(
161 npobject_, args_var, arg_count, &result_var);
162 } else {
163 return_value = false;
165 } else {
166 return_value = WebBindings::invokeDefault(
167 0, npobject_, args_var, arg_count, &result_var);
169 } else {
170 NPIdentifier id = CreateNPIdentifier(method);
171 if (IsPluginProcess()) {
172 if (npobject_->_class->invoke) {
173 return_value = npobject_->_class->invoke(
174 npobject_, id, args_var, arg_count, &result_var);
175 } else {
176 return_value = false;
178 } else {
179 return_value = WebBindings::invoke(
180 0, npobject_, id, args_var, arg_count, &result_var);
184 for (int i = 0; i < arg_count; ++i)
185 WebBindings::releaseVariantValue(&(args_var[i]));
187 delete[] args_var;
189 CreateNPVariantParam(
190 result_var, channel_, &result_param, true, containing_window_,
191 page_url_);
192 NPObjectMsg_Invoke::WriteReplyParams(reply_msg, result_param, return_value);
193 channel_->Send(reply_msg);
196 void NPObjectStub::OnHasProperty(const NPIdentifier_Param& name,
197 bool* result) {
198 NPIdentifier id = CreateNPIdentifier(name);
199 if (IsPluginProcess()) {
200 if (npobject_->_class->hasProperty) {
201 *result = npobject_->_class->hasProperty(npobject_, id);
202 } else {
203 *result = false;
205 } else {
206 *result = WebBindings::hasProperty(0, npobject_, id);
210 void NPObjectStub::OnGetProperty(const NPIdentifier_Param& name,
211 NPVariant_Param* property,
212 bool* result) {
213 NPVariant result_var;
214 VOID_TO_NPVARIANT(result_var);
215 NPIdentifier id = CreateNPIdentifier(name);
217 if (IsPluginProcess()) {
218 if (npobject_->_class->getProperty) {
219 *result = npobject_->_class->getProperty(npobject_, id, &result_var);
220 } else {
221 *result = false;
223 } else {
224 *result = WebBindings::getProperty(0, npobject_, id, &result_var);
227 CreateNPVariantParam(
228 result_var, channel_, property, true, containing_window_, page_url_);
231 void NPObjectStub::OnSetProperty(const NPIdentifier_Param& name,
232 const NPVariant_Param& property,
233 IPC::Message* reply_msg) {
234 bool result = false;
235 NPIdentifier id = CreateNPIdentifier(name);
236 NPVariant property_var;
237 if (!CreateNPVariant(
238 property, channel_, &property_var, containing_window_, page_url_)) {
239 NPObjectMsg_SetProperty::WriteReplyParams(reply_msg, result);
240 channel_->Send(reply_msg);
241 return;
244 if (IsPluginProcess()) {
245 if (npobject_->_class->setProperty) {
246 #if defined(OS_WIN)
247 static FilePath plugin_path =
248 CommandLine::ForCurrentProcess()->GetSwitchValuePath(
249 switches::kPluginPath);
250 static std::wstring filename = StringToLowerASCII(
251 plugin_path.BaseName().value());
252 static NPIdentifier fullscreen =
253 WebBindings::getStringIdentifier("fullScreen");
254 if (filename == webkit::npapi::kNewWMPPlugin && id == fullscreen) {
255 // Workaround for bug 15985, which is if Flash causes WMP to go
256 // full screen a deadlock can occur when WMP calls SetFocus.
257 NPObjectMsg_SetProperty::WriteReplyParams(reply_msg, true);
258 Send(reply_msg);
259 reply_msg = NULL;
261 #endif
262 result = npobject_->_class->setProperty(npobject_, id, &property_var);
263 } else {
264 result = false;
266 } else {
267 result = WebBindings::setProperty(0, npobject_, id, &property_var);
270 WebBindings::releaseVariantValue(&property_var);
272 if (reply_msg) {
273 NPObjectMsg_SetProperty::WriteReplyParams(reply_msg, result);
274 Send(reply_msg);
278 void NPObjectStub::OnRemoveProperty(const NPIdentifier_Param& name,
279 bool* result) {
280 NPIdentifier id = CreateNPIdentifier(name);
281 if (IsPluginProcess()) {
282 if (npobject_->_class->removeProperty) {
283 *result = npobject_->_class->removeProperty(npobject_, id);
284 } else {
285 *result = false;
287 } else {
288 *result = WebBindings::removeProperty(0, npobject_, id);
292 void NPObjectStub::OnInvalidate() {
293 if (!IsPluginProcess()) {
294 NOTREACHED() << "Should only be called on NPObjects in the plugin";
295 return;
298 if (!npobject_->_class->invalidate)
299 return;
301 npobject_->_class->invalidate(npobject_);
304 void NPObjectStub::OnEnumeration(std::vector<NPIdentifier_Param>* value,
305 bool* result) {
306 NPIdentifier* value_np = NULL;
307 unsigned int count = 0;
308 if (!IsPluginProcess()) {
309 *result = WebBindings::enumerate(0, npobject_, &value_np, &count);
310 } else {
311 if (npobject_->_class->structVersion < NP_CLASS_STRUCT_VERSION_ENUM ||
312 !npobject_->_class->enumerate) {
313 *result = false;
314 return;
317 *result = npobject_->_class->enumerate(npobject_, &value_np, &count);
320 if (!*result)
321 return;
323 for (unsigned int i = 0; i < count; ++i) {
324 NPIdentifier_Param param;
325 CreateNPIdentifierParam(value_np[i], &param);
326 value->push_back(param);
329 webkit::npapi::PluginHost::Singleton()->host_functions()->memfree(value_np);
332 void NPObjectStub::OnConstruct(const std::vector<NPVariant_Param>& args,
333 IPC::Message* reply_msg) {
334 bool return_value = false;
335 NPVariant_Param result_param;
336 NPVariant result_var;
338 VOID_TO_NPVARIANT(result_var);
340 int arg_count = static_cast<int>(args.size());
341 NPVariant* args_var = new NPVariant[arg_count];
342 for (int i = 0; i < arg_count; ++i) {
343 if (!CreateNPVariant(
344 args[i], channel_, &(args_var[i]), containing_window_,
345 page_url_)) {
346 NPObjectMsg_Invoke::WriteReplyParams(reply_msg, result_param,
347 return_value);
348 channel_->Send(reply_msg);
349 delete[] args_var;
350 return;
354 if (IsPluginProcess()) {
355 if (npobject_->_class->structVersion >= NP_CLASS_STRUCT_VERSION_CTOR &&
356 npobject_->_class->construct) {
357 return_value = npobject_->_class->construct(
358 npobject_, args_var, arg_count, &result_var);
359 } else {
360 return_value = false;
362 } else {
363 return_value = WebBindings::construct(
364 0, npobject_, args_var, arg_count, &result_var);
367 for (int i = 0; i < arg_count; ++i)
368 WebBindings::releaseVariantValue(&(args_var[i]));
370 delete[] args_var;
372 CreateNPVariantParam(
373 result_var, channel_, &result_param, true, containing_window_,
374 page_url_);
375 NPObjectMsg_Invoke::WriteReplyParams(reply_msg, result_param, return_value);
376 channel_->Send(reply_msg);
379 void NPObjectStub::OnEvaluate(const std::string& script,
380 bool popups_allowed,
381 IPC::Message* reply_msg) {
382 if (IsPluginProcess()) {
383 NOTREACHED() << "Should only be called on NPObjects in the renderer";
384 return;
387 NPVariant result_var;
388 NPString script_string;
389 script_string.UTF8Characters = script.c_str();
390 script_string.UTF8Length = static_cast<unsigned int>(script.length());
392 bool return_value = WebBindings::evaluateHelper(0, popups_allowed, npobject_,
393 &script_string, &result_var);
395 NPVariant_Param result_param;
396 CreateNPVariantParam(
397 result_var, channel_, &result_param, true, containing_window_, page_url_);
398 NPObjectMsg_Evaluate::WriteReplyParams(reply_msg, result_param, return_value);
399 channel_->Send(reply_msg);