зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1409545: Add the ability to query a handler provider for the expected interface for an IUnknown outparam; r=jimm
MozReview-Commit-ID: 7eZ2giTfVG1 --HG-- extra : rebase_source : cc36fbd875ef798c41f20951b8354880138c0037
This commit is contained in:
Родитель
efc8abf253
Коммит
8f79c15fdb
|
@ -26,6 +26,8 @@ struct HandlerProvider
|
||||||
struct IHandlerProvider : public IUnknown
|
struct IHandlerProvider : public IUnknown
|
||||||
, public HandlerProvider
|
, public HandlerProvider
|
||||||
{
|
{
|
||||||
|
virtual STDMETHODIMP_(REFIID) GetEffectiveOutParamIid(REFIID aCallIid,
|
||||||
|
ULONG aCallMethod) = 0;
|
||||||
virtual STDMETHODIMP NewInstance(REFIID aIid,
|
virtual STDMETHODIMP NewInstance(REFIID aIid,
|
||||||
InterceptorTargetPtr<IUnknown> aTarget,
|
InterceptorTargetPtr<IUnknown> aTarget,
|
||||||
NotNull<IHandlerProvider**> aOutNewPayload) = 0;
|
NotNull<IHandlerProvider**> aOutNewPayload) = 0;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "mozilla/mscom/Utils.h"
|
#include "mozilla/mscom/Utils.h"
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
#include "mozilla/DebugOnly.h"
|
#include "mozilla/DebugOnly.h"
|
||||||
|
#include "mozilla/ThreadLocal.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "nsProxyRelease.h"
|
#include "nsProxyRelease.h"
|
||||||
|
|
||||||
|
@ -154,6 +155,52 @@ private:
|
||||||
HRESULT mResult;
|
HRESULT mResult;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MOZ_RAII SavedCallFrame final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit SavedCallFrame(mozilla::NotNull<ICallFrame*> aFrame)
|
||||||
|
: mCallFrame(aFrame)
|
||||||
|
{
|
||||||
|
static const bool sIsInit = tlsFrame.init();
|
||||||
|
MOZ_ASSERT(sIsInit);
|
||||||
|
MOZ_ASSERT(!tlsFrame.get());
|
||||||
|
tlsFrame.set(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~SavedCallFrame()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(tlsFrame.get());
|
||||||
|
tlsFrame.set(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT GetIidAndMethod(mozilla::NotNull<IID*> aIid,
|
||||||
|
mozilla::NotNull<ULONG*> aMethod) const
|
||||||
|
{
|
||||||
|
return mCallFrame->GetIIDAndMethod(aIid, aMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const SavedCallFrame& Get()
|
||||||
|
{
|
||||||
|
SavedCallFrame* saved = tlsFrame.get();
|
||||||
|
MOZ_ASSERT(saved);
|
||||||
|
|
||||||
|
return *saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
SavedCallFrame(const SavedCallFrame&) = delete;
|
||||||
|
SavedCallFrame(SavedCallFrame&&) = delete;
|
||||||
|
SavedCallFrame& operator=(const SavedCallFrame&) = delete;
|
||||||
|
SavedCallFrame& operator=(SavedCallFrame&&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ICallFrame* mCallFrame;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static MOZ_THREAD_LOCAL(SavedCallFrame*) tlsFrame;
|
||||||
|
};
|
||||||
|
|
||||||
|
MOZ_THREAD_LOCAL(SavedCallFrame*) SavedCallFrame::tlsFrame;
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -338,6 +385,8 @@ MainThreadHandoff::OnCall(ICallFrame* aFrame)
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
SavedCallFrame savedFrame(WrapNotNull(aFrame));
|
||||||
|
|
||||||
// (7) Scan the outputs looking for any outparam interfaces that need wrapping.
|
// (7) Scan the outputs looking for any outparam interfaces that need wrapping.
|
||||||
// NB: WalkFrame does not correctly handle array outparams. It processes the
|
// NB: WalkFrame does not correctly handle array outparams. It processes the
|
||||||
// first element of an array but not the remaining elements (if any).
|
// first element of an array but not the remaining elements (if any).
|
||||||
|
@ -566,9 +615,26 @@ MainThreadHandoff::OnWalkInterface(REFIID aIid, PVOID* aInterface,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IID effectiveIid = aIid;
|
||||||
|
|
||||||
RefPtr<IHandlerProvider> payload;
|
RefPtr<IHandlerProvider> payload;
|
||||||
if (mHandlerProvider) {
|
if (mHandlerProvider) {
|
||||||
hr = mHandlerProvider->NewInstance(aIid,
|
if (aIid == IID_IUnknown) {
|
||||||
|
const SavedCallFrame& curFrame = SavedCallFrame::Get();
|
||||||
|
|
||||||
|
IID callIid;
|
||||||
|
ULONG callMethod;
|
||||||
|
hr = curFrame.GetIidAndMethod(WrapNotNull(&callIid),
|
||||||
|
WrapNotNull(&callMethod));
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
effectiveIid = mHandlerProvider->GetEffectiveOutParamIid(callIid,
|
||||||
|
callMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = mHandlerProvider->NewInstance(effectiveIid,
|
||||||
ToInterceptorTargetPtr(origInterface),
|
ToInterceptorTargetPtr(origInterface),
|
||||||
WrapNotNull((IHandlerProvider**)getter_AddRefs(payload)));
|
WrapNotNull((IHandlerProvider**)getter_AddRefs(payload)));
|
||||||
MOZ_ASSERT(SUCCEEDED(hr));
|
MOZ_ASSERT(SUCCEEDED(hr));
|
||||||
|
@ -585,7 +651,8 @@ MainThreadHandoff::OnWalkInterface(REFIID aIid, PVOID* aInterface,
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
REFIID interceptorIid = payload ? payload->MarshalAs(aIid) : aIid;
|
REFIID interceptorIid = payload ? payload->MarshalAs(effectiveIid) :
|
||||||
|
effectiveIid;
|
||||||
|
|
||||||
RefPtr<IUnknown> wrapped;
|
RefPtr<IUnknown> wrapped;
|
||||||
hr = Interceptor::Create(Move(origInterface), handoff, interceptorIid,
|
hr = Interceptor::Create(Move(origInterface), handoff, interceptorIid,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче