/* -*- 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_a11y_HandlerProvider_h #define mozilla_a11y_HandlerProvider_h #include "mozilla/a11y/AccessibleHandler.h" #include "mozilla/a11y/HandlerDataCleanup.h" #include "mozilla/AlreadyAddRefed.h" #include "mozilla/Atomics.h" #include "mozilla/mscom/IHandlerProvider.h" #include "mozilla/mscom/Ptr.h" #include "mozilla/mscom/StructStream.h" #include "mozilla/Mutex.h" #include "mozilla/UniquePtr.h" #include "HandlerData.h" struct NEWEST_IA2_INTERFACE; namespace mozilla { namespace mscom { class StructToStream; } // namespace mscom namespace a11y { class HandlerProvider final : public IGeckoBackChannel, public mscom::IHandlerProvider { public: HandlerProvider(REFIID aIid, mscom::InterceptorTargetPtr aTarget); // IUnknown STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override; STDMETHODIMP_(ULONG) AddRef() override; STDMETHODIMP_(ULONG) Release() override; // IHandlerProvider STDMETHODIMP GetHandler(NotNull aHandlerClsid) override; STDMETHODIMP GetHandlerPayloadSize(NotNull aInterceptor, NotNull aOutPayloadSize) override; STDMETHODIMP WriteHandlerPayload(NotNull aInterceptor, NotNull aStream) override; STDMETHODIMP_(REFIID) MarshalAs(REFIID aIid) override; STDMETHODIMP DisconnectHandlerRemotes() override; STDMETHODIMP IsInterfaceMaybeSupported(REFIID aIid) override; STDMETHODIMP_(REFIID) GetEffectiveOutParamIid(REFIID aCallIid, ULONG aCallMethod) override; STDMETHODIMP NewInstance( REFIID aIid, mscom::InterceptorTargetPtr aTarget, NotNull aOutNewPayload) override; // IGeckoBackChannel STDMETHODIMP put_HandlerControl(long aPid, IHandlerControl* aCtrl) override; STDMETHODIMP Refresh(DynamicIA2Data* aOutData) override; STDMETHODIMP get_AllTextInfo(BSTR* aText, IAccessibleHyperlink*** aHyperlinks, long* aNHyperlinks, IA2TextSegment** aAttribRuns, long* aNAttribRuns) override; STDMETHODIMP get_RelationsInfo(IARelationData** aRelations, long* aNRelations) override; STDMETHODIMP get_AllChildren(AccChildData** aChildren, ULONG* aNChildren) override; private: ~HandlerProvider() = default; void SetHandlerControlOnMainThread( DWORD aPid, mscom::ProxyUniquePtr aCtrl); void GetAndSerializePayload(const MutexAutoLock&, NotNull aInterceptor); void BuildStaticIA2Data(NotNull aInterceptor, StaticIA2Data* aOutData); /** * Pass true for aMarshaledByCom if this struct is being directly marshaled as * an out parameter of a COM method, currently only * IGeckoBackChannel::Refresh. * When aMarshaledByCom is false, this means the struct is being marshaled * by RPC encoding functions. This means we must allocate memory differently, * even though we're using this as part of a COM handler payload. */ void BuildDynamicIA2Data(DynamicIA2Data* aOutIA2Data, bool aMarshaledByCom = false); void BuildInitialIA2Data(NotNull aInterceptor, StaticIA2Data* aOutStaticData, DynamicIA2Data* aOutDynamicData); bool IsTargetInterfaceCacheable(); /** * Build the payload for later marshaling. * This is intended to be used during a bulk fetch operation and must only be * called from the main thread. */ void PrebuildPayload(NotNull aInterceptor); // Replace a raw object from the main thread with a wrapped, intercepted // object suitable for calling from the MTA. // The reference to the original object is adopted; i.e. you should not // separately release it. // This is intended for objects returned from method calls on the main thread. template HRESULT ToWrappedObject(Interface** aObj); void GetAllTextInfoMainThread(BSTR* aText, IAccessibleHyperlink*** aHyperlinks, long* aNHyperlinks, IA2TextSegment** aAttribRuns, long* aNAttribRuns, HRESULT* result); void GetRelationsInfoMainThread(IARelationData** aRelations, long* aNRelations, HRESULT* result); void GetAllChildrenMainThread(AccChildData** aChildren, ULONG* aNChildren, HRESULT* result); Atomic mRefCnt; Mutex mMutex MOZ_UNANNOTATED; // Protects mSerializer const IID mTargetUnkIid; mscom::InterceptorTargetPtr mTargetUnk; // Constant, main thread only UniquePtr mSerializer; RefPtr mFastMarshalUnk; struct IA2PayloadDeleter { void operator()(IA2Payload* aPayload) { // When CoMarshalInterface writes interfaces out to a stream, it AddRefs. // Therefore, we must release our references after this. ReleaseStaticIA2DataInterfaces(aPayload->mStaticData); CleanupDynamicIA2Data(aPayload->mDynamicData); delete aPayload; } }; using IA2PayloadPtr = UniquePtr; // Used when the payload is built prior to marshaling the object by a bulk // fetch operation. See prebuildPayload(). IA2PayloadPtr mPayload; Mutex mPayloadMutex MOZ_UNANNOTATED; // Protects mPayload }; } // namespace a11y } // namespace mozilla #endif // mozilla_a11y_HandlerProvider_h