diff options
Diffstat (limited to 'accessible/windows/msaa')
-rw-r--r-- | accessible/windows/msaa/IUnknownImpl.h | 42 | ||||
-rw-r--r-- | accessible/windows/msaa/LazyInstantiator.cpp | 82 | ||||
-rw-r--r-- | accessible/windows/msaa/LazyInstantiator.h | 27 | ||||
-rw-r--r-- | accessible/windows/msaa/Platform.cpp | 1 |
4 files changed, 122 insertions, 30 deletions
diff --git a/accessible/windows/msaa/IUnknownImpl.h b/accessible/windows/msaa/IUnknownImpl.h index 7935ebedda..757bff44bf 100644 --- a/accessible/windows/msaa/IUnknownImpl.h +++ b/accessible/windows/msaa/IUnknownImpl.h @@ -47,31 +47,31 @@ class AutoRefCnt { } // namespace a11y } // namespace mozilla -#define DECL_IUNKNOWN \ - public: \ - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**); \ - ULONG STDMETHODCALLTYPE AddRef() override { \ - MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \ - ++mRefCnt; \ - return mRefCnt; \ - } \ - ULONG STDMETHODCALLTYPE Release() override { \ - MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \ - --mRefCnt; \ - if (mRefCnt) return mRefCnt; \ - \ - delete this; \ - return 0; \ - } \ - \ - private: \ - mozilla::a11y::AutoRefCnt mRefCnt; \ - \ +#define DECL_IUNKNOWN \ + public: \ + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**) override; \ + ULONG STDMETHODCALLTYPE AddRef() override { \ + MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \ + ++mRefCnt; \ + return mRefCnt; \ + } \ + ULONG STDMETHODCALLTYPE Release() override { \ + MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \ + --mRefCnt; \ + if (mRefCnt) return mRefCnt; \ + \ + delete this; \ + return 0; \ + } \ + \ + private: \ + mozilla::a11y::AutoRefCnt mRefCnt; \ + \ public: #define DECL_IUNKNOWN_INHERITED \ public: \ - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**); + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**) override; #define IMPL_IUNKNOWN_QUERY_HEAD(Class) \ STDMETHODIMP \ diff --git a/accessible/windows/msaa/LazyInstantiator.cpp b/accessible/windows/msaa/LazyInstantiator.cpp index 61814d059a..3ace26d9c0 100644 --- a/accessible/windows/msaa/LazyInstantiator.cpp +++ b/accessible/windows/msaa/LazyInstantiator.cpp @@ -12,6 +12,7 @@ #include "mozilla/a11y/Platform.h" #include "mozilla/Assertions.h" #include "mozilla/mscom/ProcessRuntime.h" +#include "mozilla/StaticPrefs_accessibility.h" #include "mozilla/UniquePtr.h" #include "mozilla/WinHeaderOnlyUtils.h" #include "MsaaRootAccessible.h" @@ -41,9 +42,9 @@ static const wchar_t kLazyInstantiatorProp[] = Maybe<bool> LazyInstantiator::sShouldBlockUia; -/* static */ -already_AddRefed<IAccessible> LazyInstantiator::GetRootAccessible(HWND aHwnd) { - RefPtr<IAccessible> result; +template <class T> +already_AddRefed<T> LazyInstantiator::GetRoot(HWND aHwnd) { + RefPtr<T> result; // At this time we only want to check whether the acc service is running. We // don't actually want to create the acc service yet. if (!GetAccService()) { @@ -80,7 +81,7 @@ already_AddRefed<IAccessible> LazyInstantiator::GetRootAccessible(HWND aHwnd) { if (!rootAcc->IsRoot()) { // rootAcc might represent a popup as opposed to a true root accessible. // In that case we just use the regular LocalAccessible::GetNativeInterface. - rootAcc->GetNativeInterface(getter_AddRefs(result)); + result = MsaaAccessible::GetFrom(rootAcc); return result.forget(); } @@ -90,7 +91,7 @@ already_AddRefed<IAccessible> LazyInstantiator::GetRootAccessible(HWND aHwnd) { // don't need LazyInstantiator's capabilities anymore (since a11y is already // running). We can bypass LazyInstantiator by retrieving the internal // unknown (which is not wrapped by the LazyInstantiator) and then querying - // that for IID_IAccessible. + // that for the interface we want. RefPtr<IUnknown> punk(msaaRoot->GetInternalUnknown()); MOZ_ASSERT(punk); @@ -98,10 +99,24 @@ already_AddRefed<IAccessible> LazyInstantiator::GetRootAccessible(HWND aHwnd) { return nullptr; } - punk->QueryInterface(IID_IAccessible, getter_AddRefs(result)); + punk->QueryInterface(__uuidof(T), getter_AddRefs(result)); return result.forget(); } +/* static */ +already_AddRefed<IAccessible> LazyInstantiator::GetRootAccessible(HWND aHwnd) { + return GetRoot<IAccessible>(aHwnd); +} + +/* static */ +already_AddRefed<IRawElementProviderSimple> LazyInstantiator::GetRootUia( + HWND aHwnd) { + if (!StaticPrefs::accessibility_uia_enable()) { + return nullptr; + } + return GetRoot<IRawElementProviderSimple>(aHwnd); +} + /** * When marshaling an interface, COM makes a whole bunch of QueryInterface * calls to determine what kind of marshaling the interface supports. We need @@ -135,7 +150,8 @@ LazyInstantiator::LazyInstantiator(HWND aHwnd) mAllowBlindAggregation(false), mWeakMsaaRoot(nullptr), mWeakAccessible(nullptr), - mWeakDispatch(nullptr) { + mWeakDispatch(nullptr), + mWeakUia(nullptr) { MOZ_ASSERT(aHwnd); // Assign ourselves as the designated LazyInstantiator for aHwnd DebugOnly<BOOL> setPropOk = @@ -374,9 +390,16 @@ LazyInstantiator::MaybeResolveRoot() { if (FAILED(hr)) { return hr; } - // mWeakAccessible is weak, so don't hold a strong ref mWeakAccessible->Release(); + if (StaticPrefs::accessibility_uia_enable()) { + hr = mRealRootUnk->QueryInterface(IID_IRawElementProviderSimple, + (void**)&mWeakUia); + if (FAILED(hr)) { + return hr; + } + mWeakUia->Release(); + } // Now that a11y is running, we don't need to remain registered with our // HWND anymore. @@ -401,6 +424,9 @@ IMPL_IUNKNOWN_QUERY_IFACE_AMBIGIOUS(IUnknown, IAccessible) IMPL_IUNKNOWN_QUERY_IFACE(IAccessible) IMPL_IUNKNOWN_QUERY_IFACE(IDispatch) IMPL_IUNKNOWN_QUERY_IFACE(IServiceProvider) +if (StaticPrefs::accessibility_uia_enable()) { + IMPL_IUNKNOWN_QUERY_IFACE(IRawElementProviderSimple) +} // See EnableBlindAggregation for comments. if (!mAllowBlindAggregation) { return E_NOINTERFACE; @@ -771,5 +797,45 @@ LazyInstantiator::QueryService(REFGUID aServiceId, REFIID aServiceIid, return servProv->QueryService(aServiceId, aServiceIid, aOutInterface); } +STDMETHODIMP +LazyInstantiator::get_ProviderOptions( + __RPC__out enum ProviderOptions* aOptions) { + // This method is called before a UIA connection is fully established and thus + // before we can detect the client. We must not call RESOLVE_ROOT here because + // this might turn out to be a client we want to block. + if (!aOptions) { + return E_INVALIDARG; + } + *aOptions = uiaRawElmProvider::kProviderOptions; + return S_OK; +} + +STDMETHODIMP +LazyInstantiator::GetPatternProvider( + PATTERNID aPatternId, __RPC__deref_out_opt IUnknown** aPatternProvider) { + RESOLVE_ROOT; + return mWeakUia->GetPatternProvider(aPatternId, aPatternProvider); +} + +STDMETHODIMP +LazyInstantiator::GetPropertyValue(PROPERTYID aPropertyId, + __RPC__out VARIANT* aPropertyValue) { + RESOLVE_ROOT; + return mWeakUia->GetPropertyValue(aPropertyId, aPropertyValue); +} + +STDMETHODIMP +LazyInstantiator::get_HostRawElementProvider( + __RPC__deref_out_opt IRawElementProviderSimple** aRawElmProvider) { + // This method is called before a UIA connection is fully established and thus + // before we can detect the client. We must not call RESOLVE_ROOT here because + // this might turn out to be a client we want to block. + if (!aRawElmProvider) { + return E_INVALIDARG; + } + *aRawElmProvider = nullptr; + return UiaHostProviderFromHwnd(mHwnd, aRawElmProvider); +} + } // namespace a11y } // namespace mozilla diff --git a/accessible/windows/msaa/LazyInstantiator.h b/accessible/windows/msaa/LazyInstantiator.h index 00fa4ba6ed..adbb0f70b5 100644 --- a/accessible/windows/msaa/LazyInstantiator.h +++ b/accessible/windows/msaa/LazyInstantiator.h @@ -13,6 +13,7 @@ #include "nsString.h" #include <oleacc.h> +#include <uiautomation.h> class nsIFile; @@ -29,10 +30,14 @@ class MsaaRootAccessible; * services in order to fulfill; and * (2) LazyInstantiator::ShouldInstantiate returns true. */ -class LazyInstantiator final : public IAccessible, public IServiceProvider { +class LazyInstantiator final : public IAccessible, + public IServiceProvider, + public IRawElementProviderSimple { public: [[nodiscard]] static already_AddRefed<IAccessible> GetRootAccessible( HWND aHwnd); + [[nodiscard]] static already_AddRefed<IRawElementProviderSimple> GetRootUia( + HWND aHwnd); static void EnableBlindAggregation(HWND aHwnd); // IUnknown @@ -83,6 +88,22 @@ class LazyInstantiator final : public IAccessible, public IServiceProvider { STDMETHODIMP QueryService(REFGUID aServiceId, REFIID aServiceIid, void** aOutInterface) override; + // IRawElementProviderSimple + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ProviderOptions( + /* [retval][out] */ __RPC__out enum ProviderOptions* aProviderOptions); + + virtual HRESULT STDMETHODCALLTYPE GetPatternProvider( + /* [in] */ PATTERNID aPatternId, + /* [retval][out] */ __RPC__deref_out_opt IUnknown** aPatternProvider); + + virtual HRESULT STDMETHODCALLTYPE GetPropertyValue( + /* [in] */ PROPERTYID aPropertyId, + /* [retval][out] */ __RPC__out VARIANT* aPropertyValue); + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_HostRawElementProvider( + /* [retval][out] */ __RPC__deref_out_opt IRawElementProviderSimple** + aRawElmProvider); + /** * We cache the result of UIA detection because it could be expensive if a * client repeatedly queries us. This function is called to reset that cache @@ -117,6 +138,9 @@ class LazyInstantiator final : public IAccessible, public IServiceProvider { void TransplantRefCnt(); void ClearProp(); + template <class T> + static already_AddRefed<T> GetRoot(HWND aHwnd); + private: mozilla::a11y::AutoRefCnt mRefCnt; HWND mHwnd; @@ -133,6 +157,7 @@ class LazyInstantiator final : public IAccessible, public IServiceProvider { MsaaRootAccessible* mWeakMsaaRoot; IAccessible* mWeakAccessible; IDispatch* mWeakDispatch; + IRawElementProviderSimple* mWeakUia; static Maybe<bool> sShouldBlockUia; }; diff --git a/accessible/windows/msaa/Platform.cpp b/accessible/windows/msaa/Platform.cpp index f4d1c7b176..eaf9e7c126 100644 --- a/accessible/windows/msaa/Platform.cpp +++ b/accessible/windows/msaa/Platform.cpp @@ -129,6 +129,7 @@ void a11y::PlatformShowHideEvent(Accessible* aTarget, Accessible*, bool aInsert, void a11y::PlatformSelectionEvent(Accessible* aTarget, Accessible*, uint32_t aType) { MsaaAccessible::FireWinEvent(aTarget, aType); + uiaRawElmProvider::RaiseUiaEventForGeckoEvent(aTarget, aType); } static bool GetInstantiatorExecutable(const DWORD aPid, |