summaryrefslogtreecommitdiffstats
path: root/accessible/windows/msaa/LazyInstantiator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/windows/msaa/LazyInstantiator.cpp')
-rw-r--r--accessible/windows/msaa/LazyInstantiator.cpp82
1 files changed, 74 insertions, 8 deletions
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