LazyInstantiator.h (6659B)
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_LazyInstantiator_h 8 #define mozilla_a11y_LazyInstantiator_h 9 10 #include "IUnknownImpl.h" 11 #include "mozilla/Maybe.h" 12 #include "mozilla/RefPtr.h" 13 #include "nsString.h" 14 15 #include <oleacc.h> 16 #include <uiautomation.h> 17 18 class nsIFile; 19 20 namespace mozilla { 21 namespace a11y { 22 23 class MsaaRootAccessible; 24 25 /** 26 * LazyInstantiator is an IAccessible that initially acts as a placeholder. 27 * The a11y service is not actually started until two conditions are met: 28 * 29 * (1) A method is called on the LazyInstantiator that would require a11y 30 * services in order to fulfill; and 31 * (2) LazyInstantiator::ShouldInstantiate returns true. 32 */ 33 class LazyInstantiator final : public IAccessible, 34 public IServiceProvider, 35 public IRawElementProviderSimple { 36 public: 37 [[nodiscard]] static already_AddRefed<IAccessible> GetRootAccessible( 38 HWND aHwnd); 39 [[nodiscard]] static already_AddRefed<IRawElementProviderSimple> GetRootUia( 40 HWND aHwnd); 41 static void EnableBlindAggregation(HWND aHwnd); 42 43 // IUnknown 44 STDMETHODIMP QueryInterface(REFIID aIid, void** aOutInterface) override; 45 STDMETHODIMP_(ULONG) AddRef() override; 46 STDMETHODIMP_(ULONG) Release() override; 47 48 // IDispatch 49 STDMETHODIMP GetTypeInfoCount(UINT* pctinfo) override; 50 STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, 51 ITypeInfo** ppTInfo) override; 52 STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, 53 LCID lcid, DISPID* rgDispId) override; 54 STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, 55 DISPPARAMS* pDispParams, VARIANT* pVarResult, 56 EXCEPINFO* pExcepInfo, UINT* puArgErr) override; 57 58 // IAccessible 59 STDMETHODIMP get_accParent(IDispatch** ppdispParent) override; 60 STDMETHODIMP get_accChildCount(long* pcountChildren) override; 61 STDMETHODIMP get_accChild(VARIANT varChild, IDispatch** ppdispChild) override; 62 STDMETHODIMP get_accName(VARIANT varChild, BSTR* pszName) override; 63 STDMETHODIMP get_accValue(VARIANT varChild, BSTR* pszValue) override; 64 STDMETHODIMP get_accDescription(VARIANT varChild, 65 BSTR* pszDescription) override; 66 STDMETHODIMP get_accRole(VARIANT varChild, VARIANT* pvarRole) override; 67 STDMETHODIMP get_accState(VARIANT varChild, VARIANT* pvarState) override; 68 STDMETHODIMP get_accHelp(VARIANT varChild, BSTR* pszHelp) override; 69 STDMETHODIMP get_accHelpTopic(BSTR* pszHelpFile, VARIANT varChild, 70 long* pidTopic) override; 71 STDMETHODIMP get_accKeyboardShortcut(VARIANT varChild, 72 BSTR* pszKeyboardShortcut) override; 73 STDMETHODIMP get_accFocus(VARIANT* pvarChild) override; 74 STDMETHODIMP get_accSelection(VARIANT* pvarChildren) override; 75 STDMETHODIMP get_accDefaultAction(VARIANT varChild, 76 BSTR* pszDefaultAction) override; 77 STDMETHODIMP accSelect(long flagsSelect, VARIANT varChild) override; 78 STDMETHODIMP accLocation(long* pxLeft, long* pyTop, long* pcxWidth, 79 long* pcyHeight, VARIANT varChild) override; 80 STDMETHODIMP accNavigate(long navDir, VARIANT varStart, 81 VARIANT* pvarEndUpAt) override; 82 STDMETHODIMP accHitTest(long xLeft, long yTop, VARIANT* pvarChild) override; 83 STDMETHODIMP accDoDefaultAction(VARIANT varChild) override; 84 STDMETHODIMP put_accName(VARIANT varChild, BSTR szName) override; 85 STDMETHODIMP put_accValue(VARIANT varChild, BSTR szValue) override; 86 87 // IServiceProvider 88 STDMETHODIMP QueryService(REFGUID aServiceId, REFIID aServiceIid, 89 void** aOutInterface) override; 90 91 // IRawElementProviderSimple 92 virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ProviderOptions( 93 /* [retval][out] */ __RPC__out enum ProviderOptions* aProviderOptions); 94 95 virtual HRESULT STDMETHODCALLTYPE GetPatternProvider( 96 /* [in] */ PATTERNID aPatternId, 97 /* [retval][out] */ __RPC__deref_out_opt IUnknown** aPatternProvider); 98 99 virtual HRESULT STDMETHODCALLTYPE GetPropertyValue( 100 /* [in] */ PROPERTYID aPropertyId, 101 /* [retval][out] */ __RPC__out VARIANT* aPropertyValue); 102 103 virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_HostRawElementProvider( 104 /* [retval][out] */ __RPC__deref_out_opt IRawElementProviderSimple** 105 aRawElmProvider); 106 107 /** 108 * We cache the result of UIA detection because it could be expensive if a 109 * client repeatedly queries us. This function is called to reset that cache 110 * when one of our windows comes to the foreground. If there is a new UIA 111 * client that isn't blocked, instantiation will subsequently be allowed. The 112 * hope is that a user will probably need to switch apps in order to start a 113 * new client. 114 */ 115 static void ResetUiaDetectionCache() { sShouldBlockUia = Nothing(); } 116 117 private: 118 explicit LazyInstantiator(HWND aHwnd); 119 ~LazyInstantiator(); 120 121 bool IsBlockedInjection(); 122 bool ShouldInstantiate(const DWORD aClientPid); 123 bool ShouldInstantiate(); 124 125 DWORD GetRemoteMsaaClientPid(); 126 127 /** 128 * @return S_OK if we have a valid mRealRoot to invoke methods on 129 */ 130 HRESULT MaybeResolveRoot(); 131 132 /** 133 * @return S_OK if we have a valid mWeakDispatch to invoke methods on 134 */ 135 HRESULT ResolveDispatch(); 136 137 MsaaRootAccessible* ResolveMsaaRoot(); 138 void TransplantRefCnt(); 139 void ClearProp(); 140 141 template <class T> 142 static already_AddRefed<T> GetRoot(HWND aHwnd); 143 144 private: 145 mozilla::a11y::AutoRefCnt mRefCnt; 146 HWND mHwnd; 147 bool mAllowBlindAggregation; 148 RefPtr<IUnknown> mRealRootUnk; 149 RefPtr<IUnknown> mStdDispatch; 150 /** 151 * mWeakMsaaRoot, mWeakAccessible and mWeakDispatch are weak because they 152 * are interfaces that come from objects that we aggregate. Aggregated object 153 * interfaces share refcount methods with ours, so if we were to hold strong 154 * references to them, we would be holding strong references to ourselves, 155 * creating a cycle. 156 */ 157 MsaaRootAccessible* mWeakMsaaRoot; 158 IAccessible* mWeakAccessible; 159 IDispatch* mWeakDispatch; 160 IRawElementProviderSimple* mWeakUia; 161 static Maybe<bool> sShouldBlockUia; 162 }; 163 164 } // namespace a11y 165 } // namespace mozilla 166 167 #endif // mozilla_a11y_LazyInstantiator_h