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: #ifndef dom_plugins_PluginScriptableObjectUtils_h michael@0: #define dom_plugins_PluginScriptableObjectUtils_h michael@0: michael@0: #include "PluginModuleParent.h" michael@0: #include "PluginModuleChild.h" michael@0: #include "PluginInstanceParent.h" michael@0: #include "PluginInstanceChild.h" michael@0: #include "PluginScriptableObjectParent.h" michael@0: #include "PluginScriptableObjectChild.h" michael@0: michael@0: #include "npapi.h" michael@0: #include "npfunctions.h" michael@0: #include "npruntime.h" michael@0: michael@0: #include "nsDebug.h" michael@0: michael@0: namespace mozilla { michael@0: namespace plugins { michael@0: michael@0: inline PluginInstanceParent* michael@0: GetInstance(NPObject* aObject) michael@0: { michael@0: NS_ASSERTION(aObject->_class == PluginScriptableObjectParent::GetClass(), michael@0: "Bad class!"); 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 nullptr; michael@0: } michael@0: if (!object->parent) { michael@0: return nullptr; michael@0: } michael@0: return object->parent->GetInstance(); michael@0: } michael@0: michael@0: inline NPObject* michael@0: NPObjectFromVariant(const Variant& aRemoteVariant) michael@0: { michael@0: switch (aRemoteVariant.type()) { michael@0: case Variant::TPPluginScriptableObjectParent: { michael@0: PluginScriptableObjectParent* actor = michael@0: const_cast( michael@0: reinterpret_cast( michael@0: aRemoteVariant.get_PPluginScriptableObjectParent())); michael@0: return actor->GetObject(true); michael@0: } michael@0: michael@0: case Variant::TPPluginScriptableObjectChild: { michael@0: PluginScriptableObjectChild* actor = michael@0: const_cast( michael@0: reinterpret_cast( michael@0: aRemoteVariant.get_PPluginScriptableObjectChild())); michael@0: return actor->GetObject(true); michael@0: } michael@0: michael@0: default: michael@0: NS_NOTREACHED("Shouldn't get here!"); michael@0: return nullptr; michael@0: } michael@0: } michael@0: michael@0: inline NPObject* michael@0: NPObjectFromVariant(const NPVariant& aVariant) michael@0: { michael@0: NS_ASSERTION(NPVARIANT_IS_OBJECT(aVariant), "Wrong variant type!"); michael@0: return NPVARIANT_TO_OBJECT(aVariant); michael@0: } michael@0: michael@0: inline const NPNetscapeFuncs* michael@0: GetNetscapeFuncs(PluginInstanceParent* aInstance) michael@0: { michael@0: PluginModuleParent* module = aInstance->Module(); michael@0: if (!module) { michael@0: NS_WARNING("Null module?!"); michael@0: return nullptr; michael@0: } michael@0: return module->GetNetscapeFuncs(); michael@0: } michael@0: michael@0: inline const NPNetscapeFuncs* michael@0: GetNetscapeFuncs(NPObject* aObject) michael@0: { michael@0: NS_ASSERTION(aObject->_class == PluginScriptableObjectParent::GetClass(), michael@0: "Bad class!"); michael@0: michael@0: PluginInstanceParent* instance = GetInstance(aObject); michael@0: if (!instance) { michael@0: return nullptr; michael@0: } michael@0: michael@0: return GetNetscapeFuncs(instance); michael@0: } michael@0: michael@0: inline void michael@0: ReleaseRemoteVariant(Variant& aVariant) michael@0: { michael@0: switch (aVariant.type()) { michael@0: case Variant::TPPluginScriptableObjectParent: { michael@0: PluginScriptableObjectParent* actor = michael@0: const_cast( michael@0: reinterpret_cast( michael@0: aVariant.get_PPluginScriptableObjectParent())); michael@0: actor->Unprotect(); michael@0: break; michael@0: } michael@0: michael@0: case Variant::TPPluginScriptableObjectChild: { michael@0: NS_ASSERTION(PluginModuleChild::current(), michael@0: "Should only be running in the child!"); michael@0: PluginScriptableObjectChild* actor = michael@0: const_cast( michael@0: reinterpret_cast( michael@0: aVariant.get_PPluginScriptableObjectChild())); michael@0: actor->Unprotect(); michael@0: break; michael@0: } michael@0: michael@0: default: michael@0: break; // Intentional fall-through for other variant types. michael@0: } michael@0: michael@0: aVariant = mozilla::void_t(); michael@0: } michael@0: michael@0: bool michael@0: ConvertToVariant(const Variant& aRemoteVariant, michael@0: NPVariant& aVariant, michael@0: PluginInstanceParent* aInstance = nullptr); michael@0: michael@0: template michael@0: bool michael@0: ConvertToRemoteVariant(const NPVariant& aVariant, michael@0: Variant& aRemoteVariant, michael@0: InstanceType* aInstance, michael@0: bool aProtectActors = false); michael@0: michael@0: class ProtectedVariant michael@0: { michael@0: public: michael@0: ProtectedVariant(const NPVariant& aVariant, michael@0: PluginInstanceParent* aInstance) michael@0: { michael@0: mOk = ConvertToRemoteVariant(aVariant, mVariant, aInstance, true); michael@0: } michael@0: michael@0: ProtectedVariant(const NPVariant& aVariant, michael@0: PluginInstanceChild* aInstance) michael@0: { michael@0: mOk = ConvertToRemoteVariant(aVariant, mVariant, aInstance, true); michael@0: } michael@0: michael@0: ~ProtectedVariant() { michael@0: ReleaseRemoteVariant(mVariant); michael@0: } michael@0: michael@0: bool IsOk() { michael@0: return mOk; michael@0: } michael@0: michael@0: operator const Variant&() { michael@0: return mVariant; michael@0: } michael@0: michael@0: private: michael@0: Variant mVariant; michael@0: bool mOk; michael@0: }; michael@0: michael@0: class ProtectedVariantArray michael@0: { michael@0: public: michael@0: ProtectedVariantArray(const NPVariant* aArgs, michael@0: uint32_t aCount, michael@0: PluginInstanceParent* aInstance) michael@0: : mUsingShadowArray(false) michael@0: { michael@0: for (uint32_t index = 0; index < aCount; index++) { michael@0: Variant* remoteVariant = mArray.AppendElement(); michael@0: if (!(remoteVariant && michael@0: ConvertToRemoteVariant(aArgs[index], *remoteVariant, aInstance, michael@0: true))) { michael@0: mOk = false; michael@0: return; michael@0: } michael@0: } michael@0: mOk = true; michael@0: } michael@0: michael@0: ProtectedVariantArray(const NPVariant* aArgs, michael@0: uint32_t aCount, michael@0: PluginInstanceChild* aInstance) michael@0: : mUsingShadowArray(false) michael@0: { michael@0: for (uint32_t index = 0; index < aCount; index++) { michael@0: Variant* remoteVariant = mArray.AppendElement(); michael@0: if (!(remoteVariant && michael@0: ConvertToRemoteVariant(aArgs[index], *remoteVariant, aInstance, michael@0: true))) { michael@0: mOk = false; michael@0: return; michael@0: } michael@0: } michael@0: mOk = true; michael@0: } michael@0: michael@0: ~ProtectedVariantArray() michael@0: { michael@0: InfallibleTArray& vars = EnsureAndGetShadowArray(); michael@0: uint32_t count = vars.Length(); michael@0: for (uint32_t index = 0; index < count; index++) { michael@0: ReleaseRemoteVariant(vars[index]); michael@0: } michael@0: } michael@0: michael@0: operator const InfallibleTArray&() michael@0: { michael@0: return EnsureAndGetShadowArray(); michael@0: } michael@0: michael@0: bool IsOk() michael@0: { michael@0: return mOk; michael@0: } michael@0: michael@0: private: michael@0: InfallibleTArray& michael@0: EnsureAndGetShadowArray() michael@0: { michael@0: if (!mUsingShadowArray) { michael@0: mShadowArray.SwapElements(mArray); michael@0: mUsingShadowArray = true; michael@0: } michael@0: return mShadowArray; michael@0: } michael@0: michael@0: // We convert the variants fallibly, but pass them to Call*() michael@0: // methods as an infallible array michael@0: nsTArray mArray; michael@0: InfallibleTArray mShadowArray; michael@0: bool mOk; michael@0: bool mUsingShadowArray; michael@0: }; michael@0: michael@0: template michael@0: struct ProtectedActorTraits michael@0: { michael@0: static bool Nullable(); michael@0: }; michael@0: michael@0: template > michael@0: class ProtectedActor michael@0: { michael@0: public: michael@0: ProtectedActor(ActorType* aActor) : mActor(aActor) michael@0: { michael@0: if (!Traits::Nullable()) { michael@0: NS_ASSERTION(mActor, "This should never be null!"); michael@0: } michael@0: } michael@0: michael@0: ~ProtectedActor() michael@0: { michael@0: if (Traits::Nullable() && !mActor) michael@0: return; michael@0: mActor->Unprotect(); michael@0: } michael@0: michael@0: ActorType* operator->() michael@0: { michael@0: return mActor; michael@0: } michael@0: michael@0: operator bool() michael@0: { michael@0: return !!mActor; michael@0: } michael@0: michael@0: private: michael@0: ActorType* mActor; michael@0: }; michael@0: michael@0: template<> michael@0: struct ProtectedActorTraits michael@0: { michael@0: static bool Nullable() { return true; } michael@0: }; michael@0: michael@0: template<> michael@0: struct ProtectedActorTraits michael@0: { michael@0: static bool Nullable() { return false; } michael@0: }; michael@0: michael@0: } /* namespace plugins */ michael@0: } /* namespace mozilla */ michael@0: michael@0: #include "PluginScriptableObjectUtils-inl.h" michael@0: michael@0: #endif /* dom_plugins_PluginScriptableObjectUtils_h */