This shouldn't happen, but the COM runtime seems to do this sometimes.
I can't reproduce it and I haven't been able to fathom what causes it.
I suspect a Windows bug or a bug in some third party software.
This leads to trying to check the UIA pref from the wrong thread, which is not allowd and causes a crash.
Differential Revision: https://phabricator.services.mozilla.com/D248558
This is the scenario for this bug:
1. A UIA client retrieved a range for the caret at the end of a text input at the end of a document, collapsed at (input, 2).
2. Backspace was pressed, removing the last character, so (input, 2) was no longer valid.
3. The UIA client attempted to call GetAttributeValue on the previously fetched range.
4. FindTextAttrsStart couldn't move further, so it returned the document end point, (input, 1).
5. Because the range contained (input, 2), the search point was never less than the end point, so we got stuck in an infinite loop in GetAttributeValue.
To fix this, UiaTextRange now restricts offsets to the length of the leaf Accessibles when reconstructing the TextLeafRange.
Differential Revision: https://phabricator.services.mozilla.com/D248734
I removed this behaviour in bug 1951573.
Unfortunately, it turns out that contrary to the spec (which says "1 or more selections"), NVDA depends on this behaviour.
Reinstate this by supporting kRemoveAllExistingSelectedRanges in HyperTextAccessibleBase::RemoveFromSelection and using that.
Differential Revision: https://phabricator.services.mozilla.com/D247875
When we descend to the end for an embedded object character, we get the position after the last character inside that embedded object.
This isn't what we want for selections because the end offset should be exclusive, not inclusive.
Descending to the end means we include the entire content of the embedded object instead of excluding it.
Instead, always descend to the start.
Differential Revision: https://phabricator.services.mozilla.com/D247872
When a UIA client first queries us, the accessibility engine hasn't yet been initialised.
Previously, this also meant that we hadn't yet called InitConsumers() to figure out which Windows clients were present.
This in turn meant that we would initially believe UIA should be enabled, even if we later realised NVDA/a Vispero product was present and then believed it should be disabled.
To fix this, call InitConsumers() appropriately if it hasn't been called yet.
Even with the above fix, the following scenario might still be possible:
1. UIA is enabled.
2. A client QueryInterfaces to IRawElementProviderSimple.
3. UIA gets disabled.
4. Only then does the client try to call a method on IRawElementProviderSimple.
In this scenario, LazyInstantiator::MaybeResolveRoot won't set mWeakUia, but the IRawElementProviderSimple method will try to use mWeakUia, causing a crash.
To fix this, add a new RESOLVE_ROOT_UIA macro used by IRawElementProviderSimple methods.
In addition to calling RESOLVE_ROOT, this also checks mWeakUia and fails gracefully if that is null.
Differential Revision: https://phabricator.services.mozilla.com/D247504
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
Previously, we did call UiaClientsAreListening(), but only just before we fired the event.
However, there's no point doing any work at all to figure out what UIA event to fire, what data to include, etc. if there are no clients listening.
Therefore, we now do this check as early as possible.
In practice, this doesn't really help us much.
At least on some systems, there is always a UIA client listening somewhere, even if it's not specifically listening to or querying Firefox.
Unfortunately, the call is no more granular than that; it's just a simple boolean, presumably determining whether any clients are listening on the active desktop or session.
Even so, this change gives us the maximum possible benefit and is probably easier to reason about.
Differential Revision: https://phabricator.services.mozilla.com/D245372
JAWS and NVDA will continue to use IA2 in Firefox.
However, enabling native UIA in Gecko causes them both to try to use UIA, which causes breakage.
The same is presumably true for other Vispero products, as they use components shared with JAWS.
Future versions of these products will handle this correctly themselves.
Until then, disable UIA when these products are detected.
As part of this, the UIA pref has been changed from a bool to a uint32_t.
This will cause existing configurations of this pref to be reset to the default, but this is okay because this pref has never been documented, exposed in the UI or intended for public usage.
This allows for three values: 0 to never enable, 1 to always enable and 2 to enable unless incompatible clients are detected.
This makes it possible for developers to test those clients with Gecko's UIA implementation when necessary.
Differential Revision: https://phabricator.services.mozilla.com/D243245
Initially, this just checks the accessibility.uia.enable pref.
Other checks will be added in subsequent patches.
All callers which previously checked the pref directly now call this function.
Differential Revision: https://phabricator.services.mozilla.com/D243244
Previously, the LocalAccessible implementation of ISimpleDOM allowed clients to walk to DOM nodes which were not included in the accessibility tree.
Thus, it was necessary for sdnAccessible to be constructed with either an Accessible or a DOM node.
Now that this functionality has been removed, we no longer need to support construction with a DOM node.
This allows other code such as QueryInterface to be simplified as well, since an sdnAccessible now always has a corresponding MsaaAccessible.
Differential Revision: https://phabricator.services.mozilla.com/D241806
We have a lot of ISimpleDOM code which only works for LocalAccessible.
Because all web content uses RemoteAccessible now, practically, the only usable ISimpleDOM functionality is that which works for RemoteAccessible.
Therefore, remove all code that only works for LocalAccessible.
Differential Revision: https://phabricator.services.mozilla.com/D241805
Previously, a caller had to first retrieve all selection ranges and then remove them individually.
This makes it awkward to perform a fairly common operation.
Differential Revision: https://phabricator.services.mozilla.com/D240274
Text children of links are (and should be) exposed in the UIA tree, but Narrator misbehaves when we return these from GetEnclosingElement.
Children of Accessibles for which MustPrune() returns true are not exposed in the UIA tree, so they shouldn't be returned by GetEnclosingElement.
Differential Revision: https://phabricator.services.mozilla.com/D239979
For now, the core SELECTABLE_TEXT state is only exposed on text containers, not on text leaves.
We may want to reconsider this at some point.
For now, just handle this case in the UIA code, since that's the only place it matters.
Differential Revision: https://phabricator.services.mozilla.com/D239855
For now, the core SELECTABLE_TEXT state is only exposed on text containers, not on text leaves.
We may want to reconsider this at some point.
For now, just handle this case in the UIA code, since that's the only place it matters.
Differential Revision: https://phabricator.services.mozilla.com/D239855
We need to support the Text pattern on text leaves to fix issues with Narrator.
Removing support on the root isn't strictly necessary, but the Text pattern isn't normally supported on a UIA Window and Chromium doesn't do this, so I think it's best to follow.
This change necessitated moving UiaText so that it is no longer inherited by ia2AccessibleHypertext.
I initially tried to inherit UiaText into uiaRawElmProvider, but that doesn't work because ITextProvider and ISelectionProvider both have a GetSelection method with the same signature.
This meant that the ISelectionProvider implementation of GetSelection in uiaRawElmProvider was overriding the implementation in UiaText.
Instead, UiaText has now been split into a separate object.
Differential Revision: https://phabricator.services.mozilla.com/D239811
These mitigations were implemented in AccessibleHandler in bug 1798098.
However, after CtW, AccessibleHandler no longer exists and these mitigations weren't ported across.
Differential Revision: https://phabricator.services.mozilla.com/D202369
These mitigations were implemented in AccessibleHandler in bug 1798098.
However, after CtW, AccessibleHandler no longer exists and these mitigations weren't ported across.
Differential Revision: https://phabricator.services.mozilla.com/D202369
The COM marshaler seems to do this sometimes, possibly to determine whether this is a COM proxy.
Our implementation can't be used off the main thread, so just return an error.
Differential Revision: https://phabricator.services.mozilla.com/D239082
It was possible for <input> and <textarea> to incorrectly report the IsReadOnly
property as "true" to UIA, particularly when empty. There is no text leaf in
empty text inputs, so our TextLeafPoint would point to the text field itself.
Code that retrieves attributes for UIA didn't handle this case, which caused AT
issues, such as Narrator failing to switch out of scan mode automatically.
This revision fixes the issue by properly checking for text fields when figuring
out whether a TextLeafPoint's Accessible is read-only. It also adds a test to
verify the same.
Differential Revision: https://phabricator.services.mozilla.com/D237644
This revision adds a loop condition to ensure we don't hit an infinite loop
while walking backwards in UiaTextRange::FindAttribute. It also adds a test to
verify that we won't hit this loop again.
Differential Revision: https://phabricator.services.mozilla.com/D237300
This revision implements ITextRangeProvider::FindText on UiaTextRange.
The function searches for a given string in the text range, forwards or
backwards, case-sensitive or not. The algorithm to do so uses a single
pass to build the range's text string plus an acceleration structure for
lookup later. It then calls Find (or RFind) on the maybe-lowercased
string before using that resulting index to binary search the
acceleration structure for the proper start and end indices of the
search string. Once it has those associated Accessibles, it builds a
text range and returns it.
This revision also implements tests for this functionality.
Differential Revision: https://phabricator.services.mozilla.com/D236304
This revision fixes MinGW builds by avoiding use of VariantCompare,
which isn't supported by MinGW currently. On non-MinGW Windows builds,
we use VariantCompare as usual.
Differential Revision: https://phabricator.services.mozilla.com/D236441
This is currently only used by GetSelection, but it will be used by GetVisibleRanges in a subsequent patch.
There is a slight functionality change here: if there are no ranges, this returns an empty array.
GetSelection is unclear about what should be done here, but the documentation for GetVisibleRanges explicitly states an empty array should be returned, so that's what we do.
GetSelection previously left the SAFEARRAY pointer uninitialised in this case, which is definitely nasty and unsafe.
Differential Revision: https://phabricator.services.mozilla.com/D236089
This revision implements UIA function ITextRangeProvider::FindAttribute,
which allows clients to search within a UiaTextRange for a range where a
given attribute matches a given value. This revision adds the
functionality and tests for that functionality. On the way, this
revision adds GetAttribute functionality for TextLeafPoint (it already
existed for TextLeafRange). This is useful for checking single points
without wasting work constructing or searching a range.
Differential Revision: https://phabricator.services.mozilla.com/D235395
Newer versions of mingw started #define'ing them, which conflicts with
the consts we declare for older versions that don't have them.
Differential Revision: https://phabricator.services.mozilla.com/D233594
Windows screen readers must call IAccessible2::attributes for every show or text inserted event in order to determine whether the inserted content is within a live region, since this is only exposed via an object attribute.
These attributes include group position attributes: posinset, setsize and level.
When thousands of items are being inserted into a container such as a list, these queries can become expensive, even despite some of the information being cached.
For IA2, including group position attributes is redundant in most cases, since there is a dedicated IAccessible2::groupPosition property for this purpose.
Similarly, Mac code sometimes calls Accessible::Attributes, but it never uses the group position attributes, since it can use Accessible::GroupPosition() instead.
That said, I don't know of a case where this is actually a problem in practice on mac.
To address this:
1. No longer return group position attributes in Accessible::Attributes.
2. XPCOM clients, including tests and DevTools, still depend on these attributes, so update xpcAccessible::GetAttributes to include them.
3. ATK has no dedicated group position query, so update the ATK code to include these attributes too.
4. On Android, we could call GroupPosition directly, but it's easier to just pass AccAttributes to AccessibleWrap::GetRoleDescription, so include these attributes there too.
5. As an exception, IA2 requires the level attribute for headings, so include them just for roles::HEADING.
Differential Revision: https://phabricator.services.mozilla.com/D231653
This revision implements supportable styles covered by
UIA_StyleIdAttributeId. Namely, this includes the heading levels,
quotes, and emphasis. These are implemented with Accessible role checks.
To get the levels, this revision makes GetLevel a public function. It
also adds constant definitions for MinGW builds. Finally, this revision
adds tests to the existing GetAttributeValue tests.
Differential Revision: https://phabricator.services.mozilla.com/D229082
Some UIA attributes are not yet defined on the version of MinGW that we are
using to build and test Gecko. Eventually, an upgrade to MinGW will make these
definitions redundant. In the meantime, this shim allows us to keep implementing
UIA features without breaking builds. The attributes defined in the new header
come directly from the UIAutomationClient.h file, and match the UIA docs.
Differential Revision: https://phabricator.services.mozilla.com/D228366
This revision implements the annotation types attribute and a few of its
associated annotation types. Namely, implemented here are SpellingError,
GrammarError, DataValidationError, and Highlighted. This revision also
implements tests for this new functionality.
Differential Revision: https://phabricator.services.mozilla.com/D227893
This revision implements GetAttributeValue on UiaTextRange. It does not add
support for every UIA text attribute, but does implement eight and lays the
groundwork to implement the rest. To keep GetAttributeValue straightforward, it
mainly contains a switch statement that dispatches a templated GetAttribute
function which makes use of an templated AttributeTraits struct to determine
whether the text attribute is uniform throughout the text range. Finally, this
revision adds a bunch of tests for this new functionality.
Differential Revision: https://phabricator.services.mozilla.com/D227765
This revision implements UIA's TextUnit_Format, a TextUnit used to position the
boundary of a text range based on the formatting attributes of the text. This
revision modifies FindTextAttrsStart such that it does not stop at container
boundaries, and will traverse to the next or previous leaf if necessary. With
this change, FindTextAttrsStart matches FindBoundary in that it returns the true
"start" of the text run. This revision then adds a call to FindTextAttrsStart in
UIA code, and many tests exercising TextUnit_Format.
Differential Revision: https://phabricator.services.mozilla.com/D226853