зеркало из 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 "mozilla/Attributes.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <unknwn.h>
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace mscom {
|
namespace mscom {
|
||||||
|
|
||||||
|
@ -44,8 +47,53 @@ private:
|
||||||
RefCntT& mRefCnt;
|
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 mscom
|
||||||
} // namespace mozilla
|
} // 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
|
#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))
|
, mTarget(Move(aTarget))
|
||||||
, mEventSink(aSink)
|
, mEventSink(aSink)
|
||||||
, mMutex("mozilla::mscom::Interceptor::mMutex")
|
, mMutex("mozilla::mscom::Interceptor::mMutex")
|
||||||
|
, mStdMarshal(nullptr)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aSink);
|
MOZ_ASSERT(aSink);
|
||||||
MOZ_ASSERT(!IsProxy(mTarget.get()));
|
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::MapEntry*
|
||||||
Interceptor::Lookup(REFIID aIid)
|
Interceptor::Lookup(REFIID aIid)
|
||||||
{
|
{
|
||||||
|
@ -148,19 +220,22 @@ Interceptor::GetInterceptorForIID(REFIID aIid, void** aOutInterceptor)
|
||||||
|
|
||||||
if (aIid == IID_IUnknown) {
|
if (aIid == IID_IUnknown) {
|
||||||
// Special case: When we see IUnknown, we just provide a reference to this
|
// Special case: When we see IUnknown, we just provide a reference to this
|
||||||
*aOutInterceptor = static_cast<IInterceptor*>(this);
|
RefPtr<IInterceptor> intcpt(this);
|
||||||
AddRef();
|
intcpt.forget(aOutInterceptor);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
REFIID interceptorIid = mEventSink->MarshalAs(aIid);
|
||||||
|
|
||||||
RefPtr<IUnknown> unkInterceptor;
|
RefPtr<IUnknown> unkInterceptor;
|
||||||
IUnknown* interfaceForQILog = nullptr;
|
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
|
{ // Scope for lock
|
||||||
MutexAutoLock lock(mMutex);
|
MutexAutoLock lock(mMutex);
|
||||||
MapEntry* entry = Lookup(aIid);
|
MapEntry* entry = Lookup(interceptorIid);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
unkInterceptor = entry->mInterceptor;
|
unkInterceptor = entry->mInterceptor;
|
||||||
interfaceForQILog = entry->mTargetInterface;
|
interfaceForQILog = entry->mTargetInterface;
|
||||||
|
@ -175,7 +250,7 @@ Interceptor::GetInterceptorForIID(REFIID aIid, void** aOutInterceptor)
|
||||||
// was requested.
|
// was requested.
|
||||||
InterceptorLog::QI(S_OK, mTarget.get(), aIid, interfaceForQILog);
|
InterceptorLog::QI(S_OK, mTarget.get(), aIid, interfaceForQILog);
|
||||||
|
|
||||||
return unkInterceptor->QueryInterface(aIid, aOutInterceptor);
|
return unkInterceptor->QueryInterface(interceptorIid, aOutInterceptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// (2) Obtain a new target interface.
|
// (2) Obtain a new target interface.
|
||||||
|
@ -188,7 +263,7 @@ Interceptor::GetInterceptorForIID(REFIID aIid, void** aOutInterceptor)
|
||||||
|
|
||||||
STAUniquePtr<IUnknown> targetInterface;
|
STAUniquePtr<IUnknown> targetInterface;
|
||||||
IUnknown* rawTargetInterface = nullptr;
|
IUnknown* rawTargetInterface = nullptr;
|
||||||
hr = QueryInterfaceTarget(aIid, (void**)&rawTargetInterface);
|
hr = QueryInterfaceTarget(interceptorIid, (void**)&rawTargetInterface);
|
||||||
targetInterface.reset(rawTargetInterface);
|
targetInterface.reset(rawTargetInterface);
|
||||||
InterceptorLog::QI(hr, mTarget.get(), aIid, targetInterface.get());
|
InterceptorLog::QI(hr, mTarget.get(), aIid, targetInterface.get());
|
||||||
MOZ_ASSERT(SUCCEEDED(hr) || hr == E_NOINTERFACE);
|
MOZ_ASSERT(SUCCEEDED(hr) || hr == E_NOINTERFACE);
|
||||||
|
@ -206,7 +281,8 @@ Interceptor::GetInterceptorForIID(REFIID aIid, void** aOutInterceptor)
|
||||||
RefPtr<IUnknown> kungFuDeathGrip(static_cast<IUnknown*>(
|
RefPtr<IUnknown> kungFuDeathGrip(static_cast<IUnknown*>(
|
||||||
static_cast<WeakReferenceSupport*>(this)));
|
static_cast<WeakReferenceSupport*>(this)));
|
||||||
|
|
||||||
hr = CreateInterceptor(aIid, kungFuDeathGrip, getter_AddRefs(unkInterceptor));
|
hr = CreateInterceptor(interceptorIid, kungFuDeathGrip,
|
||||||
|
getter_AddRefs(unkInterceptor));
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
@ -231,7 +307,7 @@ Interceptor::GetInterceptorForIID(REFIID aIid, void** aOutInterceptor)
|
||||||
MutexAutoLock lock(mMutex);
|
MutexAutoLock lock(mMutex);
|
||||||
// We might have raced with another thread, so first check that we don't
|
// We might have raced with another thread, so first check that we don't
|
||||||
// already have an entry for this
|
// already have an entry for this
|
||||||
MapEntry* entry = Lookup(aIid);
|
MapEntry* entry = Lookup(interceptorIid);
|
||||||
if (entry && entry->mInterceptor) {
|
if (entry && entry->mInterceptor) {
|
||||||
unkInterceptor = entry->mInterceptor;
|
unkInterceptor = entry->mInterceptor;
|
||||||
} else {
|
} else {
|
||||||
|
@ -239,13 +315,13 @@ Interceptor::GetInterceptorForIID(REFIID aIid, void** aOutInterceptor)
|
||||||
// refcount for the target interface because we are just moving it into
|
// refcount for the target interface because we are just moving it into
|
||||||
// the map and its refcounting might not be thread-safe.
|
// the map and its refcounting might not be thread-safe.
|
||||||
IUnknown* rawTargetInterface = targetInterface.release();
|
IUnknown* rawTargetInterface = targetInterface.release();
|
||||||
mInterceptorMap.AppendElement(MapEntry(aIid,
|
mInterceptorMap.AppendElement(MapEntry(interceptorIid,
|
||||||
unkInterceptor,
|
unkInterceptor,
|
||||||
rawTargetInterface));
|
rawTargetInterface));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return unkInterceptor->QueryInterface(aIid, aOutInterceptor);
|
return unkInterceptor->QueryInterface(interceptorIid, aOutInterceptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
|
@ -275,9 +351,63 @@ Interceptor::QueryInterface(REFIID riid, void** ppv)
|
||||||
HRESULT
|
HRESULT
|
||||||
Interceptor::ThreadSafeQueryInterface(REFIID aIid, IUnknown** aOutInterface)
|
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) {
|
if (aIid == IID_IInterceptor) {
|
||||||
*aOutInterface = static_cast<IInterceptor*>(this);
|
RefPtr<IInterceptor> intcpt(this);
|
||||||
(*aOutInterface)->AddRef();
|
intcpt.forget(aOutInterface);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,16 +4,18 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#ifndef mozilla_mscom_interceptor_h
|
#ifndef mozilla_mscom_Interceptor_h
|
||||||
#define mozilla_mscom_interceptor_h
|
#define mozilla_mscom_Interceptor_h
|
||||||
|
|
||||||
#include "mozilla/Move.h"
|
#include "mozilla/Move.h"
|
||||||
#include "mozilla/Mutex.h"
|
#include "mozilla/Mutex.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
|
#include "mozilla/mscom/IHandlerPayload.h"
|
||||||
#include "mozilla/mscom/Ptr.h"
|
#include "mozilla/mscom/Ptr.h"
|
||||||
#include "mozilla/mscom/WeakRef.h"
|
#include "mozilla/mscom/WeakRef.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
|
|
||||||
|
#include <objidl.h>
|
||||||
#include <callobj.h>
|
#include <callobj.h>
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -24,6 +26,7 @@ DEFINE_GUID(IID_IInterceptorSink,
|
||||||
0x8831eb53, 0xa937, 0x42bc, 0x99, 0x21, 0xb3, 0xe1, 0x12, 0x1f, 0xdf, 0x86);
|
0x8831eb53, 0xa937, 0x42bc, 0x99, 0x21, 0xb3, 0xe1, 0x12, 0x1f, 0xdf, 0x86);
|
||||||
|
|
||||||
struct IInterceptorSink : public ICallFrameEvents
|
struct IInterceptorSink : public ICallFrameEvents
|
||||||
|
, public HandlerPayload
|
||||||
{
|
{
|
||||||
virtual STDMETHODIMP SetInterceptor(IWeakReference* aInterceptor) = 0;
|
virtual STDMETHODIMP SetInterceptor(IWeakReference* aInterceptor) = 0;
|
||||||
};
|
};
|
||||||
|
@ -57,6 +60,8 @@ struct IInterceptor : public IUnknown
|
||||||
* (the mscom::Interceptor we implement and control).
|
* (the mscom::Interceptor we implement and control).
|
||||||
*/
|
*/
|
||||||
class Interceptor final : public WeakReferenceSupport
|
class Interceptor final : public WeakReferenceSupport
|
||||||
|
, public IStdMarshalInfo
|
||||||
|
, public IMarshal
|
||||||
, public IInterceptor
|
, public IInterceptor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -68,6 +73,25 @@ public:
|
||||||
STDMETHODIMP_(ULONG) AddRef() override;
|
STDMETHODIMP_(ULONG) AddRef() override;
|
||||||
STDMETHODIMP_(ULONG) Release() 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
|
// IInterceptor
|
||||||
STDMETHODIMP GetTargetForIID(REFIID aIid, InterceptorTargetPtr& aTarget) override;
|
STDMETHODIMP GetTargetForIID(REFIID aIid, InterceptorTargetPtr& aTarget) override;
|
||||||
STDMETHODIMP GetInterceptorForIID(REFIID aIid, void** aOutInterceptor) override;
|
STDMETHODIMP GetInterceptorForIID(REFIID aIid, void** aOutInterceptor) override;
|
||||||
|
@ -100,6 +124,8 @@ private:
|
||||||
mozilla::Mutex mMutex; // Guards mInterceptorMap
|
mozilla::Mutex mMutex; // Guards mInterceptorMap
|
||||||
// Using a nsTArray since the # of interfaces is not going to be very high
|
// Using a nsTArray since the # of interfaces is not going to be very high
|
||||||
nsTArray<MapEntry> mInterceptorMap;
|
nsTArray<MapEntry> mInterceptorMap;
|
||||||
|
RefPtr<IUnknown> mStdMarshalUnk;
|
||||||
|
IMarshal* mStdMarshal; // WEAK
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename InterfaceT>
|
template <typename InterfaceT>
|
||||||
|
@ -122,4 +148,4 @@ CreateInterceptor(STAUniquePtr<InterfaceT> aTargetInterface,
|
||||||
} // namespace mscom
|
} // namespace mscom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
#endif // mozilla_mscom_interceptor_h
|
#endif // mozilla_mscom_Interceptor_h
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
|
|
||||||
#include "mozilla/mscom/MainThreadHandoff.h"
|
#include "mozilla/mscom/MainThreadHandoff.h"
|
||||||
|
|
||||||
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/Move.h"
|
#include "mozilla/Move.h"
|
||||||
|
#include "mozilla/mscom/AgileReference.h"
|
||||||
#include "mozilla/mscom/InterceptorLog.h"
|
#include "mozilla/mscom/InterceptorLog.h"
|
||||||
#include "mozilla/mscom/Registration.h"
|
#include "mozilla/mscom/Registration.h"
|
||||||
#include "mozilla/mscom/Utils.h"
|
#include "mozilla/mscom/Utils.h"
|
||||||
|
@ -15,9 +17,106 @@
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
|
||||||
using mozilla::DebugOnly;
|
using mozilla::DebugOnly;
|
||||||
|
using mozilla::mscom::AgileReference;
|
||||||
|
|
||||||
namespace {
|
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
|
class HandoffRunnable : public mozilla::Runnable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -26,10 +125,17 @@ public:
|
||||||
, mTargetInterface(aTargetInterface)
|
, mTargetInterface(aTargetInterface)
|
||||||
, mResult(E_UNEXPECTED)
|
, mResult(E_UNEXPECTED)
|
||||||
{
|
{
|
||||||
|
DebugOnly<HRESULT> hr = mInParamWalker.Walk(aCallFrame);
|
||||||
|
MOZ_ASSERT(SUCCEEDED(hr));
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHOD Run() override
|
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);
|
mResult = mCallFrame->Invoke(mTargetInterface);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -40,9 +146,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ICallFrame* mCallFrame;
|
ICallFrame* mCallFrame;
|
||||||
IUnknown* mTargetInterface;
|
InParamWalker mInParamWalker;
|
||||||
HRESULT mResult;
|
IUnknown* mTargetInterface;
|
||||||
|
HRESULT mResult;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
@ -51,14 +158,16 @@ namespace mozilla {
|
||||||
namespace mscom {
|
namespace mscom {
|
||||||
|
|
||||||
/* static */ HRESULT
|
/* 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);
|
return handoff->QueryInterface(IID_IInterceptorSink, (void**) aOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
MainThreadHandoff::MainThreadHandoff()
|
MainThreadHandoff::MainThreadHandoff(IHandlerPayload* aHandlerPayload)
|
||||||
: mRefCnt(0)
|
: mRefCnt(0)
|
||||||
|
, mHandlerPayload(aHandlerPayload)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +252,7 @@ MainThreadHandoff::OnCall(ICallFrame* aFrame)
|
||||||
return hr;
|
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,
|
RefPtr<HandoffRunnable> handoffInfo(new HandoffRunnable(aFrame,
|
||||||
targetInterface.get()));
|
targetInterface.get()));
|
||||||
MainThreadInvoker invoker;
|
MainThreadInvoker invoker;
|
||||||
|
@ -296,6 +405,44 @@ MainThreadHandoff::SetInterceptor(IWeakReference* aInterceptor)
|
||||||
return S_OK;
|
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
|
HRESULT
|
||||||
MainThreadHandoff::OnWalkInterface(REFIID aIid, PVOID* aInterface,
|
MainThreadHandoff::OnWalkInterface(REFIID aIid, PVOID* aInterface,
|
||||||
BOOL aIsInParam, BOOL aIsOutParam)
|
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...
|
// Now create a new MainThreadHandoff wrapper...
|
||||||
RefPtr<IInterceptorSink> handoff;
|
RefPtr<IInterceptorSink> handoff;
|
||||||
hr = MainThreadHandoff::Create(getter_AddRefs(handoff));
|
hr = MainThreadHandoff::Create(payload, getter_AddRefs(handoff));
|
||||||
MOZ_ASSERT(SUCCEEDED(hr));
|
MOZ_ASSERT(SUCCEEDED(hr));
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
REFIID interceptorIid = payload ? payload->MarshalAs(aIid) : aIid;
|
||||||
|
|
||||||
RefPtr<IUnknown> wrapped;
|
RefPtr<IUnknown> wrapped;
|
||||||
hr = Interceptor::Create(Move(origInterface), handoff, aIid,
|
hr = Interceptor::Create(Move(origInterface), handoff, interceptorIid,
|
||||||
getter_AddRefs(wrapped));
|
getter_AddRefs(wrapped));
|
||||||
MOZ_ASSERT(SUCCEEDED(hr));
|
MOZ_ASSERT(SUCCEEDED(hr));
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
|
|
@ -24,15 +24,26 @@ class MainThreadHandoff final : public IInterceptorSink
|
||||||
, public ICallFrameWalker
|
, public ICallFrameWalker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static HRESULT Create(IInterceptorSink** aOutput);
|
static HRESULT Create(IHandlerPayload* aHandlerPayload,
|
||||||
|
IInterceptorSink** aOutput);
|
||||||
|
|
||||||
template <typename Interface>
|
template <typename Interface>
|
||||||
static HRESULT WrapInterface(STAUniquePtr<Interface> aTargetInterface,
|
static HRESULT WrapInterface(STAUniquePtr<Interface> aTargetInterface,
|
||||||
Interface** aOutInterface)
|
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()));
|
MOZ_ASSERT(!IsProxy(aTargetInterface.get()));
|
||||||
RefPtr<IInterceptorSink> handoff;
|
RefPtr<IInterceptorSink> handoff;
|
||||||
HRESULT hr = MainThreadHandoff::Create(getter_AddRefs(handoff));
|
HRESULT hr = MainThreadHandoff::Create(aHandlerPayload,
|
||||||
|
getter_AddRefs(handoff));
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
@ -49,13 +60,20 @@ public:
|
||||||
|
|
||||||
// IInterceptorSink
|
// IInterceptorSink
|
||||||
STDMETHODIMP SetInterceptor(IWeakReference* aInterceptor) override;
|
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
|
// ICallFrameWalker
|
||||||
STDMETHODIMP OnWalkInterface(REFIID aIid, PVOID* aInterface, BOOL aIsInParam,
|
STDMETHODIMP OnWalkInterface(REFIID aIid, PVOID* aInterface, BOOL aIsInParam,
|
||||||
BOOL aIsOutParam) override;
|
BOOL aIsOutParam) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MainThreadHandoff();
|
explicit MainThreadHandoff(IHandlerPayload* aHandlerPayload);
|
||||||
~MainThreadHandoff();
|
~MainThreadHandoff();
|
||||||
HRESULT FixArrayElements(ICallFrame* aFrame,
|
HRESULT FixArrayElements(ICallFrame* aFrame,
|
||||||
const ArrayData& aArrayData);
|
const ArrayData& aArrayData);
|
||||||
|
@ -63,6 +81,7 @@ private:
|
||||||
private:
|
private:
|
||||||
ULONG mRefCnt;
|
ULONG mRefCnt;
|
||||||
RefPtr<IWeakReference> mInterceptor;
|
RefPtr<IWeakReference> mInterceptor;
|
||||||
|
RefPtr<IHandlerPayload> mHandlerPayload;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mscom
|
} // namespace mscom
|
||||||
|
|
|
@ -369,8 +369,8 @@ RegisteredProxy::operator=(RegisteredProxy&& aOther)
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
RegisteredProxy::GetTypeInfoForInterface(REFIID aIid,
|
RegisteredProxy::GetTypeInfoForGuid(REFGUID aGuid,
|
||||||
ITypeInfo** aOutTypeInfo) const
|
ITypeInfo** aOutTypeInfo) const
|
||||||
{
|
{
|
||||||
if (!aOutTypeInfo) {
|
if (!aOutTypeInfo) {
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
@ -378,7 +378,7 @@ RegisteredProxy::GetTypeInfoForInterface(REFIID aIid,
|
||||||
if (!mTypeLib) {
|
if (!mTypeLib) {
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
}
|
}
|
||||||
return mTypeLib->lpVtbl->GetTypeInfoOfGuid(mTypeLib, aIid, aOutTypeInfo);
|
return mTypeLib->lpVtbl->GetTypeInfoOfGuid(mTypeLib, aGuid, aOutTypeInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static StaticAutoPtr<Vector<RegisteredProxy*>> sRegistry;
|
static StaticAutoPtr<Vector<RegisteredProxy*>> sRegistry;
|
||||||
|
@ -418,7 +418,7 @@ RegisteredProxy::Find(REFIID aIid, ITypeInfo** aTypeInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto&& proxy : *sRegistry) {
|
for (auto&& proxy : *sRegistry) {
|
||||||
if (SUCCEEDED(proxy->GetTypeInfoForInterface(aIid, aTypeInfo))) {
|
if (SUCCEEDED(proxy->GetTypeInfoForGuid(aIid, aTypeInfo))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ public:
|
||||||
|
|
||||||
~RegisteredProxy();
|
~RegisteredProxy();
|
||||||
|
|
||||||
HRESULT GetTypeInfoForInterface(REFIID aIid, ITypeInfo** aOutTypeInfo) const;
|
HRESULT GetTypeInfoForGuid(REFGUID aGuid, ITypeInfo** aOutTypeInfo) const;
|
||||||
|
|
||||||
static bool Find(REFIID aIid, ITypeInfo** aOutTypeInfo);
|
static bool Find(REFIID aIid, ITypeInfo** aOutTypeInfo);
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ if CONFIG['ACCESSIBILITY']:
|
||||||
EXPORTS.mozilla.mscom += [
|
EXPORTS.mozilla.mscom += [
|
||||||
'ActivationContext.h',
|
'ActivationContext.h',
|
||||||
'DispatchForwarder.h',
|
'DispatchForwarder.h',
|
||||||
|
'IHandlerPayload.h',
|
||||||
'Interceptor.h',
|
'Interceptor.h',
|
||||||
'InterceptorLog.h',
|
'InterceptorLog.h',
|
||||||
'MainThreadHandoff.h',
|
'MainThreadHandoff.h',
|
||||||
|
|
Загрузка…
Ссылка в новой задаче