dom/plugins/ipc/PluginScriptableObjectParent.cpp

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

mercurial