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 "PluginScriptableObjectParent.h" michael@0: michael@0: #include "mozilla/DebugOnly.h" michael@0: #include "mozilla/plugins/PluginIdentifierParent.h" michael@0: #include "mozilla/unused.h" michael@0: #include "nsCxPusher.h" michael@0: #include "nsNPAPIPlugin.h" michael@0: #include "PluginScriptableObjectUtils.h" michael@0: michael@0: using namespace mozilla::plugins; michael@0: using namespace mozilla::plugins::parent; michael@0: michael@0: namespace { michael@0: michael@0: inline void michael@0: ReleaseVariant(NPVariant& aVariant, michael@0: PluginInstanceParent* aInstance) michael@0: { michael@0: const NPNetscapeFuncs* npn = GetNetscapeFuncs(aInstance); michael@0: if (npn) { michael@0: npn->releasevariantvalue(&aVariant); michael@0: } michael@0: } michael@0: michael@0: } // anonymous namespace michael@0: michael@0: // static michael@0: NPObject* michael@0: PluginScriptableObjectParent::ScriptableAllocate(NPP aInstance, michael@0: NPClass* aClass) michael@0: { michael@0: if (aClass != GetClass()) { michael@0: NS_ERROR("Huh?! Wrong class!"); michael@0: return nullptr; michael@0: } michael@0: michael@0: return new ParentNPObject(); michael@0: } michael@0: michael@0: // static michael@0: void michael@0: PluginScriptableObjectParent::ScriptableInvalidate(NPObject* aObject) michael@0: { michael@0: if (aObject->_class != GetClass()) { michael@0: NS_ERROR("Don't know what kind of object this is!"); michael@0: return; michael@0: } michael@0: michael@0: ParentNPObject* 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: // |object->parent| may be null already if the instance has gone away. michael@0: if (object->parent && !object->parent->CallInvalidate()) { michael@0: NS_ERROR("Failed to send message!"); michael@0: } michael@0: } michael@0: michael@0: // static michael@0: void michael@0: PluginScriptableObjectParent::ScriptableDeallocate(NPObject* aObject) michael@0: { michael@0: if (aObject->_class != GetClass()) { michael@0: NS_ERROR("Don't know what kind of object this is!"); michael@0: return; michael@0: } michael@0: michael@0: ParentNPObject* object = reinterpret_cast(aObject); michael@0: PluginScriptableObjectParent* 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: PluginScriptableObjectParent::ScriptableHasMethod(NPObject* aObject, michael@0: NPIdentifier aName) michael@0: { michael@0: if (aObject->_class != GetClass()) { michael@0: NS_ERROR("Don't know what kind of object this is!"); michael@0: return false; michael@0: } michael@0: michael@0: ParentNPObject* 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: if (!actor) { michael@0: return false; michael@0: } michael@0: michael@0: PluginIdentifierParent::StackIdentifier identifier(aObject, aName); michael@0: if (!identifier) { michael@0: return false; michael@0: } michael@0: michael@0: NS_ASSERTION(actor->Type() == Proxy, "Bad type!"); michael@0: michael@0: bool result; michael@0: if (!actor->CallHasMethod(identifier, &result)) { michael@0: NS_WARNING("Failed to send message!"); michael@0: return false; michael@0: } michael@0: michael@0: return result; michael@0: } michael@0: michael@0: // static michael@0: bool michael@0: PluginScriptableObjectParent::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: if (aObject->_class != GetClass()) { michael@0: NS_ERROR("Don't know what kind of object this is!"); michael@0: return false; michael@0: } michael@0: michael@0: ParentNPObject* 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: if (!actor) { michael@0: return false; michael@0: } michael@0: michael@0: PluginIdentifierParent::StackIdentifier identifier(aObject, aName); michael@0: if (!identifier) { michael@0: return false; michael@0: } michael@0: 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: if (!actor->CallInvoke(identifier, args, &remoteResult, michael@0: &success)) { michael@0: NS_WARNING("Failed to send message!"); michael@0: return false; michael@0: } michael@0: michael@0: if (!success) { michael@0: return false; michael@0: } michael@0: michael@0: if (!ConvertToVariant(remoteResult, *aResult, actor->GetInstance())) { michael@0: NS_WARNING("Failed to convert result!"); michael@0: return false; michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: // static michael@0: bool michael@0: PluginScriptableObjectParent::ScriptableInvokeDefault(NPObject* aObject, michael@0: const NPVariant* aArgs, michael@0: uint32_t aArgCount, michael@0: NPVariant* aResult) michael@0: { michael@0: if (aObject->_class != GetClass()) { michael@0: NS_ERROR("Don't know what kind of object this is!"); michael@0: return false; michael@0: } michael@0: michael@0: ParentNPObject* 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: if (!actor) { michael@0: return false; michael@0: } michael@0: 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: if (!actor->CallInvokeDefault(args, &remoteResult, &success)) { michael@0: NS_WARNING("Failed to send message!"); michael@0: return false; michael@0: } michael@0: michael@0: if (!success) { michael@0: return false; michael@0: } michael@0: michael@0: if (!ConvertToVariant(remoteResult, *aResult, actor->GetInstance())) { michael@0: NS_WARNING("Failed to convert result!"); michael@0: return false; michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: // static michael@0: bool michael@0: PluginScriptableObjectParent::ScriptableHasProperty(NPObject* aObject, michael@0: NPIdentifier aName) michael@0: { michael@0: if (aObject->_class != GetClass()) { michael@0: NS_ERROR("Don't know what kind of object this is!"); michael@0: return false; michael@0: } michael@0: michael@0: ParentNPObject* 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: if (!actor) { michael@0: return false; michael@0: } michael@0: michael@0: PluginIdentifierParent::StackIdentifier identifier(aObject, aName); michael@0: if (!identifier) { michael@0: return false; michael@0: } michael@0: michael@0: NS_ASSERTION(actor->Type() == Proxy, "Bad type!"); michael@0: michael@0: bool result; michael@0: if (!actor->CallHasProperty(identifier, &result)) { michael@0: NS_WARNING("Failed to send message!"); michael@0: return false; michael@0: } michael@0: michael@0: return result; michael@0: } michael@0: michael@0: // static michael@0: bool michael@0: PluginScriptableObjectParent::ScriptableGetProperty(NPObject* aObject, michael@0: NPIdentifier aName, michael@0: NPVariant* aResult) michael@0: { michael@0: // See GetPropertyHelper below. michael@0: NS_NOTREACHED("Shouldn't ever call this directly!"); michael@0: return false; michael@0: } michael@0: michael@0: // static michael@0: bool michael@0: PluginScriptableObjectParent::ScriptableSetProperty(NPObject* aObject, michael@0: NPIdentifier aName, michael@0: const NPVariant* aValue) michael@0: { michael@0: if (aObject->_class != GetClass()) { michael@0: NS_ERROR("Don't know what kind of object this is!"); michael@0: return false; michael@0: } michael@0: michael@0: ParentNPObject* 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: if (!actor) { michael@0: return false; michael@0: } michael@0: michael@0: PluginIdentifierParent::StackIdentifier identifier(aObject, aName); michael@0: if (!identifier) { michael@0: return false; michael@0: } michael@0: 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: if (!actor->CallSetProperty(identifier, value, &success)) { michael@0: NS_WARNING("Failed to send message!"); michael@0: return false; michael@0: } michael@0: michael@0: return success; michael@0: } michael@0: michael@0: // static michael@0: bool michael@0: PluginScriptableObjectParent::ScriptableRemoveProperty(NPObject* aObject, michael@0: NPIdentifier aName) michael@0: { michael@0: if (aObject->_class != GetClass()) { michael@0: NS_ERROR("Don't know what kind of object this is!"); michael@0: return false; michael@0: } michael@0: michael@0: ParentNPObject* 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: if (!actor) { michael@0: return false; michael@0: } michael@0: michael@0: PluginIdentifierParent::StackIdentifier identifier(aObject, aName); michael@0: if (!identifier) { michael@0: return false; michael@0: } michael@0: michael@0: NS_ASSERTION(actor->Type() == Proxy, "Bad type!"); michael@0: michael@0: bool success; michael@0: if (!actor->CallRemoveProperty(identifier, &success)) { michael@0: NS_WARNING("Failed to send message!"); michael@0: return false; michael@0: } michael@0: michael@0: return success; michael@0: } michael@0: michael@0: // static michael@0: bool michael@0: PluginScriptableObjectParent::ScriptableEnumerate(NPObject* aObject, michael@0: NPIdentifier** aIdentifiers, michael@0: uint32_t* aCount) michael@0: { michael@0: if (aObject->_class != GetClass()) { michael@0: NS_ERROR("Don't know what kind of object this is!"); michael@0: return false; michael@0: } michael@0: michael@0: ParentNPObject* 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: if (!actor) { michael@0: return false; michael@0: } michael@0: michael@0: NS_ASSERTION(actor->Type() == Proxy, "Bad type!"); michael@0: michael@0: const NPNetscapeFuncs* npn = GetNetscapeFuncs(aObject); michael@0: if (!npn) { michael@0: NS_ERROR("No netscape funcs!"); michael@0: return false; michael@0: } michael@0: michael@0: AutoInfallibleTArray identifiers; michael@0: bool success; michael@0: if (!actor->CallEnumerate(&identifiers, &success)) { michael@0: NS_WARNING("Failed to send message!"); michael@0: return false; michael@0: } 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 = (NPIdentifier*)npn->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: PluginIdentifierParent* id = michael@0: static_cast(identifiers[index]); michael@0: (*aIdentifiers)[index] = id->ToNPIdentifier(); michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: // static michael@0: bool michael@0: PluginScriptableObjectParent::ScriptableConstruct(NPObject* aObject, michael@0: const NPVariant* aArgs, michael@0: uint32_t aArgCount, michael@0: NPVariant* aResult) michael@0: { michael@0: if (aObject->_class != GetClass()) { michael@0: NS_ERROR("Don't know what kind of object this is!"); michael@0: return false; michael@0: } michael@0: michael@0: ParentNPObject* 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: if (!actor) { michael@0: return false; michael@0: } michael@0: 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: if (!actor->CallConstruct(args, &remoteResult, &success)) { michael@0: NS_WARNING("Failed to send message!"); michael@0: return false; michael@0: } michael@0: michael@0: if (!success) { michael@0: return false; michael@0: } michael@0: michael@0: if (!ConvertToVariant(remoteResult, *aResult, actor->GetInstance())) { michael@0: NS_WARNING("Failed to convert result!"); michael@0: return false; michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: const NPClass PluginScriptableObjectParent::sNPClass = { michael@0: NP_CLASS_STRUCT_VERSION, michael@0: PluginScriptableObjectParent::ScriptableAllocate, michael@0: PluginScriptableObjectParent::ScriptableDeallocate, michael@0: PluginScriptableObjectParent::ScriptableInvalidate, michael@0: PluginScriptableObjectParent::ScriptableHasMethod, michael@0: PluginScriptableObjectParent::ScriptableInvoke, michael@0: PluginScriptableObjectParent::ScriptableInvokeDefault, michael@0: PluginScriptableObjectParent::ScriptableHasProperty, michael@0: PluginScriptableObjectParent::ScriptableGetProperty, michael@0: PluginScriptableObjectParent::ScriptableSetProperty, michael@0: PluginScriptableObjectParent::ScriptableRemoveProperty, michael@0: PluginScriptableObjectParent::ScriptableEnumerate, michael@0: PluginScriptableObjectParent::ScriptableConstruct michael@0: }; michael@0: michael@0: PluginScriptableObjectParent::PluginScriptableObjectParent( michael@0: ScriptableObjectType aType) michael@0: : mInstance(nullptr), michael@0: mObject(nullptr), michael@0: mProtectCount(0), michael@0: mType(aType) michael@0: { michael@0: } michael@0: michael@0: PluginScriptableObjectParent::~PluginScriptableObjectParent() michael@0: { michael@0: if (mObject) { 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: GetInstance()->GetNPNIface()->releaseobject(mObject); michael@0: } michael@0: } michael@0: } michael@0: michael@0: void michael@0: PluginScriptableObjectParent::InitializeProxy() michael@0: { michael@0: NS_ASSERTION(mType == Proxy, "Bad type!"); michael@0: NS_ASSERTION(!mObject, "Calling Initialize more than once!"); 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 (!mInstance->RegisterNPObjectForActor(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: PluginScriptableObjectParent::InitializeLocal(NPObject* aObject) michael@0: { michael@0: NS_ASSERTION(mType == LocalObject, "Bad type!"); michael@0: NS_ASSERTION(!(mInstance && mObject), "Calling Initialize more than once!"); michael@0: michael@0: mInstance = static_cast(Manager()); michael@0: NS_ASSERTION(mInstance, "Null manager?!"); michael@0: michael@0: mInstance->GetNPNIface()->retainobject(aObject); michael@0: michael@0: NS_ASSERTION(!mProtectCount, "Should be zero!"); michael@0: mProtectCount++; michael@0: michael@0: if (!mInstance->RegisterNPObjectForActor(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: PluginScriptableObjectParent::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: const NPNetscapeFuncs* npn = GetNetscapeFuncs(mInstance); michael@0: michael@0: NPObject* npobject = npn->createobject(mInstance->GetNPP(), michael@0: const_cast(GetClass())); 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: ParentNPObject* 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, "BrowserNPObject"); michael@0: michael@0: object->parent = const_cast(this); michael@0: return object; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectParent::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: InitializeProxy(); michael@0: NS_ASSERTION(mObject, "Initialize failed!"); michael@0: michael@0: if (!SendProtect()) { michael@0: NS_WARNING("Failed to send message!"); michael@0: return false; michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: NPObject* michael@0: PluginScriptableObjectParent::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: PluginScriptableObjectParent::Protect() michael@0: { michael@0: NS_ASSERTION(mObject, "No object!"); michael@0: NS_ASSERTION(mProtectCount >= 0, "Negative protect count?!"); michael@0: michael@0: if (mType == LocalObject) { michael@0: ++mProtectCount; michael@0: } michael@0: } michael@0: michael@0: void michael@0: PluginScriptableObjectParent::Unprotect() michael@0: { michael@0: NS_ASSERTION(mObject, "No object!"); michael@0: NS_ASSERTION(mProtectCount >= 0, "Negative protect count?!"); michael@0: michael@0: if (mType == LocalObject) { michael@0: if (--mProtectCount == 0) { michael@0: unused << PluginScriptableObjectParent::Send__delete__(this); michael@0: } michael@0: } michael@0: } michael@0: michael@0: void michael@0: PluginScriptableObjectParent::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: PluginInstanceParent* instance = GetInstance(); michael@0: NS_ASSERTION(instance, "Must have an instance!"); michael@0: michael@0: instance->UnregisterNPObject(mObject); michael@0: mObject = nullptr; michael@0: michael@0: unused << SendUnprotect(); michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectParent::AnswerHasMethod(PPluginIdentifierParent* aId, michael@0: bool* aHasMethod) michael@0: { michael@0: if (!mObject) { 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: PluginInstanceParent* instance = GetInstance(); michael@0: if (!instance) { michael@0: NS_ERROR("No instance?!"); michael@0: *aHasMethod = false; michael@0: return true; michael@0: } michael@0: michael@0: const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); michael@0: if (!npn) { michael@0: NS_ERROR("No netscape funcs?!"); michael@0: *aHasMethod = false; michael@0: return true; michael@0: } michael@0: michael@0: PluginIdentifierParent* id = static_cast(aId); michael@0: *aHasMethod = npn->hasmethod(instance->GetNPP(), mObject, id->ToNPIdentifier()); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectParent::AnswerInvoke(PPluginIdentifierParent* aId, michael@0: const InfallibleTArray& aArgs, michael@0: Variant* aResult, michael@0: bool* aSuccess) michael@0: { michael@0: if (!mObject) { 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: PluginInstanceParent* instance = GetInstance(); michael@0: if (!instance) { michael@0: NS_ERROR("No instance?!"); michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); michael@0: if (!npn) { michael@0: NS_ERROR("No netscape funcs?!"); 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: if (!ConvertToVariant(aArgs[index], convertedArgs[index], instance)) { michael@0: // Don't leak things we've already converted! michael@0: while (index-- > 0) { michael@0: ReleaseVariant(convertedArgs[index], instance); michael@0: } michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: } michael@0: michael@0: PluginIdentifierParent* id = static_cast(aId); michael@0: NPVariant result; michael@0: bool success = npn->invoke(instance->GetNPP(), mObject, id->ToNPIdentifier(), michael@0: convertedArgs.Elements(), argCount, &result); michael@0: michael@0: for (uint32_t index = 0; index < argCount; index++) { michael@0: ReleaseVariant(convertedArgs[index], instance); 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: michael@0: DeferNPVariantLastRelease(npn, &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: PluginScriptableObjectParent::AnswerInvokeDefault(const InfallibleTArray& aArgs, michael@0: Variant* aResult, michael@0: bool* aSuccess) michael@0: { michael@0: if (!mObject) { 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: PluginInstanceParent* instance = GetInstance(); michael@0: if (!instance) { michael@0: NS_ERROR("No instance?!"); michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); michael@0: if (!npn) { michael@0: NS_ERROR("No netscape funcs?!"); 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: if (!ConvertToVariant(aArgs[index], convertedArgs[index], instance)) { michael@0: // Don't leak things we've already converted! michael@0: while (index-- > 0) { michael@0: ReleaseVariant(convertedArgs[index], instance); michael@0: } michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: } michael@0: michael@0: NPVariant result; michael@0: bool success = npn->invokeDefault(instance->GetNPP(), mObject, michael@0: convertedArgs.Elements(), argCount, michael@0: &result); michael@0: michael@0: for (uint32_t index = 0; index < argCount; index++) { michael@0: ReleaseVariant(convertedArgs[index], instance); 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: michael@0: DeferNPVariantLastRelease(npn, &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: PluginScriptableObjectParent::AnswerHasProperty(PPluginIdentifierParent* aId, michael@0: bool* aHasProperty) michael@0: { michael@0: if (!mObject) { 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: PluginInstanceParent* instance = GetInstance(); michael@0: if (!instance) { michael@0: NS_ERROR("No instance?!"); michael@0: *aHasProperty = false; michael@0: return true; michael@0: } michael@0: michael@0: const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); michael@0: if (!npn) { michael@0: NS_ERROR("No netscape funcs?!"); michael@0: *aHasProperty = false; michael@0: return true; michael@0: } michael@0: michael@0: PluginIdentifierParent* id = static_cast(aId); michael@0: *aHasProperty = npn->hasproperty(instance->GetNPP(), mObject, michael@0: id->ToNPIdentifier()); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectParent::AnswerGetParentProperty( michael@0: PPluginIdentifierParent* aId, michael@0: Variant* aResult, michael@0: bool* aSuccess) michael@0: { michael@0: if (!mObject) { michael@0: NS_WARNING("Calling AnswerGetProperty 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: PluginInstanceParent* instance = GetInstance(); michael@0: if (!instance) { michael@0: NS_ERROR("No instance?!"); michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); michael@0: if (!npn) { michael@0: NS_ERROR("No netscape funcs?!"); michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: PluginIdentifierParent* id = static_cast(aId); michael@0: NPVariant result; michael@0: if (!npn->getproperty(instance->GetNPP(), mObject, id->ToNPIdentifier(), michael@0: &result)) { michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: Variant converted; michael@0: if ((*aSuccess = ConvertToRemoteVariant(result, converted, instance))) { michael@0: DeferNPVariantLastRelease(npn, &result); michael@0: *aResult = converted; michael@0: } michael@0: else { michael@0: *aResult = void_t(); michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectParent::AnswerSetProperty(PPluginIdentifierParent* aId, michael@0: const Variant& aValue, michael@0: bool* aSuccess) michael@0: { michael@0: if (!mObject) { 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: PluginInstanceParent* instance = GetInstance(); michael@0: if (!instance) { michael@0: NS_ERROR("No instance?!"); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); michael@0: if (!npn) { michael@0: NS_ERROR("No netscape funcs?!"); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: NPVariant converted; michael@0: if (!ConvertToVariant(aValue, converted, instance)) { michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: PluginIdentifierParent* id = static_cast(aId); michael@0: if ((*aSuccess = npn->setproperty(instance->GetNPP(), mObject, michael@0: id->ToNPIdentifier(), &converted))) { michael@0: ReleaseVariant(converted, instance); michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectParent::AnswerRemoveProperty(PPluginIdentifierParent* aId, michael@0: bool* aSuccess) michael@0: { michael@0: if (!mObject) { 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: PluginInstanceParent* instance = GetInstance(); michael@0: if (!instance) { michael@0: NS_ERROR("No instance?!"); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); michael@0: if (!npn) { michael@0: NS_ERROR("No netscape funcs?!"); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: PluginIdentifierParent* id = static_cast(aId); michael@0: *aSuccess = npn->removeproperty(instance->GetNPP(), mObject, michael@0: id->ToNPIdentifier()); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectParent::AnswerEnumerate(InfallibleTArray* aProperties, michael@0: bool* aSuccess) michael@0: { michael@0: if (!mObject) { 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: PluginInstanceParent* instance = GetInstance(); michael@0: if (!instance) { michael@0: NS_ERROR("No instance?!"); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); michael@0: if (!npn) { michael@0: NS_WARNING("No netscape funcs?!"); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: NPIdentifier* ids; michael@0: uint32_t idCount; michael@0: if (!npn->enumerate(instance->GetNPP(), mObject, &ids, &idCount)) { michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: aProperties->SetCapacity(idCount); michael@0: michael@0: mozilla::AutoSafeJSContext cx; michael@0: for (uint32_t index = 0; index < idCount; index++) { michael@0: // Because of GC hazards, all identifiers returned from enumerate michael@0: // must be made permanent. michael@0: if (_identifierisstring(ids[index])) { michael@0: JS::Rooted str(cx, NPIdentifierToString(ids[index])); michael@0: if (!JS_StringHasBeenInterned(cx, str)) { michael@0: DebugOnly str2 = JS_InternJSString(cx, str); michael@0: NS_ASSERTION(str2 == str, "Interning a JS string which is currently an ID should return itself."); michael@0: } michael@0: } michael@0: PluginIdentifierParent* id = michael@0: instance->Module()->GetIdentifierForNPIdentifier(instance->GetNPP(), ids[index]); michael@0: aProperties->AppendElement(id); michael@0: NS_ASSERTION(!id->IsTemporary(), "Should only have permanent identifiers!"); michael@0: } michael@0: michael@0: npn->memfree(ids); michael@0: *aSuccess = true; michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginScriptableObjectParent::AnswerConstruct(const InfallibleTArray& aArgs, michael@0: Variant* aResult, michael@0: bool* aSuccess) michael@0: { michael@0: if (!mObject) { 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: PluginInstanceParent* instance = GetInstance(); michael@0: if (!instance) { michael@0: NS_ERROR("No instance?!"); michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); michael@0: if (!npn) { michael@0: NS_ERROR("No netscape funcs?!"); 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: if (!ConvertToVariant(aArgs[index], convertedArgs[index], instance)) { michael@0: // Don't leak things we've already converted! michael@0: while (index-- > 0) { michael@0: ReleaseVariant(convertedArgs[index], instance); michael@0: } michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: } michael@0: michael@0: NPVariant result; michael@0: bool success = npn->construct(instance->GetNPP(), mObject, michael@0: convertedArgs.Elements(), argCount, &result); michael@0: michael@0: for (uint32_t index = 0; index < argCount; index++) { michael@0: ReleaseVariant(convertedArgs[index], instance); 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, instance); michael@0: michael@0: DeferNPVariantLastRelease(npn, &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: PluginScriptableObjectParent::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: PluginScriptableObjectParent::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: PluginScriptableObjectParent::AnswerNPN_Evaluate(const nsCString& aScript, michael@0: Variant* aResult, michael@0: bool* aSuccess) michael@0: { michael@0: PluginInstanceParent* instance = GetInstance(); michael@0: if (!instance) { michael@0: NS_ERROR("No instance?!"); michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); michael@0: if (!npn) { michael@0: NS_ERROR("No netscape funcs?!"); michael@0: *aResult = void_t(); michael@0: *aSuccess = false; michael@0: return true; michael@0: } michael@0: michael@0: NPString script = { aScript.get(), aScript.Length() }; michael@0: michael@0: NPVariant result; michael@0: bool success = npn->evaluate(instance->GetNPP(), mObject, &script, &result); 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, instance); michael@0: michael@0: DeferNPVariantLastRelease(npn, &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: PluginScriptableObjectParent::GetPropertyHelper(NPIdentifier aName, michael@0: bool* aHasProperty, michael@0: bool* aHasMethod, michael@0: NPVariant* aResult) michael@0: { michael@0: NS_ASSERTION(Type() == Proxy, "Bad type!"); michael@0: michael@0: ParentNPObject* object = static_cast(mObject); 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: PluginIdentifierParent::StackIdentifier identifier(GetInstance(), aName); michael@0: if (!identifier) { michael@0: return false; michael@0: } michael@0: michael@0: bool hasProperty, hasMethod, success; michael@0: Variant result; michael@0: if (!CallGetChildProperty(identifier, &hasProperty, &hasMethod, &result, michael@0: &success)) { michael@0: return false; michael@0: } michael@0: michael@0: if (!success) { michael@0: return false; michael@0: } michael@0: michael@0: if (!ConvertToVariant(result, *aResult, GetInstance())) { michael@0: NS_WARNING("Failed to convert result!"); michael@0: return false; michael@0: } michael@0: michael@0: *aHasProperty = hasProperty; michael@0: *aHasMethod = hasMethod; michael@0: return true; michael@0: }