Adds code in AXTree for calculating the ignored state on the browser side and takes focus into account

Currently, Blink ensures that the focused node in the accessibility tree is never ignored.
Since we ultimately want to expose Views as an AXTree of AXNodes, we need
to share the same logic with Views and so it
cannot be just a Blink only feature.
Meanwhile, `AXNode::IsInvisibleOrIgnored()` has similar logic which ensures
that nodes that are currently focused are never marked as either invisible or ignored.
However, this same logic does not exist in `AXNode::IsIgnored()` creating
a confusing inconsistency in the codebase.
Importantly, even if the `IsInvisibleOrIgnored` method returns false due to
a change in focus, the AXNode could still have stale cached values,
such as unignored parent and unignored child count.

Clearly, both the AXTree and the AXNode need to update their internal state
when a node's ignored state has changed due to either gaining or losing focus.
This patch modifies both these classes to do that, while also informing
tree observers of the change.

This patch also conveniently lays the groundwork for computing the ignored state
completely on the browser side in the future, instead of in Blink.

This patch is the first of three patches:
The second one will switch to using `AXNode::IsIgnored()` across the whole codebase and
stop using / completely remove `AXNodeData::IsIgnored()`.
The third one will stop creating ignored objects in platform accessibility
trees., It will ensure that if an object gets ignored after it has
been created, it will be destroyed and if the same object gets
unignored again, it will be re-created.

[email protected], [email protected], [email protected]

AX-Relnotes: n/a.
Bug: 1049261
Change-Id: I69f152e2c903305d08fa16fca7ee1924eb64e298
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3000745
Commit-Queue: Nektarios Paisios <[email protected]>
Reviewed-by: Aaron Leventhal <[email protected]>
Reviewed-by: Kurt Catti-Schmidt <[email protected]>
Cr-Commit-Position: refs/heads/main@{#932943}
diff --git a/ui/accessibility/ax_tree.h b/ui/accessibility/ax_tree.h
index dcbeb5ca..61f7f85 100644
--- a/ui/accessibility/ax_tree.h
+++ b/ui/accessibility/ax_tree.h
@@ -16,6 +16,7 @@
 
 #include "base/metrics/histogram_functions.h"
 #include "base/observer_list.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/accessibility/ax_enums.mojom-forward.h"
 #include "ui/accessibility/ax_export.h"
 #include "ui/accessibility/ax_node.h"
@@ -71,6 +72,30 @@
       std::map<ax::mojom::IntListAttribute,
                std::map<AXNodeID, std::set<AXNodeID>>>;
 
+  // If called, the focused node in this tree will never be ignored, even if it
+  // has the ignored state set. For now, this boolean will be set to false for
+  // all trees except in test scenarios, in order to thoroughly test the
+  // relevant code without causing any potential regressions. Ultimately, we
+  // want to expose all focused nodes so that a user of an assistive technology
+  // will be able to interact with the application / website, even if there is
+  // an authoring error, e.g. the aria-hidden attribute has been applied to the
+  // focused element.
+  // TODO(nektar): Removed once the feature has been fully tested.
+  static void SetFocusedNodeShouldNeverBeIgnored();
+
+  // Determines the ignored state of a node, given information about the node
+  // and the tree.
+  static bool ComputeNodeIsIgnored(const AXTreeData* optional_tree_data,
+                                   const AXNodeData& node_data);
+
+  // Determines whether a node has flipped its ignored state, given information
+  // about the previous and current state of the node / tree.
+  static bool ComputeNodeIsIgnoredChanged(
+      const AXTreeData* optional_old_tree_data,
+      const AXNodeData& old_node_data,
+      const AXTreeData* optional_new_tree_data,
+      const AXNodeData& new_node_data);
+
   AXTree();
   explicit AXTree(const AXTreeUpdate& initial_state);
   virtual ~AXTree();
@@ -211,6 +236,10 @@
  private:
   friend class AXTableInfoTest;
 
+  // Indicates if the node with the focus should never be ignored, (see
+  // `SetFocusedNodeShouldNeverBeIgnored` above).
+  static bool is_focused_node_always_unignored_;
+
   // Accumulate errors as there can be more than one before Chrome is crashed
   // via AccessibilityFatalError();
   void RecordError(std::string new_error);
@@ -277,14 +306,22 @@
       AXNode* node,
       const AXTreeUpdateState* update_state);
 
-  // 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` will change its data attributes, including
+  // its ignored state.
+  void NotifyNodeAttributesWillChange(AXNode* node,
+                                      const AXTreeData* optional_old_tree_data,
+                                      const AXNodeData& old_data,
+                                      const AXTreeData* new_tree_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);
+  // Notify the delegate that `node` has changed its data attributes, including
+  // its ignored state.
+  void NotifyNodeAttributesHaveBeenChanged(
+      AXNode* node,
+      const AXTreeData* optional_old_tree_data,
+      const AXNodeData& old_data,
+      const AXTreeData* new_tree_data,
+      const AXNodeData& new_data);
 
   void UpdateReverseRelations(AXNode* node, const AXNodeData& new_data);
 
@@ -328,6 +365,10 @@
                             std::vector<AXNode*>* new_children,
                             AXTreeUpdateState* update_state);
 
+  // Returns the lowest unignored ancestor of the node with the given ID. If the
+  // node is not ignored, it returns the node.
+  AXNode* GetUnignoredAncestorFromId(AXNodeID node_id) const;
+
   // Internal implementation of RelativeToTreeBounds. It calls itself
   // recursively but ensures that it can only do so exactly once!
   gfx::RectF RelativeToTreeBoundsInternal(const AXNode* node,