#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 { /** * 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: 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) friend struct IPC::ParamTraits; friend struct IPC::ParamTraits; friend struct IPC::ParamTraits; nsTArray mTupleElements; }; template <> template<> inline void IpdlTuple::IpdlTupleElement::Set(const nsDependentCSubstring& aParam) { mValue = MaybeVariantType(mozilla::VariantType(), aParam); } } // 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 */