diff options
Diffstat (limited to 'ipc/mscom/COMPtrHolder.h')
-rw-r--r-- | ipc/mscom/COMPtrHolder.h | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/ipc/mscom/COMPtrHolder.h b/ipc/mscom/COMPtrHolder.h new file mode 100644 index 000000000..88d372a27 --- /dev/null +++ b/ipc/mscom/COMPtrHolder.h @@ -0,0 +1,144 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_mscom_COMPtrHolder_h +#define mozilla_mscom_COMPtrHolder_h + +#include "mozilla/Attributes.h" +#include "mozilla/Move.h" +#include "mozilla/mscom/ProxyStream.h" +#include "mozilla/mscom/Ptr.h" + +namespace mozilla { +namespace mscom { + +template<typename Interface, const IID& _IID> +class COMPtrHolder +{ +public: + typedef ProxyUniquePtr<Interface> COMPtrType; + typedef COMPtrHolder<Interface, _IID> ThisType; + + COMPtrHolder() {} + + MOZ_IMPLICIT COMPtrHolder(decltype(nullptr)) + { + } + + explicit COMPtrHolder(COMPtrType&& aPtr) + : mPtr(Forward<COMPtrType>(aPtr)) + { + } + + Interface* Get() const + { + return mPtr.get(); + } + + MOZ_MUST_USE Interface* Release() + { + return mPtr.release(); + } + + void Set(COMPtrType&& aPtr) + { + mPtr = Forward<COMPtrType>(aPtr); + } + + COMPtrHolder(const COMPtrHolder& aOther) = delete; + + COMPtrHolder(COMPtrHolder&& aOther) + : mPtr(Move(aOther.mPtr)) + { + } + + // COMPtrHolder is eventually added as a member of a struct that is declared + // in IPDL. The generated C++ code for that IPDL struct includes copy + // constructors and assignment operators that assume that all members are + // copyable. I don't think that those copy constructors and operator= are + // actually used by any generated code, but they are made available. Since no + // move semantics are available, this terrible hack makes COMPtrHolder build + // when used as a member of an IPDL struct. + ThisType& operator=(const ThisType& aOther) + { + Set(Move(aOther.mPtr)); + return *this; + } + + ThisType& operator=(ThisType&& aOther) + { + Set(Move(aOther.mPtr)); + return *this; + } + + bool operator==(const ThisType& aOther) const + { + return mPtr == aOther.mPtr; + } + + bool IsNull() const + { + return !mPtr; + } + +private: + // This is mutable to facilitate the above operator= hack + mutable COMPtrType mPtr; +}; + +} // namespace mscom +} // namespace mozilla + +namespace IPC { + +template<typename Interface, const IID& _IID> +struct ParamTraits<mozilla::mscom::COMPtrHolder<Interface, _IID>> +{ + typedef mozilla::mscom::COMPtrHolder<Interface, _IID> paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + mozilla::mscom::ProxyStream proxyStream(_IID, aParam.Get()); + int bufLen; + const BYTE* buf = proxyStream.GetBuffer(bufLen); + MOZ_ASSERT(buf || !bufLen); + aMsg->WriteInt(bufLen); + aMsg->WriteBytes(reinterpret_cast<const char*>(buf), bufLen); + } + + static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult) + { + int length; + if (!aMsg->ReadLength(aIter, &length)) { + return false; + } + + mozilla::UniquePtr<BYTE[]> buf; + if (length) { + buf = mozilla::MakeUnique<BYTE[]>(length); + if (!aMsg->ReadBytesInto(aIter, buf.get(), length)) { + return false; + } + } + + mozilla::mscom::ProxyStream proxyStream(buf.get(), length); + if (!proxyStream.IsValid()) { + return false; + } + Interface* rawInterface = nullptr; + if (!proxyStream.GetInterface(_IID, (void**)&rawInterface)) { + return false; + } + typename paramType::COMPtrType ptr(rawInterface); + aResult->Set(mozilla::Move(ptr)); + return true; + } +}; + +} // namespace IPC + +#endif // mozilla_mscom_COMPtrHolder_h + |