1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_a11y_HandlerProvider_h 8 #define mozilla_a11y_HandlerProvider_h 9 10 #include "mozilla/a11y/AccessibleHandler.h" 11 #include "mozilla/a11y/HandlerDataCleanup.h" 12 #include "mozilla/AlreadyAddRefed.h" 13 #include "mozilla/Atomics.h" 14 #include "mozilla/mscom/IHandlerProvider.h" 15 #include "mozilla/mscom/Ptr.h" 16 #include "mozilla/mscom/StructStream.h" 17 #include "mozilla/Mutex.h" 18 #include "mozilla/UniquePtr.h" 19 #include "HandlerData.h" 20 21 struct NEWEST_IA2_INTERFACE; 22 23 namespace mozilla { 24 25 namespace mscom { 26 27 class StructToStream; 28 29 } // namespace mscom 30 31 namespace a11y { 32 33 class HandlerProvider final : public IGeckoBackChannel, 34 public mscom::IHandlerProvider { 35 public: 36 HandlerProvider(REFIID aIid, mscom::InterceptorTargetPtr<IUnknown> aTarget); 37 38 // IUnknown 39 STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override; 40 STDMETHODIMP_(ULONG) AddRef() override; 41 STDMETHODIMP_(ULONG) Release() override; 42 43 // IHandlerProvider 44 STDMETHODIMP GetHandler(NotNull<CLSID*> aHandlerClsid) override; 45 STDMETHODIMP GetHandlerPayloadSize(NotNull<mscom::IInterceptor*> aInterceptor, 46 NotNull<DWORD*> aOutPayloadSize) override; 47 STDMETHODIMP WriteHandlerPayload(NotNull<mscom::IInterceptor*> aInterceptor, 48 NotNull<IStream*> aStream) override; 49 STDMETHODIMP_(REFIID) MarshalAs(REFIID aIid) override; 50 STDMETHODIMP DisconnectHandlerRemotes() override; 51 STDMETHODIMP IsInterfaceMaybeSupported(REFIID aIid) override; 52 STDMETHODIMP_(REFIID) 53 GetEffectiveOutParamIid(REFIID aCallIid, ULONG aCallMethod) override; 54 STDMETHODIMP NewInstance( 55 REFIID aIid, mscom::InterceptorTargetPtr<IUnknown> aTarget, 56 NotNull<mscom::IHandlerProvider**> aOutNewPayload) override; 57 58 // IGeckoBackChannel 59 STDMETHODIMP put_HandlerControl(long aPid, IHandlerControl* aCtrl) override; 60 STDMETHODIMP Refresh(DynamicIA2Data* aOutData) override; 61 STDMETHODIMP get_AllTextInfo(BSTR* aText, IAccessibleHyperlink*** aHyperlinks, 62 long* aNHyperlinks, IA2TextSegment** aAttribRuns, 63 long* aNAttribRuns) override; 64 STDMETHODIMP get_RelationsInfo(IARelationData** aRelations, 65 long* aNRelations) override; 66 STDMETHODIMP get_AllChildren(AccChildData** aChildren, 67 ULONG* aNChildren) override; 68 69 private: 70 ~HandlerProvider() = default; 71 72 void SetHandlerControlOnMainThread( 73 DWORD aPid, mscom::ProxyUniquePtr<IHandlerControl> aCtrl); 74 void GetAndSerializePayload(const MutexAutoLock&, 75 NotNull<mscom::IInterceptor*> aInterceptor); 76 void BuildStaticIA2Data(NotNull<mscom::IInterceptor*> aInterceptor, 77 StaticIA2Data* aOutData); 78 /** 79 * Pass true for aMarshaledByCom if this struct is being directly marshaled as 80 * an out parameter of a COM method, currently only 81 * IGeckoBackChannel::Refresh. 82 * When aMarshaledByCom is false, this means the struct is being marshaled 83 * by RPC encoding functions. This means we must allocate memory differently, 84 * even though we're using this as part of a COM handler payload. 85 */ 86 void BuildDynamicIA2Data(DynamicIA2Data* aOutIA2Data, 87 bool aMarshaledByCom = false); 88 void BuildInitialIA2Data(NotNull<mscom::IInterceptor*> aInterceptor, 89 StaticIA2Data* aOutStaticData, 90 DynamicIA2Data* aOutDynamicData); 91 bool IsTargetInterfaceCacheable(); 92 93 /** 94 * Build the payload for later marshaling. 95 * This is intended to be used during a bulk fetch operation and must only be 96 * called from the main thread. 97 */ 98 void PrebuildPayload(NotNull<mscom::IInterceptor*> aInterceptor); 99 100 // Replace a raw object from the main thread with a wrapped, intercepted 101 // object suitable for calling from the MTA. 102 // The reference to the original object is adopted; i.e. you should not 103 // separately release it. 104 // This is intended for objects returned from method calls on the main thread. 105 template <typename Interface> 106 HRESULT ToWrappedObject(Interface** aObj); 107 void GetAllTextInfoMainThread(BSTR* aText, 108 IAccessibleHyperlink*** aHyperlinks, 109 long* aNHyperlinks, 110 IA2TextSegment** aAttribRuns, 111 long* aNAttribRuns, HRESULT* result); 112 void GetRelationsInfoMainThread(IARelationData** aRelations, 113 long* aNRelations, HRESULT* result); 114 void GetAllChildrenMainThread(AccChildData** aChildren, ULONG* aNChildren, 115 HRESULT* result); 116 117 Atomic<uint32_t> mRefCnt; 118 Mutex mMutex; // Protects mSerializer 119 const IID mTargetUnkIid; 120 mscom::InterceptorTargetPtr<IUnknown> 121 mTargetUnk; // Constant, main thread only 122 UniquePtr<mscom::StructToStream> mSerializer; 123 RefPtr<IUnknown> mFastMarshalUnk; 124 125 struct IA2PayloadDeleter { operatorIA2PayloadDeleter126 void operator()(IA2Payload* aPayload) { 127 // When CoMarshalInterface writes interfaces out to a stream, it AddRefs. 128 // Therefore, we must release our references after this. 129 ReleaseStaticIA2DataInterfaces(aPayload->mStaticData); 130 CleanupDynamicIA2Data(aPayload->mDynamicData); 131 delete aPayload; 132 } 133 }; 134 using IA2PayloadPtr = UniquePtr<IA2Payload, IA2PayloadDeleter>; 135 136 // Used when the payload is built prior to marshaling the object by a bulk 137 // fetch operation. See prebuildPayload(). 138 IA2PayloadPtr mPayload; 139 Mutex mPayloadMutex; // Protects mPayload 140 }; 141 142 } // namespace a11y 143 } // namespace mozilla 144 145 #endif // mozilla_a11y_HandlerProvider_h 146