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.
Original Revision: https://phabricator.services.mozilla.com/D223877
Differential Revision: https://phabricator.services.mozilla.com/D225716
When we create a TextLeafAccessible for a CSS pseudo-element, we already use the alt text if present.
However, it seems layout sometimes re-renders the text of pseudo-elements.
Previously, a11y would update the text in this case like it would for any other TextLeafAccessible, thus overwriting the alt text with the text rendered by layout.
To fix this, we now skip updating text if CSS alt text is present.
Differential Revision: https://phabricator.services.mozilla.com/D211139
There's no call to AddRefreshObserver(FlushType::Layout), so we don't
need to track layout flushes. The only reason we need
mLayoutFlushObservers is so that reflows triggered from the style flush
get processed. But at that point, we can just flush layout directly.
There's no really good distinction between style flushes and layout
flushes with container queries anyways, so this makes the code simpler
to reason about.
Differential Revision: https://phabricator.services.mozilla.com/D209924
ContentRemoved recursively walks both AllChildrenIterator and direct DOM children.
In addition, we might get duplicate notifications from DOM and layout, plus PruneOrInsertSubtree might do a recursive walk and it too calls ContentRemoved.
To avoid this duplicate processing, keep a set of removed DOM nodes on the DocAccessible which we clear after mutation events are processed.
Differential Revision: https://phabricator.services.mozilla.com/D196707
std::sort used by nsTArray::Sort expects the comparator to be tolerant
for being called to compare the very same element with itself.
Differential Revision: https://phabricator.services.mozilla.com/D195482
This is just a "belt-and-suspenders" invariant tightening. Shouldn't impact
behavior at all, assuming that we don't call methods on NotificationController
objects that have been nerfed with Shutdown().
Differential Revision: https://phabricator.services.mozilla.com/D195321
If these assertions somehow fail, then we are probably doomed to crash anyway.
The new release assertions just make it so we'll crash in a controlled way,
with a more actionable backtrace, closer to the problem-spot.
This patch also removes one mDocument null-check that's becoming redundant
since it follows a release-assert that would make us abort if the pointer is
null.
Differential Revision: https://phabricator.services.mozilla.com/D195042
We can sometimes reach the code that this patch is touching, just we've been
shutdown (as can be seen by the fact that we have a null mDocument pointer); in
that case, it's problematic for us to be assigning 'mObservingState' here. The
mObservingState assignment is meant to be *undoing* the temporary assignments
earlier in the function, but in this post-Shutdown situation, it's actually
causing us to forget that we already unregistered as a refresh observer, in a
nested stack level's call to Shutdown().
I think this one place is the only mObservingState assignment that's got this
problem. The other mObservingState assignments should all be OK (they don't
need a "have we shut down" check), because they're all either:
a) modifying mObservingState to record an actual change that we just made to
our RefreshDriver registration,
...or:
b) immediately adjacent to code that dereferences mDocument, implying that
mDocument is known-to-be-non-null at that point, which means we know we haven't
been Shutdown.
This patch unblocks us from adding a release assert in the
NotificationController destructor in the next patch in this series. (Without
this patch, that assertion can be made to fail, via this inadvertent
mObservingState assignment.)
Depends on D195041
Differential Revision: https://phabricator.services.mozilla.com/D195200
If these assertions somehow fail, then we are probably doomed to crash anyway.
The new release assertions just make it so we'll crash in a controlled way,
with a more actionable backtrace, closer to the problem-spot.
This patch also removes one mDocument null-check that's becoming redundant
since it follows a release-assert that would make us abort if the pointer is
null.
Depends on D195041
Differential Revision: https://phabricator.services.mozilla.com/D195042
This patch does several things:
1. Remove virtual cursor doc accessible member.
2. Remove state-keeping nsAccessiblePivot implementation and replace it
with something that is much more similar to the native Pivot
interface.
3. Move nsIAccessiblePivot implementation to xpcom and rename it
xpcAccessiblePivot.
4. Delete mochitests and introduce browser tests.
5. Make new xpcom implementation work on remote accessibles as well.
Differential Revision: https://phabricator.services.mozilla.com/D181813
This revision updates DropMutationEvent such that it handles other event
types besides REORDER, HIDE, and SHOW. If we somehow put a different event
type through this function (particularly an inner reorder, which indicates
a reorder event that's already been dropped), we should (and now do) handle
it more gracefully.
Differential Revision: https://phabricator.services.mozilla.com/D182218
This patch does several things:
1. Remove virtual cursor doc accessible member.
2. Remove state-keeping nsAccessiblePivot implementation and replace it
with something that is much more similar to the native Pivot
interface.
3. Move nsIAccessiblePivot implementation to xpcom and rename it
xpcAccessiblePivot.
4. Delete mochitests and introduce browser tests.
5. Make new xpcom implementation work on remote accessibles as well.
Differential Revision: https://phabricator.services.mozilla.com/D181813
If we move an accessible via an aria-owns relocation on a grandparent, then move
it again via an aria-owns relocation on a parent, we can end up with multiple
hide events in the queue: one for the shallowest hide (of the grandparent), and
one for the hide of the grandchild accessible. We can't always coalesce (drop)
the hide event of the grandchild since the first move severs the relationship
between its parent and its grandparent. To address this, this revision stops us
from queueing a hide event on an accessible that's already being moved. This
revision also adds a test to verify we're getting the proper events.
Differential Revision: https://phabricator.services.mozilla.com/D180888
We only needed to defer events because of the need to wait for a parent COM proxy.
Similarly, sync text change events (as opposed to async) were only necessary with the COM proxy architecture.
Now that there are no COM proxies, neither of these are necessary.
Differential Revision: https://phabricator.services.mozilla.com/D177899
This was done using the following script:
```
matchingFiles=`git grep -l accessibility_cache_enabled`
sed -i 's/StaticPrefs::accessibility_cache_enabled_AtStartup/a11y::IsCacheActive/' $matchingFiles
for f in $matchingFiles; do
usesA11yPref=
grep -q StaticPrefs::accessibility_ $f && usesA11yPref=1
hasA11yInclude=
grep -q 'nsAccessibilityService.h' $f && hasA11yInclude=1
if [ -z $usesA11yPref ] && [ -z $hasA11yInclude ]; then
sed -i 's,mozilla/StaticPrefs_accessibility.h,nsAccessibilityService.h,' $f
elif [ -z $usesA11yPref ] && [ $hasA11yInclude ]; then
sed -i '/"mozilla.StaticPrefs_accessibility.h"/d' $f
elif [ $usesA11yPref ] && [ -z $hasA11yInclude ]; then
sed -i '/"mozilla.StaticPrefs_accessibility.h"/a#include "nsAccessibilityService.h"' $f
fi
done
```
Differential Revision: https://phabricator.services.mozilla.com/D177722
Previously, PushNameOrDescriptionChange wouldn't consider the target itself as a candidate for a name change event.
If the text of a text leaf changes without replacing the leaf, the only event we will get is text inserted on its parent.
If that parent calculated its name from its subtree, this meant that we wouldn't fire a name change in this case.
We address this by allowing this function to fire on the target itself in this case.
Differential Revision: https://phabricator.services.mozilla.com/D172953
As of the prior patch, these are no longer needed. I removed
these with a script, then ran clang-format on the files, then
manually reverted a few unrelated changed from the formatter.
Differential Revision: https://phabricator.services.mozilla.com/D164829
We use profiler categories to separate out the profiler markers for major
components, such as DOM or Layout, to quickly understand what is happening in
each of them: this will also be helpful for accessibility. One might be
concerned that we're adding too many categories but I think it's fine: the
accessibility category shouldn't appear if accessibility services aren't in use.
Furthermore, if accessibility code is running when it's unexpected, having the
accessibility category appear will only highlight that fact.
Differential Revision: https://phabricator.services.mozilla.com/D160846
If the process is asked to shut down while we're in the middle of handling long-running tasks, we should return early to avoid pointless work and allow the process to shut down sooner.
This patch adds ExpectingShutdown checks near various things which could potentially take a while; e.g. building the local tree, serializing the IPC tree, building the IPC cache, etc.
Differential Revision: https://phabricator.services.mozilla.com/D156809
This was moved to a post refresh observer on the misunderstanding that this would allow us to benefit from retained display lists.
In reality, it doesn't; work would need to be done in layout to benefit from those, and since there are different display lists for hit testing and painting, this may not be feasible anyway.
Furthermore, the post refresh implementation was broken because WillRefresh often removes the post refresh observer, which meant that a viewport cache update was never actually pushed!
We could fix this by adding the post refresh observer only if the viewport cache is dirty, removing the post refresh observer in DidRefresh and also removing the post refresh observer in Shutdown only if the viewport cache is dirty.
However, given that we can't benefit from retained display lists anyway, using a post refresh observer doesn't serve any purpose at this stage.
Among other things, this fixes intermittent problems with image maps, which often get inserted into the tree after the initial tree is built.
Differential Revision: https://phabricator.services.mozilla.com/D149492
This hittesting approach is borrowed from our Android implementation.
We maintain a cache of ID's for accessibles which are visible in the viewport.
This cache is created with a call to `nsLayoutUtils::GetFramesForArea`, which
returns frames in the viewport, in hittesting order.
In the parent process, we walk through the cache, keeping track of accs whose
bounds contain the hittesting point. Depending on if we're searching for the
direct child, or the deepest child, we walk the entire cache or return the
first match.
Each document (in the content process) maintains a dirty bit, which gets set
any time an acc it contains bundles either a text update, or an update that
affects bounds. We check whether this bit is set in `DidRefresh` after getting
a notification from our post-refresh observer. If that bit is set, we
queue a cache update for the `::Viewport` domain on the current document.
Because this cache depends on the viewport being painted, we include the
`IgnorePaintSuppression` flag in our `GetFramesForArea` call. This ensures
the display lists are built before the page finishes loading.
Differential Revision: https://phabricator.services.mozilla.com/D147225
This hittesting approach is borrowed from our Android implementation.
We maintain a cache of ID's for accessibles which are visible in the viewport.
This cache is created with a call to `nsLayoutUtils::GetFramesForArea`, which
returns frames in the viewport, in hittesting order.
In the parent process, we walk through the cache, keeping track of accs whose
bounds contain the hittesting point. Depending on if we're searching for the
direct child, or the deepest child, we walk the entire cache or return the
first match.
Each document (in the content process) maintains a dirty bit, which gets set
any time an acc it contains bundles either a text update, or an update that
affects bounds. We check whether this bit is set in `DidRefresh` after getting
a notification from our post-refresh observer. If that bit is set, we
queue a cache update for the `::Viewport` domain on the current document.
Because this cache depends on the viewport being painted, we include the
`IgnorePaintSuppression` flag in our `GetFramesForArea` call. This ensures
the display lists are built before the page finishes loading.
Differential Revision: https://phabricator.services.mozilla.com/D147225
Layout sends a11y text update notifications during reflow even if the text hasn't changed.
TextUpdater already detects this case, so just move our cache update calls to TextUpdater.
Differential Revision: https://phabricator.services.mozilla.com/D147656
Previously, even for remote in-process iframes, it was only possible to retrieve the top level BrowsingContext for the remote process by getting the managing BrowserParent.
This makes it possible to get the correct BrowsingContext even for in-process iframes.
Differential Revision: https://phabricator.services.mozilla.com/D147716
It's critical that we fire mutation events first because our RemoteAccessible tree is created thus and we can't fire events on RemoteAccessibles we haven't created yet.
Beyond that, though, focus events are of primary importance.
See the comments in EventQueue::ProcessEventQueue for the reasons.
Differential Revision: https://phabricator.services.mozilla.com/D145319
It's critical that we fire mutation events first because our RemoteAccessible tree is created thus and we can't fire events on RemoteAccessibles we haven't created yet.
Beyond that, though, focus events are of primary importance.
See the comments in EventQueue::ProcessEventQueue for the reasons.
Differential Revision: https://phabricator.services.mozilla.com/D145319
If text or bounds change, it's very likely that line starts have changed too, so we push an update for them.
However, if a non-rectangular text span changes its line wrapping without changing its text, the bounds might not change.
In that case, we still get a bounds cache update request; we just determine not to push bounds.
This happens a lot, though.
To limit this, we compare against the cached first line start in LocalAccessible and push an update only if it's different.
If text and bounds both change, we don't want to push two separate cache updates.
We use queued cache updates to prevent this.
This necessitated moving where we send queued cache updates so that we do it before firing mutation events, since clients might need the text to be up to date when handling those events.
Differential Revision: https://phabricator.services.mozilla.com/D144949