blob: a55442b0bcbb697401b5d401dfdeeabb0ebbc8b8 [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 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.
initial.commit09911bf2008-07-26 23:55:294
5#include "chrome/plugin/npobject_proxy.h"
6
7#include "chrome/common/plugin_messages.h"
initial.commit09911bf2008-07-26 23:55:298#include "chrome/plugin/npobject_util.h"
[email protected]8beff0762009-09-29 02:18:309#include "chrome/plugin/plugin_channel.h"
[email protected]418ed5ab2009-11-12 01:14:4910#include "third_party/WebKit/WebKit/chromium/public/WebBindings.h"
initial.commit09911bf2008-07-26 23:55:2911#include "webkit/glue/webkit_glue.h"
12#include "webkit/glue/plugins/plugin_instance.h"
13
[email protected]a3929292009-07-30 00:35:3314using WebKit::WebBindings;
initial.commit09911bf2008-07-26 23:55:2915
16struct NPObjectWrapper {
17 NPObject object;
18 NPObjectProxy* proxy;
19};
20
21NPClass NPObjectProxy::npclass_proxy_ = {
[email protected]bc296f32009-05-27 09:26:5822 NP_CLASS_STRUCT_VERSION,
initial.commit09911bf2008-07-26 23:55:2923 NPObjectProxy::NPAllocate,
24 NPObjectProxy::NPDeallocate,
25 NPObjectProxy::NPPInvalidate,
26 NPObjectProxy::NPHasMethod,
27 NPObjectProxy::NPInvoke,
28 NPObjectProxy::NPInvokeDefault,
29 NPObjectProxy::NPHasProperty,
30 NPObjectProxy::NPGetProperty,
31 NPObjectProxy::NPSetProperty,
32 NPObjectProxy::NPRemoveProperty,
[email protected]bc296f32009-05-27 09:26:5833 NPObjectProxy::NPNEnumerate,
34 NPObjectProxy::NPNConstruct
initial.commit09911bf2008-07-26 23:55:2935};
36
37NPObjectProxy* NPObjectProxy::GetProxy(NPObject* object) {
38 NPObjectProxy* proxy = NULL;
39
40 // Wrapper exists only for NPObjects that we had created.
41 if (&npclass_proxy_ == object->_class) {
42 NPObjectWrapper* wrapper = reinterpret_cast<NPObjectWrapper*>(object);
43 proxy = wrapper->proxy;
44 }
45
46 return proxy;
47}
48
49NPObjectProxy::NPObjectProxy(
50 PluginChannelBase* channel,
51 int route_id,
[email protected]829c2842009-04-01 01:48:5252 intptr_t npobject_ptr,
[email protected]8beff0762009-09-29 02:18:3053 gfx::NativeViewId containing_window,
[email protected]ef916272009-07-08 21:40:5554 const GURL& page_url)
initial.commit09911bf2008-07-26 23:55:2955 : channel_(channel),
56 route_id_(route_id),
57 npobject_ptr_(npobject_ptr),
[email protected]8beff0762009-09-29 02:18:3058 containing_window_(containing_window),
[email protected]ef916272009-07-08 21:40:5559 page_url_(page_url) {
initial.commit09911bf2008-07-26 23:55:2960 channel_->AddRoute(route_id, this, true);
61}
62
63NPObjectProxy::~NPObjectProxy() {
64 if (channel_.get()) {
65 Send(new NPObjectMsg_Release(route_id_));
66 if (channel_.get())
67 channel_->RemoveRoute(route_id_);
68 }
69}
70
71NPObject* NPObjectProxy::Create(PluginChannelBase* channel,
72 int route_id,
[email protected]829c2842009-04-01 01:48:5273 intptr_t npobject_ptr,
[email protected]8beff0762009-09-29 02:18:3074 gfx::NativeViewId containing_window,
[email protected]ef916272009-07-08 21:40:5575 const GURL& page_url) {
initial.commit09911bf2008-07-26 23:55:2976 NPObjectWrapper* obj = reinterpret_cast<NPObjectWrapper*>(
[email protected]a3929292009-07-30 00:35:3377 WebBindings::createObject(0, &npclass_proxy_));
initial.commit09911bf2008-07-26 23:55:2978 obj->proxy = new NPObjectProxy(
[email protected]8beff0762009-09-29 02:18:3079 channel, route_id, npobject_ptr, containing_window, page_url);
initial.commit09911bf2008-07-26 23:55:2980
81 return reinterpret_cast<NPObject*>(obj);
82}
83
84bool NPObjectProxy::Send(IPC::Message* msg) {
85 if (channel_.get())
86 return channel_->Send(msg);
87
88 delete msg;
89 return false;
90}
91
92NPObject* NPObjectProxy::NPAllocate(NPP, NPClass*) {
93 return reinterpret_cast<NPObject*>(new NPObjectWrapper);
94}
95
96void NPObjectProxy::NPDeallocate(NPObject* npObj) {
97 NPObjectWrapper* obj = reinterpret_cast<NPObjectWrapper*>(npObj);
98 delete obj->proxy;
99 delete obj;
100}
101
102void NPObjectProxy::OnMessageReceived(const IPC::Message& msg) {
103 NOTREACHED();
104}
105
106void NPObjectProxy::OnChannelError() {
107 // Release our ref count of the plugin channel object, as it addrefs the
108 // process.
109 channel_ = NULL;
110}
111
112bool NPObjectProxy::NPHasMethod(NPObject *obj,
113 NPIdentifier name) {
[email protected]6b7a13e2009-07-17 07:47:23114 if (obj == NULL)
115 return false;
116
initial.commit09911bf2008-07-26 23:55:29117 bool result = false;
118 NPObjectProxy* proxy = GetProxy(obj);
119
120 if (!proxy) {
121 return obj->_class->hasMethod(obj, name);
122 }
123
124 NPIdentifier_Param name_param;
125 CreateNPIdentifierParam(name, &name_param);
126
[email protected]f09c7182009-03-10 12:54:04127 proxy->Send(new NPObjectMsg_HasMethod(proxy->route_id(), name_param,
128 &result));
initial.commit09911bf2008-07-26 23:55:29129 return result;
130}
131
132bool NPObjectProxy::NPInvoke(NPObject *obj,
133 NPIdentifier name,
134 const NPVariant *args,
135 uint32_t arg_count,
136 NPVariant *result) {
137 return NPInvokePrivate(0, obj, false, name, args, arg_count, result);
138}
139
140bool NPObjectProxy::NPInvokeDefault(NPObject *npobj,
141 const NPVariant *args,
142 uint32_t arg_count,
143 NPVariant *result) {
144 return NPInvokePrivate(0, npobj, true, 0, args, arg_count, result);
145}
146
147bool NPObjectProxy::NPInvokePrivate(NPP npp,
148 NPObject *obj,
149 bool is_default,
150 NPIdentifier name,
151 const NPVariant *args,
152 uint32_t arg_count,
153 NPVariant *np_result) {
[email protected]6b7a13e2009-07-17 07:47:23154 if (obj == NULL)
155 return false;
156
initial.commit09911bf2008-07-26 23:55:29157 NPObjectProxy* proxy = GetProxy(obj);
158 if (!proxy) {
[email protected]9aeaa122009-10-15 22:09:34159 if (is_default) {
160 return obj->_class->invokeDefault(obj, args, arg_count, np_result);
161 } else {
162 return obj->_class->invoke(obj, name, args, arg_count, np_result);
163 }
initial.commit09911bf2008-07-26 23:55:29164 }
165
166 bool result = false;
[email protected]8beff0762009-09-29 02:18:30167 gfx::NativeViewId containing_window = proxy->containing_window_;
initial.commit09911bf2008-07-26 23:55:29168 NPIdentifier_Param name_param;
169 if (is_default) {
[email protected]f09c7182009-03-10 12:54:04170 // The data won't actually get used, but set it so we don't send random
171 // data.
[email protected]6408eba2008-08-06 18:44:29172 name_param.identifier = NULL;
initial.commit09911bf2008-07-26 23:55:29173 } else {
174 CreateNPIdentifierParam(name, &name_param);
175 }
176
177 // Note: This instance can get destroyed in the context of
178 // Send so addref the channel in this scope.
179 scoped_refptr<PluginChannelBase> channel_copy = proxy->channel_;
180 std::vector<NPVariant_Param> args_param;
181 for (unsigned int i = 0; i < arg_count; ++i) {
182 NPVariant_Param param;
[email protected]b62de6b22009-02-21 08:10:29183 CreateNPVariantParam(
[email protected]8beff0762009-09-29 02:18:30184 args[i], channel_copy, &param, false, containing_window,
[email protected]ef916272009-07-08 21:40:55185 proxy->page_url_);
initial.commit09911bf2008-07-26 23:55:29186 args_param.push_back(param);
187 }
188
189 NPVariant_Param param_result;
190 NPObjectMsg_Invoke* msg = new NPObjectMsg_Invoke(
191 proxy->route_id_, is_default, name_param, args_param, &param_result,
192 &result);
193
194 // If we're in the plugin process and this invoke leads to a dialog box, the
195 // plugin will hang the window hierarchy unless we pump the window message
196 // queue while waiting for a reply. We need to do this to simulate what
197 // happens when everything runs in-process (while calling MessageBox window
198 // messages are pumped).
[email protected]8beff0762009-09-29 02:18:30199 if (IsPluginProcess()) {
200 PluginChannel* channel = static_cast<PluginChannel*>(proxy->channel_.get());
201 if (channel) {
202 msg->set_pump_messages_event(
203 channel->GetModalDialogEvent(containing_window));
204 }
205 }
[email protected]25e7d392008-12-23 22:55:06206
[email protected]ef916272009-07-08 21:40:55207 GURL page_url = proxy->page_url_;
initial.commit09911bf2008-07-26 23:55:29208 proxy->Send(msg);
209
[email protected]25e7d392008-12-23 22:55:06210 // Send may delete proxy.
211 proxy = NULL;
212
initial.commit09911bf2008-07-26 23:55:29213 if (!result)
214 return false;
215
216 CreateNPVariant(
[email protected]8beff0762009-09-29 02:18:30217 param_result, channel_copy, np_result, containing_window, page_url);
initial.commit09911bf2008-07-26 23:55:29218 return true;
219}
220
221bool NPObjectProxy::NPHasProperty(NPObject *obj,
222 NPIdentifier name) {
[email protected]6b7a13e2009-07-17 07:47:23223 if (obj == NULL)
224 return false;
225
initial.commit09911bf2008-07-26 23:55:29226 bool result = false;
227 NPObjectProxy* proxy = GetProxy(obj);
228 if (!proxy) {
229 return obj->_class->hasProperty(obj, name);
230 }
231
232 NPIdentifier_Param name_param;
233 CreateNPIdentifierParam(name, &name_param);
234
235 NPVariant_Param param;
236 proxy->Send(new NPObjectMsg_HasProperty(
237 proxy->route_id(), name_param, &result));
238
[email protected]25e7d392008-12-23 22:55:06239 // Send may delete proxy.
240 proxy = NULL;
241
initial.commit09911bf2008-07-26 23:55:29242 return result;
243}
244
245bool NPObjectProxy::NPGetProperty(NPObject *obj,
246 NPIdentifier name,
247 NPVariant *np_result) {
[email protected]c328da82008-09-20 00:09:09248 // Please refer to http://code.google.com/p/chromium/issues/detail?id=2556,
249 // which was a crash in the XStandard plugin during plugin shutdown. The
250 // crash occured because the plugin requests the plugin script object,
251 // which fails. The plugin does not check the result of the operation and
252 // invokes NPN_GetProperty on a NULL object which lead to the crash. If
253 // we observe similar crashes in other methods in the future, these null
254 // checks may have to be replicated in the other methods in this class.
255 if (obj == NULL)
256 return false;
257
initial.commit09911bf2008-07-26 23:55:29258 NPObjectProxy* proxy = GetProxy(obj);
259 if (!proxy) {
260 return obj->_class->getProperty(obj, name, np_result);
261 }
262
[email protected]8beff0762009-09-29 02:18:30263 bool result = false;
264 gfx::NativeViewId containing_window = proxy->containing_window_;
initial.commit09911bf2008-07-26 23:55:29265 NPIdentifier_Param name_param;
266 CreateNPIdentifierParam(name, &name_param);
267
268 NPVariant_Param param;
[email protected]25e7d392008-12-23 22:55:06269 scoped_refptr<PluginChannelBase> channel(proxy->channel_);
[email protected]ef916272009-07-08 21:40:55270
271 GURL page_url = proxy->page_url_;
initial.commit09911bf2008-07-26 23:55:29272 proxy->Send(new NPObjectMsg_GetProperty(
273 proxy->route_id(), name_param, &param, &result));
[email protected]25e7d392008-12-23 22:55:06274 // Send may delete proxy.
275 proxy = NULL;
initial.commit09911bf2008-07-26 23:55:29276 if (!result)
277 return false;
278
279 CreateNPVariant(
[email protected]8beff0762009-09-29 02:18:30280 param, channel.get(), np_result, containing_window, page_url);
initial.commit09911bf2008-07-26 23:55:29281
282 return true;
283}
284
285bool NPObjectProxy::NPSetProperty(NPObject *obj,
286 NPIdentifier name,
287 const NPVariant *value) {
[email protected]6b7a13e2009-07-17 07:47:23288 if (obj == NULL)
289 return false;
290
initial.commit09911bf2008-07-26 23:55:29291 NPObjectProxy* proxy = GetProxy(obj);
292 if (!proxy) {
293 return obj->_class->setProperty(obj, name, value);
294 }
295
[email protected]8beff0762009-09-29 02:18:30296 bool result = false;
297 gfx::NativeViewId containing_window = proxy->containing_window_;
initial.commit09911bf2008-07-26 23:55:29298 NPIdentifier_Param name_param;
299 CreateNPIdentifierParam(name, &name_param);
300
301 NPVariant_Param value_param;
[email protected]b62de6b22009-02-21 08:10:29302 CreateNPVariantParam(
303 *value, proxy->channel(), &value_param, false,
[email protected]8beff0762009-09-29 02:18:30304 containing_window, proxy->page_url_);
initial.commit09911bf2008-07-26 23:55:29305
306 proxy->Send(new NPObjectMsg_SetProperty(
307 proxy->route_id(), name_param, value_param, &result));
[email protected]25e7d392008-12-23 22:55:06308 // Send may delete proxy.
309 proxy = NULL;
initial.commit09911bf2008-07-26 23:55:29310
311 return result;
312}
313
314bool NPObjectProxy::NPRemoveProperty(NPObject *obj,
315 NPIdentifier name) {
[email protected]6b7a13e2009-07-17 07:47:23316 if (obj == NULL)
317 return false;
318
initial.commit09911bf2008-07-26 23:55:29319 bool result = false;
320 NPObjectProxy* proxy = GetProxy(obj);
321 if (!proxy) {
322 return obj->_class->removeProperty(obj, name);
323 }
324
325 NPIdentifier_Param name_param;
326 CreateNPIdentifierParam(name, &name_param);
327
328 NPVariant_Param param;
329 proxy->Send(new NPObjectMsg_RemoveProperty(
330 proxy->route_id(), name_param, &result));
[email protected]25e7d392008-12-23 22:55:06331 // Send may delete proxy.
332 proxy = NULL;
initial.commit09911bf2008-07-26 23:55:29333
334 return result;
335}
336
337void NPObjectProxy::NPPInvalidate(NPObject *obj) {
[email protected]6b7a13e2009-07-17 07:47:23338 if (obj == NULL)
339 return;
340
initial.commit09911bf2008-07-26 23:55:29341 NPObjectProxy* proxy = GetProxy(obj);
342 if (!proxy) {
[email protected]157e5d22009-04-23 18:43:35343 obj->_class->invalidate(obj);
344 return;
initial.commit09911bf2008-07-26 23:55:29345 }
346
347 proxy->Send(new NPObjectMsg_Invalidate(proxy->route_id()));
[email protected]25e7d392008-12-23 22:55:06348 // Send may delete proxy.
349 proxy = NULL;
initial.commit09911bf2008-07-26 23:55:29350}
351
352bool NPObjectProxy::NPNEnumerate(NPObject *obj,
353 NPIdentifier **value,
354 uint32_t *count) {
[email protected]6b7a13e2009-07-17 07:47:23355 if (obj == NULL)
356 return false;
357
initial.commit09911bf2008-07-26 23:55:29358 bool result = false;
359 NPObjectProxy* proxy = GetProxy(obj);
360 if (!proxy) {
361 return obj->_class->enumerate(obj, value, count);
362 }
363
364 std::vector<NPIdentifier_Param> value_param;
365 proxy->Send(new NPObjectMsg_Enumeration(
366 proxy->route_id(), &value_param, &result));
[email protected]25e7d392008-12-23 22:55:06367 // Send may delete proxy.
368 proxy = NULL;
initial.commit09911bf2008-07-26 23:55:29369
370 if (!result)
371 return false;
372
373 *count = static_cast<unsigned int>(value_param.size());
374 *value = static_cast<NPIdentifier *>(
375 NPN_MemAlloc(sizeof(NPIdentifier) * *count));
376 for (unsigned int i = 0; i < *count; ++i)
377 (*value)[i] = CreateNPIdentifier(value_param[i]);
378
379 return true;
380}
381
[email protected]bc296f32009-05-27 09:26:58382bool NPObjectProxy::NPNConstruct(NPObject *obj,
383 const NPVariant *args,
384 uint32_t arg_count,
385 NPVariant *np_result) {
[email protected]6b7a13e2009-07-17 07:47:23386 if (obj == NULL)
387 return false;
388
[email protected]bc296f32009-05-27 09:26:58389 NPObjectProxy* proxy = GetProxy(obj);
390 if (!proxy) {
391 return obj->_class->construct(obj, args, arg_count, np_result);
392 }
393
394 bool result = false;
[email protected]8beff0762009-09-29 02:18:30395 gfx::NativeViewId containing_window = proxy->containing_window_;
[email protected]bc296f32009-05-27 09:26:58396
397 // Note: This instance can get destroyed in the context of
398 // Send so addref the channel in this scope.
399 scoped_refptr<PluginChannelBase> channel_copy = proxy->channel_;
400 std::vector<NPVariant_Param> args_param;
401 for (unsigned int i = 0; i < arg_count; ++i) {
402 NPVariant_Param param;
403 CreateNPVariantParam(
[email protected]8beff0762009-09-29 02:18:30404 args[i], channel_copy, &param, false, containing_window,
[email protected]ef916272009-07-08 21:40:55405 proxy->page_url_);
[email protected]bc296f32009-05-27 09:26:58406 args_param.push_back(param);
407 }
408
409 NPVariant_Param param_result;
410 NPObjectMsg_Construct* msg = new NPObjectMsg_Construct(
411 proxy->route_id_, args_param, &param_result, &result);
412
413 // See comment in NPObjectProxy::NPInvokePrivate.
[email protected]8beff0762009-09-29 02:18:30414 if (IsPluginProcess()) {
415 PluginChannel* channel = static_cast<PluginChannel*>(proxy->channel_.get());
416 if (channel) {
417 msg->set_pump_messages_event(
418 channel->GetModalDialogEvent(proxy->containing_window_));
419 }
420 }
[email protected]bc296f32009-05-27 09:26:58421
[email protected]ef916272009-07-08 21:40:55422 GURL page_url = proxy->page_url_;
[email protected]bc296f32009-05-27 09:26:58423 proxy->Send(msg);
424
425 // Send may delete proxy.
426 proxy = NULL;
427
428 if (!result)
429 return false;
430
431 CreateNPVariant(
[email protected]8beff0762009-09-29 02:18:30432 param_result, channel_copy, np_result, containing_window, page_url);
[email protected]bc296f32009-05-27 09:26:58433 return true;
434}
435
initial.commit09911bf2008-07-26 23:55:29436bool NPObjectProxy::NPNEvaluate(NPP npp,
437 NPObject *obj,
438 NPString *script,
439 NPVariant *result_var) {
initial.commit09911bf2008-07-26 23:55:29440 NPObjectProxy* proxy = GetProxy(obj);
441 if (!proxy) {
442 return false;
443 }
444
[email protected]8beff0762009-09-29 02:18:30445 bool result = false;
446 gfx::NativeViewId containing_window = proxy->containing_window_;
[email protected]35bb1432008-10-09 19:58:15447 bool popups_allowed = false;
448
449 if (npp) {
450 NPAPI::PluginInstance* plugin_instance =
451 reinterpret_cast<NPAPI::PluginInstance*>(npp->ndata);
452 if (plugin_instance)
453 popups_allowed = plugin_instance->popups_allowed();
454 }
455
initial.commit09911bf2008-07-26 23:55:29456 NPVariant_Param result_param;
457 std::string script_str = std::string(
458 script->UTF8Characters, script->UTF8Length);
459
460 NPObjectMsg_Evaluate* msg = new NPObjectMsg_Evaluate(proxy->route_id(),
461 script_str,
[email protected]35bb1432008-10-09 19:58:15462 popups_allowed,
initial.commit09911bf2008-07-26 23:55:29463 &result_param,
464 &result);
465
[email protected]8beff0762009-09-29 02:18:30466 // See comment in NPObjectProxy::NPInvokePrivate.
467 if (IsPluginProcess()) {
468 PluginChannel* channel = static_cast<PluginChannel*>(proxy->channel_.get());
469 if (channel) {
470 msg->set_pump_messages_event(
471 channel->GetModalDialogEvent(proxy->containing_window_));
472 }
473 }
[email protected]25e7d392008-12-23 22:55:06474 scoped_refptr<PluginChannelBase> channel(proxy->channel_);
[email protected]ef916272009-07-08 21:40:55475
476 GURL page_url = proxy->page_url_;
initial.commit09911bf2008-07-26 23:55:29477 proxy->Send(msg);
[email protected]25e7d392008-12-23 22:55:06478 // Send may delete proxy.
479 proxy = NULL;
initial.commit09911bf2008-07-26 23:55:29480 if (!result)
481 return false;
482
483 CreateNPVariant(
[email protected]8beff0762009-09-29 02:18:30484 result_param, channel.get(), result_var, containing_window, page_url);
initial.commit09911bf2008-07-26 23:55:29485 return true;
486}