Commit 153e6759 authored by Aaron Klotz's avatar Aaron Klotz
Browse files

Bug 1390652: Part 2 - Add support for TABLESTRONG marshaling to mscom::ProxyStream; r=jimm

MozReview-Commit-ID: 8hSvkULxF50
parent 73197406
Loading
Loading
Loading
Loading
+36 −17
Original line number Diff line number Diff line
@@ -60,10 +60,10 @@ public:
  // This method is const because we need to call it during IPC write, where
  // we are passed as a const argument. At higher sandboxing levels we need to
  // save this artifact from the serialization process for later deletion.
  void PreserveStream(RefPtr<IStream>&& aPtr) const
  void PreserveStream(PreservedStreamPtr aPtr) const
  {
    MOZ_ASSERT(!mMarshaledStream);
    mMarshaledStream = ToPreservedStreamPtr(Move(aPtr));
    mMarshaledStream = Move(aPtr);
  }

  PreservedStreamPtr GetPreservedStream()
@@ -76,6 +76,9 @@ public:

  COMPtrHolder(COMPtrHolder&& aOther)
    : mPtr(Move(aOther.mPtr))
#if defined(MOZ_CONTENT_SANDBOX)
    , mMarshaledStream(Move(aOther.mMarshaledStream))
#endif // defined(MOZ_CONTENT_SANDBOX)
  {
  }

@@ -89,12 +92,22 @@ public:
  ThisType& operator=(const ThisType& aOther)
  {
    Set(Move(aOther.mPtr));

#if defined(MOZ_CONTENT_SANDBOX)
    mMarshaledStream = Move(aOther.mMarshaledStream);
#endif // defined(MOZ_CONTENT_SANDBOX)

    return *this;
  }

  ThisType& operator=(ThisType&& aOther)
  {
    Set(Move(aOther.mPtr));

#if defined(MOZ_CONTENT_SANDBOX)
    mMarshaledStream = Move(aOther.mMarshaledStream);
#endif // defined(MOZ_CONTENT_SANDBOX)

    return *this;
  }

@@ -131,7 +144,18 @@ struct ParamTraits<mozilla::mscom::COMPtrHolder<Interface, _IID>>

  static void Write(Message* aMsg, const paramType& aParam)
  {
    mozilla::mscom::ProxyStream proxyStream(_IID, aParam.Get());
#if defined(MOZ_CONTENT_SANDBOX)
    static const bool sIsStreamPreservationNeeded =
      XRE_IsParentProcess() && mozilla::GetEffectiveContentSandboxLevel() >= 3;
#else
    const bool sIsStreamPreservationNeeded = false;
#endif // defined(MOZ_CONTENT_SANDBOX)

    mozilla::mscom::ProxyStreamFlags flags = sIsStreamPreservationNeeded ?
         mozilla::mscom::ProxyStreamFlags::ePreservable :
         mozilla::mscom::ProxyStreamFlags::eDefault;

    mozilla::mscom::ProxyStream proxyStream(_IID, aParam.Get(), flags);
    int bufLen;
    const BYTE* buf = proxyStream.GetBuffer(bufLen);
    MOZ_ASSERT(buf || !bufLen);
@@ -141,9 +165,6 @@ struct ParamTraits<mozilla::mscom::COMPtrHolder<Interface, _IID>>
    }

#if defined(MOZ_CONTENT_SANDBOX)
    if (XRE_IsParentProcess()) {
      static const bool sIsStreamPreservationNeeded =
        mozilla::GetEffectiveContentSandboxLevel() >= 3;
    if (sIsStreamPreservationNeeded) {
      /**
       * When we're sending a ProxyStream from parent to content and the
@@ -152,9 +173,7 @@ struct ParamTraits<mozilla::mscom::COMPtrHolder<Interface, _IID>>
       * marshaled proxy data here and later manually release it on content's
       * behalf.
       */
        RefPtr<IStream> stream(proxyStream.GetStream());
        aParam.PreserveStream(mozilla::Move(stream));
      }
      aParam.PreserveStream(proxyStream.GetPreservedStream());
    }
#endif // defined(MOZ_CONTENT_SANDBOX)
  }
+31 −8
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ ProxyStream::ProxyStream()
  : mGlobalLockedBuf(nullptr)
  , mHGlobal(nullptr)
  , mBufSize(0)
  , mPreserveStream(false)
{
}

@@ -36,6 +37,7 @@ ProxyStream::ProxyStream(REFIID aIID, const BYTE* aInitBuf,
  : mGlobalLockedBuf(nullptr)
  , mHGlobal(nullptr)
  , mBufSize(aInitBufSize)
  , mPreserveStream(false)
{
#if defined(MOZ_CRASHREPORTER)
  NS_NAMED_LITERAL_CSTRING(kCrashReportKey, "ProxyStreamUnmarshalStatus");
@@ -110,6 +112,7 @@ ProxyStream::ProxyStream(ProxyStream&& aOther)
  : mGlobalLockedBuf(nullptr)
  , mHGlobal(nullptr)
  , mBufSize(0)
  , mPreserveStream(false)
{
  *this = mozilla::Move(aOther);
}
@@ -135,6 +138,8 @@ ProxyStream::operator=(ProxyStream&& aOther)
  aOther.mBufSize = 0;

  mUnmarshaledProxy = Move(aOther.mUnmarshaledProxy);

  mPreserveStream = aOther.mPreserveStream;
  return *this;
}

@@ -145,6 +150,11 @@ ProxyStream::~ProxyStream()
    MOZ_ASSERT(!result && ::GetLastError() == NO_ERROR);
    // ::GlobalFree() is called implicitly when mStream is released
  }

  // If this assert triggers then we will be leaking a marshaled proxy!
  // Call GetPreservedStream to obtain a preservable stream and then save it
  // until the proxy is no longer needed.
  MOZ_ASSERT(!mPreserveStream);
}

