зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1303060: ipc/mscom changes for handler and payload support; r=jimm
MozReview-Commit-ID: 13NFW1pgxix --HG-- extra : rebase_source : 18cc11d4c1dc62bc0ee428608f6cb57e32c4d0af
This commit is contained in:
Родитель
4f68f40cfe
Коммит
af5bd498da
|
@ -9,6 +9,9 @@
|
|||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <unknwn.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace mscom {
|
||||
|
||||
|
@ -44,8 +47,53 @@ private:
|
|||
RefCntT& mRefCnt;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
class InternalUnknown : public IUnknown
|
||||
{
|
||||
public:
|
||||
STDMETHODIMP QueryInterface(REFIID aIid, void** aOutInterface) override
|
||||
{
|
||||
return This()->InternalQueryInterface(aIid, aOutInterface);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) AddRef() override
|
||||
{
|
||||
return This()->InternalAddRef();
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) Release() override
|
||||
{
|
||||
return This()->InternalRelease();
|
||||
}
|
||||
|
||||
private:
|
||||
T* This()
|
||||
{
|
||||
return reinterpret_cast<T*>(reinterpret_cast<char*>(this) -
|
||||
offsetof(T, mInternalUnknown));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace mscom
|
||||
} // namespace mozilla
|
||||
|
||||
#define DECLARE_AGGREGATABLE(Type) \
|
||||
public: \
|
||||
STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override \
|
||||
{ return mOuter->QueryInterface(riid, ppv); } \
|
||||
STDMETHODIMP_(ULONG) AddRef() override \
|
||||
{ return mOuter->AddRef(); } \
|
||||
STDMETHODIMP_(ULONG) Release() override \
|
||||
{ return mOuter->Release(); } \
|
||||
protected: \
|
||||
STDMETHODIMP InternalQueryInterface(REFIID riid, void** ppv); \
|
||||
STDMETHODIMP_(ULONG) InternalAddRef(); \
|
||||
STDMETHODIMP_(ULONG) InternalRelease(); \
|
||||
friend class mozilla::mscom::detail::InternalUnknown<Type>; \
|
||||
mozilla::mscom::detail::InternalUnknown<Type> mInternalUnknown
|
||||
|
||||
#endif // mozilla_mscom_Aggregation_h
|
||||
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/* -*- 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_IHandlerPayload_h
|
||||
#define mozilla_mscom_IHandlerPayload_h
|
||||
|
||||
#include <objidl.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace mscom {
|
||||
|
||||
struct HandlerPayload
|
||||
{
|
||||
virtual STDMETHODIMP GetHandler(CLSID* aHandlerClsid) = 0;
|
||||
virtual STDMETHODIMP GetHandlerPayloadSize(REFIID aIid,
|
||||
IUnknown* aTarget,
|
||||
DWORD* aOutPayloadSize) = 0;
|
||||
virtual STDMETHODIMP WriteHandlerPayload(IStream* aStream, REFIID aIid,
|
||||
IUnknown* aTarget) = 0;
|
||||
virtual REFIID MarshalAs(REFIID aIid) = 0;
|
||||
};
|
||||
|
||||
struct IHandlerPayload : public IUnknown
|
||||
, public HandlerPayload
|
||||
{
|
||||
virtual STDMETHODIMP Clone(IHandlerPayload** aOutNewPayload) = 0;
|
||||
};
|
||||
|
||||
} // namespace mscom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_mscom_IHandlerPayload_h
|
|
@ -46,6 +46,7 @@ Interceptor::Interceptor(STAUniquePtr<IUnknown> aTarget, IInterceptorSink* aSink
|
|||
, mTarget(Move(aTarget))
|
||||
, mEventSink(aSink)
|
||||
, mMutex("mozilla::mscom::Interceptor::mMutex")
|
||||
, mStdMarshal(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(aSink);
|
||||
MOZ_ASSERT(!IsProxy(mTarget.get()));
|
||||
|
@ -67,6 +68,77 @@ Interceptor::~Interceptor()
|
|||
}
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Interceptor::GetClassForHandler(DWORD aDestContext, void* aDestContextPtr,
|
||||
CLSID* aHandlerClsid)
|
||||
{
|
||||
if (aDestContextPtr || !aHandlerClsid ||
|
||||
aDestContext == MSHCTX_DIFFERENTMACHINE) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
MOZ_ASSERT(mEventSink);
|
||||
return mEventSink->GetHandler(aHandlerClsid);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Interceptor::GetUnmarshalClass(REFIID riid, void* pv, DWORD dwDestContext,
|
||||
void* pvDestContext, DWORD mshlflags,
|
||||
CLSID* pCid)
|
||||
{
|
||||
return mStdMarshal->GetUnmarshalClass(riid, pv, dwDestContext, pvDestContext,
|
||||
mshlflags, pCid);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Interceptor::GetMarshalSizeMax(REFIID riid, void* pv, DWORD dwDestContext,
|
||||
void* pvDestContext, DWORD mshlflags,
|
||||
DWORD* pSize)
|
||||
{
|
||||
HRESULT hr = mStdMarshal->GetMarshalSizeMax(riid, pv, dwDestContext,
|
||||
pvDestContext, mshlflags, pSize);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
DWORD payloadSize = 0;
|
||||
hr = mEventSink->GetHandlerPayloadSize(riid, mTarget.get(), &payloadSize);
|
||||
*pSize += payloadSize;
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Interceptor::MarshalInterface(IStream* pStm, REFIID riid, void* pv,
|
||||
DWORD dwDestContext, void* pvDestContext,
|
||||
DWORD mshlflags)
|
||||
{
|
||||
HRESULT hr = mStdMarshal->MarshalInterface(pStm, riid, pv, dwDestContext,
|
||||
pvDestContext, mshlflags);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
return mEventSink->WriteHandlerPayload(pStm, riid, mTarget.get());
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Interceptor::UnmarshalInterface(IStream* pStm, REFIID riid,
|
||||
void** ppv)
|
||||
{
|
||||
return mStdMarshal->UnmarshalInterface(pStm, riid, ppv);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Interceptor::ReleaseMarshalData(IStream* pStm)
|
||||
{
|
||||
return mStdMarshal->ReleaseMarshalData(pStm);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Interceptor::DisconnectObject(DWORD dwReserved)
|
||||
{
|
||||
return mStdMarshal->DisconnectObject(dwReserved);
|
||||
}
|
||||
|
||||
Interceptor::MapEntry*
|
||||
Interceptor::Lookup(REFIID aIid)
|
||||
{
|
||||
|
@ -148,19 +220,22 @@ Interceptor::GetInterceptorForIID(REFIID aIid, void** aOutInterceptor)
|
|||
|
||||
if (aIid == IID_IUnknown) {
|
||||
// Special case: When we see IUnknown, we just provide a reference to this
|
||||
*aOutInterceptor = static_cast<IInterceptor*>(this);
|
||||
AddRef();
|
||||
RefPtr<IInterceptor> intcpt(this);
|
||||
intcpt.forget(aOutInterceptor);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
REFIID interceptorIid = mEventSink->MarshalAs(aIid);
|
||||
|
||||
RefPtr<IUnknown> unkInterceptor;
|
||||
IUnknown* interfaceForQILog = nullptr;
|
||||
|
||||
// (1) Check to see if we already have an existing interceptor for aIid.
|
||||
// (1) Check to see if we already have an existing interceptor for
|
||||
// interceptorIid.
|
||||
|
||||
{ // Scope for lock
|
||||
MutexAutoLock lock(mMutex);
|
||||
MapEntry* entry = Lookup(aIid);
|
||||
MapEntry* entry = Lookup(interceptorIid);
|
||||
if (entry) {
|
||||
unkInterceptor = entry->mInterceptor;
|
||||
interfaceForQILog = entry->mTargetInterface;
|
||||
|
@ -175,7 +250,7 @@ Interceptor::GetInterceptorForIID(REFIID aIid, void** aOutInterceptor)
|
|||
// was requested.
|
||||
InterceptorLog::QI(S_OK, mTarget.get(), aIid, interfaceForQILog);
|
||||
|
||||
return unkInterceptor->QueryInterface(aIid, aOutInterceptor);
|
||||
return unkInterceptor->QueryInterface(interceptorIid, aOutInterceptor);
|
||||
}
|
||||
|
||||
// (2) Obtain a new target interface.
|
||||
|
@ -188,7 +263,7 @@ Interceptor::GetInterceptorForIID(REFIID aIid, void** aOutInterceptor)
|
|||
|
||||
STAUniquePtr<IUnknown> targetInterface;
|
||||
IUnknown* rawTargetInterface = nullptr;
|
||||
hr = QueryInterfaceTarget(aIid, (void**)&rawTargetInterface);
|
||||
hr = QueryInterfaceTarget(interceptorIid, (void**)&rawTargetInterface);
|
||||
targetInterface.reset(rawTargetInterface);
|
||||
InterceptorLog::QI(hr, mTarget.get(), aIid, targetInterface.get());
|
||||
MOZ_ASSERT(SUCCEEDED(hr) || hr == E_NOINTERFACE);
|
||||
|
@ -206,7 +281,8 @@ Interceptor::GetInterceptorForIID(REFIID aIid, void** aOutInterceptor)
|
|||
RefPtr<IUnknown> kungFuDeathGrip(static_cast<IUnknown*>(
|
||||
static_cast<WeakReferenceSupport*>(this)));
|
||||
|
||||
hr = CreateInterceptor(aIid, kungFuDeathGrip, getter_AddRefs(unkInterceptor));
|
||||
hr = CreateInterceptor(interceptorIid, kungFuDeathGrip,
|
||||
getter_AddRefs(unkInterceptor));
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
@ -231,7 +307,7 @@ Interceptor::GetInterceptorForIID(REFIID aIid, void** aOutInterceptor)
|
|||
MutexAutoLock lock(mMutex);
|
||||
// We might have raced with another thread, so first check that we don't
|
||||
// already have an entry for this
|
||||
MapEntry* entry = Lookup(aIid);
|
||||
MapEntry* entry = Lookup(interceptorIid);
|
||||
if (entry && entry->mInterceptor) {
|
||||
unkInterceptor = entry->mInterceptor;
|
||||
} else {
|
||||
|
@ -239,13 +315,13 @@ Interceptor::GetInterceptorForIID(REFIID aIid, void** aOutInterceptor)
|
|||
// refcount for the target interface because we are just moving it into
|
||||
// the map and its refcounting might not be thread-safe.
|
||||
IUnknown* rawTargetInterface = targetInterface.release();
|
||||
mInterceptorMap.AppendElement(MapEntry(aIid,
|
||||
mInterceptorMap.AppendElement(MapEntry(interceptorIid,
|
||||
unkInterceptor,
|
||||
rawTargetInterface));
|
||||
}
|
||||
}
|
||||
|
||||
return unkInterceptor->QueryInterface(aIid, aOutInterceptor);
|
||||
return unkInterceptor->QueryInterface(interceptorIid, aOutInterceptor);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
|
@ -275,9 +351,63 @@ Interceptor::QueryInterface(REFIID riid, void** ppv)
|
|||
HRESULT
|
||||
Interceptor::ThreadSafeQueryInterface(REFIID aIid, IUnknown** aOutInterface)
|
||||
{
|
||||
if (aIid == IID_INoMarshal) {
|
||||
// This entire library is designed around marshaling, so there's no point
|
||||
// propagating this QI request all over the place!
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
if (aIid == IID_IStdMarshalInfo) {
|
||||
// Do not indicate that this interface is available unless we actually
|
||||
// support it. We'll check that by looking for a successful call to
|
||||
// IInterceptorSink::GetHandler()
|
||||
CLSID dummy;
|
||||
if (FAILED(mEventSink->GetHandler(&dummy))) {
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
RefPtr<IStdMarshalInfo> std(this);
|
||||
std.forget(aOutInterface);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (aIid == IID_IMarshal) {
|
||||
// Do not indicate that this interface is available unless we actually
|
||||
// support it. We'll check that by looking for a successful call to
|
||||
// IInterceptorSink::GetHandler()
|
||||
CLSID dummy;
|
||||
if (FAILED(mEventSink->GetHandler(&dummy))) {
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
if (!mStdMarshalUnk) {
|
||||
HRESULT hr = ::CoGetStdMarshalEx(static_cast<IWeakReferenceSource*>(this),
|
||||
SMEXF_SERVER,
|
||||
getter_AddRefs(mStdMarshalUnk));
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mStdMarshal) {
|
||||
HRESULT hr = mStdMarshalUnk->QueryInterface(IID_IMarshal,
|
||||
(void**)&mStdMarshal);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
// mStdMarshal is weak, so drop its refcount
|
||||
mStdMarshal->Release();
|
||||
}
|
||||
|
||||
RefPtr<IMarshal> marshal(this);
|
||||
marshal.forget(aOutInterface);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (aIid == IID_IInterceptor) {
|
||||
*aOutInterface = static_cast<IInterceptor*>(this);
|
||||
(*aOutInterface)->AddRef();
|
||||
RefPtr<IInterceptor> intcpt(this);
|
||||
intcpt.forget(aOutInterface);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,16 +4,18 @@
|
|||
* 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_interceptor_h
|
||||
#define mozilla_mscom_interceptor_h
|
||||
#ifndef mozilla_mscom_Interceptor_h
|
||||
#define mozilla_mscom_Interceptor_h
|
||||
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/mscom/IHandlerPayload.h"
|
||||
#include "mozilla/mscom/Ptr.h"
|
||||
#include "mozilla/mscom/WeakRef.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
#include <objidl.h>
|
||||
#include <callobj.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -24,6 +26,7 @@ DEFINE_GUID(IID_IInterceptorSink,
|
|||
0x8831eb53, 0xa937, 0x42bc, 0x99, 0x21, 0xb3, 0xe1, 0x12, 0x1f, 0xdf, 0x86);
|
||||
|
||||
struct IInterceptorSink : public ICallFrameEvents
|
||||
, public HandlerPayload
|
||||
{
|
||||
virtual STDMETHODIMP SetInterceptor(IWeakReference* aInterceptor) = 0;
|
||||
};
|
||||
|
@ -57,6 +60,8 @@ struct IInterceptor : public IUnknown
|
|||
* (the mscom::Interceptor we implement and control).
|
||||
*/
|
||||
class Interceptor final : public WeakReferenceSupport
|
||||
, public IStdMarshalInfo
|
||||
, public IMarshal
|
||||
, public IInterceptor
|
||||
{
|
||||
public:
|
||||
|
@ -68,6 +73,25 @@ public:
|
|||
STDMETHODIMP_(ULONG) AddRef() override;
|
||||
STDMETHODIMP_(ULONG) Release() override;
|
||||
|
||||
// IStdMarshalInfo
|
||||
STDMETHODIMP GetClassForHandler(DWORD aDestContext, void* aDestContextPtr,
|
||||
CLSID* aHandlerClsid) override;
|
||||
|
||||
// IMarshal
|
||||
STDMETHODIMP GetUnmarshalClass(REFIID riid, void* pv, DWORD dwDestContext,
|
||||
void* pvDestContext, DWORD mshlflags,
|
||||
CLSID* pCid) override;
|
||||
STDMETHODIMP GetMarshalSizeMax(REFIID riid, void* pv, DWORD dwDestContext,
|
||||
void* pvDestContext, DWORD mshlflags,
|
||||
DWORD* pSize) override;
|
||||
STDMETHODIMP MarshalInterface(IStream* pStm, REFIID riid, void* pv,
|
||||
DWORD dwDestContext, void* pvDestContext,
|
||||
DWORD mshlflags) override;
|
||||
STDMETHODIMP UnmarshalInterface(IStream* pStm, REFIID riid,
|
||||
void** ppv) override;
|
||||
STDMETHODIMP ReleaseMarshalData(IStream* pStm) override;
|
||||
STDMETHODIMP DisconnectObject(DWORD dwReserved) override;
|
||||
|
||||
// IInterceptor
|
||||
STDMETHODIMP GetTargetForIID(REFIID aIid, InterceptorTargetPtr& aTarget) override;
|
||||
STDMETHODIMP GetInterceptorForIID(REFIID aIid, void** aOutInterceptor) override;
|
||||
|
@ -100,6 +124,8 @@ private:
|
|||
mozilla::Mutex mMutex; // Guards mInterceptorMap
|
||||
// Using a nsTArray since the # of interfaces is not going to be very high
|
||||
nsTArray<MapEntry> mInterceptorMap;
|
||||
RefPtr<IUnknown> mStdMarshalUnk;
|
||||
IMarshal* mStdMarshal; // WEAK
|
||||
};
|
||||
|
||||
template <typename InterfaceT>
|
||||
|
@ -122,4 +148,4 @@ CreateInterceptor(STAUniquePtr<InterfaceT> aTargetInterface,
|
|||
} // namespace mscom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_mscom_interceptor_h
|
||||
#endif // mozilla_mscom_Interceptor_h
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
|
||||
#include "mozilla/mscom/MainThreadHandoff.h"
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/mscom/AgileReference.h"
|
||||
#include "mozilla/mscom/InterceptorLog.h"
|
||||
#include "mozilla/mscom/Registration.h"
|
||||
#include "mozilla/mscom/Utils.h"
|
||||
|
@ -15,9 +17,106 @@
|
|||
#include "nsThreadUtils.h"
|
||||
|
||||
using mozilla::DebugOnly;
|
||||
using mozilla::mscom::AgileReference;
|
||||
|
||||
namespace {
|
||||
|
||||
class MOZ_NONHEAP_CLASS InParamWalker : private ICallFrameWalker
|
||||
{
|
||||
public:
|
||||
InParamWalker()
|
||||
: mPreHandoff(true)
|
||||
{
|
||||
}
|
||||
|
||||
void SetHandoffDone()
|
||||
{
|
||||
mPreHandoff = false;
|
||||
mAgileRefsItr = mAgileRefs.begin();
|
||||
}
|
||||
|
||||
HRESULT Walk(ICallFrame* aFrame)
|
||||
{
|
||||
MOZ_ASSERT(aFrame);
|
||||
if (!aFrame) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
return aFrame->WalkFrame(CALLFRAME_WALK_IN, this);
|
||||
}
|
||||
|
||||
private:
|
||||
// IUnknown
|
||||
STDMETHODIMP QueryInterface(REFIID aIid, void** aOutInterface) override
|
||||
{
|
||||
if (!aOutInterface) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*aOutInterface = nullptr;
|
||||
|
||||
if (aIid == IID_IUnknown || aIid == IID_ICallFrameWalker) {
|
||||
*aOutInterface = static_cast<ICallFrameWalker*>(this);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) AddRef() override
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) Release() override
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ICallFrameWalker
|
||||
STDMETHODIMP OnWalkInterface(REFIID aIid, PVOID* aInterface, BOOL aIn,
|
||||
BOOL aOut) override
|
||||
{
|
||||
MOZ_ASSERT(aIn);
|
||||
if (!aIn) {
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
IUnknown* origInterface = static_cast<IUnknown*>(*aInterface);
|
||||
if (!origInterface) {
|
||||
// Nothing to do
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (mPreHandoff) {
|
||||
mAgileRefs.AppendElement(AgileReference(aIid, origInterface));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mAgileRefsItr != mAgileRefs.end());
|
||||
if (mAgileRefsItr == mAgileRefs.end()) {
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
HRESULT hr = mAgileRefsItr->Resolve(aIid, aInterface);
|
||||
MOZ_ASSERT(SUCCEEDED(hr));
|
||||
if (SUCCEEDED(hr)) {
|
||||
++mAgileRefsItr;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
InParamWalker(const InParamWalker&) = delete;
|
||||
InParamWalker(InParamWalker&&) = delete;
|
||||
InParamWalker& operator=(const InParamWalker&) = delete;
|
||||
InParamWalker& operator=(InParamWalker&&) = delete;
|
||||
|
||||
private:
|
||||
bool mPreHandoff;
|
||||
AutoTArray<AgileReference, 1> mAgileRefs;
|
||||
nsTArray<AgileReference>::iterator mAgileRefsItr;
|
||||
};
|
||||
|
||||
class HandoffRunnable : public mozilla::Runnable
|
||||
{
|
||||
public:
|
||||
|
@ -26,10 +125,17 @@ public:
|
|||
, mTargetInterface(aTargetInterface)
|
||||
, mResult(E_UNEXPECTED)
|
||||
{
|
||||
DebugOnly<HRESULT> hr = mInParamWalker.Walk(aCallFrame);
|
||||
MOZ_ASSERT(SUCCEEDED(hr));
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
mInParamWalker.SetHandoffDone();
|
||||
// We declare hr a DebugOnly because if mInParamWalker.Walk() fails, then
|
||||
// mCallFrame->Invoke will fail anyway.
|
||||
DebugOnly<HRESULT> hr = mInParamWalker.Walk(mCallFrame);
|
||||
MOZ_ASSERT(SUCCEEDED(hr));
|
||||
mResult = mCallFrame->Invoke(mTargetInterface);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -40,9 +146,10 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
ICallFrame* mCallFrame;
|
||||
IUnknown* mTargetInterface;
|
||||
HRESULT mResult;
|
||||
ICallFrame* mCallFrame;
|
||||
InParamWalker mInParamWalker;
|
||||
IUnknown* mTargetInterface;
|
||||
HRESULT mResult;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
@ -51,14 +158,16 @@ namespace mozilla {
|
|||
namespace mscom {
|
||||
|
||||
/* static */ HRESULT
|
||||
MainThreadHandoff::Create(IInterceptorSink** aOutput)
|
||||
MainThreadHandoff::Create(IHandlerPayload* aHandlerPayload,
|
||||
IInterceptorSink** aOutput)
|
||||
{
|
||||
RefPtr<MainThreadHandoff> handoff(new MainThreadHandoff());
|
||||
RefPtr<MainThreadHandoff> handoff(new MainThreadHandoff(aHandlerPayload));
|
||||
return handoff->QueryInterface(IID_IInterceptorSink, (void**) aOutput);
|
||||
}
|
||||
|
||||
MainThreadHandoff::MainThreadHandoff()
|
||||
MainThreadHandoff::MainThreadHandoff(IHandlerPayload* aHandlerPayload)
|
||||
: mRefCnt(0)
|
||||
, mHandlerPayload(aHandlerPayload)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -143,7 +252,7 @@ MainThreadHandoff::OnCall(ICallFrame* aFrame)
|
|||
return hr;
|
||||
}
|
||||
|
||||
// (2) Execute the method call syncrhonously on the main thread
|
||||
// (2) Execute the method call synchronously on the main thread
|
||||
RefPtr<HandoffRunnable> handoffInfo(new HandoffRunnable(aFrame,
|
||||
targetInterface.get()));
|
||||
MainThreadInvoker invoker;
|
||||
|
@ -296,6 +405,44 @@ MainThreadHandoff::SetInterceptor(IWeakReference* aInterceptor)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
MainThreadHandoff::GetHandler(CLSID* aHandlerClsid)
|
||||
{
|
||||
if (!mHandlerPayload) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
return mHandlerPayload->GetHandler(aHandlerClsid);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
MainThreadHandoff::GetHandlerPayloadSize(REFIID aIid, IUnknown* aTarget,
|
||||
DWORD* aOutPayloadSize)
|
||||
{
|
||||
if (!mHandlerPayload) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
return mHandlerPayload->GetHandlerPayloadSize(aIid, aTarget, aOutPayloadSize);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
MainThreadHandoff::WriteHandlerPayload(IStream* aStream, REFIID aIid,
|
||||
IUnknown* aTarget)
|
||||
{
|
||||
if (!mHandlerPayload) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
return mHandlerPayload->WriteHandlerPayload(aStream, aIid, aTarget);
|
||||
}
|
||||
|
||||
REFIID
|
||||
MainThreadHandoff::MarshalAs(REFIID aIid)
|
||||
{
|
||||
if (!mHandlerPayload) {
|
||||
return aIid;
|
||||
}
|
||||
return mHandlerPayload->MarshalAs(aIid);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
MainThreadHandoff::OnWalkInterface(REFIID aIid, PVOID* aInterface,
|
||||
BOOL aIsInParam, BOOL aIsOutParam)
|
||||
|
@ -369,16 +516,27 @@ MainThreadHandoff::OnWalkInterface(REFIID aIid, PVOID* aInterface,
|
|||
}
|
||||
}
|
||||
|
||||
RefPtr<IHandlerPayload> payload;
|
||||
if (mHandlerPayload) {
|
||||
hr = mHandlerPayload->Clone(getter_AddRefs(payload));
|
||||
MOZ_ASSERT(SUCCEEDED(hr));
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
// Now create a new MainThreadHandoff wrapper...
|
||||
RefPtr<IInterceptorSink> handoff;
|
||||
hr = MainThreadHandoff::Create(getter_AddRefs(handoff));
|
||||
hr = MainThreadHandoff::Create(payload, getter_AddRefs(handoff));
|
||||
MOZ_ASSERT(SUCCEEDED(hr));
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
REFIID interceptorIid = payload ? payload->MarshalAs(aIid) : aIid;
|
||||
|
||||
RefPtr<IUnknown> wrapped;
|
||||
hr = Interceptor::Create(Move(origInterface), handoff, aIid,
|
||||
hr = Interceptor::Create(Move(origInterface), handoff, interceptorIid,
|
||||
getter_AddRefs(wrapped));
|
||||
MOZ_ASSERT(SUCCEEDED(hr));
|
||||
if (FAILED(hr)) {
|
||||
|
|
|
@ -24,15 +24,26 @@ class MainThreadHandoff final : public IInterceptorSink
|
|||
, public ICallFrameWalker
|
||||
{
|
||||
public:
|
||||
static HRESULT Create(IInterceptorSink** aOutput);
|
||||
static HRESULT Create(IHandlerPayload* aHandlerPayload,
|
||||
IInterceptorSink** aOutput);
|
||||
|
||||
template <typename Interface>
|
||||
static HRESULT WrapInterface(STAUniquePtr<Interface> aTargetInterface,
|
||||
Interface** aOutInterface)
|
||||
{
|
||||
return WrapInterface<Interface>(Move(aTargetInterface), nullptr,
|
||||
aOutInterface);
|
||||
}
|
||||
|
||||
template <typename Interface>
|
||||
static HRESULT WrapInterface(STAUniquePtr<Interface> aTargetInterface,
|
||||
IHandlerPayload* aHandlerPayload,
|
||||
Interface** aOutInterface)
|
||||
{
|
||||
MOZ_ASSERT(!IsProxy(aTargetInterface.get()));
|
||||
RefPtr<IInterceptorSink> handoff;
|
||||
HRESULT hr = MainThreadHandoff::Create(getter_AddRefs(handoff));
|
||||
HRESULT hr = MainThreadHandoff::Create(aHandlerPayload,
|
||||
getter_AddRefs(handoff));
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
@ -49,13 +60,20 @@ public:
|
|||
|
||||
// IInterceptorSink
|
||||
STDMETHODIMP SetInterceptor(IWeakReference* aInterceptor) override;
|
||||
STDMETHODIMP GetHandler(CLSID* aHandlerClsid) override;
|
||||
STDMETHODIMP GetHandlerPayloadSize(REFIID aIid,
|
||||
IUnknown* aTarget,
|
||||
DWORD* aOutPayloadSize) override;
|
||||
STDMETHODIMP WriteHandlerPayload(IStream* aStream, REFIID aIid,
|
||||
IUnknown* aTarget) override;
|
||||
REFIID MarshalAs(REFIID aIid) override;
|
||||
|
||||
// ICallFrameWalker
|
||||
STDMETHODIMP OnWalkInterface(REFIID aIid, PVOID* aInterface, BOOL aIsInParam,
|
||||
BOOL aIsOutParam) override;
|
||||
|
||||
private:
|
||||
MainThreadHandoff();
|
||||
explicit MainThreadHandoff(IHandlerPayload* aHandlerPayload);
|
||||
~MainThreadHandoff();
|
||||
HRESULT FixArrayElements(ICallFrame* aFrame,
|
||||
const ArrayData& aArrayData);
|
||||
|
@ -63,6 +81,7 @@ private:
|
|||
private:
|
||||
ULONG mRefCnt;
|
||||
RefPtr<IWeakReference> mInterceptor;
|
||||
RefPtr<IHandlerPayload> mHandlerPayload;
|
||||
};
|
||||
|
||||
} // namespace mscom
|
||||
|
|
|
@ -369,8 +369,8 @@ RegisteredProxy::operator=(RegisteredProxy&& aOther)
|
|||
}
|
||||
|
||||
HRESULT
|
||||
RegisteredProxy::GetTypeInfoForInterface(REFIID aIid,
|
||||
ITypeInfo** aOutTypeInfo) const
|
||||
RegisteredProxy::GetTypeInfoForGuid(REFGUID aGuid,
|
||||
ITypeInfo** aOutTypeInfo) const
|
||||
{
|
||||
if (!aOutTypeInfo) {
|
||||
return E_INVALIDARG;
|
||||
|
@ -378,7 +378,7 @@ RegisteredProxy::GetTypeInfoForInterface(REFIID aIid,
|
|||
if (!mTypeLib) {
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
return mTypeLib->lpVtbl->GetTypeInfoOfGuid(mTypeLib, aIid, aOutTypeInfo);
|
||||
return mTypeLib->lpVtbl->GetTypeInfoOfGuid(mTypeLib, aGuid, aOutTypeInfo);
|
||||
}
|
||||
|
||||
static StaticAutoPtr<Vector<RegisteredProxy*>> sRegistry;
|
||||
|
@ -418,7 +418,7 @@ RegisteredProxy::Find(REFIID aIid, ITypeInfo** aTypeInfo)
|
|||
}
|
||||
|
||||
for (auto&& proxy : *sRegistry) {
|
||||
if (SUCCEEDED(proxy->GetTypeInfoForInterface(aIid, aTypeInfo))) {
|
||||
if (SUCCEEDED(proxy->GetTypeInfoForGuid(aIid, aTypeInfo))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public:
|
|||
|
||||
~RegisteredProxy();
|
||||
|
||||
HRESULT GetTypeInfoForInterface(REFIID aIid, ITypeInfo** aOutTypeInfo) const;
|
||||
HRESULT GetTypeInfoForGuid(REFGUID aGuid, ITypeInfo** aOutTypeInfo) const;
|
||||
|
||||
static bool Find(REFIID aIid, ITypeInfo** aOutTypeInfo);
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ if CONFIG['ACCESSIBILITY']:
|
|||
EXPORTS.mozilla.mscom += [
|
||||
'ActivationContext.h',
|
||||
'DispatchForwarder.h',
|
||||
'IHandlerPayload.h',
|
||||
'Interceptor.h',
|
||||
'InterceptorLog.h',
|
||||
'MainThreadHandoff.h',
|
||||
|
|
Загрузка…
Ссылка в новой задаче