This revision modifies the way that ProcessMutationEvents works. Rather than
firing mutation events immediately, it instead causes them to be queued on
DocAccessibleChild via HandleAccEvent. The code then fires the events in batches
with a new IPC method, SendMutationEvents. The net effect of this change is a
significant reduction in pressure on the IPC system, in favor of fewer, larger
messages. For pages that generate many mutation events often, this represents a
big win for performance. Without this, the IPC queue can get backed up, failing
to keep up with the amount of accessibility IPC messages as they flood in.
The method of batching is carefully written to maximize the amount of
accessibles that can be touched in a mutation event batch without going
over the IPC message size limit. This revision does not implement size
tracking, but does make a reasonable approximation. With these changes,
heterogenous mutation event types can sit together in batches, including
sub-batches of show events. A side effect of this change is that initial
page load is further amalgamated; multiple document children that
produce separate calls to InsertIntoIpcTree now use this queueing
mechanism and can have their show events sent together.
Some messages may fire differently from their former ordering with this change,
particularly EVENT_MENUPOPUP_END for content processes. However, that event
appears to have been fired out of order with the existing code, meaning
that this change represents a fix to that ordering issue as well.
Finally, this revision makes a slight modification to an Android test
for clarity and correctness. I discovered this issue while debugging
event ordering and realized it was valuable to fix.
Differential Revision: https://phabricator.services.mozilla.com/D229842
We have RemoteAccessible::mParent and RemoteAccessible::mDoc, so DocAccessibleParent::mParentDoc was redundant.
Aside from the redundancy, this was one extra thing we needed to keep up to date and reason about.
This involved changing the call to RemoveChildDoc in Destroy to use Unbind instead because Unbind clears the parent RemoteAccessible, but RemoveChildDoc didn't.
That meant we had a dangling RemoteAccessible::mParent pointer, which was always a problem, but is more problematic now that we no longer have mParentDoc and the destructor checks the parent document.
Since Unbind is the only caller of RemoveChildDoc, RemoveChildDoc has been merged into Unbind.
This means there is now only a single place where child documents are unbound from their parent, which should make things easier to reason about.
Differential Revision: https://phabricator.services.mozilla.com/D218802
This is needed in order to support find in page on Android using remote caret events instead of virtual cursor change events.
Depends on D192641
Differential Revision: https://phabricator.services.mozilla.com/D192642
This is needed in order to support find in page on Android using remote caret events instead of virtual cursor change events.
Depends on D192641
Differential Revision: https://phabricator.services.mozilla.com/D192642
In the content process, we simply split into multiple calls when the number of Accessibles exceeds our maximum.
The maximum is calculated to allow for every Accessible to consume 2 KB in the IPDL message.
Currently, this means we split every 131072 Accessibles.
Of course, we could still exceed this IPDL message size if one or more Accessibles consumed a lot more than this; e.g. many labels longer than 2 KB.
However, this seems unlikely in the real world.
If this turns out to be a problem, we'll need to count the actual size of the serialized data for each Accessible.
For example, we could use AccAttributes::SizeOfExcludingThis, though that isn't exactly the serialized size.
I worry though that such data structure traversal could get expensive at scale.
In the parent process, we defer attaching the root of the new subtree to its parent until the final call.
This is achieved by saving the root during the first call and using that to attach and fire events in the final call.
Differential Revision: https://phabricator.services.mozilla.com/D184367
When we serialize a subtree, we put it into a flat list.
Previously, we included the child count for each Accessible so that we knew how many Accessibels to consume as children when de-serializing.
We also de-serialized recursively.
This made it very difficult to split serialization across IPDL calls, since we would always end up splitting in the middle of some Accessible's children.
Instead, we now no longer include the child count, but we do include the parent id and the index of the child in that parent.
This means that each Accessible can be de-serialized independently and iteratively, making it possible to split wherever we need to.
RemoteAccessible creation has also been separated from attachment of the child to its parent, since we will need this when splitting.
Differential Revision: https://phabricator.services.mozilla.com/D184366
On Windows, focus and caret move events include the caret rectangle.
This isn't used on other platforms.
To simplify the cross-platform interface (including Platform.h), remove the ifdefs from there.
However, we use ifdefs to avoid calculating the rectangle on non-Windows platforms, instead just sending an empty rectangle.
Differential Revision: https://phabricator.services.mozilla.com/D182138
This should fully eliminate the case where remote accessibles fail to
unregister because of the outer PresShell's lifecycle.
Differential Revision: https://phabricator.services.mozilla.com/D172473
After bug 1779156, show events were fired from RecvCache, rather than from RecvShowEvent.
This was done to ensure that cache data was available when the event was fired.
However, because RecvCache fired a show event for every initial cache push, this meant that it also fired one for the document itself, plus all the document's initial direct children.
Firing an event for the document caused problems for ATK, since the parent was null for all top level documents.
This also meant we were firing a lot of unnecessary show events, which could be a performance problem for documents with a lot of initial direct children.
To fix this, provide an explicit argument to PDocAccessible::Cache specifying whether to dispatch a show event or not.
This replaces the existing aFinal argument, which was never used.
Differential Revision: https://phabricator.services.mozilla.com/D163192
It might be possible for a short while to have a DocAccessibleParent which has been shut down but is still managed by its BrowserParent.
In that case, DocAccessibleParent::GetFrom might previously have found the document via its BrowsingContext, thus returning a destroyed document.
This could cause problems when returning the focus if the document itself was the last thing focused.
To fix this, clear the BrowsingContext when shutting down a DocAccessibleParent so that it can't be found this way.
There is one case during actor construction where we call MarkAsShutdown instead of Destroy, and MarkAsShutdown isn't supposed to do any cleanup.
To deal with this, don't set the BrowsingContext until we're sure we're not going to call MarkAsShutdown.
Differential Revision: https://phabricator.services.mozilla.com/D161421
It might be possible for a short while to have a DocAccessibleParent which has been shut down but is still managed by its BrowserParent.
In that case, DocAccessibleParent::GetFrom might previously have found the document via its BrowsingContext, thus returning a destroyed document.
This could cause problems when returning the focus if the document itself was the last thing focused.
To fix this, clear the BrowsingContext when shutting down a DocAccessibleParent so that it can't be found this way.
There is one case during actor construction where we call MarkAsShutdown instead of Destroy, and MarkAsShutdown isn't supposed to do any cleanup.
To deal with this, don't set the BrowsingContext until we're sure we're not going to call MarkAsShutdown.
I also added an assertion to DocAccessibleParent::GetAccessible, since we should really never call that on a destroyed document.
Differential Revision: https://phabricator.services.mozilla.com/D161421
We'd like to provide NODE_CHILD_OF and NODE_PARENT_OF relations in the parent
process, relying on cached information, to avoid sync IPDL messages. This
revision implements most of the use cases for this relation for remote
accessibles, notably setting aside handling of MathML's <mroot> parent/child
relation. ARIA trees, treegrids, lists, and so on are handled in the remote
accessible largely identically to how they were handled in LocalAccessible.
Rather than define a new rule for walking the tree to find children, this
revision unifies the ItemIterator so it works on generic Accessibles, and uses
it in RemoteAccessibleBase the same way it's used in LocalAccessible. The
special case carve-out for MSAA clients now exists as a simpler IsTopLevel
check in DocAccessibleParent.
Differential Revision: https://phabricator.services.mozilla.com/D159452
This revision slightly reworks the way that we calculate accessible bounds in
RemoteAccessibleBase::BoundsWithOffset. Rather than looking "below" the current
accessible for a doc accessible to determine whether we should apply a cached
cross-process offset, we instead look "above" the current accessible, to its
parent, to check for a cross-process offset to apply. Then, in ApplyTransform,
we ensure that we maintain that cross-process offset.
Differential Revision: https://phabricator.services.mozilla.com/D157240