Bumping manifests a=b2g-bump
[gecko.git] / dom / plugins / ipc / PluginScriptableObjectParent.cpp
blobbaea05c1715a2df70548de07ce19da1fe4a85489
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/. */
7 #include "PluginScriptableObjectParent.h"
9 #include "mozilla/DebugOnly.h"
10 #include "mozilla/plugins/PluginIdentifierParent.h"
11 #include "mozilla/unused.h"
12 #include "nsNPAPIPlugin.h"
13 #include "PluginScriptableObjectUtils.h"
15 using namespace mozilla::plugins;
16 using namespace mozilla::plugins::parent;
18 namespace {
20 inline void
21 ReleaseVariant(NPVariant& aVariant,
22 PluginInstanceParent* aInstance)
24 const NPNetscapeFuncs* npn = GetNetscapeFuncs(aInstance);
25 if (npn) {
26 npn->releasevariantvalue(&aVariant);
30 } // anonymous namespace
32 // static
33 NPObject*
34 PluginScriptableObjectParent::ScriptableAllocate(NPP aInstance,
35 NPClass* aClass)
37 if (aClass != GetClass()) {
38 NS_ERROR("Huh?! Wrong class!");
39 return nullptr;
42 return new ParentNPObject();
45 // static
46 void
47 PluginScriptableObjectParent::ScriptableInvalidate(NPObject* aObject)
49 if (aObject->_class != GetClass()) {
50 NS_ERROR("Don't know what kind of object this is!");
51 return;
54 ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
55 if (object->invalidated) {
56 // This can happen more than once, and is just fine.
57 return;
60 object->invalidated = true;
62 // |object->parent| may be null already if the instance has gone away.
63 if (object->parent && !object->parent->CallInvalidate()) {
64 NS_ERROR("Failed to send message!");
68 // static
69 void
70 PluginScriptableObjectParent::ScriptableDeallocate(NPObject* aObject)
72 if (aObject->_class != GetClass()) {
73 NS_ERROR("Don't know what kind of object this is!");
74 return;
77 ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
78 PluginScriptableObjectParent* actor = object->parent;
79 if (actor) {
80 NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
81 actor->DropNPObject();
84 delete object;
87 // static
88 bool
89 PluginScriptableObjectParent::ScriptableHasMethod(NPObject* aObject,
90 NPIdentifier aName)
92 if (aObject->_class != GetClass()) {
93 NS_ERROR("Don't know what kind of object this is!");
94 return false;
97 ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
98 if (object->invalidated) {
99 NS_WARNING("Calling method on an invalidated object!");
100 return false;
103 ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
104 if (!actor) {
105 return false;
108 PluginIdentifierParent::StackIdentifier identifier(aObject, aName);
109 if (!identifier) {
110 return false;
113 NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
115 bool result;
116 if (!actor->CallHasMethod(identifier, &result)) {
117 NS_WARNING("Failed to send message!");
118 return false;
121 return result;
124 // static
125 bool
126 PluginScriptableObjectParent::ScriptableInvoke(NPObject* aObject,
127 NPIdentifier aName,
128 const NPVariant* aArgs,
129 uint32_t aArgCount,
130 NPVariant* aResult)
132 if (aObject->_class != GetClass()) {
133 NS_ERROR("Don't know what kind of object this is!");
134 return false;
137 ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
138 if (object->invalidated) {
139 NS_WARNING("Calling method on an invalidated object!");
140 return false;
143 ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
144 if (!actor) {
145 return false;
148 PluginIdentifierParent::StackIdentifier identifier(aObject, aName);
149 if (!identifier) {
150 return false;
153 NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
155 ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance());
156 if (!args.IsOk()) {
157 NS_ERROR("Failed to convert arguments!");
158 return false;
161 Variant remoteResult;
162 bool success;
163 if (!actor->CallInvoke(identifier, args, &remoteResult,
164 &success)) {
165 NS_WARNING("Failed to send message!");
166 return false;
169 if (!success) {
170 return false;
173 if (!ConvertToVariant(remoteResult, *aResult, actor->GetInstance())) {
174 NS_WARNING("Failed to convert result!");
175 return false;
177 return true;
180 // static
181 bool
182 PluginScriptableObjectParent::ScriptableInvokeDefault(NPObject* aObject,
183 const NPVariant* aArgs,
184 uint32_t aArgCount,
185 NPVariant* aResult)
187 if (aObject->_class != GetClass()) {
188 NS_ERROR("Don't know what kind of object this is!");
189 return false;
192 ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
193 if (object->invalidated) {
194 NS_WARNING("Calling method on an invalidated object!");
195 return false;
198 ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
199 if (!actor) {
200 return false;
203 NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
205 ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance());
206 if (!args.IsOk()) {
207 NS_ERROR("Failed to convert arguments!");
208 return false;
211 Variant remoteResult;
212 bool success;
213 if (!actor->CallInvokeDefault(args, &remoteResult, &success)) {
214 NS_WARNING("Failed to send message!");
215 return false;
218 if (!success) {
219 return false;
222 if (!ConvertToVariant(remoteResult, *aResult, actor->GetInstance())) {
223 NS_WARNING("Failed to convert result!");
224 return false;
226 return true;
229 // static
230 bool
231 PluginScriptableObjectParent::ScriptableHasProperty(NPObject* aObject,
232 NPIdentifier aName)
234 if (aObject->_class != GetClass()) {
235 NS_ERROR("Don't know what kind of object this is!");
236 return false;
239 ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
240 if (object->invalidated) {
241 NS_WARNING("Calling method on an invalidated object!");
242 return false;
245 ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
246 if (!actor) {
247 return false;
250 PluginIdentifierParent::StackIdentifier identifier(aObject, aName);
251 if (!identifier) {
252 return false;
255 NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
257 bool result;
258 if (!actor->CallHasProperty(identifier, &result)) {
259 NS_WARNING("Failed to send message!");
260 return false;
263 return result;
266 // static
267 bool
268 PluginScriptableObjectParent::ScriptableGetProperty(NPObject* aObject,
269 NPIdentifier aName,
270 NPVariant* aResult)
272 // See GetPropertyHelper below.
273 NS_NOTREACHED("Shouldn't ever call this directly!");
274 return false;
277 // static
278 bool
279 PluginScriptableObjectParent::ScriptableSetProperty(NPObject* aObject,
280 NPIdentifier aName,
281 const NPVariant* aValue)
283 if (aObject->_class != GetClass()) {
284 NS_ERROR("Don't know what kind of object this is!");
285 return false;
288 ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
289 if (object->invalidated) {
290 NS_WARNING("Calling method on an invalidated object!");
291 return false;
294 ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
295 if (!actor) {
296 return false;
299 PluginIdentifierParent::StackIdentifier identifier(aObject, aName);
300 if (!identifier) {
301 return false;
304 NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
306 ProtectedVariant value(*aValue, actor->GetInstance());
307 if (!value.IsOk()) {
308 NS_WARNING("Failed to convert variant!");
309 return false;
312 bool success;
313 if (!actor->CallSetProperty(identifier, value, &success)) {
314 NS_WARNING("Failed to send message!");
315 return false;
318 return success;
321 // static
322 bool
323 PluginScriptableObjectParent::ScriptableRemoveProperty(NPObject* aObject,
324 NPIdentifier aName)
326 if (aObject->_class != GetClass()) {
327 NS_ERROR("Don't know what kind of object this is!");
328 return false;
331 ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
332 if (object->invalidated) {
333 NS_WARNING("Calling method on an invalidated object!");
334 return false;
337 ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
338 if (!actor) {
339 return false;
342 PluginIdentifierParent::StackIdentifier identifier(aObject, aName);
343 if (!identifier) {
344 return false;
347 NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
349 bool success;
350 if (!actor->CallRemoveProperty(identifier, &success)) {
351 NS_WARNING("Failed to send message!");
352 return false;
355 return success;
358 // static
359 bool
360 PluginScriptableObjectParent::ScriptableEnumerate(NPObject* aObject,
361 NPIdentifier** aIdentifiers,
362 uint32_t* aCount)
364 if (aObject->_class != GetClass()) {
365 NS_ERROR("Don't know what kind of object this is!");
366 return false;
369 ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
370 if (object->invalidated) {
371 NS_WARNING("Calling method on an invalidated object!");
372 return false;
375 ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
376 if (!actor) {
377 return false;
380 NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
382 const NPNetscapeFuncs* npn = GetNetscapeFuncs(aObject);
383 if (!npn) {
384 NS_ERROR("No netscape funcs!");
385 return false;
388 AutoInfallibleTArray<PPluginIdentifierParent*, 10> identifiers;
389 bool success;
390 if (!actor->CallEnumerate(&identifiers, &success)) {
391 NS_WARNING("Failed to send message!");
392 return false;
395 if (!success) {
396 return false;
399 *aCount = identifiers.Length();
400 if (!*aCount) {
401 *aIdentifiers = nullptr;
402 return true;
405 *aIdentifiers = (NPIdentifier*)npn->memalloc(*aCount * sizeof(NPIdentifier));
406 if (!*aIdentifiers) {
407 NS_ERROR("Out of memory!");
408 return false;
411 for (uint32_t index = 0; index < *aCount; index++) {
412 PluginIdentifierParent* id =
413 static_cast<PluginIdentifierParent*>(identifiers[index]);
414 (*aIdentifiers)[index] = id->ToNPIdentifier();
416 return true;
419 // static
420 bool
421 PluginScriptableObjectParent::ScriptableConstruct(NPObject* aObject,
422 const NPVariant* aArgs,
423 uint32_t aArgCount,
424 NPVariant* aResult)
426 if (aObject->_class != GetClass()) {
427 NS_ERROR("Don't know what kind of object this is!");
428 return false;
431 ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
432 if (object->invalidated) {
433 NS_WARNING("Calling method on an invalidated object!");
434 return false;
437 ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
438 if (!actor) {
439 return false;
442 NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
444 ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance());
445 if (!args.IsOk()) {
446 NS_ERROR("Failed to convert arguments!");
447 return false;
450 Variant remoteResult;
451 bool success;
452 if (!actor->CallConstruct(args, &remoteResult, &success)) {
453 NS_WARNING("Failed to send message!");
454 return false;
457 if (!success) {
458 return false;
461 if (!ConvertToVariant(remoteResult, *aResult, actor->GetInstance())) {
462 NS_WARNING("Failed to convert result!");
463 return false;
465 return true;
468 const NPClass PluginScriptableObjectParent::sNPClass = {
469 NP_CLASS_STRUCT_VERSION,
470 PluginScriptableObjectParent::ScriptableAllocate,
471 PluginScriptableObjectParent::ScriptableDeallocate,
472 PluginScriptableObjectParent::ScriptableInvalidate,
473 PluginScriptableObjectParent::ScriptableHasMethod,
474 PluginScriptableObjectParent::ScriptableInvoke,
475 PluginScriptableObjectParent::ScriptableInvokeDefault,
476 PluginScriptableObjectParent::ScriptableHasProperty,
477 PluginScriptableObjectParent::ScriptableGetProperty,
478 PluginScriptableObjectParent::ScriptableSetProperty,
479 PluginScriptableObjectParent::ScriptableRemoveProperty,
480 PluginScriptableObjectParent::ScriptableEnumerate,
481 PluginScriptableObjectParent::ScriptableConstruct
484 PluginScriptableObjectParent::PluginScriptableObjectParent(
485 ScriptableObjectType aType)
486 : mInstance(nullptr),
487 mObject(nullptr),
488 mProtectCount(0),
489 mType(aType)
493 PluginScriptableObjectParent::~PluginScriptableObjectParent()
495 if (mObject) {
496 if (mObject->_class == GetClass()) {
497 NS_ASSERTION(mType == Proxy, "Wrong type!");
498 static_cast<ParentNPObject*>(mObject)->parent = nullptr;
500 else {
501 NS_ASSERTION(mType == LocalObject, "Wrong type!");
502 GetInstance()->GetNPNIface()->releaseobject(mObject);
507 void
508 PluginScriptableObjectParent::InitializeProxy()
510 NS_ASSERTION(mType == Proxy, "Bad type!");
511 NS_ASSERTION(!mObject, "Calling Initialize more than once!");
513 mInstance = static_cast<PluginInstanceParent*>(Manager());
514 NS_ASSERTION(mInstance, "Null manager?!");
516 NPObject* object = CreateProxyObject();
517 NS_ASSERTION(object, "Failed to create object!");
519 if (!mInstance->RegisterNPObjectForActor(object, this)) {
520 NS_ERROR("Out of memory?");
523 mObject = object;
526 void
527 PluginScriptableObjectParent::InitializeLocal(NPObject* aObject)
529 NS_ASSERTION(mType == LocalObject, "Bad type!");
530 NS_ASSERTION(!(mInstance && mObject), "Calling Initialize more than once!");
532 mInstance = static_cast<PluginInstanceParent*>(Manager());
533 NS_ASSERTION(mInstance, "Null manager?!");
535 mInstance->GetNPNIface()->retainobject(aObject);
537 NS_ASSERTION(!mProtectCount, "Should be zero!");
538 mProtectCount++;
540 if (!mInstance->RegisterNPObjectForActor(aObject, this)) {
541 NS_ERROR("Out of memory?");
544 mObject = aObject;
547 NPObject*
548 PluginScriptableObjectParent::CreateProxyObject()
550 NS_ASSERTION(mInstance, "Must have an instance!");
551 NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!");
553 const NPNetscapeFuncs* npn = GetNetscapeFuncs(mInstance);
555 NPObject* npobject = npn->createobject(mInstance->GetNPP(),
556 const_cast<NPClass*>(GetClass()));
557 NS_ASSERTION(npobject, "Failed to create object?!");
558 NS_ASSERTION(npobject->_class == GetClass(), "Wrong kind of object!");
559 NS_ASSERTION(npobject->referenceCount == 1, "Some kind of live object!");
561 ParentNPObject* object = static_cast<ParentNPObject*>(npobject);
562 NS_ASSERTION(!object->invalidated, "Bad object!");
563 NS_ASSERTION(!object->parent, "Bad object!");
565 // We don't want to have the actor own this object but rather let the object
566 // own this actor. Set the reference count to 0 here so that when the object
567 // dies we will send the destructor message to the child.
568 object->referenceCount = 0;
569 NS_LOG_RELEASE(object, 0, "BrowserNPObject");
571 object->parent = const_cast<PluginScriptableObjectParent*>(this);
572 return object;
575 bool
576 PluginScriptableObjectParent::ResurrectProxyObject()
578 NS_ASSERTION(mInstance, "Must have an instance already!");
579 NS_ASSERTION(!mObject, "Should not have an object already!");
580 NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!");
582 InitializeProxy();
583 NS_ASSERTION(mObject, "Initialize failed!");
585 if (!SendProtect()) {
586 NS_WARNING("Failed to send message!");
587 return false;
590 return true;
593 NPObject*
594 PluginScriptableObjectParent::GetObject(bool aCanResurrect)
596 if (!mObject && aCanResurrect && !ResurrectProxyObject()) {
597 NS_ERROR("Null object!");
598 return nullptr;
600 return mObject;
603 void
604 PluginScriptableObjectParent::Protect()
606 NS_ASSERTION(mObject, "No object!");
607 NS_ASSERTION(mProtectCount >= 0, "Negative protect count?!");
609 if (mType == LocalObject) {
610 ++mProtectCount;
614 void
615 PluginScriptableObjectParent::Unprotect()
617 NS_ASSERTION(mObject, "No object!");
618 NS_ASSERTION(mProtectCount >= 0, "Negative protect count?!");
620 if (mType == LocalObject) {
621 if (--mProtectCount == 0) {
622 unused << PluginScriptableObjectParent::Send__delete__(this);
627 void
628 PluginScriptableObjectParent::DropNPObject()
630 NS_ASSERTION(mObject, "Invalidated object!");
631 NS_ASSERTION(mObject->_class == GetClass(), "Wrong type of object!");
632 NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!");
634 // We think we're about to be deleted, but we could be racing with the other
635 // process.
636 PluginInstanceParent* instance = GetInstance();
637 NS_ASSERTION(instance, "Must have an instance!");
639 instance->UnregisterNPObject(mObject);
640 mObject = nullptr;
642 unused << SendUnprotect();
645 void
646 PluginScriptableObjectParent::ActorDestroy(ActorDestroyReason aWhy)
648 // Implement me! Bug 1005163
651 bool
652 PluginScriptableObjectParent::AnswerHasMethod(PPluginIdentifierParent* aId,
653 bool* aHasMethod)
655 if (!mObject) {
656 NS_WARNING("Calling AnswerHasMethod with an invalidated object!");
657 *aHasMethod = false;
658 return true;
661 NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
662 NS_ASSERTION(mType == LocalObject, "Bad type!");
664 PluginInstanceParent* instance = GetInstance();
665 if (!instance) {
666 NS_ERROR("No instance?!");
667 *aHasMethod = false;
668 return true;
671 const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
672 if (!npn) {
673 NS_ERROR("No netscape funcs?!");
674 *aHasMethod = false;
675 return true;
678 PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
679 *aHasMethod = npn->hasmethod(instance->GetNPP(), mObject, id->ToNPIdentifier());
680 return true;
683 bool
684 PluginScriptableObjectParent::AnswerInvoke(PPluginIdentifierParent* aId,
685 const InfallibleTArray<Variant>& aArgs,
686 Variant* aResult,
687 bool* aSuccess)
689 if (!mObject) {
690 NS_WARNING("Calling AnswerInvoke with an invalidated object!");
691 *aResult = void_t();
692 *aSuccess = false;
693 return true;
696 NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
697 NS_ASSERTION(mType == LocalObject, "Bad type!");
699 PluginInstanceParent* instance = GetInstance();
700 if (!instance) {
701 NS_ERROR("No instance?!");
702 *aResult = void_t();
703 *aSuccess = false;
704 return true;
707 const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
708 if (!npn) {
709 NS_ERROR("No netscape funcs?!");
710 *aResult = void_t();
711 *aSuccess = false;
712 return true;
715 AutoFallibleTArray<NPVariant, 10> convertedArgs;
716 uint32_t argCount = aArgs.Length();
718 if (!convertedArgs.SetLength(argCount)) {
719 *aResult = void_t();
720 *aSuccess = false;
721 return true;
724 for (uint32_t index = 0; index < argCount; index++) {
725 if (!ConvertToVariant(aArgs[index], convertedArgs[index], instance)) {
726 // Don't leak things we've already converted!
727 while (index-- > 0) {
728 ReleaseVariant(convertedArgs[index], instance);
730 *aResult = void_t();
731 *aSuccess = false;
732 return true;
736 PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
737 NPVariant result;
738 bool success = npn->invoke(instance->GetNPP(), mObject, id->ToNPIdentifier(),
739 convertedArgs.Elements(), argCount, &result);
741 for (uint32_t index = 0; index < argCount; index++) {
742 ReleaseVariant(convertedArgs[index], instance);
745 if (!success) {
746 *aResult = void_t();
747 *aSuccess = false;
748 return true;
751 Variant convertedResult;
752 success = ConvertToRemoteVariant(result, convertedResult, GetInstance());
754 DeferNPVariantLastRelease(npn, &result);
756 if (!success) {
757 *aResult = void_t();
758 *aSuccess = false;
759 return true;
762 *aResult = convertedResult;
763 *aSuccess = true;
764 return true;
767 bool
768 PluginScriptableObjectParent::AnswerInvokeDefault(const InfallibleTArray<Variant>& aArgs,
769 Variant* aResult,
770 bool* aSuccess)
772 if (!mObject) {
773 NS_WARNING("Calling AnswerInvoke with an invalidated object!");
774 *aResult = void_t();
775 *aSuccess = false;
776 return true;
779 NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
780 NS_ASSERTION(mType == LocalObject, "Bad type!");
782 PluginInstanceParent* instance = GetInstance();
783 if (!instance) {
784 NS_ERROR("No instance?!");
785 *aResult = void_t();
786 *aSuccess = false;
787 return true;
790 const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
791 if (!npn) {
792 NS_ERROR("No netscape funcs?!");
793 *aResult = void_t();
794 *aSuccess = false;
795 return true;
798 AutoFallibleTArray<NPVariant, 10> convertedArgs;
799 uint32_t argCount = aArgs.Length();
801 if (!convertedArgs.SetLength(argCount)) {
802 *aResult = void_t();
803 *aSuccess = false;
804 return true;
807 for (uint32_t index = 0; index < argCount; index++) {
808 if (!ConvertToVariant(aArgs[index], convertedArgs[index], instance)) {
809 // Don't leak things we've already converted!
810 while (index-- > 0) {
811 ReleaseVariant(convertedArgs[index], instance);
813 *aResult = void_t();
814 *aSuccess = false;
815 return true;
819 NPVariant result;
820 bool success = npn->invokeDefault(instance->GetNPP(), mObject,
821 convertedArgs.Elements(), argCount,
822 &result);
824 for (uint32_t index = 0; index < argCount; index++) {
825 ReleaseVariant(convertedArgs[index], instance);
828 if (!success) {
829 *aResult = void_t();
830 *aSuccess = false;
831 return true;
834 Variant convertedResult;
835 success = ConvertToRemoteVariant(result, convertedResult, GetInstance());
837 DeferNPVariantLastRelease(npn, &result);
839 if (!success) {
840 *aResult = void_t();
841 *aSuccess = false;
842 return true;
845 *aResult = convertedResult;
846 *aSuccess = true;
847 return true;
850 bool
851 PluginScriptableObjectParent::AnswerHasProperty(PPluginIdentifierParent* aId,
852 bool* aHasProperty)
854 if (!mObject) {
855 NS_WARNING("Calling AnswerHasProperty with an invalidated object!");
856 *aHasProperty = false;
857 return true;
860 NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
861 NS_ASSERTION(mType == LocalObject, "Bad type!");
863 PluginInstanceParent* instance = GetInstance();
864 if (!instance) {
865 NS_ERROR("No instance?!");
866 *aHasProperty = false;
867 return true;
870 const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
871 if (!npn) {
872 NS_ERROR("No netscape funcs?!");
873 *aHasProperty = false;
874 return true;
877 PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
878 *aHasProperty = npn->hasproperty(instance->GetNPP(), mObject,
879 id->ToNPIdentifier());
880 return true;
883 bool
884 PluginScriptableObjectParent::AnswerGetParentProperty(
885 PPluginIdentifierParent* aId,
886 Variant* aResult,
887 bool* aSuccess)
889 if (!mObject) {
890 NS_WARNING("Calling AnswerGetProperty with an invalidated object!");
891 *aResult = void_t();
892 *aSuccess = false;
893 return true;
896 NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
897 NS_ASSERTION(mType == LocalObject, "Bad type!");
899 PluginInstanceParent* instance = GetInstance();
900 if (!instance) {
901 NS_ERROR("No instance?!");
902 *aResult = void_t();
903 *aSuccess = false;
904 return true;
907 const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
908 if (!npn) {
909 NS_ERROR("No netscape funcs?!");
910 *aResult = void_t();
911 *aSuccess = false;
912 return true;
915 PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
916 NPVariant result;
917 if (!npn->getproperty(instance->GetNPP(), mObject, id->ToNPIdentifier(),
918 &result)) {
919 *aResult = void_t();
920 *aSuccess = false;
921 return true;
924 Variant converted;
925 if ((*aSuccess = ConvertToRemoteVariant(result, converted, instance))) {
926 DeferNPVariantLastRelease(npn, &result);
927 *aResult = converted;
929 else {
930 *aResult = void_t();
933 return true;
936 bool
937 PluginScriptableObjectParent::AnswerSetProperty(PPluginIdentifierParent* aId,
938 const Variant& aValue,
939 bool* aSuccess)
941 if (!mObject) {
942 NS_WARNING("Calling AnswerSetProperty with an invalidated object!");
943 *aSuccess = false;
944 return true;
947 NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
948 NS_ASSERTION(mType == LocalObject, "Bad type!");
950 PluginInstanceParent* instance = GetInstance();
951 if (!instance) {
952 NS_ERROR("No instance?!");
953 *aSuccess = false;
954 return true;
957 const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
958 if (!npn) {
959 NS_ERROR("No netscape funcs?!");
960 *aSuccess = false;
961 return true;
964 NPVariant converted;
965 if (!ConvertToVariant(aValue, converted, instance)) {
966 *aSuccess = false;
967 return true;
970 PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
971 if ((*aSuccess = npn->setproperty(instance->GetNPP(), mObject,
972 id->ToNPIdentifier(), &converted))) {
973 ReleaseVariant(converted, instance);
975 return true;
978 bool
979 PluginScriptableObjectParent::AnswerRemoveProperty(PPluginIdentifierParent* aId,
980 bool* aSuccess)
982 if (!mObject) {
983 NS_WARNING("Calling AnswerRemoveProperty with an invalidated object!");
984 *aSuccess = false;
985 return true;
988 NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
989 NS_ASSERTION(mType == LocalObject, "Bad type!");
991 PluginInstanceParent* instance = GetInstance();
992 if (!instance) {
993 NS_ERROR("No instance?!");
994 *aSuccess = false;
995 return true;
998 const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
999 if (!npn) {
1000 NS_ERROR("No netscape funcs?!");
1001 *aSuccess = false;
1002 return true;
1005 PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
1006 *aSuccess = npn->removeproperty(instance->GetNPP(), mObject,
1007 id->ToNPIdentifier());
1008 return true;
1011 bool
1012 PluginScriptableObjectParent::AnswerEnumerate(InfallibleTArray<PPluginIdentifierParent*>* aProperties,
1013 bool* aSuccess)
1015 if (!mObject) {
1016 NS_WARNING("Calling AnswerEnumerate with an invalidated object!");
1017 *aSuccess = false;
1018 return true;
1021 NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
1022 NS_ASSERTION(mType == LocalObject, "Bad type!");
1024 PluginInstanceParent* instance = GetInstance();
1025 if (!instance) {
1026 NS_ERROR("No instance?!");
1027 *aSuccess = false;
1028 return true;
1031 const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
1032 if (!npn) {
1033 NS_WARNING("No netscape funcs?!");
1034 *aSuccess = false;
1035 return true;
1038 NPIdentifier* ids;
1039 uint32_t idCount;
1040 if (!npn->enumerate(instance->GetNPP(), mObject, &ids, &idCount)) {
1041 *aSuccess = false;
1042 return true;
1045 aProperties->SetCapacity(idCount);
1047 mozilla::AutoSafeJSContext cx;
1048 for (uint32_t index = 0; index < idCount; index++) {
1049 // Because of GC hazards, all identifiers returned from enumerate
1050 // must be made permanent.
1051 if (_identifierisstring(ids[index])) {
1052 JS::Rooted<JSString*> str(cx, NPIdentifierToString(ids[index]));
1053 if (!JS_StringHasBeenInterned(cx, str)) {
1054 DebugOnly<JSString*> str2 = JS_InternJSString(cx, str);
1055 NS_ASSERTION(str2 == str, "Interning a JS string which is currently an ID should return itself.");
1058 PluginIdentifierParent* id =
1059 instance->Module()->GetIdentifierForNPIdentifier(instance->GetNPP(), ids[index]);
1060 aProperties->AppendElement(id);
1061 NS_ASSERTION(!id->IsTemporary(), "Should only have permanent identifiers!");
1064 npn->memfree(ids);
1065 *aSuccess = true;
1066 return true;
1069 bool
1070 PluginScriptableObjectParent::AnswerConstruct(const InfallibleTArray<Variant>& aArgs,
1071 Variant* aResult,
1072 bool* aSuccess)
1074 if (!mObject) {
1075 NS_WARNING("Calling AnswerConstruct with an invalidated object!");
1076 *aResult = void_t();
1077 *aSuccess = false;
1078 return true;
1081 NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
1082 NS_ASSERTION(mType == LocalObject, "Bad type!");
1084 PluginInstanceParent* instance = GetInstance();
1085 if (!instance) {
1086 NS_ERROR("No instance?!");
1087 *aResult = void_t();
1088 *aSuccess = false;
1089 return true;
1092 const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
1093 if (!npn) {
1094 NS_ERROR("No netscape funcs?!");
1095 *aResult = void_t();
1096 *aSuccess = false;
1097 return true;
1100 AutoFallibleTArray<NPVariant, 10> convertedArgs;
1101 uint32_t argCount = aArgs.Length();
1103 if (!convertedArgs.SetLength(argCount)) {
1104 *aResult = void_t();
1105 *aSuccess = false;
1106 return true;
1109 for (uint32_t index = 0; index < argCount; index++) {
1110 if (!ConvertToVariant(aArgs[index], convertedArgs[index], instance)) {
1111 // Don't leak things we've already converted!
1112 while (index-- > 0) {
1113 ReleaseVariant(convertedArgs[index], instance);
1115 *aResult = void_t();
1116 *aSuccess = false;
1117 return true;
1121 NPVariant result;
1122 bool success = npn->construct(instance->GetNPP(), mObject,
1123 convertedArgs.Elements(), argCount, &result);
1125 for (uint32_t index = 0; index < argCount; index++) {
1126 ReleaseVariant(convertedArgs[index], instance);
1129 if (!success) {
1130 *aResult = void_t();
1131 *aSuccess = false;
1132 return true;
1135 Variant convertedResult;
1136 success = ConvertToRemoteVariant(result, convertedResult, instance);
1138 DeferNPVariantLastRelease(npn, &result);
1140 if (!success) {
1141 *aResult = void_t();
1142 *aSuccess = false;
1143 return true;
1146 *aSuccess = true;
1147 *aResult = convertedResult;
1148 return true;
1151 bool
1152 PluginScriptableObjectParent::RecvProtect()
1154 NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
1155 NS_ASSERTION(mType == LocalObject, "Bad type!");
1157 Protect();
1158 return true;
1161 bool
1162 PluginScriptableObjectParent::RecvUnprotect()
1164 NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
1165 NS_ASSERTION(mType == LocalObject, "Bad type!");
1167 Unprotect();
1168 return true;
1171 bool
1172 PluginScriptableObjectParent::AnswerNPN_Evaluate(const nsCString& aScript,
1173 Variant* aResult,
1174 bool* aSuccess)
1176 PluginInstanceParent* instance = GetInstance();
1177 if (!instance) {
1178 NS_ERROR("No instance?!");
1179 *aResult = void_t();
1180 *aSuccess = false;
1181 return true;
1184 const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
1185 if (!npn) {
1186 NS_ERROR("No netscape funcs?!");
1187 *aResult = void_t();
1188 *aSuccess = false;
1189 return true;
1192 NPString script = { aScript.get(), aScript.Length() };
1194 NPVariant result;
1195 bool success = npn->evaluate(instance->GetNPP(), mObject, &script, &result);
1196 if (!success) {
1197 *aResult = void_t();
1198 *aSuccess = false;
1199 return true;
1202 Variant convertedResult;
1203 success = ConvertToRemoteVariant(result, convertedResult, instance);
1205 DeferNPVariantLastRelease(npn, &result);
1207 if (!success) {
1208 *aResult = void_t();
1209 *aSuccess = false;
1210 return true;
1213 *aSuccess = true;
1214 *aResult = convertedResult;
1215 return true;
1218 bool
1219 PluginScriptableObjectParent::GetPropertyHelper(NPIdentifier aName,
1220 bool* aHasProperty,
1221 bool* aHasMethod,
1222 NPVariant* aResult)
1224 NS_ASSERTION(Type() == Proxy, "Bad type!");
1226 ParentNPObject* object = static_cast<ParentNPObject*>(mObject);
1227 if (object->invalidated) {
1228 NS_WARNING("Calling method on an invalidated object!");
1229 return false;
1232 PluginIdentifierParent::StackIdentifier identifier(GetInstance(), aName);
1233 if (!identifier) {
1234 return false;
1237 bool hasProperty, hasMethod, success;
1238 Variant result;
1239 if (!CallGetChildProperty(identifier, &hasProperty, &hasMethod, &result,
1240 &success)) {
1241 return false;
1244 if (!success) {
1245 return false;
1248 if (!ConvertToVariant(result, *aResult, GetInstance())) {
1249 NS_WARNING("Failed to convert result!");
1250 return false;
1253 *aHasProperty = hasProperty;
1254 *aHasMethod = hasMethod;
1255 return true;