The iterator uses both explicitly set element attributes and content attributes
with IDs to iterate over all associated elements
Differential Revision: https://phabricator.services.mozilla.com/D215688
Previously, we used the primary frame.
This was problematic for image map areas because they don't have a frame, so we were always using the top left of the entire image.
RelativeBounds has been overridden for image map areas to correctly calculate coordinates.
Therefore, rather than special casing image map areas again, use RelativeBounds in DispatchClickEvent.
Differential Revision: https://phabricator.services.mozilla.com/D229300
As part of these tests, we need to wait for all specified DOM events to fire on a node.
We do this by setting up a Promise for each event, wrapping these in a single Promise which resolves when all events fire, storing this wrapping Promise on the Window object, and later (in a separate task) waiting on this wrapping Promise.
Previously, after any event fired, we set the Window object variable holding the wrapping Promise to null in order to clean it up.
This resulted in a race condition where if the first event fired before the second task ran to wait on the wrapping Promise, the second task would simply await null, meaning that it didn't wait at all.
The practical upshot is that we could potentially pass the tests even if the required DOM events never fired and remain blissfully unaware.
To fix this, we instead clear the wrapping Promise variable in the second task after waiting on it.
Without this fix, the test I add in the next patch would pass even without the bug being fixed.
In addition, to make debugging timeouts easier, we now log the id of the element being tested.
Differential Revision: https://phabricator.services.mozilla.com/D229299
This just improves readability.
There should be no functional change except that I gave this Runnable a proper name while I was at it.
Differential Revision: https://phabricator.services.mozilla.com/D229298
We never set this argument to anything other than the default, which meant it always used the LocalAccessible's mContent.
This makes the argument unnecessary and potentially confusing in an area which is already a bit difficult to follow, so just remove it.
There should be no functional change.
Differential Revision: https://phabricator.services.mozilla.com/D229297
The iterator uses both explicitly set element attributes and content attributes
with IDs to iterate over all associated elements
Differential Revision: https://phabricator.services.mozilla.com/D215688
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
A container can recieve a content CSS property after its initial
construction. At that stage it should be considered a leaf. Its
children, who should be frameless at this point, should be pruned.
Differential Revision: https://phabricator.services.mozilla.com/D228484
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
<textarea type="password"> isn't a thing.
However, we use HTMLTextFieldAccessible for both text <kinput> and <textarea>, and NativeState() wasn't restricting the password check.
Now, we restrict the password check to <input>.
Differential Revision: https://phabricator.services.mozilla.com/D227794
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
This is vestigial dead code from before CtW when HyperTextAccessible used TextAttrsMgr to calculate offsets for text attribute runs.
Now, offset calculation is handled by TextLeafPoint::FindTextAttrsStart and HyperTextAccessibleBase::TextAttributes.
Aside from removing code directly related to offsets, this also involved removal of TextAttr::Equal and TextAttr::GetValueFor.
These were only used for offset calculation.
Even if we wanted something similar in future, these can't be made compatible with RemoteAccessible in their current form.
Differential Revision: https://phabricator.services.mozilla.com/D227312
MOZ_RUNINIT => initialized at runtime
MOZ_CONSTINIT => initialized at compile time
MOZ_GLOBINIT => initialized either at runtime or compile time, depending on template parameter, macro parameter etc
This annotation is only understood by our clang-tidy plugin. It has no
effect on regular compilation.
Differential Revision: https://phabricator.services.mozilla.com/D223341
Previously, scrolling start events always fired on an Accessible for an element, never a text leaf.
However, a text fragment starts in a text leaf node and there may be many other children of the parent element prior to the start of the text fragment.
We want to get a11y clients as close as possible to the fragment, so fire the event on the text leaf node instead.
Unfortunately, we can't fire the Windows event on text leaf nodes, so we have to override this to use the parent in Windows specific code.
Fortunately, we can expose the highlight on Windows via text attributes, so clients can find out exactly what is highlighted, albeit with a bit more work.
This text leaf change is of most benefit on Android, where we can't expose the highlight, but we can move accessibility focus to a text leaf.
Differential Revision: https://phabricator.services.mozilla.com/D226587
Each browser test file is run with a separate instance of shared-head.js and thus a distinct WebSocket connection to the a11y Python runner.
pywebsocket3 is multi-threaded and may thus choose different threads to handle different WebSocket requests.
Python comtypes implicitly initialises COM when it is imported, but COM initialisation is thread specific and Python modules are cached, so this only applies to the thread on which comtypes was imported.
These factors were causing problems such as event timeouts when running multiple IA2 test files because IA2 relies on COM being initialised.
To fix this, add a setup() function to a11y_setup.py which is called when a request is handled.
For Windows, this calls CoInitialize once in each thread in which it is run.
Differential Revision: https://phabricator.services.mozilla.com/D227143
The target might be an element for which we don't create an Accessible; e.g. a <b> element.
Previously, we wouldn't fire an event in NotifyOfAnchorJumpTo and would instead defer the event until the next document focus.
However, the document might already have focus, in which case we won't fire this event when the user expects it (if ever).
Instead, use GetAccessibleOrContainer, which is also consistent with the deferred anchor jump code in FocusManager.
This means we will fire the event on the correct container Accessible immediately.
Differential Revision: https://phabricator.services.mozilla.com/D226437
Previously, scrolling start events always fired on an Accessible for an element, never a text leaf.
However, a text fragment starts in a text leaf node and there may be many other children of the parent element prior to the start of the text fragment.
We want to get a11y clients as close as possible to the fragment, so fire the event on the text leaf node instead.
Unfortunately, we can't fire the Windows event on text leaf nodes, so we have to override this to use the parent in Windows specific code.
Fortunately, we can expose the highlight on Windows via text attributes, so clients can find out exactly what is highlighted, albeit with a bit more work.
This text leaf change is of most benefit on Android, where we can't expose the highlight, but we can move accessibility focus to a text leaf.
Differential Revision: https://phabricator.services.mozilla.com/D226587
The target might be an element for which we don't create an Accessible; e.g. a <b> element.
Previously, we wouldn't fire an event in NotifyOfAnchorJumpTo and would instead defer the event until the next document focus.
However, the document might already have focus, in which case we won't fire this event when the user expects it (if ever).
Instead, use GetAccessibleOrContainer, which is also consistent with the deferred anchor jump code in FocusManager.
This means we will fire the event on the correct container Accessible immediately.
Differential Revision: https://phabricator.services.mozilla.com/D226437
If no text is selected, this is the same as passing the caret offset, since the selection range is already where we want it.
However, if text is selected, this allows the caller to replace it, just as it would be when pasting using the keyboard or GUI.
Note that this doesn't break any existing expectations because TEXT_OFFSET_CARET was never supported for this method previously.
This allows us to remove the DeleteText call from Android SessionAccessibility::Paste.
This separate DeleteText call was causing problems because it could result in the deletion and the insertion happening in two separate ticks, resulting in incorrect events.
Now, this should always happen in a single tick.
Differential Revision: https://phabricator.services.mozilla.com/D226108
Since the method is deferred we need to do extra guesswork for possible
situtations where the name has changed because we don't have the
privilege to calculate the name in-line when content is deleted.
I tried to account for all cases as we have in our test coverage. I
hope that if there are edge cases they are false positives, and we are
firing extra name changes and not the opposite.
Differential Revision: https://phabricator.services.mozilla.com/D223877