1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * vim: sw=2 ts=2 et :
3 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is Mozilla Plugin App.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Ben Turner <bent.mozilla@gmail.com>
20 : * Portions created by the Initial Developer are Copyright (C) 2009
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "PluginScriptableObjectParent.h"
40 : #include "PluginScriptableObjectUtils.h"
41 :
42 : #include "nsNPAPIPlugin.h"
43 : #include "mozilla/unused.h"
44 : #include "mozilla/Util.h"
45 :
46 : using namespace mozilla::plugins;
47 : using namespace mozilla::plugins::parent;
48 :
49 : namespace {
50 :
51 : typedef PluginIdentifierParent::StackIdentifier StackIdentifier;
52 :
53 : inline void
54 0 : ReleaseVariant(NPVariant& aVariant,
55 : PluginInstanceParent* aInstance)
56 : {
57 0 : const NPNetscapeFuncs* npn = GetNetscapeFuncs(aInstance);
58 0 : if (npn) {
59 0 : npn->releasevariantvalue(&aVariant);
60 : }
61 0 : }
62 :
63 : } // anonymous namespace
64 :
65 : // static
66 : NPObject*
67 0 : PluginScriptableObjectParent::ScriptableAllocate(NPP aInstance,
68 : NPClass* aClass)
69 : {
70 0 : if (aClass != GetClass()) {
71 0 : NS_ERROR("Huh?! Wrong class!");
72 0 : return nsnull;
73 : }
74 :
75 0 : return new ParentNPObject();
76 : }
77 :
78 : // static
79 : void
80 0 : PluginScriptableObjectParent::ScriptableInvalidate(NPObject* aObject)
81 : {
82 0 : if (aObject->_class != GetClass()) {
83 0 : NS_ERROR("Don't know what kind of object this is!");
84 0 : return;
85 : }
86 :
87 0 : ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
88 0 : if (object->invalidated) {
89 : // This can happen more than once, and is just fine.
90 0 : return;
91 : }
92 :
93 0 : object->invalidated = true;
94 :
95 : // |object->parent| may be null already if the instance has gone away.
96 0 : if (object->parent && !object->parent->CallInvalidate()) {
97 0 : NS_ERROR("Failed to send message!");
98 : }
99 : }
100 :
101 : // static
102 : void
103 0 : PluginScriptableObjectParent::ScriptableDeallocate(NPObject* aObject)
104 : {
105 0 : if (aObject->_class != GetClass()) {
106 0 : NS_ERROR("Don't know what kind of object this is!");
107 0 : return;
108 : }
109 :
110 0 : ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
111 0 : PluginScriptableObjectParent* actor = object->parent;
112 0 : if (actor) {
113 0 : NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
114 0 : actor->DropNPObject();
115 : }
116 :
117 : delete object;
118 : }
119 :
120 : // static
121 : bool
122 0 : PluginScriptableObjectParent::ScriptableHasMethod(NPObject* aObject,
123 : NPIdentifier aName)
124 : {
125 0 : if (aObject->_class != GetClass()) {
126 0 : NS_ERROR("Don't know what kind of object this is!");
127 0 : return false;
128 : }
129 :
130 0 : ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
131 0 : if (object->invalidated) {
132 0 : NS_WARNING("Calling method on an invalidated object!");
133 0 : return false;
134 : }
135 :
136 0 : ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
137 0 : if (!actor) {
138 0 : return false;
139 : }
140 :
141 0 : StackIdentifier identifier(aObject, aName);
142 0 : if (!identifier) {
143 0 : return false;
144 : }
145 :
146 0 : NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
147 :
148 : bool result;
149 0 : if (!actor->CallHasMethod(identifier, &result)) {
150 0 : NS_WARNING("Failed to send message!");
151 0 : return false;
152 : }
153 :
154 0 : return result;
155 : }
156 :
157 : // static
158 : bool
159 0 : PluginScriptableObjectParent::ScriptableInvoke(NPObject* aObject,
160 : NPIdentifier aName,
161 : const NPVariant* aArgs,
162 : uint32_t aArgCount,
163 : NPVariant* aResult)
164 : {
165 0 : if (aObject->_class != GetClass()) {
166 0 : NS_ERROR("Don't know what kind of object this is!");
167 0 : return false;
168 : }
169 :
170 0 : ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
171 0 : if (object->invalidated) {
172 0 : NS_WARNING("Calling method on an invalidated object!");
173 0 : return false;
174 : }
175 :
176 0 : ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
177 0 : if (!actor) {
178 0 : return false;
179 : }
180 :
181 0 : StackIdentifier identifier(aObject, aName);
182 0 : if (!identifier) {
183 0 : return false;
184 : }
185 :
186 0 : NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
187 :
188 0 : ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance());
189 0 : if (!args.IsOk()) {
190 0 : NS_ERROR("Failed to convert arguments!");
191 0 : return false;
192 : }
193 :
194 0 : Variant remoteResult;
195 : bool success;
196 0 : if (!actor->CallInvoke(identifier, args, &remoteResult,
197 0 : &success)) {
198 0 : NS_WARNING("Failed to send message!");
199 0 : return false;
200 : }
201 :
202 0 : if (!success) {
203 0 : return false;
204 : }
205 :
206 0 : if (!ConvertToVariant(remoteResult, *aResult, actor->GetInstance())) {
207 0 : NS_WARNING("Failed to convert result!");
208 0 : return false;
209 : }
210 0 : return true;
211 : }
212 :
213 : // static
214 : bool
215 0 : PluginScriptableObjectParent::ScriptableInvokeDefault(NPObject* aObject,
216 : const NPVariant* aArgs,
217 : uint32_t aArgCount,
218 : NPVariant* aResult)
219 : {
220 0 : if (aObject->_class != GetClass()) {
221 0 : NS_ERROR("Don't know what kind of object this is!");
222 0 : return false;
223 : }
224 :
225 0 : ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
226 0 : if (object->invalidated) {
227 0 : NS_WARNING("Calling method on an invalidated object!");
228 0 : return false;
229 : }
230 :
231 0 : ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
232 0 : if (!actor) {
233 0 : return false;
234 : }
235 :
236 0 : NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
237 :
238 0 : ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance());
239 0 : if (!args.IsOk()) {
240 0 : NS_ERROR("Failed to convert arguments!");
241 0 : return false;
242 : }
243 :
244 0 : Variant remoteResult;
245 : bool success;
246 0 : if (!actor->CallInvokeDefault(args, &remoteResult, &success)) {
247 0 : NS_WARNING("Failed to send message!");
248 0 : return false;
249 : }
250 :
251 0 : if (!success) {
252 0 : return false;
253 : }
254 :
255 0 : if (!ConvertToVariant(remoteResult, *aResult, actor->GetInstance())) {
256 0 : NS_WARNING("Failed to convert result!");
257 0 : return false;
258 : }
259 0 : return true;
260 : }
261 :
262 : // static
263 : bool
264 0 : PluginScriptableObjectParent::ScriptableHasProperty(NPObject* aObject,
265 : NPIdentifier aName)
266 : {
267 0 : if (aObject->_class != GetClass()) {
268 0 : NS_ERROR("Don't know what kind of object this is!");
269 0 : return false;
270 : }
271 :
272 0 : ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
273 0 : if (object->invalidated) {
274 0 : NS_WARNING("Calling method on an invalidated object!");
275 0 : return false;
276 : }
277 :
278 0 : ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
279 0 : if (!actor) {
280 0 : return false;
281 : }
282 :
283 0 : StackIdentifier identifier(aObject, aName);
284 0 : if (!identifier) {
285 0 : return false;
286 : }
287 :
288 0 : NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
289 :
290 : bool result;
291 0 : if (!actor->CallHasProperty(identifier, &result)) {
292 0 : NS_WARNING("Failed to send message!");
293 0 : return false;
294 : }
295 :
296 0 : return result;
297 : }
298 :
299 : // static
300 : bool
301 0 : PluginScriptableObjectParent::ScriptableGetProperty(NPObject* aObject,
302 : NPIdentifier aName,
303 : NPVariant* aResult)
304 : {
305 : // See GetPropertyHelper below.
306 0 : NS_NOTREACHED("Shouldn't ever call this directly!");
307 0 : return false;
308 : }
309 :
310 : // static
311 : bool
312 0 : PluginScriptableObjectParent::ScriptableSetProperty(NPObject* aObject,
313 : NPIdentifier aName,
314 : const NPVariant* aValue)
315 : {
316 0 : if (aObject->_class != GetClass()) {
317 0 : NS_ERROR("Don't know what kind of object this is!");
318 0 : return false;
319 : }
320 :
321 0 : ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
322 0 : if (object->invalidated) {
323 0 : NS_WARNING("Calling method on an invalidated object!");
324 0 : return false;
325 : }
326 :
327 0 : ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
328 0 : if (!actor) {
329 0 : return false;
330 : }
331 :
332 0 : StackIdentifier identifier(aObject, aName);
333 0 : if (!identifier) {
334 0 : return false;
335 : }
336 :
337 0 : NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
338 :
339 0 : ProtectedVariant value(*aValue, actor->GetInstance());
340 0 : if (!value.IsOk()) {
341 0 : NS_WARNING("Failed to convert variant!");
342 0 : return false;
343 : }
344 :
345 : bool success;
346 0 : if (!actor->CallSetProperty(identifier, value, &success)) {
347 0 : NS_WARNING("Failed to send message!");
348 0 : return false;
349 : }
350 :
351 0 : return success;
352 : }
353 :
354 : // static
355 : bool
356 0 : PluginScriptableObjectParent::ScriptableRemoveProperty(NPObject* aObject,
357 : NPIdentifier aName)
358 : {
359 0 : if (aObject->_class != GetClass()) {
360 0 : NS_ERROR("Don't know what kind of object this is!");
361 0 : return false;
362 : }
363 :
364 0 : ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
365 0 : if (object->invalidated) {
366 0 : NS_WARNING("Calling method on an invalidated object!");
367 0 : return false;
368 : }
369 :
370 0 : ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
371 0 : if (!actor) {
372 0 : return false;
373 : }
374 :
375 0 : StackIdentifier identifier(aObject, aName);
376 0 : if (!identifier) {
377 0 : return false;
378 : }
379 :
380 0 : NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
381 :
382 : bool success;
383 0 : if (!actor->CallRemoveProperty(identifier, &success)) {
384 0 : NS_WARNING("Failed to send message!");
385 0 : return false;
386 : }
387 :
388 0 : return success;
389 : }
390 :
391 : // static
392 : bool
393 0 : PluginScriptableObjectParent::ScriptableEnumerate(NPObject* aObject,
394 : NPIdentifier** aIdentifiers,
395 : uint32_t* aCount)
396 : {
397 0 : if (aObject->_class != GetClass()) {
398 0 : NS_ERROR("Don't know what kind of object this is!");
399 0 : return false;
400 : }
401 :
402 0 : ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
403 0 : if (object->invalidated) {
404 0 : NS_WARNING("Calling method on an invalidated object!");
405 0 : return false;
406 : }
407 :
408 0 : ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
409 0 : if (!actor) {
410 0 : return false;
411 : }
412 :
413 0 : NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
414 :
415 0 : const NPNetscapeFuncs* npn = GetNetscapeFuncs(aObject);
416 0 : if (!npn) {
417 0 : NS_ERROR("No netscape funcs!");
418 0 : return false;
419 : }
420 :
421 0 : AutoInfallibleTArray<PPluginIdentifierParent*, 10> identifiers;
422 : bool success;
423 0 : if (!actor->CallEnumerate(&identifiers, &success)) {
424 0 : NS_WARNING("Failed to send message!");
425 0 : return false;
426 : }
427 :
428 0 : if (!success) {
429 0 : return false;
430 : }
431 :
432 0 : *aCount = identifiers.Length();
433 0 : if (!*aCount) {
434 0 : *aIdentifiers = nsnull;
435 0 : return true;
436 : }
437 :
438 0 : *aIdentifiers = (NPIdentifier*)npn->memalloc(*aCount * sizeof(NPIdentifier));
439 0 : if (!*aIdentifiers) {
440 0 : NS_ERROR("Out of memory!");
441 0 : return false;
442 : }
443 :
444 0 : for (PRUint32 index = 0; index < *aCount; index++) {
445 : PluginIdentifierParent* id =
446 0 : static_cast<PluginIdentifierParent*>(identifiers[index]);
447 0 : (*aIdentifiers)[index] = id->ToNPIdentifier();
448 : }
449 0 : return true;
450 : }
451 :
452 : // static
453 : bool
454 0 : PluginScriptableObjectParent::ScriptableConstruct(NPObject* aObject,
455 : const NPVariant* aArgs,
456 : uint32_t aArgCount,
457 : NPVariant* aResult)
458 : {
459 0 : if (aObject->_class != GetClass()) {
460 0 : NS_ERROR("Don't know what kind of object this is!");
461 0 : return false;
462 : }
463 :
464 0 : ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
465 0 : if (object->invalidated) {
466 0 : NS_WARNING("Calling method on an invalidated object!");
467 0 : return false;
468 : }
469 :
470 0 : ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
471 0 : if (!actor) {
472 0 : return false;
473 : }
474 :
475 0 : NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
476 :
477 0 : ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance());
478 0 : if (!args.IsOk()) {
479 0 : NS_ERROR("Failed to convert arguments!");
480 0 : return false;
481 : }
482 :
483 0 : Variant remoteResult;
484 : bool success;
485 0 : if (!actor->CallConstruct(args, &remoteResult, &success)) {
486 0 : NS_WARNING("Failed to send message!");
487 0 : return false;
488 : }
489 :
490 0 : if (!success) {
491 0 : return false;
492 : }
493 :
494 0 : if (!ConvertToVariant(remoteResult, *aResult, actor->GetInstance())) {
495 0 : NS_WARNING("Failed to convert result!");
496 0 : return false;
497 : }
498 0 : return true;
499 : }
500 :
501 : const NPClass PluginScriptableObjectParent::sNPClass = {
502 : NP_CLASS_STRUCT_VERSION,
503 : PluginScriptableObjectParent::ScriptableAllocate,
504 : PluginScriptableObjectParent::ScriptableDeallocate,
505 : PluginScriptableObjectParent::ScriptableInvalidate,
506 : PluginScriptableObjectParent::ScriptableHasMethod,
507 : PluginScriptableObjectParent::ScriptableInvoke,
508 : PluginScriptableObjectParent::ScriptableInvokeDefault,
509 : PluginScriptableObjectParent::ScriptableHasProperty,
510 : PluginScriptableObjectParent::ScriptableGetProperty,
511 : PluginScriptableObjectParent::ScriptableSetProperty,
512 : PluginScriptableObjectParent::ScriptableRemoveProperty,
513 : PluginScriptableObjectParent::ScriptableEnumerate,
514 : PluginScriptableObjectParent::ScriptableConstruct
515 : };
516 :
517 0 : PluginScriptableObjectParent::PluginScriptableObjectParent(
518 : ScriptableObjectType aType)
519 : : mInstance(nsnull),
520 : mObject(nsnull),
521 : mProtectCount(0),
522 0 : mType(aType)
523 : {
524 0 : }
525 :
526 0 : PluginScriptableObjectParent::~PluginScriptableObjectParent()
527 : {
528 0 : if (mObject) {
529 0 : if (mObject->_class == GetClass()) {
530 0 : NS_ASSERTION(mType == Proxy, "Wrong type!");
531 0 : static_cast<ParentNPObject*>(mObject)->parent = nsnull;
532 : }
533 : else {
534 0 : NS_ASSERTION(mType == LocalObject, "Wrong type!");
535 0 : GetInstance()->GetNPNIface()->releaseobject(mObject);
536 : }
537 : }
538 0 : }
539 :
540 : void
541 0 : PluginScriptableObjectParent::InitializeProxy()
542 : {
543 0 : NS_ASSERTION(mType == Proxy, "Bad type!");
544 0 : NS_ASSERTION(!mObject, "Calling Initialize more than once!");
545 :
546 0 : mInstance = static_cast<PluginInstanceParent*>(Manager());
547 0 : NS_ASSERTION(mInstance, "Null manager?!");
548 :
549 0 : NPObject* object = CreateProxyObject();
550 0 : NS_ASSERTION(object, "Failed to create object!");
551 :
552 0 : if (!mInstance->RegisterNPObjectForActor(object, this)) {
553 0 : NS_ERROR("Out of memory?");
554 : }
555 :
556 0 : mObject = object;
557 0 : }
558 :
559 : void
560 0 : PluginScriptableObjectParent::InitializeLocal(NPObject* aObject)
561 : {
562 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
563 0 : NS_ASSERTION(!(mInstance && mObject), "Calling Initialize more than once!");
564 :
565 0 : mInstance = static_cast<PluginInstanceParent*>(Manager());
566 0 : NS_ASSERTION(mInstance, "Null manager?!");
567 :
568 0 : mInstance->GetNPNIface()->retainobject(aObject);
569 :
570 0 : NS_ASSERTION(!mProtectCount, "Should be zero!");
571 0 : mProtectCount++;
572 :
573 0 : if (!mInstance->RegisterNPObjectForActor(aObject, this)) {
574 0 : NS_ERROR("Out of memory?");
575 : }
576 :
577 0 : mObject = aObject;
578 0 : }
579 :
580 : NPObject*
581 0 : PluginScriptableObjectParent::CreateProxyObject()
582 : {
583 0 : NS_ASSERTION(mInstance, "Must have an instance!");
584 0 : NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!");
585 :
586 0 : const NPNetscapeFuncs* npn = GetNetscapeFuncs(mInstance);
587 :
588 : NPObject* npobject = npn->createobject(mInstance->GetNPP(),
589 0 : const_cast<NPClass*>(GetClass()));
590 0 : NS_ASSERTION(npobject, "Failed to create object?!");
591 0 : NS_ASSERTION(npobject->_class == GetClass(), "Wrong kind of object!");
592 0 : NS_ASSERTION(npobject->referenceCount == 1, "Some kind of live object!");
593 :
594 0 : ParentNPObject* object = static_cast<ParentNPObject*>(npobject);
595 0 : NS_ASSERTION(!object->invalidated, "Bad object!");
596 0 : NS_ASSERTION(!object->parent, "Bad object!");
597 :
598 : // We don't want to have the actor own this object but rather let the object
599 : // own this actor. Set the reference count to 0 here so that when the object
600 : // dies we will send the destructor message to the child.
601 0 : object->referenceCount = 0;
602 0 : NS_LOG_RELEASE(object, 0, "BrowserNPObject");
603 :
604 0 : object->parent = const_cast<PluginScriptableObjectParent*>(this);
605 0 : return object;
606 : }
607 :
608 : bool
609 0 : PluginScriptableObjectParent::ResurrectProxyObject()
610 : {
611 0 : NS_ASSERTION(mInstance, "Must have an instance already!");
612 0 : NS_ASSERTION(!mObject, "Should not have an object already!");
613 0 : NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!");
614 :
615 0 : InitializeProxy();
616 0 : NS_ASSERTION(mObject, "Initialize failed!");
617 :
618 0 : if (!SendProtect()) {
619 0 : NS_WARNING("Failed to send message!");
620 0 : return false;
621 : }
622 :
623 0 : return true;
624 : }
625 :
626 : NPObject*
627 0 : PluginScriptableObjectParent::GetObject(bool aCanResurrect)
628 : {
629 0 : if (!mObject && aCanResurrect && !ResurrectProxyObject()) {
630 0 : NS_ERROR("Null object!");
631 0 : return nsnull;
632 : }
633 0 : return mObject;
634 : }
635 :
636 : void
637 0 : PluginScriptableObjectParent::Protect()
638 : {
639 0 : NS_ASSERTION(mObject, "No object!");
640 0 : NS_ASSERTION(mProtectCount >= 0, "Negative protect count?!");
641 :
642 0 : if (mType == LocalObject) {
643 0 : ++mProtectCount;
644 : }
645 0 : }
646 :
647 : void
648 0 : PluginScriptableObjectParent::Unprotect()
649 : {
650 0 : NS_ASSERTION(mObject, "No object!");
651 0 : NS_ASSERTION(mProtectCount >= 0, "Negative protect count?!");
652 :
653 0 : if (mType == LocalObject) {
654 0 : if (--mProtectCount == 0) {
655 0 : unused << PluginScriptableObjectParent::Send__delete__(this);
656 : }
657 : }
658 0 : }
659 :
660 : void
661 0 : PluginScriptableObjectParent::DropNPObject()
662 : {
663 0 : NS_ASSERTION(mObject, "Invalidated object!");
664 0 : NS_ASSERTION(mObject->_class == GetClass(), "Wrong type of object!");
665 0 : NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!");
666 :
667 : // We think we're about to be deleted, but we could be racing with the other
668 : // process.
669 0 : PluginInstanceParent* instance = GetInstance();
670 0 : NS_ASSERTION(instance, "Must have an instance!");
671 :
672 0 : instance->UnregisterNPObject(mObject);
673 0 : mObject = nsnull;
674 :
675 0 : unused << SendUnprotect();
676 0 : }
677 :
678 : bool
679 0 : PluginScriptableObjectParent::AnswerHasMethod(PPluginIdentifierParent* aId,
680 : bool* aHasMethod)
681 : {
682 0 : if (!mObject) {
683 0 : NS_WARNING("Calling AnswerHasMethod with an invalidated object!");
684 0 : *aHasMethod = false;
685 0 : return true;
686 : }
687 :
688 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
689 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
690 :
691 0 : PluginInstanceParent* instance = GetInstance();
692 0 : if (!instance) {
693 0 : NS_ERROR("No instance?!");
694 0 : *aHasMethod = false;
695 0 : return true;
696 : }
697 :
698 0 : const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
699 0 : if (!npn) {
700 0 : NS_ERROR("No netscape funcs?!");
701 0 : *aHasMethod = false;
702 0 : return true;
703 : }
704 :
705 0 : PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
706 0 : *aHasMethod = npn->hasmethod(instance->GetNPP(), mObject, id->ToNPIdentifier());
707 0 : return true;
708 : }
709 :
710 : bool
711 0 : PluginScriptableObjectParent::AnswerInvoke(PPluginIdentifierParent* aId,
712 : const InfallibleTArray<Variant>& aArgs,
713 : Variant* aResult,
714 : bool* aSuccess)
715 : {
716 0 : if (!mObject) {
717 0 : NS_WARNING("Calling AnswerInvoke with an invalidated object!");
718 0 : *aResult = void_t();
719 0 : *aSuccess = false;
720 0 : return true;
721 : }
722 :
723 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
724 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
725 :
726 0 : PluginInstanceParent* instance = GetInstance();
727 0 : if (!instance) {
728 0 : NS_ERROR("No instance?!");
729 0 : *aResult = void_t();
730 0 : *aSuccess = false;
731 0 : return true;
732 : }
733 :
734 0 : const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
735 0 : if (!npn) {
736 0 : NS_ERROR("No netscape funcs?!");
737 0 : *aResult = void_t();
738 0 : *aSuccess = false;
739 0 : return true;
740 : }
741 :
742 0 : nsAutoTArray<NPVariant, 10> convertedArgs;
743 0 : PRUint32 argCount = aArgs.Length();
744 :
745 0 : if (!convertedArgs.SetLength(argCount)) {
746 0 : *aResult = void_t();
747 0 : *aSuccess = false;
748 0 : return true;
749 : }
750 :
751 0 : for (PRUint32 index = 0; index < argCount; index++) {
752 0 : if (!ConvertToVariant(aArgs[index], convertedArgs[index], instance)) {
753 : // Don't leak things we've already converted!
754 0 : while (index-- > 0) {
755 0 : ReleaseVariant(convertedArgs[index], instance);
756 : }
757 0 : *aResult = void_t();
758 0 : *aSuccess = false;
759 0 : return true;
760 : }
761 : }
762 :
763 0 : PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
764 : NPVariant result;
765 : bool success = npn->invoke(instance->GetNPP(), mObject, id->ToNPIdentifier(),
766 0 : convertedArgs.Elements(), argCount, &result);
767 :
768 0 : for (PRUint32 index = 0; index < argCount; index++) {
769 0 : ReleaseVariant(convertedArgs[index], instance);
770 : }
771 :
772 0 : if (!success) {
773 0 : *aResult = void_t();
774 0 : *aSuccess = false;
775 0 : return true;
776 : }
777 :
778 0 : Variant convertedResult;
779 0 : success = ConvertToRemoteVariant(result, convertedResult, GetInstance());
780 :
781 0 : DeferNPVariantLastRelease(npn, &result);
782 :
783 0 : if (!success) {
784 0 : *aResult = void_t();
785 0 : *aSuccess = false;
786 0 : return true;
787 : }
788 :
789 0 : *aResult = convertedResult;
790 0 : *aSuccess = true;
791 0 : return true;
792 : }
793 :
794 : bool
795 0 : PluginScriptableObjectParent::AnswerInvokeDefault(const InfallibleTArray<Variant>& aArgs,
796 : Variant* aResult,
797 : bool* aSuccess)
798 : {
799 0 : if (!mObject) {
800 0 : NS_WARNING("Calling AnswerInvoke with an invalidated object!");
801 0 : *aResult = void_t();
802 0 : *aSuccess = false;
803 0 : return true;
804 : }
805 :
806 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
807 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
808 :
809 0 : PluginInstanceParent* instance = GetInstance();
810 0 : if (!instance) {
811 0 : NS_ERROR("No instance?!");
812 0 : *aResult = void_t();
813 0 : *aSuccess = false;
814 0 : return true;
815 : }
816 :
817 0 : const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
818 0 : if (!npn) {
819 0 : NS_ERROR("No netscape funcs?!");
820 0 : *aResult = void_t();
821 0 : *aSuccess = false;
822 0 : return true;
823 : }
824 :
825 0 : nsAutoTArray<NPVariant, 10> convertedArgs;
826 0 : PRUint32 argCount = aArgs.Length();
827 :
828 0 : if (!convertedArgs.SetLength(argCount)) {
829 0 : *aResult = void_t();
830 0 : *aSuccess = false;
831 0 : return true;
832 : }
833 :
834 0 : for (PRUint32 index = 0; index < argCount; index++) {
835 0 : if (!ConvertToVariant(aArgs[index], convertedArgs[index], instance)) {
836 : // Don't leak things we've already converted!
837 0 : while (index-- > 0) {
838 0 : ReleaseVariant(convertedArgs[index], instance);
839 : }
840 0 : *aResult = void_t();
841 0 : *aSuccess = false;
842 0 : return true;
843 : }
844 : }
845 :
846 : NPVariant result;
847 : bool success = npn->invokeDefault(instance->GetNPP(), mObject,
848 0 : convertedArgs.Elements(), argCount,
849 0 : &result);
850 :
851 0 : for (PRUint32 index = 0; index < argCount; index++) {
852 0 : ReleaseVariant(convertedArgs[index], instance);
853 : }
854 :
855 0 : if (!success) {
856 0 : *aResult = void_t();
857 0 : *aSuccess = false;
858 0 : return true;
859 : }
860 :
861 0 : Variant convertedResult;
862 0 : success = ConvertToRemoteVariant(result, convertedResult, GetInstance());
863 :
864 0 : DeferNPVariantLastRelease(npn, &result);
865 :
866 0 : if (!success) {
867 0 : *aResult = void_t();
868 0 : *aSuccess = false;
869 0 : return true;
870 : }
871 :
872 0 : *aResult = convertedResult;
873 0 : *aSuccess = true;
874 0 : return true;
875 : }
876 :
877 : bool
878 0 : PluginScriptableObjectParent::AnswerHasProperty(PPluginIdentifierParent* aId,
879 : bool* aHasProperty)
880 : {
881 0 : if (!mObject) {
882 0 : NS_WARNING("Calling AnswerHasProperty with an invalidated object!");
883 0 : *aHasProperty = false;
884 0 : return true;
885 : }
886 :
887 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
888 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
889 :
890 0 : PluginInstanceParent* instance = GetInstance();
891 0 : if (!instance) {
892 0 : NS_ERROR("No instance?!");
893 0 : *aHasProperty = false;
894 0 : return true;
895 : }
896 :
897 0 : const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
898 0 : if (!npn) {
899 0 : NS_ERROR("No netscape funcs?!");
900 0 : *aHasProperty = false;
901 0 : return true;
902 : }
903 :
904 0 : PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
905 : *aHasProperty = npn->hasproperty(instance->GetNPP(), mObject,
906 0 : id->ToNPIdentifier());
907 0 : return true;
908 : }
909 :
910 : bool
911 0 : PluginScriptableObjectParent::AnswerGetParentProperty(
912 : PPluginIdentifierParent* aId,
913 : Variant* aResult,
914 : bool* aSuccess)
915 : {
916 0 : if (!mObject) {
917 0 : NS_WARNING("Calling AnswerGetProperty with an invalidated object!");
918 0 : *aResult = void_t();
919 0 : *aSuccess = false;
920 0 : return true;
921 : }
922 :
923 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
924 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
925 :
926 0 : PluginInstanceParent* instance = GetInstance();
927 0 : if (!instance) {
928 0 : NS_ERROR("No instance?!");
929 0 : *aResult = void_t();
930 0 : *aSuccess = false;
931 0 : return true;
932 : }
933 :
934 0 : const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
935 0 : if (!npn) {
936 0 : NS_ERROR("No netscape funcs?!");
937 0 : *aResult = void_t();
938 0 : *aSuccess = false;
939 0 : return true;
940 : }
941 :
942 0 : PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
943 : NPVariant result;
944 0 : if (!npn->getproperty(instance->GetNPP(), mObject, id->ToNPIdentifier(),
945 0 : &result)) {
946 0 : *aResult = void_t();
947 0 : *aSuccess = false;
948 0 : return true;
949 : }
950 :
951 0 : Variant converted;
952 0 : if ((*aSuccess = ConvertToRemoteVariant(result, converted, instance))) {
953 0 : DeferNPVariantLastRelease(npn, &result);
954 0 : *aResult = converted;
955 : }
956 : else {
957 0 : *aResult = void_t();
958 : }
959 :
960 0 : return true;
961 : }
962 :
963 : bool
964 0 : PluginScriptableObjectParent::AnswerSetProperty(PPluginIdentifierParent* aId,
965 : const Variant& aValue,
966 : bool* aSuccess)
967 : {
968 0 : if (!mObject) {
969 0 : NS_WARNING("Calling AnswerSetProperty with an invalidated object!");
970 0 : *aSuccess = false;
971 0 : return true;
972 : }
973 :
974 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
975 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
976 :
977 0 : PluginInstanceParent* instance = GetInstance();
978 0 : if (!instance) {
979 0 : NS_ERROR("No instance?!");
980 0 : *aSuccess = false;
981 0 : return true;
982 : }
983 :
984 0 : const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
985 0 : if (!npn) {
986 0 : NS_ERROR("No netscape funcs?!");
987 0 : *aSuccess = false;
988 0 : return true;
989 : }
990 :
991 : NPVariant converted;
992 0 : if (!ConvertToVariant(aValue, converted, instance)) {
993 0 : *aSuccess = false;
994 0 : return true;
995 : }
996 :
997 0 : PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
998 0 : if ((*aSuccess = npn->setproperty(instance->GetNPP(), mObject,
999 0 : id->ToNPIdentifier(), &converted))) {
1000 0 : ReleaseVariant(converted, instance);
1001 : }
1002 0 : return true;
1003 : }
1004 :
1005 : bool
1006 0 : PluginScriptableObjectParent::AnswerRemoveProperty(PPluginIdentifierParent* aId,
1007 : bool* aSuccess)
1008 : {
1009 0 : if (!mObject) {
1010 0 : NS_WARNING("Calling AnswerRemoveProperty with an invalidated object!");
1011 0 : *aSuccess = false;
1012 0 : return true;
1013 : }
1014 :
1015 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
1016 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
1017 :
1018 0 : PluginInstanceParent* instance = GetInstance();
1019 0 : if (!instance) {
1020 0 : NS_ERROR("No instance?!");
1021 0 : *aSuccess = false;
1022 0 : return true;
1023 : }
1024 :
1025 0 : const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
1026 0 : if (!npn) {
1027 0 : NS_ERROR("No netscape funcs?!");
1028 0 : *aSuccess = false;
1029 0 : return true;
1030 : }
1031 :
1032 0 : PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
1033 : *aSuccess = npn->removeproperty(instance->GetNPP(), mObject,
1034 0 : id->ToNPIdentifier());
1035 0 : return true;
1036 : }
1037 :
1038 : bool
1039 0 : PluginScriptableObjectParent::AnswerEnumerate(InfallibleTArray<PPluginIdentifierParent*>* aProperties,
1040 : bool* aSuccess)
1041 : {
1042 0 : if (!mObject) {
1043 0 : NS_WARNING("Calling AnswerEnumerate with an invalidated object!");
1044 0 : *aSuccess = false;
1045 0 : return true;
1046 : }
1047 :
1048 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
1049 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
1050 :
1051 0 : PluginInstanceParent* instance = GetInstance();
1052 0 : if (!instance) {
1053 0 : NS_ERROR("No instance?!");
1054 0 : *aSuccess = false;
1055 0 : return true;
1056 : }
1057 :
1058 0 : const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
1059 0 : if (!npn) {
1060 0 : NS_WARNING("No netscape funcs?!");
1061 0 : *aSuccess = false;
1062 0 : return true;
1063 : }
1064 :
1065 : NPIdentifier* ids;
1066 : uint32_t idCount;
1067 0 : if (!npn->enumerate(instance->GetNPP(), mObject, &ids, &idCount)) {
1068 0 : *aSuccess = false;
1069 0 : return true;
1070 : }
1071 :
1072 0 : if (!aProperties->SetCapacity(idCount)) {
1073 0 : npn->memfree(ids);
1074 0 : *aSuccess = false;
1075 0 : return true;
1076 : }
1077 :
1078 0 : JSContext* cx = GetJSContext(instance->GetNPP());
1079 0 : JSAutoRequest ar(cx);
1080 :
1081 0 : for (uint32_t index = 0; index < idCount; index++) {
1082 : // Because of GC hazards, all identifiers returned from enumerate
1083 : // must be made permanent.
1084 0 : if (_identifierisstring(ids[index])) {
1085 0 : JSString* str = NPIdentifierToString(ids[index]);
1086 0 : if (!JS_StringHasBeenInterned(cx, str)) {
1087 0 : DebugOnly<JSString*> str2 = JS_InternJSString(cx, str);
1088 0 : NS_ASSERTION(str2 == str, "Interning a JS string which is currently an ID should return itself.");
1089 : }
1090 : }
1091 : PluginIdentifierParent* id =
1092 0 : instance->Module()->GetIdentifierForNPIdentifier(instance->GetNPP(), ids[index]);
1093 0 : aProperties->AppendElement(id);
1094 0 : NS_ASSERTION(!id->IsTemporary(), "Should only have permanent identifiers!");
1095 : }
1096 :
1097 0 : npn->memfree(ids);
1098 0 : *aSuccess = true;
1099 0 : return true;
1100 : }
1101 :
1102 : bool
1103 0 : PluginScriptableObjectParent::AnswerConstruct(const InfallibleTArray<Variant>& aArgs,
1104 : Variant* aResult,
1105 : bool* aSuccess)
1106 : {
1107 0 : if (!mObject) {
1108 0 : NS_WARNING("Calling AnswerConstruct with an invalidated object!");
1109 0 : *aResult = void_t();
1110 0 : *aSuccess = false;
1111 0 : return true;
1112 : }
1113 :
1114 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
1115 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
1116 :
1117 0 : PluginInstanceParent* instance = GetInstance();
1118 0 : if (!instance) {
1119 0 : NS_ERROR("No instance?!");
1120 0 : *aResult = void_t();
1121 0 : *aSuccess = false;
1122 0 : return true;
1123 : }
1124 :
1125 0 : const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
1126 0 : if (!npn) {
1127 0 : NS_ERROR("No netscape funcs?!");
1128 0 : *aResult = void_t();
1129 0 : *aSuccess = false;
1130 0 : return true;
1131 : }
1132 :
1133 0 : nsAutoTArray<NPVariant, 10> convertedArgs;
1134 0 : PRUint32 argCount = aArgs.Length();
1135 :
1136 0 : if (!convertedArgs.SetLength(argCount)) {
1137 0 : *aResult = void_t();
1138 0 : *aSuccess = false;
1139 0 : return true;
1140 : }
1141 :
1142 0 : for (PRUint32 index = 0; index < argCount; index++) {
1143 0 : if (!ConvertToVariant(aArgs[index], convertedArgs[index], instance)) {
1144 : // Don't leak things we've already converted!
1145 0 : while (index-- > 0) {
1146 0 : ReleaseVariant(convertedArgs[index], instance);
1147 : }
1148 0 : *aResult = void_t();
1149 0 : *aSuccess = false;
1150 0 : return true;
1151 : }
1152 : }
1153 :
1154 : NPVariant result;
1155 : bool success = npn->construct(instance->GetNPP(), mObject,
1156 0 : convertedArgs.Elements(), argCount, &result);
1157 :
1158 0 : for (PRUint32 index = 0; index < argCount; index++) {
1159 0 : ReleaseVariant(convertedArgs[index], instance);
1160 : }
1161 :
1162 0 : if (!success) {
1163 0 : *aResult = void_t();
1164 0 : *aSuccess = false;
1165 0 : return true;
1166 : }
1167 :
1168 0 : Variant convertedResult;
1169 0 : success = ConvertToRemoteVariant(result, convertedResult, instance);
1170 :
1171 0 : DeferNPVariantLastRelease(npn, &result);
1172 :
1173 0 : if (!success) {
1174 0 : *aResult = void_t();
1175 0 : *aSuccess = false;
1176 0 : return true;
1177 : }
1178 :
1179 0 : *aSuccess = true;
1180 0 : *aResult = convertedResult;
1181 0 : return true;
1182 : }
1183 :
1184 : bool
1185 0 : PluginScriptableObjectParent::RecvProtect()
1186 : {
1187 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
1188 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
1189 :
1190 0 : Protect();
1191 0 : return true;
1192 : }
1193 :
1194 : bool
1195 0 : PluginScriptableObjectParent::RecvUnprotect()
1196 : {
1197 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
1198 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
1199 :
1200 0 : Unprotect();
1201 0 : return true;
1202 : }
1203 :
1204 : bool
1205 0 : PluginScriptableObjectParent::AnswerNPN_Evaluate(const nsCString& aScript,
1206 : Variant* aResult,
1207 : bool* aSuccess)
1208 : {
1209 0 : PluginInstanceParent* instance = GetInstance();
1210 0 : if (!instance) {
1211 0 : NS_ERROR("No instance?!");
1212 0 : *aResult = void_t();
1213 0 : *aSuccess = false;
1214 0 : return true;
1215 : }
1216 :
1217 0 : const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
1218 0 : if (!npn) {
1219 0 : NS_ERROR("No netscape funcs?!");
1220 0 : *aResult = void_t();
1221 0 : *aSuccess = false;
1222 0 : return true;
1223 : }
1224 :
1225 0 : NPString script = { aScript.get(), aScript.Length() };
1226 :
1227 : NPVariant result;
1228 0 : bool success = npn->evaluate(instance->GetNPP(), mObject, &script, &result);
1229 0 : if (!success) {
1230 0 : *aResult = void_t();
1231 0 : *aSuccess = false;
1232 0 : return true;
1233 : }
1234 :
1235 0 : Variant convertedResult;
1236 0 : success = ConvertToRemoteVariant(result, convertedResult, instance);
1237 :
1238 0 : DeferNPVariantLastRelease(npn, &result);
1239 :
1240 0 : if (!success) {
1241 0 : *aResult = void_t();
1242 0 : *aSuccess = false;
1243 0 : return true;
1244 : }
1245 :
1246 0 : *aSuccess = true;
1247 0 : *aResult = convertedResult;
1248 0 : return true;
1249 : }
1250 :
1251 : JSBool
1252 0 : PluginScriptableObjectParent::GetPropertyHelper(NPIdentifier aName,
1253 : bool* aHasProperty,
1254 : bool* aHasMethod,
1255 : NPVariant* aResult)
1256 : {
1257 0 : NS_ASSERTION(Type() == Proxy, "Bad type!");
1258 :
1259 0 : ParentNPObject* object = static_cast<ParentNPObject*>(mObject);
1260 0 : if (object->invalidated) {
1261 0 : NS_WARNING("Calling method on an invalidated object!");
1262 0 : return JS_FALSE;
1263 : }
1264 :
1265 0 : StackIdentifier identifier(GetInstance(), aName);
1266 0 : if (!identifier) {
1267 0 : return JS_FALSE;
1268 : }
1269 :
1270 : bool hasProperty, hasMethod, success;
1271 0 : Variant result;
1272 0 : if (!CallGetChildProperty(identifier, &hasProperty, &hasMethod, &result,
1273 0 : &success)) {
1274 0 : return JS_FALSE;
1275 : }
1276 :
1277 0 : if (!success) {
1278 0 : return JS_FALSE;
1279 : }
1280 :
1281 0 : if (!ConvertToVariant(result, *aResult, GetInstance())) {
1282 0 : NS_WARNING("Failed to convert result!");
1283 0 : return JS_FALSE;
1284 : }
1285 :
1286 0 : *aHasProperty = hasProperty;
1287 0 : *aHasMethod = hasMethod;
1288 0 : return JS_TRUE;
1289 : }
|