michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * vim: sw=2 ts=2 et : michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "PluginScriptableObjectChild.h" michael@0: #include "PluginScriptableObjectUtils.h" michael@0: #include "PluginIdentifierChild.h" michael@0: michael@0: using namespace mozilla::plugins; michael@0: michael@0: // static michael@0: NPObject* michael@0: PluginScriptableObjectChild::ScriptableAllocate(NPP aInstance, michael@0: NPClass* aClass) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (aClass != GetClass()) { michael@0: NS_RUNTIMEABORT("Huh?! Wrong class!"); michael@0: } michael@0: michael@0: return new ChildNPObject(); michael@0: } michael@0: michael@0: // static michael@0: void michael@0: PluginScriptableObjectChild::ScriptableInvalidate(NPObject* aObject) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (aObject->_class != GetClass()) { michael@0: NS_RUNTIMEABORT("Don't know what kind of object this is!"); michael@0: } michael@0: michael@0: ChildNPObject* object = reinterpret_cast(aObject); michael@0: if (object->invalidated) { michael@0: // This can happen more than once, and is just fine. michael@0: return; michael@0: } michael@0: michael@0: object->invalidated = true; michael@0: } michael@0: michael@0: // static michael@0: void michael@0: PluginScriptableObjectChild::ScriptableDeallocate(NPObject* aObject) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (aObject->_class != GetClass()) { michael@0: NS_RUNTIMEABORT("Don't know what kind of object this is!"); michael@0: } michael@0: michael@0: ChildNPObject* object = reinterpret_cast(aObject); michael@0: PluginScriptableObjectChild* actor = object->parent; michael@0: if (actor) { michael@0: NS_ASSERTION(actor->Type() == Proxy, "Bad type!"); michael@0: actor->DropNPObject(); michael@0: } michael@0: michael@0: delete object; michael@0: } michael@0: michael@0: // static michael@0: bool michael@0: PluginScriptableObjectChild::ScriptableHasMethod(NPObject* aObject, michael@0: NPIdentifier aName) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (aObject->_class != GetClass()) { michael@0: NS_RUNTIMEABORT("Don't know what kind of object this is!"); michael@0: } michael@0: michael@0: ChildNPObject* object = reinterpret_cast(aObject); michael@0: if (object->invalidated) { michael@0: NS_WARNING("Calling method on an invalidated object!"); michael@0: return false; michael@0: } michael@0: michael@0: ProtectedActor actor(object->parent); michael@0: NS_ASSERTION(actor, "This shouldn't ever be null!"); michael@0: NS_ASSERTION(actor->Type() == Proxy, "Bad type!"); michael@0: michael@0: bool result; michael@0: actor->CallHasMethod(static_cast(aName), &result); michael@0: michael@0: return result; michael@0: } michael@0: michael@0: // static michael@0: bool michael@0: PluginScriptableObjectChild::ScriptableInvoke(NPObject* aObject, michael@0: NPIdentifier aName, michael@0: const NPVariant* aArgs, michael@0: uint32_t aArgCount, michael@0: NPVariant* aResult) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (aObject->_class != GetClass()) { michael@0: NS_RUNTIMEABORT("Don't know what kind of object this is!"); michael@0: } michael@0: michael@0: ChildNPObject* object = reinterpret_cast(aObject); michael@0: if (object->invalidated) { michael@0: NS_WARNING("Calling method on an invalidated object!"); michael@0: return false; michael@0: } michael@0: michael@0: ProtectedActor actor(object->parent); michael@0: NS_ASSERTION(actor, "This shouldn't ever be null!"); michael@0: NS_ASSERTION(actor->Type() == Proxy, "Bad type!"); michael@0: michael@0: ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance()); michael@0: if (!args.IsOk()) { michael@0: NS_ERROR("Failed to convert arguments!"); michael@0: return false; michael@0: } michael@0: michael@0: Variant remoteResult; michael@0: bool success; michael@0: actor->CallInvoke(static_cast(aName), args, michael@0: &remoteResult, &success); michael@0: michael@0: if (!success) { michael@0: return false; michael@0: } michael@0: michael@0: ConvertToVariant(remoteResult, *aResult); michael@0: return true; michael@0: } michael@0: michael@0: // static michael@0: bool michael@0: PluginScriptableObjectChild::ScriptableInvokeDefault(NPObject* aObject, michael@0: const NPVariant* aArgs, michael@0: uint32_t aArgCount, michael@0: NPVariant* aResult) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (aObject->_class != GetClass()) { michael@0: NS_RUNTIMEABORT("Don't know what kind of object this is!"); michael@0: } michael@0: michael@0: ChildNPObject* object = reinterpret_cast(aObject); michael@0: if (object->invalidated) { michael@0: NS_WARNING("Calling method on an invalidated object!"); michael@0: return false; michael@0: } michael@0: michael@0: ProtectedActor actor(object->parent); michael@0: NS_ASSERTION(actor, "This shouldn't ever be null!"); michael@0: NS_ASSERTION(actor->Type() == Proxy, "Bad type!"); michael@0: michael@0: ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance()); michael@0: if (!args.IsOk()) { michael@0: NS_ERROR("Failed to convert arguments!"); michael@0: return false; michael@0: } michael@0: michael@0: Variant remoteResult; michael@0: bool success; michael@0: actor->CallInvokeDefault(args, &remoteResult, &success); michael@0: michael@0: if (!success) { michael@0: return false; michael@0: } michael@0: michael@0: ConvertToVariant(remoteResult, *aResult); michael@0: return true; michael@0: } michael@0: michael@0: // static michael@0: bool michael@0: PluginScriptableObjectChild::ScriptableHasProperty(NPObject* aObject, michael@0: NPIdentifier aName) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (aObject->_class != GetClass()) { michael@0: NS_RUNTIMEABORT("Don't know what kind of object this is!"); michael@0: } michael@0: michael@0: ChildNPObject* object = reinterpret_cast(aObject); michael@0: if (object->invalidated) { michael@0: NS_WARNING("Calling method on an invalidated object!"); michael@0: return false; michael@0: } michael@0: michael@0: ProtectedActor actor(object->parent); michael@0: NS_ASSERTION(actor, "This shouldn't ever be null!"); michael@0: NS_ASSERTION(actor->Type() == Proxy, "Bad type!"); michael@0: michael@0: bool result; michael@0: actor->CallHasProperty(static_cast(aName), &result); michael@0: michael@0: return result; michael@0: } michael@0: michael@0: // static michael@0: bool michael@0: PluginScriptableObjectChild::ScriptableGetProperty(NPObject* aObject, michael@0: NPIdentifier aName, michael@0: NPVariant* aResult) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (aObject->_class != GetClass()) { michael@0: NS_RUNTIMEABORT("Don't know what kind of object this is!"); michael@0: } michael@0: michael@0: ChildNPObject* object = reinterpret_cast(aObject); michael@0: if (object->invalidated) { michael@0: NS_WARNING("Calling method on an invalidated object!"); michael@0: return false; michael@0: } michael@0: michael@0: ProtectedActor actor(object->parent); michael@0: NS_ASSERTION(actor, "This shouldn't ever be null!"); michael@0: NS_ASSERTION(actor->Type() == Proxy, "Bad type!"); michael@0: michael@0: Variant result; michael@0: bool success; michael@0: actor->CallGetParentProperty(static_cast(aName), michael@0: &result, &success); michael@0: michael@0: if (!success) { michael@0: return false; michael@0: } michael@0: michael@0: ConvertToVariant(result, *aResult); michael@0: return true; michael@0: } michael@0: michael@0: // static michael@0: bool michael@0: PluginScriptableObjectChild::ScriptableSetProperty(NPObject* aObject, michael@0: NPIdentifier aName, michael@0: const NPVariant* aValue) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (aObject->_class != GetClass()) { michael@0: NS_RUNTIMEABORT("Don't know what kind of object this is!"); michael@0: } michael@0: michael@0: ChildNPObject* object = reinterpret_cast(aObject); michael@0: if (object->invalidated) { michael@0: NS_WARNING("Calling method on an invalidated object!"); michael@0: return false; michael@0: } michael@0: michael@0: ProtectedActor actor(object->parent); michael@0: NS_ASSERTION(actor, "This shouldn't ever be null!"); michael@0: NS_ASSERTION(actor->Type() == Proxy, "Bad type!"); michael@0: michael@0: ProtectedVariant value(*aValue, actor->GetInstance()); michael@0: if (!value.IsOk()) { michael@0: NS_WARNING("Failed to convert variant!"); michael@0: return false; michael@0: } michael@0: michael@0: bool success; michael@0: actor->CallSetProperty(static_cast(aName), value, michael@0: &success); michael@0: michael@0: return success; michael@0: } michael@0: michael@0: // static michael@0: bool michael@0: PluginScriptableObjectChild::ScriptableRemoveProperty(NPObject* aObject, michael@0: NPIdentifier aName) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (aObject->_class != GetClass()) { michael@0: NS_RUNTIMEABORT("Don't know what kind of object this is!"); michael@0: } michael@0: michael@0: ChildNPObject* object = reinterpret_cast(aObject); michael@0: if (object->invalidated) { michael@0: NS_WARNING("Calling method on an invalidated object!"); michael@0: return false; michael@0: } michael@0: michael@0: ProtectedActor actor(object->parent); michael@0: NS_ASSERTION(actor, "This shouldn't ever be null!"); michael@0: NS_ASSERTION(actor->Type() == Proxy, "Bad type!"); michael@0: michael@0: bool success; michael@0: actor->CallRemoveProperty(static_cast(aName), michael@0: &success); michael@0: michael@0: return success; michael@0: } michael@0: michael@0: // static michael@0: bool michael@0: PluginScriptableObjectChild::ScriptableEnumerate(NPObject* aObject, michael@0: NPIdentifier** aIdentifiers, michael@0: uint32_t* aCount) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (aObject->_class != GetClass()) { michael@0: NS_RUNTIMEABORT("Don't know what kind of object this is!"); michael@0: } michael@0: michael@0: ChildNPObject* object = reinterpret_cast(aObject); michael@0: if (object->invalidated) { michael@0: NS_WARNING("Calling method on an invalidated object!"); michael@0: return false; michael@0: } michael@0: michael@0: ProtectedActor actor(object->parent); michael@0: NS_ASSERTION(actor, "This shouldn't ever be null!"); michael@0: NS_ASSERTION(actor->Type() == Proxy, "Bad type!"); michael@0: michael@0: AutoInfallibleTArray identifiers; michael@0: bool success; michael@0: actor->CallEnumerate(&identifiers, &success); michael@0: michael@0: if (!success) { michael@0: return false; michael@0: } michael@0: michael@0: *aCount = identifiers.Length(); michael@0: if (!*aCount) { michael@0: *aIdentifiers = nullptr; michael@0: return true; michael@0: } michael@0: michael@0: *aIdentifiers = reinterpret_cast( michael@0: PluginModuleChild::sBrowserFuncs.memalloc(*aCount * sizeof(NPIdentifier))); michael@0: if (!*aIdentifiers) { michael@0: NS_ERROR("Out of memory!"); michael@0: return false; michael@0: } michael@0: michael@0: for (uint32_t index = 0; index < *aCount; index++) { michael@0: (*aIdentifiers)[index] = michael@0: static_cast(identifiers[index]); michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: // static michael@0: bool michael@0: PluginScriptableObjectChild::ScriptableConstruct(NPObject* aObject, michael@0: const NPVariant* aArgs, michael@0: uint32_t aArgCount, michael@0: NPVariant* aResult) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (aObject->_class != GetClass()) { michael@0: NS_RUNTIMEABORT("Don't know what kind of object this is!"); michael@0: } michael@0: michael@0: ChildNPObject* object = reinterpret_cast(aObject); michael@0: if (object->invalidated) { michael@0: NS_WARNING("Calling method on an invalidated object!"); michael@0: return false; michael@0: } michael@0: michael@0: ProtectedActor actor(object->parent); michael@0: NS_ASSERTION(actor, "This shouldn't ever be null!"); michael@0: NS_ASSERTION(actor->Type() == Proxy, "Bad type!"); michael@0: michael@0: ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance()); michael@0: if (!args.IsOk()) { michael@0: NS_ERROR("Failed to convert arguments!"); michael@0: return false; michael@0: } michael@0: michael@0: Variant remoteResult; michael@0: bool success; michael@0: actor->CallConstruct(args, &remoteResult, &success); michael@0: michael@0: if (!success) { michael@0: return false; michael@0: } michael@0: michael@0: ConvertToVariant(remoteResult, *aResult); michael@0: return true; michael@0: } michael@0: michael@0: const NPClass PluginScriptableObjectChild::sNPClass = { michael@0: NP_CLASS_STRUCT_VERSION, michael@0: PluginScriptableObjectChild::ScriptableAllocate, michael@0: PluginScriptableObjectChild::ScriptableDeallocate, michael@0: PluginScriptableObjectChild::ScriptableInvalidate, michael@0: PluginScriptableObjectChild::ScriptableHasMethod, michael@0: PluginScriptableObjectChild::ScriptableInvoke, michael@0: PluginScriptableObjectChild::ScriptableInvokeDefault, michael@0: PluginScriptableObjectChild::ScriptableHasProperty, michael@0: PluginScriptableObjectChild::ScriptableGetProperty, michael@0: PluginScriptableObjectChild::ScriptableSetProperty, michael@0: PluginScriptableObjectChild::ScriptableRemoveProperty, michael@0: PluginScriptableObjectChild::ScriptableEnumerate, michael@0: PluginScriptableObjectChild::ScriptableConstruct michael@0: }; michael@0: michael@0: PluginScriptableObjectChild::PluginScriptableObjectChild( michael@0: ScriptableObjectType aType) michael@0: : mInstance(nullptr), michael@0: mObject(nullptr), michael@0: mInvalidated(false), michael@0: mProtectCount(0), michael@0: mType(aType) michael@0: { michael@0: AssertPluginThread(); michael@0: } michael@0: michael@0: PluginScriptableObjectChild::~PluginScriptableObjectChild() michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (mObject) { michael@0: PluginModuleChild::current()->UnregisterActorForNPObject(mObject); michael@0: michael@0: if (mObject->_class == GetClass()) { michael@0: NS_ASSERTION(mType == Proxy, "Wrong type!"); michael@0: static_cast(mObject)->parent = nullptr; michael@0: } michael@0: else { michael@0: NS_ASSERTION(mType == LocalObject, "Wrong type!"); michael@0: PluginModuleChild::sBrowserFuncs.releaseobject(mObject); michael@0: } michael@0: } michael@0: } michael@0: michael@0: void michael@0: PluginScriptableObjectChild::InitializeProxy() michael@0: { michael@0: AssertPluginThread(); michael@0: NS_ASSERTION(mType == Proxy, "Bad type!"); michael@0: NS_ASSERTION(!mObject, "Calling Initialize more than once!"); michael@0: NS_ASSERTION(!mInvalidated, "Already invalidated?!"); michael@0: michael@0: mInstance = static_cast(Manager()); michael@0: NS_ASSERTION(mInstance, "Null manager?!"); michael@0: michael@0: NPObject* object = CreateProxyObject(); michael@0: NS_ASSERTION(object, "Failed to create object!"); michael@0: michael@0: if (!PluginModuleChild::current()->RegisterActorForNPObject(object, this)) { michael@0: NS_ERROR("Out of memory?"); michael@0: } michael@0: michael@0: mObject = object; michael@0: } michael@0: michael@0: void michael@0: PluginScriptableObjectChild::InitializeLocal(NPObject* aObject) michael@0: { michael@0: AssertPluginThread(); michael@0: NS_ASSERTION(mType == LocalObject, "Bad type!"); michael@0: NS_ASSERTION(!mObject, "Calling Initialize more than once!"); michael@0: NS_ASSERTION(!mInvalidated, "Already invalidated?!"); michael@0: michael@0: mInstance = static_cast(Manager()); michael@0: NS_ASSERTION(mInstance, "Null manager?!"); michael@0: michael@0: PluginModuleChild::sBrowserFuncs.retainobject(aObject); michael@0: michael@0: NS_ASSERTION(!mProtectCount, "Should be zero!"); michael@0: mProtectCount++; michael@0: michael@0: if (!PluginModuleChild::current()->RegisterActorForNPObject(aObject, this)) { michael@0: NS_ERROR("Out of memory?"); michael@0: } michael@0: michael@0: mObject = aObject; michael@0: } michael@0: michael@0: NPObject* michael@0: PluginScriptableObjectChild::CreateProxyObject() michael@0: { michael@0: NS_ASSERTION(mInstance, "Must have an instance!"); michael@0: NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!"); michael@0: michael@0: NPClass* proxyClass = const_cast(GetClass()); michael@0: NPObject* npobject = michael@0: PluginModuleChild::sBrowserFuncs.createobject(mInstance->GetNPP(), michael@0: proxyClass); michael@0: NS_ASSERTION(npobject, "Failed to create object?!"); michael@0: NS_ASSERTION(npobject->_class == GetClass(), "Wrong kind of object!"); michael@0: NS_ASSERTION(npobject->referenceCount == 1, "Some kind of live object!"); michael@0: michael@0: ChildNPObject* object = static_cast(npobject); michael@0: NS_ASSERTION(!object->invalidated, "Bad object!"); michael@0: NS_ASSERTION(!object->parent, "Bad object!"); michael@0: michael@0: // We don't want to have the actor own this object but rather let the object michael@0: // own this actor. Set the reference count to 0 here so that when the object michael@0: // dies we will send the destructor message to the child. michael@0: object->referenceCount = 0; michael@0: NS_LOG_RELEASE(object, 0, "NPObject"); michael@0: michael@0: object->parent = const_cast(this); michael@0: return object; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectChild::ResurrectProxyObject() michael@0: { michael@0: NS_ASSERTION(mInstance, "Must have an instance already!"); michael@0: NS_ASSERTION(!mObject, "Should not have an object already!"); michael@0: NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!"); michael@0: michael@0: NPObject* object = CreateProxyObject(); michael@0: if (!object) { michael@0: NS_WARNING("Failed to create object!"); michael@0: return false; michael@0: } michael@0: michael@0: InitializeProxy(); michael@0: NS_ASSERTION(mObject, "Initialize failed!"); michael@0: michael@0: SendProtect(); michael@0: return true; michael@0: } michael@0: michael@0: NPObject* michael@0: PluginScriptableObjectChild::GetObject(bool aCanResurrect) michael@0: { michael@0: if (!mObject && aCanResurrect && !ResurrectProxyObject()) { michael@0: NS_ERROR("Null object!"); michael@0: return nullptr; michael@0: } michael@0: return mObject; michael@0: } michael@0: michael@0: void michael@0: PluginScriptableObjectChild::Protect() michael@0: { michael@0: NS_ASSERTION(mObject, "No object!"); michael@0: NS_ASSERTION(mProtectCount >= 0, "Negative retain count?!"); michael@0: michael@0: if (mType == LocalObject) { michael@0: ++mProtectCount; michael@0: } michael@0: } michael@0: michael@0: void michael@0: PluginScriptableObjectChild::Unprotect() michael@0: { michael@0: NS_ASSERTION(mObject, "Bad state!"); michael@0: NS_ASSERTION(mProtectCount >= 0, "Negative retain count?!"); michael@0: michael@0: if (mType == LocalObject) { michael@0: if (--mProtectCount == 0) { michael@0: PluginScriptableObjectChild::Send__delete__(this); michael@0: } michael@0: } michael@0: } michael@0: michael@0: void michael@0: PluginScriptableObjectChild::DropNPObject() michael@0: { michael@0: NS_ASSERTION(mObject, "Invalidated object!"); michael@0: NS_ASSERTION(mObject->_class == GetClass(), "Wrong type of object!"); michael@0: NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!"); michael@0: michael@0: // We think we're about to be deleted, but we could be racing with the other michael@0: // process. michael@0: PluginModuleChild::current()->UnregisterActorForNPObject(mObject); michael@0: mObject = nullptr; michael@0: michael@0: SendUnprotect(); michael@0: } michael@0: michael@0: void michael@0: PluginScriptableObjectChild::NPObjectDestroyed() michael@0: { michael@0: NS_ASSERTION(LocalObject == mType, michael@0: "ScriptableDeallocate should have handled this for proxies"); michael@0: mInvalidated = true; michael@0: mObject = nullptr; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectChild::AnswerInvalidate() michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (mInvalidated) { michael@0: return true; michael@0: } michael@0: michael@0: mInvalidated = true; michael@0: michael@0: NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); michael@0: NS_ASSERTION(mType == LocalObject, "Bad type!"); michael@0: michael@0: if (mObject->_class && mObject->_class->invalidate) { michael@0: mObject->_class->invalidate(mObject); michael@0: } michael@0: michael@0: Unprotect(); michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectChild::AnswerHasMethod(PPluginIdentifierChild* aId, michael@0: bool* aHasMethod) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (mInvalidated) { michael@0: NS_WARNING("Calling AnswerHasMethod with an invalidated object!"); michael@0: *aHasMethod = false; michael@0: return true; michael@0: } michael@0: michael@0: NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); michael@0: NS_ASSERTION(mType == LocalObject, "Bad type!"); michael@0: michael@0: if (!(mObject->_class && mObject->_class->hasMethod)) { michael@0: *aHasMethod = false; michael@0: return true; michael@0: } michael@0: michael@0: PluginIdentifierChild::StackIdentifier id(aId); michael@0: *aHasMethod = mObject->_class->hasMethod(mObject, id->ToNPIdentifier()); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectChild::AnswerInvoke(PPluginIdentifierChild* aId, michael@0: const InfallibleTArray& aArgs, michael@0: Variant* aResult, michael@0: bool* aSuccess) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (mInvalidated) { michael@0: NS_WARNING("Calling AnswerInvoke with an invalidated object!"); michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); michael@0: NS_ASSERTION(mType == LocalObject, "Bad type!"); michael@0: michael@0: if (!(mObject->_class && mObject->_class->invoke)) { michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: AutoFallibleTArray convertedArgs; michael@0: uint32_t argCount = aArgs.Length(); michael@0: michael@0: if (!convertedArgs.SetLength(argCount)) { michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: for (uint32_t index = 0; index < argCount; index++) { michael@0: ConvertToVariant(aArgs[index], convertedArgs[index]); michael@0: } michael@0: michael@0: NPVariant result; michael@0: VOID_TO_NPVARIANT(result); michael@0: PluginIdentifierChild::StackIdentifier id(aId); michael@0: bool success = mObject->_class->invoke(mObject, id->ToNPIdentifier(), michael@0: convertedArgs.Elements(), argCount, michael@0: &result); michael@0: michael@0: for (uint32_t index = 0; index < argCount; index++) { michael@0: PluginModuleChild::sBrowserFuncs.releasevariantvalue(&convertedArgs[index]); michael@0: } michael@0: michael@0: if (!success) { michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: Variant convertedResult; michael@0: success = ConvertToRemoteVariant(result, convertedResult, GetInstance(), michael@0: false); michael@0: michael@0: DeferNPVariantLastRelease(&PluginModuleChild::sBrowserFuncs, &result); michael@0: michael@0: if (!success) { michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: *aSuccess = true; michael@0: *aResult = convertedResult; michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectChild::AnswerInvokeDefault(const InfallibleTArray& aArgs, michael@0: Variant* aResult, michael@0: bool* aSuccess) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (mInvalidated) { michael@0: NS_WARNING("Calling AnswerInvokeDefault with an invalidated object!"); michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); michael@0: NS_ASSERTION(mType == LocalObject, "Bad type!"); michael@0: michael@0: if (!(mObject->_class && mObject->_class->invokeDefault)) { michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: AutoFallibleTArray convertedArgs; michael@0: uint32_t argCount = aArgs.Length(); michael@0: michael@0: if (!convertedArgs.SetLength(argCount)) { michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: for (uint32_t index = 0; index < argCount; index++) { michael@0: ConvertToVariant(aArgs[index], convertedArgs[index]); michael@0: } michael@0: michael@0: NPVariant result; michael@0: VOID_TO_NPVARIANT(result); michael@0: bool success = mObject->_class->invokeDefault(mObject, michael@0: convertedArgs.Elements(), michael@0: argCount, &result); michael@0: michael@0: for (uint32_t index = 0; index < argCount; index++) { michael@0: PluginModuleChild::sBrowserFuncs.releasevariantvalue(&convertedArgs[index]); michael@0: } michael@0: michael@0: if (!success) { michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: Variant convertedResult; michael@0: success = ConvertToRemoteVariant(result, convertedResult, GetInstance(), michael@0: false); michael@0: michael@0: DeferNPVariantLastRelease(&PluginModuleChild::sBrowserFuncs, &result); michael@0: michael@0: if (!success) { michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: *aResult = convertedResult; michael@0: *aSuccess = true; michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectChild::AnswerHasProperty(PPluginIdentifierChild* aId, michael@0: bool* aHasProperty) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (mInvalidated) { michael@0: NS_WARNING("Calling AnswerHasProperty with an invalidated object!"); michael@0: *aHasProperty = false; michael@0: return true; michael@0: } michael@0: michael@0: NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); michael@0: NS_ASSERTION(mType == LocalObject, "Bad type!"); michael@0: michael@0: if (!(mObject->_class && mObject->_class->hasProperty)) { michael@0: *aHasProperty = false; michael@0: return true; michael@0: } michael@0: michael@0: PluginIdentifierChild::StackIdentifier id(aId); michael@0: *aHasProperty = mObject->_class->hasProperty(mObject, id->ToNPIdentifier()); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectChild::AnswerGetChildProperty(PPluginIdentifierChild* aId, michael@0: bool* aHasProperty, michael@0: bool* aHasMethod, michael@0: Variant* aResult, michael@0: bool* aSuccess) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: *aHasProperty = *aHasMethod = *aSuccess = false; michael@0: *aResult = void_t(); michael@0: michael@0: if (mInvalidated) { michael@0: NS_WARNING("Calling AnswerGetProperty with an invalidated object!"); michael@0: return true; michael@0: } michael@0: michael@0: NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); michael@0: NS_ASSERTION(mType == LocalObject, "Bad type!"); michael@0: michael@0: if (!(mObject->_class && mObject->_class->hasProperty && michael@0: mObject->_class->hasMethod && mObject->_class->getProperty)) { michael@0: return true; michael@0: } michael@0: michael@0: PluginIdentifierChild::StackIdentifier stackID(aId); michael@0: NPIdentifier id = stackID->ToNPIdentifier(); michael@0: michael@0: *aHasProperty = mObject->_class->hasProperty(mObject, id); michael@0: *aHasMethod = mObject->_class->hasMethod(mObject, id); michael@0: michael@0: if (*aHasProperty) { michael@0: NPVariant result; michael@0: VOID_TO_NPVARIANT(result); michael@0: michael@0: if (!mObject->_class->getProperty(mObject, id, &result)) { michael@0: return true; michael@0: } michael@0: michael@0: Variant converted; michael@0: if ((*aSuccess = ConvertToRemoteVariant(result, converted, GetInstance(), michael@0: false))) { michael@0: DeferNPVariantLastRelease(&PluginModuleChild::sBrowserFuncs, &result); michael@0: *aResult = converted; michael@0: } michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectChild::AnswerSetProperty(PPluginIdentifierChild* aId, michael@0: const Variant& aValue, michael@0: bool* aSuccess) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (mInvalidated) { michael@0: NS_WARNING("Calling AnswerSetProperty with an invalidated object!"); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); michael@0: NS_ASSERTION(mType == LocalObject, "Bad type!"); michael@0: michael@0: if (!(mObject->_class && mObject->_class->hasProperty && michael@0: mObject->_class->setProperty)) { michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: PluginIdentifierChild::StackIdentifier stackID(aId); michael@0: NPIdentifier id = stackID->ToNPIdentifier(); michael@0: michael@0: if (!mObject->_class->hasProperty(mObject, id)) { michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: NPVariant converted; michael@0: ConvertToVariant(aValue, converted); michael@0: michael@0: if ((*aSuccess = mObject->_class->setProperty(mObject, id, &converted))) { michael@0: PluginModuleChild::sBrowserFuncs.releasevariantvalue(&converted); michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectChild::AnswerRemoveProperty(PPluginIdentifierChild* aId, michael@0: bool* aSuccess) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (mInvalidated) { michael@0: NS_WARNING("Calling AnswerRemoveProperty with an invalidated object!"); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); michael@0: NS_ASSERTION(mType == LocalObject, "Bad type!"); michael@0: michael@0: if (!(mObject->_class && mObject->_class->hasProperty && michael@0: mObject->_class->removeProperty)) { michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: PluginIdentifierChild::StackIdentifier stackID(aId); michael@0: NPIdentifier id = stackID->ToNPIdentifier(); michael@0: *aSuccess = mObject->_class->hasProperty(mObject, id) ? michael@0: mObject->_class->removeProperty(mObject, id) : michael@0: true; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectChild::AnswerEnumerate(InfallibleTArray* aProperties, michael@0: bool* aSuccess) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (mInvalidated) { michael@0: NS_WARNING("Calling AnswerEnumerate with an invalidated object!"); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); michael@0: NS_ASSERTION(mType == LocalObject, "Bad type!"); michael@0: michael@0: if (!(mObject->_class && mObject->_class->enumerate)) { michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: NPIdentifier* ids; michael@0: uint32_t idCount; michael@0: if (!mObject->_class->enumerate(mObject, &ids, &idCount)) { michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: aProperties->SetCapacity(idCount); michael@0: michael@0: for (uint32_t index = 0; index < idCount; index++) { michael@0: PluginIdentifierChild* id = static_cast(ids[index]); michael@0: aProperties->AppendElement(id); michael@0: } michael@0: michael@0: PluginModuleChild::sBrowserFuncs.memfree(ids); michael@0: *aSuccess = true; michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectChild::AnswerConstruct(const InfallibleTArray& aArgs, michael@0: Variant* aResult, michael@0: bool* aSuccess) michael@0: { michael@0: AssertPluginThread(); michael@0: michael@0: if (mInvalidated) { michael@0: NS_WARNING("Calling AnswerConstruct with an invalidated object!"); michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); michael@0: NS_ASSERTION(mType == LocalObject, "Bad type!"); michael@0: michael@0: if (!(mObject->_class && mObject->_class->construct)) { michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: AutoFallibleTArray convertedArgs; michael@0: uint32_t argCount = aArgs.Length(); michael@0: michael@0: if (!convertedArgs.SetLength(argCount)) { michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: for (uint32_t index = 0; index < argCount; index++) { michael@0: ConvertToVariant(aArgs[index], convertedArgs[index]); michael@0: } michael@0: michael@0: NPVariant result; michael@0: VOID_TO_NPVARIANT(result); michael@0: bool success = mObject->_class->construct(mObject, convertedArgs.Elements(), michael@0: argCount, &result); michael@0: michael@0: for (uint32_t index = 0; index < argCount; index++) { michael@0: PluginModuleChild::sBrowserFuncs.releasevariantvalue(&convertedArgs[index]); michael@0: } michael@0: michael@0: if (!success) { michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: Variant convertedResult; michael@0: success = ConvertToRemoteVariant(result, convertedResult, GetInstance(), michael@0: false); michael@0: michael@0: DeferNPVariantLastRelease(&PluginModuleChild::sBrowserFuncs, &result); michael@0: michael@0: if (!success) { michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: *aResult = convertedResult; michael@0: *aSuccess = true; michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectChild::RecvProtect() michael@0: { michael@0: NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); michael@0: NS_ASSERTION(mType == LocalObject, "Bad type!"); michael@0: michael@0: Protect(); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectChild::RecvUnprotect() michael@0: { michael@0: NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); michael@0: NS_ASSERTION(mType == LocalObject, "Bad type!"); michael@0: michael@0: Unprotect(); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectChild::Evaluate(NPString* aScript, michael@0: NPVariant* aResult) michael@0: { michael@0: nsDependentCString script(""); michael@0: if (aScript->UTF8Characters && aScript->UTF8Length) { michael@0: script.Rebind(aScript->UTF8Characters, aScript->UTF8Length); michael@0: } michael@0: michael@0: bool success; michael@0: Variant result; michael@0: CallNPN_Evaluate(script, &result, &success); michael@0: michael@0: if (!success) { michael@0: return false; michael@0: } michael@0: michael@0: ConvertToVariant(result, *aResult); michael@0: return true; michael@0: }