Adjust AXTree::Unserialize to notify events outside of UpdateNode [2/3]
This change separates updating AXNodeData in AXTree::UpdateNode from
notifying that the node data will change, and node data has changed.
---
Problem :
AXTree notifies AXTreeObservers of node and subtree changes in the middle
of a tree update, which means observers may be seeing a tree state that's
incomplete. This can lead to subtle bugs when observers access nodes in the
AXTree other than the node being updated.
e.g. |GetUnignoredParent| may be invalid during a notification, but
correct afterwards.
Proposed solution :
Separate notifications from updates in AXTree::Unserialize.
This requires the following steps :
1. Record all operations that would be performed on the tree.
2. Fire all on destroy and OnNodeDataWillChange callbacks.
3. Apply all update operations.
4. Fire all created and node data changed callbacks.
For additional context, see these comments by Nektarios and Dominic :
https://chromium-review.googlesource.com/c/chromium/src/+/1650222/20#message-ffe9bf96b616a915bebf2e69d7803bcae6a18b24
https://chromium-review.googlesource.com/c/chromium/src/+/1535171/69#message-7b62970b193439a1878d7339cdc94d2556d0a416
I plan to submit approximately 3 CLs to resolve this :
1. Handle Pre/Post Tree changes (create node / destroy subtree)
2. Handle Pre/Post Node data changes (attributes will / have changes)
3. Add DCHECKs to AXNode::*Unignored* accessors, along with any remaining
work required to do so, to help harden these paths.
Bug: 974444
Change-Id: Iade343a572003e31d79039b08cced689fb6e9cbe
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1710128
Commit-Queue: Adam Ettenberger <[email protected]>
Reviewed-by: Nektarios Paisios <[email protected]>
Reviewed-by: Kurt Catti-Schmidt <[email protected]>
Cr-Commit-Position: refs/heads/master@{#684391}
diff --git a/ui/accessibility/ax_tree.h b/ui/accessibility/ax_tree.h
index 9a4db98..b2dfc3c 100644
--- a/ui/accessibility/ax_tree.h
+++ b/ui/accessibility/ax_tree.h
@@ -214,9 +214,14 @@
AXNode* node,
const AXTreeUpdateState* update_state);
- void CallNodeChangeCallbacks(AXNode* node,
- const AXNodeData& old_data,
- const AXNodeData& new_data);
+ // Notify the delegate that a node will change its data.
+ void NotifyNodeDataWillChange(const AXNodeData& old_data,
+ const AXNodeData& new_data);
+
+ // Notify the delegate that |node| has changed its data.
+ void NotifyNodeDataHasBeenChanged(AXNode* node,
+ const AXNodeData& old_data,
+ const AXNodeData& new_data);
void UpdateReverseRelations(AXNode* node, const AXNodeData& new_data);