gecko-dev/ipc/mscom/MainThreadHandoff.h
James Teh a26d4b939e Bug 1434822 part 2: mscom: Add a function to disconnect all remote clients associated with a given target. r=aklotz
Because Interceptors disable COM garbage collection to improve performance, they never receive Release calls from remote clients.
If the object can be shut down while clients still hold a reference, this function can be used to force COM to disconnect all remote connections (using CoDisconnectObject) and thus release the associated references to the Interceptor, its target and any objects associated with the HandlerProvider.
A HandlerProvider::DisconnectHandlerRemotes method also had to be added to allow HandlerProviders to disconnect clients for their own objects.

MozReview-Commit-ID: JaxEkOtrP1M

--HG--
extra : rebase_source : bc7a4ab79458eaaddcef8df74ff4d6f685fbfdce
extra : histedit_source : 087f17f09a0c0e1c8e3b5f6d9690f331c15f0b95
2018-02-19 16:08:57 +10:00

92 lines
3.2 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_MainThreadHandoff_h
#define mozilla_mscom_MainThreadHandoff_h
#include "mozilla/Assertions.h"
#include "mozilla/Move.h"
#include "mozilla/mscom/Interceptor.h"
#include "mozilla/mscom/MainThreadInvoker.h"
#include "mozilla/mscom/Utils.h"
#include "mozilla/Mutex.h"
#include "nsTArray.h"
namespace mozilla {
namespace mscom {
struct ArrayData;
class MainThreadHandoff final : public IInterceptorSink
, public ICallFrameWalker
{
public:
static HRESULT Create(IHandlerProvider* aHandlerProvider,
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,
IHandlerProvider* aHandlerProvider,
Interface** aOutInterface)
{
MOZ_ASSERT(!IsProxy(aTargetInterface.get()));
RefPtr<IInterceptorSink> handoff;
HRESULT hr = MainThreadHandoff::Create(aHandlerProvider,
getter_AddRefs(handoff));
if (FAILED(hr)) {
return hr;
}
return CreateInterceptor(Move(aTargetInterface), handoff, aOutInterface);
}
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override;
STDMETHODIMP_(ULONG) AddRef() override;
STDMETHODIMP_(ULONG) Release() override;
// ICallFrameEvents
STDMETHODIMP OnCall(ICallFrame* aFrame) override;
// IInterceptorSink
STDMETHODIMP SetInterceptor(IWeakReference* aInterceptor) override;
STDMETHODIMP GetHandler(NotNull<CLSID*> aHandlerClsid) override;
STDMETHODIMP GetHandlerPayloadSize(NotNull<IInterceptor*> aInterceptor,
NotNull<DWORD*> aOutPayloadSize) override;
STDMETHODIMP WriteHandlerPayload(NotNull<IInterceptor*> aInterceptor,
NotNull<IStream*> aStream) override;
STDMETHODIMP_(REFIID) MarshalAs(REFIID aIid) override;
STDMETHODIMP DisconnectHandlerRemotes() override;
// ICallFrameWalker
STDMETHODIMP OnWalkInterface(REFIID aIid, PVOID* aInterface, BOOL aIsInParam,
BOOL aIsOutParam) override;
private:
explicit MainThreadHandoff(IHandlerProvider* aHandlerProvider);
~MainThreadHandoff();
HRESULT FixArrayElements(ICallFrame* aFrame,
const ArrayData& aArrayData);
HRESULT FixIServiceProvider(ICallFrame* aFrame);
private:
ULONG mRefCnt;
RefPtr<IWeakReference> mInterceptor;
RefPtr<IHandlerProvider> mHandlerProvider;
};
} // namespace mscom
} // namespace mozilla
#endif // mozilla_mscom_MainThreadHandoff_h