mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-05 02:39:10 +02:00
Previously, UIA requested certain cache domains just by firing events, even if no client cared about those events. This happened because unlike MSAA/IA2 win events, many UIA events include information about the thing that is changing; e.g. a name change event includes the new name. In addition, live region events are based on other events (name change, text inserted, text removed) and thus need to query whether the element is a live region, which requires additional domains. this caused our caching granularity tests to break, since those deliberately request only specific domains. Firing core events caused us to fire UIA events (even if a UIA client didn't actually query us), which in turn caused us to request domains the test doesn't expect. Less critical (but still important), this meant that these domains would always have been enabled as soon as an event is fired. That's not great, since it somewhat defeats the point of caching granularity. As mentioned in the previous patch, checking UiaClientsAreListening() is not sufficient to mitigate this in most cases. The ideal solution is perhaps to avoid firing those events in the first place. However, that would require checking for specific domains in the UIA code, which seems fragile if we change what domains are required for existing core methods, add new core methods, etc. Also, we should probably really be avoiding these events at the core level, rather than requiring OS specific code to filter these out. Instead, as a more straightforward solution, this patch adds a CacheDomainActivationBlocker RAII class to prevent requesting of new domains. This is used specifically when firing UIA events. The events we fire won't contain all the data they should, but that's okay because no client likely cares yet. We still use explicit client queries (plus a list of known clients) as a signal to request new domains, after which the events will contain information from all the domains that are now active. This approach could also easily be used on other platforms where needed. Differential Revision: https://phabricator.services.mozilla.com/D245373
72 lines
2.6 KiB
C++
72 lines
2.6 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set expandtab shiftwidth=2 tabstop=2: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "CacheConstants.h"
|
|
#include "nsAccessibilityService.h"
|
|
|
|
namespace mozilla::a11y {
|
|
|
|
// Get the set of cache domains required by the given cache domains, which will
|
|
// always be equal to or a superset of the given set of cache domains.
|
|
static uint64_t GetCacheDomainSuperset(uint64_t aCacheDomains) {
|
|
uint64_t allNecessaryDomains = aCacheDomains;
|
|
if (aCacheDomains & CacheDomain::TextOffsetAttributes) {
|
|
allNecessaryDomains |= CacheDomain::Text;
|
|
}
|
|
if (aCacheDomains & CacheDomain::TextBounds) {
|
|
allNecessaryDomains |= CacheDomain::Text;
|
|
allNecessaryDomains |= CacheDomain::Bounds;
|
|
}
|
|
MOZ_ASSERT((allNecessaryDomains & aCacheDomains) == aCacheDomains,
|
|
"Return value is not a superset of the input.");
|
|
return allNecessaryDomains;
|
|
}
|
|
|
|
bool DomainsAreActive(uint64_t aRequiredCacheDomains) {
|
|
const uint64_t activeCacheDomains =
|
|
nsAccessibilityService::GetActiveCacheDomains();
|
|
const bool allRequiredDomainsAreActive =
|
|
(aRequiredCacheDomains & ~activeCacheDomains) == 0;
|
|
return allRequiredDomainsAreActive;
|
|
}
|
|
|
|
bool RequestDomainsIfInactive(uint64_t aRequiredCacheDomains) {
|
|
nsAccessibilityService* accService = GetAccService();
|
|
if (!accService) {
|
|
return true;
|
|
}
|
|
const uint64_t activeCacheDomains =
|
|
nsAccessibilityService::GetActiveCacheDomains();
|
|
const bool isMissingRequiredCacheDomain =
|
|
(aRequiredCacheDomains & ~activeCacheDomains) != 0;
|
|
if (isMissingRequiredCacheDomain) {
|
|
if (!accService->ShouldAllowNewCacheDomains()) {
|
|
// Return true to indicate that the domain is not active, but don't
|
|
// actually request it.
|
|
return true;
|
|
}
|
|
aRequiredCacheDomains = GetCacheDomainSuperset(aRequiredCacheDomains);
|
|
|
|
const uint64_t cacheDomains = aRequiredCacheDomains | activeCacheDomains;
|
|
#if defined(ANDROID)
|
|
// We might not be on the main Android thread, but we must be in order to
|
|
// send IPDL messages. Dispatch to the main thread to set cache domains.
|
|
NS_DispatchToMainThread(
|
|
NS_NewRunnableFunction("a11y::SetCacheDomains", [cacheDomains]() {
|
|
if (nsAccessibilityService* accService = GetAccService()) {
|
|
accService->SetCacheDomains(cacheDomains);
|
|
}
|
|
}));
|
|
return true;
|
|
#endif
|
|
|
|
accService->SetCacheDomains(cacheDomains);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
} // namespace mozilla::a11y
|