const BYTE*
@@ -161,13 +171,20 @@ ProxyStream::GetBuffer(int& aReturnedBufSize) const
  return mGlobalLockedBuf;
}

RefPtr<IStream>
ProxyStream::GetStream() const
PreservedStreamPtr
ProxyStream::GetPreservedStream()
{
  MOZ_ASSERT(mStream);
  MOZ_ASSERT(mHGlobal);

  if (!mStream) {
  if (!mStream || !mPreserveStream) {
    return nullptr;
  }

  // Clone the stream so that the result has a distinct seek pointer.
  RefPtr<IStream> cloned;
  HRESULT hr = mStream->Clone(getter_AddRefs(cloned));
  if (FAILED(hr)) {
    return nullptr;
  }

@@ -175,10 +192,13 @@ ProxyStream::GetStream() const
  // the stream to be pointing to the beginning of the marshal data.
  LARGE_INTEGER pos;
  pos.QuadPart = 0LL;
  DebugOnly<HRESULT> hr = mStream->Seek(pos, STREAM_SEEK_SET, nullptr);
  MOZ_ASSERT(SUCCEEDED(hr));
  hr = cloned->Seek(pos, STREAM_SEEK_SET, nullptr);
  if (FAILED(hr)) {
    return nullptr;
  }

  return mStream;
  mPreserveStream = false;
  return ToPreservedStreamPtr(Move(cloned));
}

bool
@@ -203,10 +223,12 @@ ProxyStream::GetInterface(void** aOutInterface)
  return true;
}

ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject)
ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject,
                         ProxyStreamFlags aFlags)
  : mGlobalLockedBuf(nullptr)
  , mHGlobal(nullptr)
  , mBufSize(0)
  , mPreserveStream(aFlags & ProxyStreamFlags::ePreservable)
{
  if (!aObject) {
    return;
@@ -215,6 +237,7 @@ ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject)
  RefPtr<IStream> stream;
  HGLOBAL hglobal = NULL;
  int streamSize = 0;
  DWORD mshlFlags = mPreserveStream ? MSHLFLAGS_TABLESTRONG : MSHLFLAGS_NORMAL;

  HRESULT createStreamResult = S_OK;
  HRESULT marshalResult = S_OK;
@@ -229,7 +252,7 @@ ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject)
    }

    marshalResult = ::CoMarshalInterface(stream, aIID, aObject, MSHCTX_LOCAL,
                                         nullptr, MSHLFLAGS_NORMAL);
                                         nullptr, mshlFlags);
    if (FAILED(marshalResult)) {
      return;
    }
+16 −2
Original line number Diff line number Diff line
@@ -11,16 +11,28 @@

#include "mozilla/mscom/Ptr.h"
#include "mozilla/RefPtr.h"
#include "mozilla/TypedEnumBits.h"
#include "mozilla/UniquePtr.h"

namespace mozilla {
namespace mscom {

enum class ProxyStreamFlags : uint32_t
{
  eDefault = 0,
  // When ePreservable is set on a ProxyStream, its caller *must* call
  // GetPreservableStream() before the ProxyStream is destroyed.
  ePreservable = 1
};

MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(ProxyStreamFlags);

class ProxyStream final
{
public:
  ProxyStream();
  ProxyStream(REFIID aIID, IUnknown* aObject);
  ProxyStream(REFIID aIID, IUnknown* aObject,
              ProxyStreamFlags aFlags = ProxyStreamFlags::eDefault);
  ProxyStream(REFIID aIID, const BYTE* aInitBuf, const int aInitBufSize);

  ~ProxyStream();
@@ -39,7 +51,8 @@ public:

  bool GetInterface(void** aOutInterface);
  const BYTE* GetBuffer(int& aReturnedBufSize) const;
  RefPtr<IStream> GetStream() const;

  PreservedStreamPtr GetPreservedStream();

  bool operator==(const ProxyStream& aOther) const
  {
@@ -52,6 +65,7 @@ private:
  HGLOBAL         mHGlobal;
  int             mBufSize;
  ProxyUniquePtr<IUnknown> mUnmarshaledProxy;
  bool            mPreserveStream;
};

} // namespace mscom
+6 −0
Original line number Diff line number Diff line
@@ -310,6 +310,12 @@ ToPreservedStreamPtr(RefPtr<IStream>&& aStream)
  return PreservedStreamPtr(aStream.forget().take());
}

inline PreservedStreamPtr
ToPreservedStreamPtr(already_AddRefed<IStream>& aStream)
{
  return PreservedStreamPtr(aStream.take());
}

template <typename T, typename Deleter>
inline detail::UniquePtrGetterAddRefs<T, Deleter>
getter_AddRefs(UniquePtr<T, Deleter>& aSmartPtr)