[Fuchsia] Add special handling of a11y root node

The root of the Fuchsia semantic tree always has root id 0. This isn't
a constraint in Chromium, so some special handling has been added to
ensure the semantic tree received by Fuchsia maintains a consistent,
valid state.

Test: Expanded AccessibilityBridgeTest.

Bug: fuchsia:42172
Change-Id: Ic1e2398e0a6793bcbfef36643af64b78f79fea22
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1954321
Commit-Queue: Sharon Yang <[email protected]>
Reviewed-by: Kevin Marshall <[email protected]>
Cr-Commit-Position: refs/heads/master@{#726157}
diff --git a/fuchsia/engine/browser/accessibility_bridge.h b/fuchsia/engine/browser/accessibility_bridge.h
index 1e93610..936d2baf 100644
--- a/fuchsia/engine/browser/accessibility_bridge.h
+++ b/fuchsia/engine/browser/accessibility_bridge.h
@@ -50,9 +50,30 @@
  private:
   FRIEND_TEST_ALL_PREFIXES(AccessibilityBridgeTest, OnSemanticsModeChanged);
 
-  // Handles batching of semantic nodes and committing them to the SemanticTree.
+  // A struct used for caching semantic information. This allows for updates and
+  // deletes to be stored in the same vector to preserve all ordering
+  // information.
+  struct SemanticUpdateOrDelete {
+    enum Type { UPDATE, DELETE };
+
+    SemanticUpdateOrDelete(SemanticUpdateOrDelete&& m);
+    SemanticUpdateOrDelete(Type type,
+                           fuchsia::accessibility::semantics::Node node,
+                           uint32_t id_to_delete);
+    ~SemanticUpdateOrDelete() = default;
+
+    Type type;
+    fuchsia::accessibility::semantics::Node update_node;
+    uint32_t id_to_delete;
+  };
+
+  // Processes pending data and commits it to the Semantic Tree.
   void TryCommit();
 
+  // Helper function for TryCommit() that sends the contents of |to_send_| to
+  // the Semantic Tree, starting at |start|.
+  void DispatchSemanticsMessages(size_t start, size_t size);
+
   // Callback for SemanticTree::CommitUpdates.
   void OnCommitComplete();
 
@@ -60,6 +81,11 @@
   // root.
   uint32_t ConvertToFuchsiaNodeId(int32_t ax_node_id);
 
+  // Deletes all nodes in subtree rooted at and including |node|, unless |node|
+  // is the root of the tree.
+  // |tree| and |node| are owned by the accessibility bridge.
+  void DeleteSubtree(ui::AXTree* tree, ui::AXNode* node);
+
   // content::WebContentsObserver implementation.
   void AccessibilityEventReceived(
       const content::AXEventNotificationDetails& details) override;
@@ -76,6 +102,7 @@
 
   // ui::AXTreeObserver implementation.
   void OnNodeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override;
+  void OnSubtreeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override;
   void OnAtomicUpdateFinished(
       ui::AXTree* tree,
       bool root_changed,
@@ -86,8 +113,8 @@
   content::WebContents* web_contents_;
   ui::AXSerializableTree tree_;
 
-  std::vector<fuchsia::accessibility::semantics::Node> to_send_;
-  std::vector<uint32_t> to_delete_;
+  // Cache for pending data to be sent to the Semantic Tree between commits.
+  std::vector<SemanticUpdateOrDelete> to_send_;
   bool commit_inflight_ = false;
 
   // Maintain a map of callbacks as multiple hit test events can happen at once.