gecko-dev/ipc/mscom/COMPtrHolder.h
Gabriele Svelto 15adf94f4d Bug 1348273 - Convert crash annotations into a machine-readable list of constants; r=ted.mielczarek,njn,dholbert,mak,cpearce,mcmanus,froydnj,Dexter,jrmuizel,jchen,jimm,bz,surkov
This introduces the machinery needed to generate crash annotations from a YAML
file. The relevant C++ functions are updated to take a typed enum. JavaScript
calls are unaffected but they will throw if the string argument does not
correspond to one of the known entries in the C++ enum. The existing whitelists
and blacklists of annotations are also generated from the YAML file and all
duplicate code related to them has been consolidated. Once written out to the
.extra file the annotations are converted in string form and are no different
than the existing ones.

All existing annotations have been included in the list (and some obsolete ones
have been removed) and all call sites have been updated including tests where
appropriate.

--HG--
extra : source : 4f6c43f2830701ec5552e08e3f1b06fe6d045860
2018-07-05 15:42:11 +02:00

233 lines
6.4 KiB
C++

/* -*- 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/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Move.h"
#include "mozilla/mscom/ProxyStream.h"
#include "mozilla/mscom/Ptr.h"
#if defined(MOZ_CONTENT_SANDBOX)
#include "mozilla/SandboxSettings.h"
#endif // defined(MOZ_CONTENT_SANDBOX)
#include "nsExceptionHandler.h"
namespace mozilla {
namespace mscom {
template<typename Interface, const IID& _IID>
class COMPtrHolder
{
public:
typedef ProxyUniquePtr<Interface> COMPtrType;
typedef COMPtrHolder<Interface, _IID> ThisType;
typedef typename detail::EnvironmentSelector<Interface>::Type EnvType;
COMPtrHolder() {}
MOZ_IMPLICIT COMPtrHolder(decltype(nullptr))
{
}
explicit COMPtrHolder(COMPtrType&& aPtr)
: mPtr(std::forward<COMPtrType>(aPtr))
{
}
COMPtrHolder(COMPtrType&& aPtr, const ActivationContext& aActCtx)
: mPtr(std::forward<COMPtrType>(aPtr))
, mActCtx(aActCtx)
{
}
Interface* Get() const
{
return mPtr.get();
}
MOZ_MUST_USE Interface* Release()
{
return mPtr.release();
}
void Set(COMPtrType&& aPtr)
{
mPtr = std::forward<COMPtrType>(aPtr);
}
void SetActCtx(const ActivationContext& aActCtx)
{
mActCtx = aActCtx;
}
#if defined(MOZ_CONTENT_SANDBOX)
// 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(PreservedStreamPtr aPtr) const
{
MOZ_ASSERT(!mMarshaledStream);
mMarshaledStream = std::move(aPtr);
}
PreservedStreamPtr GetPreservedStream()
{
return std::move(mMarshaledStream);
}
#endif // defined(MOZ_CONTENT_SANDBOX)
COMPtrHolder(const COMPtrHolder& aOther) = delete;
COMPtrHolder(COMPtrHolder&& aOther)
: mPtr(std::move(aOther.mPtr))
#if defined(MOZ_CONTENT_SANDBOX)
, mMarshaledStream(std::move(aOther.mMarshaledStream))
#endif // defined(MOZ_CONTENT_SANDBOX)
{
}
// 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(std::move(aOther.mPtr));
#if defined(MOZ_CONTENT_SANDBOX)
mMarshaledStream = std::move(aOther.mMarshaledStream);
#endif // defined(MOZ_CONTENT_SANDBOX)
return *this;
}
ThisType& operator=(ThisType&& aOther)
{
Set(std::move(aOther.mPtr));
#if defined(MOZ_CONTENT_SANDBOX)
mMarshaledStream = std::move(aOther.mMarshaledStream);
#endif // defined(MOZ_CONTENT_SANDBOX)
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;
ActivationContext mActCtx;
#if defined(MOZ_CONTENT_SANDBOX)
// This is mutable so that we may optionally store a reference to a marshaled
// stream to be cleaned up later via PreserveStream().
mutable PreservedStreamPtr mMarshaledStream;
#endif // defined(MOZ_CONTENT_SANDBOX)
};
} // 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)
{
#if defined(MOZ_CONTENT_SANDBOX)
static const bool sIsStreamPreservationNeeded =
XRE_IsParentProcess() && mozilla::GetEffectiveContentSandboxLevel() >= 3;
#else
const bool sIsStreamPreservationNeeded = false;
#endif // defined(MOZ_CONTENT_SANDBOX)
typename paramType::EnvType env;
mozilla::mscom::ProxyStreamFlags flags = sIsStreamPreservationNeeded ?
mozilla::mscom::ProxyStreamFlags::ePreservable :
mozilla::mscom::ProxyStreamFlags::eDefault;
mozilla::mscom::ProxyStream proxyStream(_IID, aParam.Get(), &env, flags);
int bufLen;
const BYTE* buf = proxyStream.GetBuffer(bufLen);
MOZ_ASSERT(buf || !bufLen);
aMsg->WriteInt(bufLen);
if (bufLen) {
aMsg->WriteBytes(reinterpret_cast<const char*>(buf), bufLen);
}
#if defined(MOZ_CONTENT_SANDBOX)
if (sIsStreamPreservationNeeded) {
/**
* When we're sending a ProxyStream from parent to content and the
* content sandboxing level is >= 3, content is unable to communicate
* its releasing of its reference to the proxied object. We preserve the
* marshaled proxy data here and later manually release it on content's
* behalf.
*/
aParam.PreserveStream(proxyStream.GetPreservedStream());
}
#endif // defined(MOZ_CONTENT_SANDBOX)
}
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;
}
}
typename paramType::EnvType env;
mozilla::mscom::ProxyStream proxyStream(_IID, buf.get(), length, &env);
if (!proxyStream.IsValid()) {
CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::ProxyStreamValid,
NS_LITERAL_CSTRING("false"));
return false;
}
typename paramType::COMPtrType ptr;
if (!proxyStream.GetInterface(mozilla::mscom::getter_AddRefs(ptr))) {
return false;
}
aResult->Set(std::move(ptr));
return true;
}
};
} // namespace IPC
#endif // mozilla_mscom_COMPtrHolder_h