summaryrefslogtreecommitdiffstats
path: root/accessible/windows/msaa
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/windows/msaa')
-rw-r--r--accessible/windows/msaa/IUnknownImpl.h42
-rw-r--r--accessible/windows/msaa/LazyInstantiator.cpp82
-rw-r--r--accessible/windows/msaa/LazyInstantiator.h27
-rw-r--r--accessible/windows/msaa/Platform.cpp1
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,