#ifndef dom_plugins_ipc_ipdltuple_h #define dom_plugins_ipc_ipdltuple_h #include "mozilla/plugins/FunctionBrokerIPCUtils.h" #include "mozilla/Variant.h" namespace mozilla { namespace plugins { // The stuff in this "internal" namespace used to be inside the IpdlTuple // class, but that prevented the DECLARE_USE_COPY_CONSTRUCTORS that is // needed on the IpdlTupleElement struct. Without this, nsTArray can end // up using a move constructor on this struct, which is not memmovable on // Windows. namespace internal { struct InvalidType {}; // Like Variant but with a default constructor. template struct MaybeVariant { public: MaybeVariant() : mValue(InvalidType()) {} MaybeVariant(MaybeVariant&& o) : mValue(std::move(o.mValue)) {} template void Set(const Param& aParam) { mValue = mozilla::AsVariant(aParam); } typedef mozilla::Variant MaybeVariantType; MaybeVariantType& GetVariant() { return mValue; } const MaybeVariantType& GetVariant() const { return mValue; } private: MaybeVariantType mValue; }; #if defined(XP_WIN) typedef MaybeVariant IpdlTupleElement; #else typedef MaybeVariant IpdlTupleElement; #endif // defined(XP_WIN) } // namespace internal } // namespace plugins } // namespace mozilla DECLARE_USE_COPY_CONSTRUCTORS(mozilla::plugins::internal::IpdlTupleElement) namespace mozilla { namespace plugins { /** * IpdlTuple is used by automatic function brokering to pass parameter * lists for brokered functions. It supports a limited set of types * (see IpdlTuple::IpdlTupleElement). */ class IpdlTuple { public: uint32_t NumElements() const { return mTupleElements.Length(); } template EltType* Element(uint32_t index) { if ((index >= mTupleElements.Length()) || !mTupleElements[index].GetVariant().is()) { return nullptr; } return &mTupleElements[index].GetVariant().as(); } template const EltType* Element(uint32_t index) const { return const_cast(this)->Element(index); } template void AddElement(const EltType& aElt) { IpdlTupleElement* newEntry = mTupleElements.AppendElement(); newEntry->Set(aElt); } private: typedef mozilla::plugins::internal::InvalidType InvalidType; typedef mozilla::plugins::internal::IpdlTupleElement IpdlTupleElement; friend struct IPC::ParamTraits; friend struct IPC::ParamTraits; friend struct IPC::ParamTraits; nsTArray mTupleElements; }; namespace internal { template <> template <> inline void IpdlTupleElement::Set( const nsDependentCSubstring& aParam) { mValue = MaybeVariantType(mozilla::VariantType(), aParam); } } // namespace internal } // namespace plugins } // namespace mozilla namespace IPC { using namespace mozilla::plugins; template <> struct ParamTraits { typedef IpdlTuple paramType; static void Write(Message* aMsg, const paramType& aParam) { WriteParam(aMsg, aParam.mTupleElements); } static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aParam) { return ReadParam(aMsg, aIter, &aParam->mTupleElements); } static void Log(const paramType& aParam, std::wstring* aLog) { LogParam(aParam.mTupleElements, aLog); } }; template <> struct ParamTraits { typedef IpdlTuple::IpdlTupleElement paramType; static void Write(Message* aMsg, const paramType& aParam) { MOZ_RELEASE_ASSERT(!aParam.GetVariant().is()); WriteParam(aMsg, aParam.GetVariant()); } static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aParam) { bool ret = ReadParam(aMsg, aIter, &aParam->GetVariant()); MOZ_RELEASE_ASSERT(!aParam->GetVariant().is()); return ret; } struct LogMatcher { explicit LogMatcher(std::wstring* aLog) : mLog(aLog) {} template void match(const EntryType& aParam) { LogParam(aParam, mLog); } private: std::wstring* mLog; }; static void Log(const paramType& aParam, std::wstring* aLog) { aParam.GetVariant().match(LogMatcher(aLog)); } }; template <> struct ParamTraits { typedef IpdlTuple::InvalidType paramType; static void Write(Message* aMsg, const paramType& aParam) { MOZ_ASSERT_UNREACHABLE("Attempt to serialize an invalid tuple element"); } static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aParam) { MOZ_ASSERT_UNREACHABLE("Attempt to deserialize an invalid tuple element"); return false; } static void Log(const paramType& aParam, std::wstring* aLog) { aLog->append(L""); } }; } // namespace IPC #endif /* dom_plugins_ipc_ipdltuple_h */