// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_ACCESSIBILITY_AX_POSITION_H_
#define UI_ACCESSIBILITY_AX_POSITION_H_

#include <math.h>
#include <stdint.h>
#include <functional>
#include <memory>
#include <ostream>
#include <stack>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>

#include "ax_enum_util.h"
#include "ax_enums.h"
#include "ax_node.h"
#include "ax_node_text_styles.h"
#include "ax_role_properties.h"
#include "ax_tree_id.h"
#include "base/container_utils.h"
#include "base/logging.h"
#include "base/string_utils.h"

namespace ui {

// Defines the type of position in the accessibility tree.
// A tree position is used when referring to a specific child of a node in the
// accessibility tree.
// A text position is used when referring to a specific character of text inside
// a particular node.
// A null position is used to signify that the provided data is invalid or that
// a boundary has been reached.
enum class AXPositionKind { NULL_POSITION, TREE_POSITION, TEXT_POSITION };

// Defines how creating the next or previous position should behave whenever we
// are at or are crossing a boundary, such as at the start of an anchor, a word
// or a line.
enum class AXBoundaryBehavior {
  CrossBoundary,
  StopAtAnchorBoundary,
  StopIfAlreadyAtBoundary,
  StopAtLastAnchorBoundary
};

// Describes in further detail what type of boundary a current position is on.
// For complex boundaries such as format boundaries, it can be useful to know
// why a particular boundary was chosen.
enum class AXBoundaryType {
  // Not at a unit boundary.
  kNone,
  // At a unit boundary (e.g. a format boundary).
  kUnitBoundary,
  // At the start of a document.
  kDocumentStart,
  // At the end of a document.
  kDocumentEnd
};

// When converting to an unignored position, determines how to adjust the new
// position in order to make it valid, either moving backward or forward in
// the accessibility tree.
enum class AXPositionAdjustmentBehavior { kMoveBackward, kMoveForward };

// Specifies how AXPosition::ExpandToEnclosingTextBoundary behaves.
//
// As an example, imagine we have the text "hello world" and a position before
// the space character. We want to expand to the surrounding word boundary.
// Since we are right at the end of the first word, we could either expand to
// the left first, find the start of the first word and then use that to find
// the corresponding word end, resulting in the word "Hello". Another
// possibility is to expand to the right first, find the end of the next word
// and use that as our starting point to find the previous word start, resulting
// in the word "world".
enum class AXRangeExpandBehavior {
  // Expands to the left boundary first and then uses that position as the
  // starting point to find the boundary to the right.
  kLeftFirst,
  // Expands to the right boundary first and then uses that position as the
  // starting point to find the boundary to the left.
  kRightFirst
};

// Some platforms require empty objects to be represented by a replacement
// character in order for text navigation to work correctly. This enum controls
// whether a replacement character will be exposed for such objects.
//
// When an embedded object is replaced by a real character, the expectations
// are the same with this character as with other ordinary characters.
// For example, with UIA on Windows, we need to be able to navigate inside and
// outside of this character as if it was an ordinary character, using the
// AXPlatformNodeTextRangeProvider methods. Since an embedded object character
// is the only character in a node, we also treat this character as a word.
enum class AXEmbeddedObjectBehavior {
  kExposeCharacter,
  kSuppressCharacter,
};

// Controls whether embedded objects are represented by a replacement
// character. This is initialized to a per-platform default but can be
// overridden for testing.
AX_EXPORT extern AXEmbeddedObjectBehavior g_ax_embedded_object_behavior;

// Forward declarations.
template <class AXPositionType, class AXNodeType>
class AXPosition;
template <class AXPositionType>
class AXRange;
template <class AXPositionType, class AXNodeType>
bool operator==(const AXPosition<AXPositionType, AXNodeType>& first,
                const AXPosition<AXPositionType, AXNodeType>& second);
template <class AXPositionType, class AXNodeType>
bool operator!=(const AXPosition<AXPositionType, AXNodeType>& first,
                const AXPosition<AXPositionType, AXNodeType>& second);

// A position in the accessibility tree.
//
// This class could either represent a tree position or a text position.
// Tree positions point to either a child of a specific node or at the end of a
// node (i.e. an "after children" position).
// Text positions point to either a character offset in the text inside a
// particular node including text from all its children, or to the end of the
// node's text, (i.e. an "after text" position).
// On tree positions that have a leaf node as their anchor, we also need to
// distinguish between "before text" and "after text" positions. To do this, if
// the child index is 0 and the anchor is a leaf node, then it's an "after text"
// position. If the child index is |BEFORE_TEXT| and the anchor is a leaf node,
// then this is a "before text" position.
// It doesn't make sense to have a "before text" position on a text position,
// because it is identical to setting its offset to the first character.
//
// To avoid re-computing either the text offset or the child index when
// converting between the two types of positions, both values are saved after
// the first conversion.
//
// This class template uses static polymorphism in order to allow sub-classes to
// be created from the base class without the base class knowing the type of the
// sub-class in advance.
// The template argument |AXPositionType| should always be set to the type of
// any class that inherits from this template, making this a
// "curiously recursive template".
//
// This class can be copied using the |Clone| method. It is designed to be
// immutable.
template <class AXPositionType, class AXNodeType>
class AXPosition {
 public:
  using AXPositionInstance =
      std::unique_ptr<AXPosition<AXPositionType, AXNodeType>>;

  using AXRangeType = AXRange<AXPosition<AXPositionType, AXNodeType>>;

  typedef bool BoundaryConditionPredicate(const AXPositionInstance&);

  typedef std::vector<int32_t> BoundaryTextOffsetsFunc(
      const AXPositionInstance&);

  static const int BEFORE_TEXT = -1;
  static const int INVALID_INDEX = -2;
  static const int INVALID_OFFSET = -1;

  // Replacement character used to represent an empty object. See
  // AXEmbeddedObjectBehavior for more information.
  //
  // Duplicate of AXPlatformNodeBase::kEmbeddedCharacter because we don't want
  // to include platform specific code in here.
  static constexpr char16_t kEmbeddedCharacter = L'\xfffc';

  static AXPositionInstance CreateNullPosition() {
    AXPositionInstance new_position(new AXPositionType());
    new_position->Initialize(
        AXPositionKind::NULL_POSITION, AXTreeIDUnknown(), AXNode::kInvalidAXID,
        INVALID_INDEX, INVALID_OFFSET, ax::mojom::TextAffinity::kDownstream);
    return new_position;
  }

  static AXPositionInstance CreateTreePosition(AXTreeID tree_id,
                                               AXNode::AXID anchor_id,
                                               int child_index) {
    AXPositionInstance new_position(new AXPositionType());
    new_position->Initialize(AXPositionKind::TREE_POSITION, tree_id, anchor_id,
                             child_index, INVALID_OFFSET,
                             ax::mojom::TextAffinity::kDownstream);
    return new_position;
  }

  static AXPositionInstance CreateTextPosition(
      AXTreeID tree_id,
      AXNode::AXID anchor_id,
      int text_offset,
      ax::mojom::TextAffinity affinity) {
    AXPositionInstance new_position(new AXPositionType());
    new_position->Initialize(AXPositionKind::TEXT_POSITION, tree_id, anchor_id,
                             INVALID_INDEX, text_offset, affinity);
    return new_position;
  }

  virtual ~AXPosition() = default;

  // Implemented based on the copy and swap idiom.
  AXPosition& operator=(const AXPosition& other) {
    AXPositionInstance clone = other.Clone();
    swap(*clone);
    return *this;
  }

  virtual AXPositionInstance Clone() const = 0;

  // A serialization of a position as POD. Not for sharing on disk or sharing
  // across thread or process boundaries, just for passing a position to an
  // API that works with positions as opaque objects.
  struct SerializedPosition {
    AXPositionKind kind;
    AXNode::AXID anchor_id;
    int child_index;
    int text_offset;
    ax::mojom::TextAffinity affinity;
    char tree_id[33];
  };

  static_assert(std::is_trivially_copyable<SerializedPosition>::value,
                "SerializedPosition must be POD");

  SerializedPosition Serialize() {
    SerializedPosition result;
    result.kind = kind_;

    // A tree ID can be serialized as a 32-byte string.
    std::string tree_id_string = tree_id_.ToString();
    BASE_DCHECK(tree_id_string.size() <= 32U);
    strncpy(result.tree_id, tree_id_string.c_str(), 32);
    result.tree_id[32] = 0;

    result.anchor_id = anchor_id_;
    result.child_index = child_index_;
    result.text_offset = text_offset_;
    result.affinity = affinity_;
    return result;
  }

  static AXPositionInstance Unserialize(
      const SerializedPosition& serialization) {
    AXPositionInstance new_position(new AXPositionType());
    new_position->Initialize(serialization.kind,
                             ui::AXTreeID::FromString(serialization.tree_id),
                             serialization.anchor_id, serialization.child_index,
                             serialization.text_offset, serialization.affinity);
    return new_position;
  }

  std::string ToString() const {
    std::string str;
    switch (kind_) {
      case AXPositionKind::NULL_POSITION:
        return "NullPosition";
      case AXPositionKind::TREE_POSITION: {
        std::string str_child_index;
        if (child_index_ == BEFORE_TEXT) {
          str_child_index = "before_text";
        } else if (child_index_ == INVALID_INDEX) {
          str_child_index = "invalid";
        } else {
          str_child_index = base::NumberToString(child_index_);
        }
        str = "TreePosition tree_id=" + tree_id_.ToString() +
              " anchor_id=" + base::NumberToString(anchor_id_) +
              " child_index=" + str_child_index;
        break;
      }
      case AXPositionKind::TEXT_POSITION: {
        std::string str_text_offset;
        if (text_offset_ == INVALID_OFFSET) {
          str_text_offset = "invalid";
        } else {
          str_text_offset = base::NumberToString(text_offset_);
        }
        str = "TextPosition anchor_id=" + base::NumberToString(anchor_id_) +
              " text_offset=" + str_text_offset + " affinity=" +
              ui::ToString(static_cast<ax::mojom::TextAffinity>(affinity_));
        break;
      }
    }

    if (!IsTextPosition() || text_offset_ > MaxTextOffset())
      return str;

    std::u16string text = GetText();
    BASE_DCHECK(text_offset_ >= 0);
    int max_text_offset = MaxTextOffset();
    BASE_DCHECK(text_offset_ <= max_text_offset);
    std::u16string annotated_text;
    if (text_offset_ == max_text_offset) {
      annotated_text = text + u"<>";
    } else {
      annotated_text = text.substr(0, text_offset_) + u"<" +
                       text[text_offset_] + u">" +
                       text.substr(text_offset_ + 1);
    }
    return str + " annotated_text=" + base::UTF16ToUTF8(annotated_text);
  }

  AXTreeID tree_id() const { return tree_id_; }
  AXNode::AXID anchor_id() const { return anchor_id_; }

  AXNodeType* GetAnchor() const {
    if (tree_id_ == AXTreeIDUnknown() || anchor_id_ == AXNode::kInvalidAXID)
      return nullptr;
    return GetNodeInTree(tree_id_, anchor_id_);
  }

  AXPositionKind kind() const { return kind_; }
  int child_index() const { return child_index_; }
  int text_offset() const { return text_offset_; }
  ax::mojom::TextAffinity affinity() const { return affinity_; }

  bool IsIgnored() const {
    if (IsNullPosition())
      return false;

    BASE_DCHECK(GetAnchor());
    // If this position is anchored to an ignored node, then consider this
    // position to be ignored.
    if (GetAnchor()->IsIgnored())
      return true;

    switch (kind_) {
      case AXPositionKind::NULL_POSITION:
        BASE_UNREACHABLE();
        return false;
      case AXPositionKind::TREE_POSITION: {
        // If this is a "before text" or an "after text" tree position, it's
        // pointing to the anchor itself, which we've determined to be
        // unignored.
        BASE_DCHECK(!IsLeaf() || child_index_ == BEFORE_TEXT ||
                    child_index_ == 0)
            << "\"Before text\" and \"after text\" tree positions are only "
               "valid on leaf nodes.";
        if (child_index_ == BEFORE_TEXT || IsLeaf())
          return false;

        // If this position is an "after children" position, consider the
        // position to be ignored if the last child is ignored. This is because
        // the last child will not be visible in the unignored tree. If the
        // position is not adjusted, the resulting position would erroneously
        // point before the second child in the unignored subtree rooted at the
        // last child.
        //
        // 1 kRootWebArea
        // ++2 kGenericContainer ignored
        // ++++3 kStaticText "Line 1."
        // ++++4 kStaticText "Line 2."
        //
        // Tree position anchor=kGenericContainer, child_index=1.
        //
        // Alternatively, if there is a node at the position pointed to by
        // "child_index_", i.e. this position is neither a leaf position nor an
        // "after children" position, consider this tree position to be ignored
        // if the child node is ignored.
        int adjusted_child_index = child_index_ != AnchorChildCount()
                                       ? child_index_
                                       : child_index_ - 1;
        AXPositionInstance child_position =
            CreateChildPositionAt(adjusted_child_index);
        BASE_DCHECK(child_position && !child_position->IsNullPosition());
        return child_position->GetAnchor()->IsIgnored();
      }
      case AXPositionKind::TEXT_POSITION:
        // If the corresponding leaf position is ignored, the current text
        // offset will point to ignored text. Therefore, consider this position
        // to be ignored.
        if (!IsLeaf())
          return AsLeafTreePosition()->IsIgnored();
        return false;
    }
  }

  bool IsNullPosition() const {
    return kind_ == AXPositionKind::NULL_POSITION || !GetAnchor();
  }

  bool IsTreePosition() const {
    return GetAnchor() && kind_ == AXPositionKind::TREE_POSITION;
  }

  bool IsLeafTreePosition() const { return IsTreePosition() && IsLeaf(); }

  bool IsTextPosition() const {
    return GetAnchor() && kind_ == AXPositionKind::TEXT_POSITION;
  }

  bool IsLeafTextPosition() const { return IsTextPosition() && IsLeaf(); }

  bool IsLeaf() const {
    if (IsNullPosition())
      return false;

    return !AnchorChildCount() || IsEmptyObjectReplacedByCharacter();
  }

  // Returns true if this is a valid position, e.g. the child_index_ or
  // text_offset_ is within a valid range.
  bool IsValid() const {
    switch (kind_) {
      case AXPositionKind::NULL_POSITION:
        return tree_id_ == AXTreeIDUnknown() &&
               anchor_id_ == AXNode::kInvalidAXID &&
               child_index_ == INVALID_INDEX &&
               text_offset_ == INVALID_OFFSET &&
               affinity_ == ax::mojom::TextAffinity::kDownstream;
      case AXPositionKind::TREE_POSITION:
        return GetAnchor() &&
               (child_index_ == BEFORE_TEXT ||
                (child_index_ >= 0 && child_index_ <= AnchorChildCount())) &&
               !IsInDescendantOfEmptyObject();
      case AXPositionKind::TEXT_POSITION:
        if (!GetAnchor() || IsInDescendantOfEmptyObject())
          return false;

        // For performance reasons we skip any validation of the text offset
        // that involves retrieving the anchor's text, if the offset is set to
        // 0, because 0 is frequently used and always valid regardless of the
        // actual text.
        return text_offset_ == 0 ||
               (text_offset_ > 0 && text_offset_ <= MaxTextOffset());
    }
  }

  // TODO(nektar): Update logic of AtStartOfAnchor() for text_offset_ == 0 and
  // fix related bug.
  bool AtStartOfAnchor() const {
    if (!GetAnchor())
      return false;
    switch (kind_) {
      case AXPositionKind::NULL_POSITION:
        return false;
      case AXPositionKind::TREE_POSITION:
        if (text_offset_ > 0)
          return false;
        if (!IsLeaf() || text_offset_ == 0)
          return child_index_ == 0;
        return child_index_ == BEFORE_TEXT;
      case AXPositionKind::TEXT_POSITION:
        return text_offset_ == 0;
    }
  }

  bool AtEndOfAnchor() const {
    if (!GetAnchor())
      return false;
    switch (kind_) {
      case AXPositionKind::NULL_POSITION:
        return false;
      case AXPositionKind::TREE_POSITION:
        return child_index_ == AnchorChildCount();
      case AXPositionKind::TEXT_POSITION:
        return text_offset_ == MaxTextOffset();
    }
  }

  bool AtStartOfWord() const {
    AXPositionInstance text_position = AsLeafTextPosition();
    switch (text_position->kind_) {
      case AXPositionKind::NULL_POSITION:
        return false;
      case AXPositionKind::TREE_POSITION:
        BASE_UNREACHABLE();
        return false;
      case AXPositionKind::TEXT_POSITION: {
        const std::vector<int32_t> word_starts =
            text_position->GetWordStartOffsets();
        return base::Contains(word_starts,
                              int32_t{text_position->text_offset_});
      }
    }
  }

  bool AtEndOfWord() const {
    AXPositionInstance text_position = AsLeafTextPosition();
    switch (text_position->kind_) {
      case AXPositionKind::NULL_POSITION:
        return false;
      case AXPositionKind::TREE_POSITION:
        BASE_UNREACHABLE();
        return false;
      case AXPositionKind::TEXT_POSITION: {
        const std::vector<int32_t> word_ends =
            text_position->GetWordEndOffsets();
        return base::Contains(word_ends, int32_t{text_position->text_offset_});
      }
    }
  }

  bool AtStartOfLine() const {
    AXPositionInstance text_position = AsLeafTextPosition();
    switch (text_position->kind_) {
      case AXPositionKind::NULL_POSITION:
        return false;
      case AXPositionKind::TREE_POSITION:
        BASE_UNREACHABLE();
        return false;
      case AXPositionKind::TEXT_POSITION:
        // We treat a position after some white space that is not connected to
        // any node after it via "next on line ID", to be equivalent to a
        // position before the next line, and therefore as being at start of
        // line.
        //
        // We assume that white space, including but not limited to hard line
        // breaks, might be used to separate lines. For example, an inline text
        // box with just a single space character inside it can be used to
        // represent a soft line break. If an inline text box containing white
        // space separates two lines, it should always be connected to the first
        // line via "kPreviousOnLineId". This is guaranteed by the renderer. If
        // there are multiple line breaks separating the two lines, then only
        // the first line break is connected to the first line via
        // "kPreviousOnLineId".
        //
        // Sometimes there might be an inline text box with a single space in it
        // at the end of a text field. We should not mark positions that are at
        // the end of text fields, or in general at the end of their anchor, as
        // being at the start of line, except when that anchor is an inline text
        // box that is in the middle of a text span. Note that in most but not
        // all cases, the parent of an inline text box is a static text object,
        // whose end signifies the end of the text span. One exception is line
        // breaks.
        if (text_position->AtEndOfAnchor() &&
            !text_position->AtEndOfTextSpan() &&
            text_position->IsInWhiteSpace() &&
            GetNextOnLineID(text_position->anchor_id_) ==
                AXNode::kInvalidAXID) {
          return true;
        }

        return GetPreviousOnLineID(text_position->anchor_id_) ==
                   AXNode::kInvalidAXID &&
               text_position->AtStartOfAnchor();
    }
  }

  bool AtEndOfLine() const {
    AXPositionInstance text_position = AsLeafTextPosition();
    switch (text_position->kind_) {
      case AXPositionKind::NULL_POSITION:
        return false;
      case AXPositionKind::TREE_POSITION:
        BASE_UNREACHABLE();
        return false;
      case AXPositionKind::TEXT_POSITION:
        // Text positions on objects with no text should not be considered at
        // end of line because the empty position may share a text offset with
        // a non-empty text position in which case the end of line iterators
        // must move to the line end of the non-empty content. Specified next
        // line IDs are ignored.
        if (!text_position->MaxTextOffset())
          return false;

        // If affinity has been used to specify whether the caret is at the end
        // of a line or at the start of the next one, this should have been
        // reflected in the leaf text position we got via "AsLeafTextPosition".
        // If affinity had been set to upstream, the leaf text position should
        // be pointing to the end of the inline text box that ends the first
        // line. If it had been set to downstream, the leaf text position should
        // be pointing to the start of the inline text box that starts the
        // second line.
        //
        // In other cases, we assume that white space, including but not limited
        // to hard line breaks, might be used to separate lines. For example, an
        // inline text box with just a single space character inside it can be
        // used to represent a soft line break. If an inline text box containing
        // white space separates two lines, it should always be connected to the
        // first line via "kPreviousOnLineId". This is guaranteed by the
        // renderer. If there are multiple line breaks separating the two lines,
        // then only the first line break is connected to the first line via
        // "kPreviousOnLineId".
        //
        // We don't treat a position that is at the start of white space that is
        // on a line by itself as being at the end of the line. This is in order
        // to enable screen readers to recognize and announce blank lines
        // correctly. However, we do treat positions at the start of white space
        // that end a line of text as being at the end of that line. We also
        // treat positions at the end of white space that is on a line by
        // itself, i.e. on a blank line, as being at the end of that line.
        //
        // Sometimes there might be an inline text box with a single space in it
        // at the end of a text field. We should mark positions that are at the
        // end of text fields, or in general at the end of an anchor with no
        // "kNextOnLineId", as being at end of line, except when that anchor is
        // an inline text box that is in the middle of a text span. Note that
        // in most but not all cases, the parent of an inline text box is a
        // static text object, whose end signifies the end of the text span. One
        // exception is line breaks.
        if (GetNextOnLineID(text_position->anchor_id_) ==
            AXNode::kInvalidAXID) {
          return (!text_position->AtEndOfTextSpan() &&
                  text_position->IsInWhiteSpace() &&
                  GetPreviousOnLineID(text_position->anchor_id_) !=
                      AXNode::kInvalidAXID)
                     ? text_position->AtStartOfAnchor()
                     : text_position->AtEndOfAnchor();
        }

        // The current anchor might be followed by a soft line break.
        return text_position->AtEndOfAnchor() &&
               text_position->CreateNextLeafTextPosition()->AtEndOfLine();
    }
  }

  // |AtStartOfParagraph| is asymmetric from |AtEndOfParagraph| because of
  // trailing whitespace collapse rules.
  // The start of a paragraph should be a leaf text position (or equivalent),
  // either at the start of the document, or at the start of the next leaf text
  // position from the one representing the end of the previous paragraph.
  // A position |AsLeafTextPosition| is the start of a paragraph if all of the
  // following are true :
  // 1. The current leaf text position must be an unignored position at
  //    the start of an anchor.
  // 2. The current position is not whitespace only, unless it is also
  //    the first leaf text position within the document.
  // 3. Either (a) the current leaf text position is the first leaf text
  //    position in the document, or (b) there are no line breaking
  //    objects between it and the previous non-whitespace leaf text
  //    position.
  bool AtStartOfParagraph() const {
    AXPositionInstance text_position = AsLeafTextPosition();
    switch (text_position->kind_) {
      case AXPositionKind::NULL_POSITION:
        return false;
      case AXPositionKind::TREE_POSITION:
        BASE_UNREACHABLE();
        return false;
      case AXPositionKind::TEXT_POSITION: {
        // 1. The current leaf text position must be an unignored position at
        //    the start of an anchor.
        if (text_position->IsIgnored() || !text_position->AtStartOfAnchor())
          return false;

        // 2. The current position is not whitespace only, unless it is also
        //    the first leaf text position within the document.
        if (text_position->IsInWhiteSpace()) {
          return text_position->CreatePreviousLeafTextPosition()
              ->IsNullPosition();
        }

        // 3. Either (a) the current leaf text position is the first leaf text
        //    position in the document, or (b) there are no line breaking
        //    objects between it and the previous non-whitespace leaf text
        //    position.
        //
        // Search for the previous text position within the current paragraph,
        // using the paragraph boundary abort predicate.
        // If a valid position was found, then this position cannot be
        // the start of a paragraph.
        // This will return a null position when an anchor movement would
        // cross a paragraph boundary, or the start of document was reached.
        bool crossed_line_breaking_object_token = false;
        auto abort_move_predicate =
            [&crossed_line_breaking_object_token](
                const AXPosition& move_from, const AXPosition& move_to,
                const AXMoveType type, const AXMoveDirection direction) {
              return AbortMoveAtParagraphBoundary(
                  crossed_line_breaking_object_token, move_from, move_to, type,
                  direction);
            };

        AXPositionInstance previous_text_position = text_position->Clone();
        do {
          previous_text_position =
              previous_text_position->CreatePreviousTextAnchorPosition(
                  abort_move_predicate);
          // If the previous position is whitespace, then continue searching
          // until a non-whitespace leaf text position is found within the
          // current paragraph because whitespace is supposed to be collapsed.
          // There's a chance that |CreatePreviousTextAnchorPosition| will
          // return whitespace that should be appended to a previous paragraph
          // rather than separating two pieces of the current paragraph.
        } while (previous_text_position->IsInWhiteSpace() ||
                 previous_text_position->IsIgnored());
        return previous_text_position->IsNullPosition();
      }
    }
  }

  // |AtEndOfParagraph| is asymmetric from |AtStartOfParagraph| because of
  // trailing whitespace collapse rules.
  // The end of a paragraph should be a leaf text position (or equivalent),
  // either at the end of the document, or at the end of the previous leaf text
  // position from the one representing the start of the next paragraph.
  // A position |AsLeafTextPosition| is the end of a paragraph if all of the
  // following are true :
  // 1. The current leaf text position must be an unignored position at
  //    the end of an anchor.
  // 2. Either (a) the current leaf text position is the last leaf text
  //    position in the document, or (b) there are no line breaking
  //    objects between it and the next leaf text position except when
  //    the next leaf text position is whitespace only since whitespace
  //    must be collapsed.
  // 3. If there is a next leaf text position then it must not be
  //    whitespace only.
  // 4. If there is a next leaf text position and it is not whitespace
  //    only, it must also be the start of a paragraph for the current
  //    position to be the end of a paragraph.
  bool AtEndOfParagraph() const {
    AXPositionInstance text_position = AsLeafTextPosition();
    switch (text_position->kind_) {
      case AXPositionKind::NULL_POSITION:
        return false;
      case AXPositionKind::TREE_POSITION:
        BASE_UNREACHABLE();
        return false;
      case AXPositionKind::TEXT_POSITION: {
        // 1. The current leaf text position must be an unignored position at
        //    the end of an anchor.
        if (text_position->IsIgnored() || !text_position->AtEndOfAnchor())
          return false;

        // 2. Either (a) the current leaf text position is the last leaf text
        //    position in the document, or (b) there are no line breaking
        //    objects between it and the next leaf text position except when
        //    the next leaf text position is whitespace only since whitespace
        //    must be collapsed.
        //
        // Search for the next text position within the current paragraph,
        // using the paragraph boundary abort predicate.
        // If a null position was found, then this position must be the end of
        // a paragraph.
        // |CreateNextTextAnchorPosition| + |AbortMoveAtParagraphBoundary|
        // will return a null position when an anchor movement would
        // cross a paragraph boundary and there is no doubt that it is the end
        // of a paragraph, or the end of document was reached.
        // There are some fringe cases related to whitespace collapse that
        // cannot be handled easily with only |AbortMoveAtParagraphBoundary|.
        bool crossed_line_breaking_object_token = false;
        auto abort_move_predicate =
            [&crossed_line_breaking_object_token](
                const AXPosition& move_from, const AXPosition& move_to,
                const AXMoveType type, const AXMoveDirection direction) {
              return AbortMoveAtParagraphBoundary(
                  crossed_line_breaking_object_token, move_from, move_to, type,
                  direction);
            };

        AXPositionInstance next_text_position = text_position->Clone();
        do {
          next_text_position = next_text_position->CreateNextTextAnchorPosition(
              abort_move_predicate);
        } while (next_text_position->IsIgnored());
        if (next_text_position->IsNullPosition())
          return true;

        // 3. If there is a next leaf text position then it must not be
        //    whitespace only.
        if (next_text_position->IsInWhiteSpace())
          return false;

        // 4. If there is a next leaf text position and it is not whitespace
        //    only, it must also be the start of a paragraph for the current
        //    position to be the end of a paragraph.
        //
        // Consider the following example :
        // ++{1} kStaticText "First Paragraph"
        // ++++{2} kInlineTextBox "First Paragraph"
        // ++{3} kStaticText "\n Second Paragraph"
        // ++++{4} kInlineTextBox "\n" kIsLineBreakingObject
        // ++++{5} kInlineTextBox " "
        // ++++{6} kInlineTextBox "Second Paragraph"
        // A position at the end of {5} is the end of a paragraph, because
        // the first paragraph must collapse trailing whitespace and contain
        // leaf text anchors {2, 4, 5}. The second paragraph is only {6}.
        return next_text_position->CreatePositionAtStartOfAnchor()
            ->AtStartOfParagraph();
      }
    }
  }

  bool AtStartOfPage() const {
    AXPositionInstance text_position = AsLeafTextPosition();
    switch (text_position->kind_) {
      case AXPositionKind::NULL_POSITION:
        return false;
      case AXPositionKind::TREE_POSITION:
        BASE_UNREACHABLE();
        return false;
      case AXPositionKind::TEXT_POSITION: {
        if (!text_position->AtStartOfAnchor())
          return false;

        // Search for the previous text position within the current page,
        // using the page boundary abort predicate.
        // If a valid position was found, then this position cannot be
        // the start of a page.
        // This will return a null position when an anchor movement would
        // cross a page boundary, or the start of document was reached.
        AXPositionInstance previous_text_position =
            text_position->CreatePreviousTextAnchorPosition(
                AbortMoveAtPageBoundary);
        return previous_text_position->IsNullPosition();
      }
    }
  }

  bool AtEndOfPage() const {
    AXPositionInstance text_position = AsLeafTextPosition();
    switch (text_position->kind_) {
      case AXPositionKind::NULL_POSITION:
        return false;
      case AXPositionKind::TREE_POSITION:
        BASE_UNREACHABLE();
        return false;
      case AXPositionKind::TEXT_POSITION: {
        if (!text_position->AtEndOfAnchor())
          return false;

        // Search for the next text position within the current page,
        // using the page boundary abort predicate.
        // If a valid position was found, then this position cannot be
        // the end of a page.
        // This will return a null position when an anchor movement would
        // cross a page boundary, or the end of document was reached.
        AXPositionInstance next_text_position =
            text_position->CreateNextTextAnchorPosition(
                AbortMoveAtPageBoundary);
        return next_text_position->IsNullPosition();
      }
    }
  }

  bool AtStartOfAXTree() const {
    if (IsNullPosition())
      return false;

    if (AtStartOfAnchor()) {
      AXPositionInstance previous_anchor = CreatePreviousAnchorPosition();

      // Consider the start of the document as the start of an AXTree.
      if (previous_anchor->IsNullPosition())
        return true;
      else
        return previous_anchor->tree_id() != tree_id();
    }
    return false;
  }

  bool AtEndOfAXTree() const {
    if (IsNullPosition())
      return false;

    if (AtEndOfAnchor()) {
      AXPositionInstance next_anchor = CreateNextAnchorPosition();

      // Consider the end of the document as the end of an AXTree.
      if (next_anchor->IsNullPosition())
        return true;
      else
        return next_anchor->tree_id() != tree_id();
    }
    return false;
  }

  AXBoundaryType GetFormatStartBoundaryType() const {
    // Since formats are stored on text anchors, the start of a format boundary
    // must be at the start of an anchor.
    if (IsNullPosition() || !AtStartOfAnchor())
      return AXBoundaryType::kNone;

    // Treat the first iterable node as a format boundary.
    if (CreatePreviousLeafTreePosition()->IsNullPosition())
      return AXBoundaryType::kDocumentStart;

    // Ignored positions cannot be format boundaries.
    if (IsIgnored())
      return AXBoundaryType::kNone;

    // Iterate over anchors until a format boundary is found. This will return a
    // null position upon crossing a boundary. Make sure the previous position
    // is not on an ignored node.
    AXPositionInstance previous_position = Clone();
    do {
      previous_position = previous_position->CreatePreviousLeafTreePosition(
          AbortMoveAtFormatBoundary);
    } while (previous_position->IsIgnored());

    if (previous_position->IsNullPosition())
      return AXBoundaryType::kUnitBoundary;

    return AXBoundaryType::kNone;
  }

  bool AtStartOfFormat() const {
    return GetFormatStartBoundaryType() != AXBoundaryType::kNone;
  }

  AXBoundaryType GetFormatEndBoundaryType() const {
    // Since formats are stored on text anchors, the end of a format break must
    // be at the end of an anchor.
    if (IsNullPosition() || !AtEndOfAnchor())
      return AXBoundaryType::kNone;

    // Treat the last iterable node as a format boundary
    if (CreateNextLeafTreePosition()->IsNullPosition())
      return AXBoundaryType::kDocumentEnd;

    // Ignored positions cannot be format boundaries.
    if (IsIgnored())
      return AXBoundaryType::kNone;

    // Iterate over anchors until a format boundary is found. This will return a
    // null position upon crossing a boundary. Make sure the next position is
    // not on an ignored node.
    AXPositionInstance next_position = Clone();
    do {
      next_position =
          next_position->CreateNextLeafTreePosition(AbortMoveAtFormatBoundary);
    } while (next_position->IsIgnored());

    if (next_position->IsNullPosition())
      return AXBoundaryType::kUnitBoundary;

    return AXBoundaryType::kNone;
  }

  bool AtEndOfFormat() const {
    return GetFormatEndBoundaryType() != AXBoundaryType::kNone;
  }

  bool AtStartOfInlineBlock() const {
    AXPositionInstance text_position = AsLeafTextPosition();
    switch (text_position->kind_) {
      case AXPositionKind::NULL_POSITION:
        return false;
      case AXPositionKind::TREE_POSITION:
        BASE_UNREACHABLE();
        return false;
      case AXPositionKind::TEXT_POSITION: {
        if (text_position->AtStartOfAnchor()) {
          AXPositionInstance previous_position =
              text_position->CreatePreviousLeafTreePosition();

          // Check that this position is not the start of the first anchor.
          if (!previous_position->IsNullPosition()) {
            previous_position = text_position->CreatePreviousLeafTreePosition(
                &AbortMoveAtStartOfInlineBlock);

            // If we get a null position here it means we have crossed an inline
            // block's start, thus this position is located at such start.
            if (previous_position->IsNullPosition())
              return true;
          }
        }
        if (text_position->AtEndOfAnchor()) {
          AXPositionInstance next_position =
              text_position->CreateNextLeafTreePosition();

          // Check that this position is not the end of the last anchor.
          if (!next_position->IsNullPosition()) {
            next_position = text_position->CreateNextLeafTreePosition(
                &AbortMoveAtStartOfInlineBlock);

            // If we get a null position here it means we have crossed an inline
            // block's start, thus this position is located at such start.
            if (next_position->IsNullPosition())
              return true;
          }
        }
        return false;
      }
    }
  }

  bool AtStartOfDocument() const {
    if (IsNullPosition())
      return false;
    return IsDocument(GetAnchorRole()) && AtStartOfAnchor();
  }

  bool AtEndOfDocument() const {
    if (IsNullPosition())
      return false;
    return AtLastNodeInTree() && AtEndOfAnchor();
  }

  bool AtLastNodeInTree() const {
    if (IsNullPosition())
      return false;

    // Avoid a potentionally expensive MaxTextOffset call by only using tree
    // positions. The only thing that matters is whether our anchor_id_ is at
    // the last anchor of the document, so we're free to ignore text_offset_.
    AXPositionInstance tree_position =
        CreateTreePosition(tree_id_, anchor_id_, 0);
    return tree_position->CreateNextAnchorPosition()->IsNullPosition();
  }

  // This method finds the lowest common AXNodeType of |this| and |second|.
  AXNodeType* LowestCommonAnchor(const AXPosition& second) const {
    if (IsNullPosition() || second.IsNullPosition())
      return nullptr;
    if (GetAnchor() == second.GetAnchor())
      return GetAnchor();

    std::stack<AXNodeType*> our_ancestors = GetAncestorAnchors();
    std::stack<AXNodeType*> other_ancestors = second.GetAncestorAnchors();

    AXNodeType* common_anchor = nullptr;
    while (!our_ancestors.empty() && !other_ancestors.empty() &&
           our_ancestors.top() == other_ancestors.top()) {
      common_anchor = our_ancestors.top();
      our_ancestors.pop();
      other_ancestors.pop();
    }
    return common_anchor;
  }

  // This method returns a position instead of a node because this allows us to
  // return the corresponding text offset or child index in the ancestor that
  // relates to the current position.
  // Also, this method uses position instead of tree logic to traverse the tree,
  // because positions can handle moving across multiple trees, while trees
  // cannot.
  AXPositionInstance LowestCommonAncestor(const AXPosition& second) const {
    return CreateAncestorPosition(LowestCommonAnchor(second));
  }

  // See "CreateParentPosition" for an explanation of the use of
  // |move_direction|.
  AXPositionInstance CreateAncestorPosition(
      const AXNodeType* ancestor_anchor,
      ax::mojom::MoveDirection move_direction =
          ax::mojom::MoveDirection::kForward) const {
    if (!ancestor_anchor)
      return CreateNullPosition();

    AXPositionInstance ancestor_position = Clone();
    while (!ancestor_position->IsNullPosition() &&
           ancestor_position->GetAnchor() != ancestor_anchor) {
      ancestor_position =
          ancestor_position->CreateParentPosition(move_direction);
    }
    return ancestor_position;
  }

  // If the position is not valid, we return a new valid position that is
  // closest to the original position if possible, or a null position otherwise.
  AXPositionInstance AsValidPosition() const {
    AXPositionInstance position = Clone();
    switch (position->kind_) {
      case AXPositionKind::NULL_POSITION:
        // We avoid cloning to ensure that all fields will be valid.
        return CreateNullPosition();
      case AXPositionKind::TREE_POSITION: {
        if (!position->GetAnchor())
          return CreateNullPosition();

        if (AXNodeType* empty_object_node = GetEmptyObjectAncestorNode()) {
          // In this class and on certain platforms, we define the empty object
          // as one that doesn't expose its underlying content. Its content is
          // replaced by the empty object character (string of length 1). A
          // position on a descendant of an empty object is invalid. To make it
          // valid we move the position from the descendant to the empty object
          // node itself.
          return CreateTreePosition(
              position->tree_id(), GetAnchorID(empty_object_node),
              position->child_index() == BEFORE_TEXT ? BEFORE_TEXT : 0);
        }

        if (position->child_index_ == BEFORE_TEXT)
          return position;

        if (position->child_index_ < 0)
          position->child_index_ = 0;
        else if (position->child_index_ > position->AnchorChildCount())
          position->child_index_ = position->AnchorChildCount();
        break;
      }
      case AXPositionKind::TEXT_POSITION: {
        if (!position->GetAnchor())
          return CreateNullPosition();

        if (AXNodeType* empty_object_node = GetEmptyObjectAncestorNode()) {
          // This is needed because an empty object as defined in this class and
          // on certain platforms can have descendants that should not be
          // exposed. See comment above in similar implementation for
          // AXPositionKind::TREE_POSITION.
          //
          // We set the |text_offset_| to either 0 or 1 here because the
          // MaxTextOffset of an empty object is 1 (the empty object character,
          // a string of length 1). If the invalid position was already at the
          // start of the node, we set it to 0.
          return CreateTextPosition(position->tree_id(),
                                    GetAnchorID(empty_object_node),
                                    position->text_offset() > 0 ? 1 : 0,
                                    ax::mojom::TextAffinity::kDownstream);
        }

        if (position->text_offset_ <= 0) {
          // 0 is always a valid offset, so skip calling MaxTextOffset in that
          // case.
          position->text_offset_ = 0;
          position->affinity_ = ax::mojom::TextAffinity::kDownstream;
        } else {
          int max_text_offset = position->MaxTextOffset();
          if (position->text_offset_ > max_text_offset) {
            position->text_offset_ = max_text_offset;
            position->affinity_ = ax::mojom::TextAffinity::kDownstream;
          }
        }
        break;
      }
    }
    BASE_DCHECK(position->IsValid());
    return position;
  }

  AXPositionInstance AsTreePosition() const {
    if (IsNullPosition() || IsTreePosition())
      return Clone();

    AXPositionInstance copy = Clone();
    BASE_DCHECK(copy);
    BASE_DCHECK(copy->text_offset_ >= 0);
    if (copy->IsLeaf()) {
      const int max_text_offset = copy->MaxTextOffset();
      copy->child_index_ =
          (max_text_offset != 0 && copy->text_offset_ != max_text_offset)
              ? BEFORE_TEXT
              : 0;
      copy->kind_ = AXPositionKind::TREE_POSITION;
      return copy;
    }

    // We stop at the last child that we can reach with the current text offset
    // and ignore any remaining children. This is for defensive programming
    // purposes, in case "MaxTextOffset" doesn't match the total length of all
    // our children. This may happen if, for example, there is a bug in the
    // internal accessibility tree we get from the renderer. In contrast, the
    // current offset could not be greater than the length of all our children
    // because the position would have been invalid.
    int current_offset = 0;
    int child_index = 0;
    for (; child_index < copy->AnchorChildCount(); ++child_index) {
      AXPositionInstance child = copy->CreateChildPositionAt(child_index);
      BASE_DCHECK(child);
      int child_length = child->MaxTextOffsetInParent();
      // If the text offset falls on the boundary between two adjacent children,
      // we look at the affinity to decide whether to place the tree position on
      // the first child vs. the second child. Upstream affinity would always
      // choose the first child, whilst downstream affinity the second. This
      // also has implications when converting the resulting tree position back
      // to a text position. In that case, maintaining an upstream affinity
      // would place the text position at the end of the first child, whilst
      // maintaining a downstream affinity will place the text position at the
      // beginning of the second child.
      //
      // This is vital for text positions on soft line breaks, as well as text
      // positions before and after character, to work properly.
      //
      // See also `CreateLeafTextPositionBeforeCharacter` and
      // `CreateLeafTextPositionAfterCharacter`.
      if (copy->text_offset_ >= current_offset &&
          (copy->text_offset_ < (current_offset + child_length) ||
           (copy->affinity_ == ax::mojom::TextAffinity::kUpstream &&
            copy->text_offset_ == (current_offset + child_length)))) {
        break;
      }

      current_offset += child_length;
    }

    copy->child_index_ = child_index;
    copy->kind_ = AXPositionKind::TREE_POSITION;
    return copy;
  }

  // This is an optimization over "AsLeafTextPosition", in cases when computing
  // the corresponding text offset on the leaf node is not needed. If this
  // method is called on a text position, it will conservatively fall back to
  // the non-optimized "AsLeafTextPosition", if the current text offset is
  // greater than 0, or the affinity is upstream, since converting to a tree
  // position at any point before reaching the leaf node could potentially lose
  // information.
  AXPositionInstance AsLeafTreePosition() const {
    if (IsNullPosition() || IsLeaf())
      return AsTreePosition();

    // If our text offset is greater than 0, or if our affinity is set to
    // upstream, we need to ensure that text offset and affinity will be taken
    // into consideration during our descend to the leaves. Switching to a tree
    // position early in this case will potentially lose information, so we
    // descend using a text position instead.
    //
    // We purposely don't check whether this position is a text position, to
    // allow for the possibility that this position has recently been converted
    // from a text to a tree position and text offset or affinity information
    // has been left intact.
    if (text_offset_ > 0 || affinity_ == ax::mojom::TextAffinity::kUpstream)
      return AsLeafTextPosition()->AsTreePosition();

    AXPositionInstance tree_position = AsTreePosition();
    do {
      if (tree_position->child_index_ == tree_position->AnchorChildCount()) {
        tree_position =
            tree_position
                ->CreateChildPositionAt(tree_position->child_index_ - 1)
                ->CreatePositionAtEndOfAnchor();
      } else {
        tree_position =
            tree_position->CreateChildPositionAt(tree_position->child_index_);
      }
      BASE_DCHECK(tree_position && !tree_position->IsNullPosition());
    } while (!tree_position->IsLeaf());

    BASE_DCHECK(tree_position && tree_position->IsLeafTreePosition());
    return tree_position;
  }

  AXPositionInstance AsTextPosition() const {
    if (IsNullPosition() || IsTextPosition())
      return Clone();

    AXPositionInstance copy = Clone();
    BASE_DCHECK(copy);
    // Check if it is a "before text" position.
    if (copy->child_index_ == BEFORE_TEXT) {
      // "Before text" positions can only appear on leaf nodes.
      BASE_DCHECK(copy->IsLeaf());
      // If the current text offset is valid, we don't touch it to potentially
      // allow converting from a text position to a tree position and back
      // without losing information.
      //
      // We test for INVALID_OFFSET first, due to the possible performance
      // implications of calling MaxTextOffset().
      BASE_DCHECK(copy->text_offset_ >= INVALID_OFFSET);
      if (copy->text_offset_ == INVALID_OFFSET ||
          (copy->text_offset_ > 0 &&
           copy->text_offset_ >= copy->MaxTextOffset())) {
        copy->text_offset_ = 0;
      }
    } else if (copy->child_index_ == copy->AnchorChildCount()) {
      copy->text_offset_ = copy->MaxTextOffset();
    } else {
      BASE_DCHECK(copy->child_index_ >= 0);
      BASE_DCHECK(copy->child_index_ < copy->AnchorChildCount());
      int new_offset = 0;
      for (int i = 0; i <= child_index_; ++i) {
        AXPositionInstance child = copy->CreateChildPositionAt(i);
        BASE_DCHECK(child);
        // If the current text offset is valid, we don't touch it to
        // potentially allow converting from a text position to a tree
        // position and back without losing information. Otherwise, if the
        // text_offset is invalid, equals to 0 or is smaller than
        // |new_offset|, we reset it to the beginning of the current child
        // node.
        if (i == child_index_ && copy->text_offset_ <= new_offset) {
          copy->text_offset_ = new_offset;
          break;
        }

        int child_length = child->MaxTextOffsetInParent();
        // Same comment as above: we don't touch the text offset if it's
        // already valid.
        if (i == child_index_ &&
            (copy->text_offset_ > (new_offset + child_length) ||
             // When the text offset is equal to the text's length but this is
             // not an "after text" position.
             (!copy->AtEndOfAnchor() &&
              copy->text_offset_ == (new_offset + child_length)))) {
          copy->text_offset_ = new_offset;
          break;
        }

        new_offset += child_length;
      }
    }

    // Affinity should always be left as downstream. The only case when the
    // resulting text position is at the end of the line is when we get an
    // "after text" leaf position, but even in this case downstream is
    // appropriate because there is no ambiguity whetehr the position is at the
    // end of the current line vs. the start of the next line. It would always
    // be the former.
    copy->kind_ = AXPositionKind::TEXT_POSITION;
    return copy;
  }

  AXPositionInstance AsLeafTextPosition() const {
    if (IsNullPosition() || IsLeaf())
      return AsTextPosition();

    // Adjust the text offset.
    // No need to check for "before text" positions here because they are only
    // present on leaf anchor nodes.
    AXPositionInstance text_position = AsTextPosition();
    int adjusted_offset = text_position->text_offset_;
    do {
      AXPositionInstance child_position =
          text_position->CreateChildPositionAt(0);
      BASE_DCHECK(child_position);

      // If the text offset corresponds to multiple child positions because some
      // of the children have empty text, the condition "adjusted_offset > 0"
      // below ensures that the first child will be chosen.
      for (int i = 1;
           i < text_position->AnchorChildCount() && adjusted_offset > 0; ++i) {
        const int max_text_offset_in_parent =
            child_position->MaxTextOffsetInParent();
        if (adjusted_offset < max_text_offset_in_parent) {
          break;
        }
        if (affinity_ == ax::mojom::TextAffinity::kUpstream &&
            adjusted_offset == max_text_offset_in_parent) {
          // Maintain upstream affinity so that we'll be able to choose the
          // correct leaf anchor if the text offset is right on the boundary
          // between two leaves.
          child_position->affinity_ = ax::mojom::TextAffinity::kUpstream;
          break;
        }
        child_position = text_position->CreateChildPositionAt(i);
        adjusted_offset -= max_text_offset_in_parent;
      }

      text_position = std::move(child_position);
    } while (!text_position->IsLeaf());

    BASE_DCHECK(text_position);
    BASE_DCHECK(text_position->IsLeafTextPosition());
    text_position->text_offset_ = adjusted_offset;
    // A leaf Text position is always downstream since there is no ambiguity as
    // to whether it refers to the end of the current or the start of the next
    // line.
    text_position->affinity_ = ax::mojom::TextAffinity::kDownstream;
    return text_position;
  }

  // We deploy three strategies in order to find the best match for an ignored
  // position in the accessibility tree:
  //
  // 1. In the case of a text position, we move up the parent positions until we
  // find the next unignored equivalent parent position. We don't do this for
  // tree positions because, unlike text positions which maintain the
  // corresponding text offset in the inner text of the parent node, tree
  // positions would lose some information every time a parent position is
  // computed. In other words, the parent position of a tree position is, in
  // most cases, non-equivalent to the child position.
  // 2. If no equivalent and unignored parent position can be computed, we try
  // computing the leaf equivalent position. If this is unignored, we return it.
  // This can happen both for tree and text positions, provided that the leaf
  // node and its inner text is visible to platform APIs, i.e. it's unignored.
  // 3. As a last resort, we move either to the next or previous unignored
  // position in the accessibility tree, based on the "adjustment_behavior".
  AXPositionInstance AsUnignoredPosition(
      AXPositionAdjustmentBehavior adjustment_behavior) const {
    if (IsNullPosition() || !IsIgnored())
      return Clone();

    AXPositionInstance leaf_tree_position = AsLeafTreePosition();

    // If this is a text position, first try moving up to a parent equivalent
    // position and check if the resulting position is still ignored. This
    // won't result in the loss of any information. We can't do that in the
    // case of tree positions, because we would be better off to move to the
    // next or previous position within the same anchor, as this would lose
    // less information than moving to a parent equivalent position.
    //
    // Text positions are considered ignored if either the current anchor is
    // ignored, or if the equivalent leaf tree position is ignored.
    // If this position is a leaf text position, or the equivalent leaf tree
    // position is ignored, then it's not possible to create an ancestor text
    // position that is unignored.
    if (IsTextPosition() && !IsLeafTextPosition() &&
        !leaf_tree_position->IsIgnored()) {
      AXPositionInstance unignored_position = CreateParentPosition();
      while (!unignored_position->IsNullPosition()) {
        // Since the equivalent leaf tree position is unignored, search for the
        // first unignored ancestor anchor and return that text position.
        if (!unignored_position->GetAnchor()->IsIgnored()) {
          BASE_DCHECK(!unignored_position->IsIgnored());
          return unignored_position;
        }
        unignored_position = unignored_position->CreateParentPosition();
      }
    }

    // There is a possibility that the position became unignored by moving to a
    // leaf equivalent position. Otherwise, we have no choice but to move to the
    // next or previous position and lose some information in the process.
    while (leaf_tree_position->IsIgnored()) {
      switch (adjustment_behavior) {
        case AXPositionAdjustmentBehavior::kMoveForward:
          leaf_tree_position = leaf_tree_position->CreateNextLeafTreePosition();
          break;
        case AXPositionAdjustmentBehavior::kMoveBackward:
          leaf_tree_position =
              leaf_tree_position->CreatePreviousLeafTreePosition();
          // in case the unignored leaf node contains some text, ensure that the
          // resulting position is an "after text" position, as such a position
          // would be the closest to the ignored one, given the fact that we are
          // moving backwards through the tree.
          leaf_tree_position =
              leaf_tree_position->CreatePositionAtEndOfAnchor();
          break;
      }
    }

    if (IsTextPosition())
      return leaf_tree_position->AsTextPosition();
    return leaf_tree_position;
  }

  // Searches backward and forward from this position until it finds the given
  // text boundary, and creates an AXRange that spans from the former to the
  // latter. The resulting AXRange is always a forward range: its anchor always
  // comes before its focus in document order. The resulting AXRange is bounded
  // by the anchor of this position, i.e. the AXBoundaryBehavior is set to
  // StopAtAnchorBoundary. The exception is ax::mojom::TextBoundary::kWebPage,
  // where this behavior won't make sense. This behavior is based on current
  // platform needs and might be relaxed if necessary in the future.
  //
  // Please note that |expand_behavior| should have no effect for
  // ax::mojom::TextBoundary::kObject and ax::mojom::TextBoundary::kWebPage
  // because the range should be the same regardless if we first move left or
  // right.
  AXRangeType ExpandToEnclosingTextBoundary(
      ax::mojom::TextBoundary boundary,
      AXRangeExpandBehavior expand_behavior) const {
    AXBoundaryBehavior boundary_behavior =
        AXBoundaryBehavior::StopAtAnchorBoundary;
    if (boundary == ax::mojom::TextBoundary::kWebPage)
      boundary_behavior = AXBoundaryBehavior::CrossBoundary;

    switch (expand_behavior) {
      case AXRangeExpandBehavior::kLeftFirst: {
        AXPositionInstance left_position = CreatePositionAtTextBoundary(
            boundary, ax::mojom::MoveDirection::kBackward, boundary_behavior);
        AXPositionInstance right_position =
            left_position->CreatePositionAtTextBoundary(
                boundary, ax::mojom::MoveDirection::kForward,
                boundary_behavior);
        return AXRangeType(std::move(left_position), std::move(right_position));
      }
      case AXRangeExpandBehavior::kRightFirst: {
        AXPositionInstance right_position = CreatePositionAtTextBoundary(
            boundary, ax::mojom::MoveDirection::kForward, boundary_behavior);
        AXPositionInstance left_position =
            right_position->CreatePositionAtTextBoundary(
                boundary, ax::mojom::MoveDirection::kBackward,
                boundary_behavior);
        return AXRangeType(std::move(left_position), std::move(right_position));
      }
    }
  }

  // Starting from this position, moves in the given direction until it finds
  // the given text boundary, and creates a new position at that location.
  //
  // When a boundary has the "StartOrEnd" suffix, it means that this method will
  // find the start boundary when moving in the backward direction, and the end
  // boundary when moving in the forward direction.
  AXPositionInstance CreatePositionAtTextBoundary(
      ax::mojom::TextBoundary boundary,
      ax::mojom::MoveDirection direction,
      AXBoundaryBehavior boundary_behavior) const {
    AXPositionInstance resulting_position = CreateNullPosition();
    switch (boundary) {
      case ax::mojom::TextBoundary::kCharacter:
        switch (direction) {
          case ax::mojom::MoveDirection::kBackward:
            resulting_position =
                CreatePreviousCharacterPosition(boundary_behavior);
            break;
          case ax::mojom::MoveDirection::kForward:
            resulting_position = CreateNextCharacterPosition(boundary_behavior);
            break;
        }
        break;

      case ax::mojom::TextBoundary::kFormat:
        switch (direction) {
          case ax::mojom::MoveDirection::kBackward:
            resulting_position =
                CreatePreviousFormatStartPosition(boundary_behavior);
            break;
          case ax::mojom::MoveDirection::kForward:
            resulting_position = CreateNextFormatEndPosition(boundary_behavior);
            break;
        }
        break;

      case ax::mojom::TextBoundary::kLineEnd:
        switch (direction) {
          case ax::mojom::MoveDirection::kBackward:
            resulting_position =
                CreatePreviousLineEndPosition(boundary_behavior);
            break;
          case ax::mojom::MoveDirection::kForward:
            resulting_position = CreateNextLineEndPosition(boundary_behavior);
            break;
        }
        break;

      case ax::mojom::TextBoundary::kLineStart:
        switch (direction) {
          case ax::mojom::MoveDirection::kBackward:
            resulting_position =
                CreatePreviousLineStartPosition(boundary_behavior);
            break;
          case ax::mojom::MoveDirection::kForward:
            resulting_position = CreateNextLineStartPosition(boundary_behavior);
            break;
        }
        break;

      case ax::mojom::TextBoundary::kLineStartOrEnd:
        switch (direction) {
          case ax::mojom::MoveDirection::kBackward:
            resulting_position =
                CreatePreviousLineStartPosition(boundary_behavior);
            break;
          case ax::mojom::MoveDirection::kForward:
            resulting_position = CreateNextLineEndPosition(boundary_behavior);
            break;
        }
        break;

      case ax::mojom::TextBoundary::kObject:
        switch (direction) {
          case ax::mojom::MoveDirection::kBackward:
            resulting_position = CreatePositionAtStartOfAnchor();
            break;
          case ax::mojom::MoveDirection::kForward:
            resulting_position = CreatePositionAtEndOfAnchor();
            break;
        }
        break;

      case ax::mojom::TextBoundary::kPageEnd:
        switch (direction) {
          case ax::mojom::MoveDirection::kBackward:
            resulting_position =
                CreatePreviousPageEndPosition(boundary_behavior);
            break;
          case ax::mojom::MoveDirection::kForward:
            resulting_position = CreateNextPageEndPosition(boundary_behavior);
            break;
        }
        break;

      case ax::mojom::TextBoundary::kPageStart:
        switch (direction) {
          case ax::mojom::MoveDirection::kBackward:
            resulting_position =
                CreatePreviousPageStartPosition(boundary_behavior);
            break;
          case ax::mojom::MoveDirection::kForward:
            resulting_position = CreateNextPageStartPosition(boundary_behavior);
            break;
        }
        break;

      case ax::mojom::TextBoundary::kPageStartOrEnd:
        switch (direction) {
          case ax::mojom::MoveDirection::kBackward:
            resulting_position =
                CreatePreviousPageStartPosition(boundary_behavior);
            break;
          case ax::mojom::MoveDirection::kForward:
            resulting_position = CreateNextPageEndPosition(boundary_behavior);
            break;
        }
        break;

      case ax::mojom::TextBoundary::kParagraphEnd:
        switch (direction) {
          case ax::mojom::MoveDirection::kBackward:
            resulting_position =
                CreatePreviousParagraphEndPosition(boundary_behavior);
            break;
          case ax::mojom::MoveDirection::kForward:
            resulting_position =
                CreateNextParagraphEndPosition(boundary_behavior);
            break;
        }
        break;

      case ax::mojom::TextBoundary::kParagraphStart:
        switch (direction) {
          case ax::mojom::MoveDirection::kBackward:
            resulting_position =
                CreatePreviousParagraphStartPosition(boundary_behavior);
            break;
          case ax::mojom::MoveDirection::kForward:
            resulting_position =
                CreateNextParagraphStartPosition(boundary_behavior);
            break;
        }
        break;

      case ax::mojom::TextBoundary::kParagraphStartOrEnd:
        switch (direction) {
          case ax::mojom::MoveDirection::kBackward:
            resulting_position =
                CreatePreviousParagraphStartPosition(boundary_behavior);
            break;
          case ax::mojom::MoveDirection::kForward:
            resulting_position =
                CreateNextParagraphEndPosition(boundary_behavior);
            break;
        }
        break;

      case ax::mojom::TextBoundary::kSentenceEnd:
        BASE_LOG() << "Sentence boundaries are not yet supported.";
        BASE_UNREACHABLE();
        return CreateNullPosition();

      case ax::mojom::TextBoundary::kSentenceStart:
        BASE_LOG() << "Sentence boundaries are not yet supported.";
        BASE_UNREACHABLE();
        return CreateNullPosition();

      case ax::mojom::TextBoundary::kSentenceStartOrEnd:
        BASE_LOG() << "Sentence boundaries are not yet supported.";
        BASE_UNREACHABLE();
        return CreateNullPosition();

      case ax::mojom::TextBoundary::kWebPage:
        if (boundary_behavior != AXBoundaryBehavior::CrossBoundary) {
          BASE_LOG() << "We can't reach the start of the document if we "
                        "are disallowed "
                        "from crossing boundaries.";
          BASE_UNREACHABLE();
        }
        switch (direction) {
          case ax::mojom::MoveDirection::kBackward:
            resulting_position = CreatePositionAtStartOfDocument();
            break;
          case ax::mojom::MoveDirection::kForward:
            resulting_position = CreatePositionAtEndOfDocument();
            break;
        }
        break;

      case ax::mojom::TextBoundary::kWordEnd:
        switch (direction) {
          case ax::mojom::MoveDirection::kBackward:
            resulting_position =
                CreatePreviousWordEndPosition(boundary_behavior);
            break;
          case ax::mojom::MoveDirection::kForward:
            resulting_position = CreateNextWordEndPosition(boundary_behavior);
            break;
        }
        break;

      case ax::mojom::TextBoundary::kWordStart:
        switch (direction) {
          case ax::mojom::MoveDirection::kBackward:
            resulting_position =
                CreatePreviousWordStartPosition(boundary_behavior);
            break;
          case ax::mojom::MoveDirection::kForward:
            resulting_position = CreateNextWordStartPosition(boundary_behavior);
            break;
        }
        break;

      case ax::mojom::TextBoundary::kWordStartOrEnd:
        switch (direction) {
          case ax::mojom::MoveDirection::kBackward:
            resulting_position =
                CreatePreviousWordStartPosition(boundary_behavior);
            break;
          case ax::mojom::MoveDirection::kForward:
            resulting_position = CreateNextWordEndPosition(boundary_behavior);
            break;
        }
        break;
    }
    return resulting_position;
  }

  AXPositionInstance CreatePositionAtStartOfAnchor() const {
    switch (kind_) {
      case AXPositionKind::NULL_POSITION:
        return CreateNullPosition();
      case AXPositionKind::TREE_POSITION:
        if (IsLeaf())
          return CreateTreePosition(tree_id_, anchor_id_, BEFORE_TEXT);
        return CreateTreePosition(tree_id_, anchor_id_, 0 /* child_index */);
      case AXPositionKind::TEXT_POSITION:
        return CreateTextPosition(tree_id_, anchor_id_, 0 /* text_offset */,
                                  ax::mojom::TextAffinity::kDownstream);
    }
    return CreateNullPosition();
  }

  AXPositionInstance CreatePositionAtEndOfAnchor() const {
    switch (kind_) {
      case AXPositionKind::NULL_POSITION:
        return CreateNullPosition();
      case AXPositionKind::TREE_POSITION:
        return CreateTreePosition(
            tree_id_, anchor_id_,
            IsEmptyObjectReplacedByCharacter() ? 0 : AnchorChildCount());
      case AXPositionKind::TEXT_POSITION:
        return CreateTextPosition(tree_id_, anchor_id_, MaxTextOffset(),
                                  ax::mojom::TextAffinity::kDownstream);
    }
    return CreateNullPosition();
  }

  AXPositionInstance CreatePositionAtStartOfAXTree() const {
    if (IsNullPosition() || AtStartOfAXTree())
      return Clone();

    // First check for positions on nodes which are AXTree boundaries, but where
    // the text position on that node is not at the start of the anchor.
    if (CreatePositionAtStartOfAnchor()->AtStartOfAXTree())
      return CreatePositionAtStartOfAnchor();

    // Iterate over tree positions until a boundary is reached.
    AXPositionInstance previous_position = AsTreePosition();
    do {
      previous_position = previous_position->CreatePreviousAnchorPosition();
    } while (!previous_position->AtStartOfAXTree());

    // This method should not cross tree boundaries.
    BASE_DCHECK(previous_position->tree_id() == tree_id());

    if (IsTextPosition())
      previous_position = previous_position->AsTextPosition();
    return previous_position;
  }

  AXPositionInstance CreatePositionAtEndOfAXTree() const {
    if (IsNullPosition() || AtEndOfAXTree())
      return Clone();

    // First check for positions on nodes which are AXTree boundaries, but where
    // the text position on that node is not at the end of the anchor.
    if (CreatePositionAtEndOfAnchor()->AtEndOfAXTree())
      return CreatePositionAtEndOfAnchor();

    // Iterate over tree positions until a boundary is reached.
    AXPositionInstance next_position = AsTreePosition();
    do {
      next_position = next_position->CreateNextAnchorPosition()
                          ->CreatePositionAtEndOfAnchor();
    } while (!next_position->AtEndOfAXTree());

    // This method should not cross tree boundaries.
    BASE_DCHECK(next_position->tree_id() == tree_id());

    if (IsTextPosition())
      next_position = next_position->AsTextPosition();
    return next_position->CreatePositionAtEndOfAnchor();
  }

  // "document" is defined here as a single, top-level, navigatable unit from
  //  a user's perspective. This means that all iframes are part of a single
  // "document" that contains the top-level navigatable page. So this method
  // will break out of an iframe and return a position at the start of the
  // top-level document.
  //
  // Note that this definition is different than HTML's definition of
  // "document", where each iframe has its own document object. For a similar
  // method that stops at iframe boundaries, see
  // CreatePositionAtStartOfAXTree().
  AXPositionInstance CreatePositionAtStartOfDocument() const {
    AXPositionInstance position =
        AsTreePosition()->CreateDocumentAncestorPosition();
    if (!position->IsNullPosition()) {
      position = position->CreatePositionAtStartOfAnchor();
      if (IsTextPosition())
        position = position->AsTextPosition();
    }
    return position;
  }

  // "document" is defined here as a single, top-level, navigatable unit from
  //  a user's perspective. This means that all iframes are part of a single
  // "document" that contains the top-level navigatable page. So this method
  // will break out of an iframe and return a position at the end of the
  // top-level document.
  //
  // Note that this definition is different than HTML's definition of
  // "document", where each iframe has its own document object. For a similar
  // method that stops at iframe boundaries, see CreatePositionAtEndOfAXTree().
  AXPositionInstance CreatePositionAtEndOfDocument() const {
    AXPositionInstance position =
        AsTreePosition()->CreateDocumentAncestorPosition();
    if (!position->IsNullPosition()) {
      while (!position->IsLeaf()) {
        position =
            position->CreateChildPositionAt(position->AnchorChildCount() - 1);
      }
      position = position->CreatePositionAtEndOfAnchor();
      if (IsTextPosition())
        position = position->AsTextPosition();
    }
    return position;
  }

  AXPositionInstance CreateChildPositionAt(int child_index) const {
    if (IsNullPosition() || IsLeaf())
      return CreateNullPosition();

    if (child_index < 0 || child_index >= AnchorChildCount())
      return CreateNullPosition();

    AXTreeID tree_id = AXTreeIDUnknown();
    AXNode::AXID child_id = AXNode::kInvalidAXID;
    AnchorChild(child_index, &tree_id, &child_id);
    BASE_DCHECK(tree_id != AXTreeIDUnknown());
    BASE_DCHECK(child_id != AXNode::kInvalidAXID);
    switch (kind_) {
      case AXPositionKind::NULL_POSITION:
        BASE_UNREACHABLE();
        return CreateNullPosition();
      case AXPositionKind::TREE_POSITION: {
        AXPositionInstance child_position =
            CreateTreePosition(tree_id, child_id, 0 /* child_index */);
        // If the child's anchor is a leaf node, make this a "before text"
        // position.
        if (child_position->IsLeaf())
          child_position->child_index_ = BEFORE_TEXT;
        return child_position;
      }
      case AXPositionKind::TEXT_POSITION:
        return CreateTextPosition(tree_id, child_id, 0 /* text_offset */,
                                  ax::mojom::TextAffinity::kDownstream);
    }

    return CreateNullPosition();
  }

  // Creates a parent equivalent position.
  //
  // "move_direction" is used only in the case of a text position, when in
  // the process of searching for a text boundary, and on platforms where child
  // nodes are represented by embedded object characters. On such platforms, the
  // "IsEmbeddedObjectInParent" method returns true. We need to decide whether
  // to create a parent equivalent position that is before or after the child
  // node, since moving to a parent position would always cause us to lose some
  // information. We can't simply re-use the text offset of the child position
  // because by definition the parent node doesn't include all the text of the
  // child node, but only a single embedded object character.
  //
  // staticText name='Line one' IA2-hypertext='<embedded_object>'
  // ++inlineTextBox name='Line one'
  //
  // If we are given a text position pointing to somewhere inside the
  // inlineTextBox, and we move to the parent equivalent position, we need to
  // decide whether the parent position would be set to point to before the
  // embedded object character or after it. Both are valid, depending on the
  // direction on motion, e.g. if we are trying to find the start of the line
  // vs. the end of the line.
  AXPositionInstance CreateParentPosition(
      ax::mojom::MoveDirection move_direction =
          ax::mojom::MoveDirection::kForward) const {
    if (IsNullPosition())
      return CreateNullPosition();

    AXTreeID tree_id = AXTreeIDUnknown();
    AXNode::AXID parent_id = AXNode::kInvalidAXID;
    AnchorParent(&tree_id, &parent_id);
    if (tree_id == AXTreeIDUnknown() || parent_id == AXNode::kInvalidAXID)
      return CreateNullPosition();

    switch (kind_) {
      case AXPositionKind::NULL_POSITION:
        BASE_UNREACHABLE();
        return CreateNullPosition();
      case AXPositionKind::TREE_POSITION:
        return CreateTreePosition(tree_id, parent_id, AnchorIndexInParent());
      case AXPositionKind::TEXT_POSITION: {
        // On some platforms, such as Android, Mac and Chrome OS, the inner text
        // of a node is made up by concatenating the text of child nodes. On
        // other platforms, such as Windows IA2 and Linux ATK, child nodes are
        // represented by a single embedded object character.
        //
        // If our parent's inner text is a concatenation of all its children's
        // text, we need to maintain the affinity and compute the corresponding
        // text offset. Otherwise, we have no choice but to return a position
        // that is either before or after this child, losing some information in
        // the process. Regardless to whether our parent contains all our text,
        // we always recompute the affinity when the position is after the
        // child.
        //
        // Recomputing the affinity in the latter situation is important because
        // even though a text position might unambiguously be at the end of a
        // line, its parent position might be the same as the parent position of
        // a position that represents the start of the next line. For example:
        //
        // staticText name='Line oneLine two'
        // ++inlineTextBox name='Line one'
        // ++inlineTextBox name='Line two'
        //
        // If the original position is at the end of the inline text box for
        // "Line one", then the resulting parent equivalent position would be
        // the same as the one that would have been computed if the original
        // position were at the start of the inline text box for "Line two".
        const int max_text_offset = MaxTextOffset();
        const int max_text_offset_in_parent =
            IsEmbeddedObjectInParent() ? 1 : max_text_offset;
        int parent_offset = AnchorTextOffsetInParent();
        ax::mojom::TextAffinity parent_affinity = affinity_;
        if (max_text_offset == max_text_offset_in_parent) {
          // Our parent contains all our text. No information would be lost when
          // moving to a parent equivalent position.
          parent_offset += text_offset_;
        } else if (text_offset_ > 0) {
          // If "text_offset_" == 0, then the child position is clearly before
          // any embedded object character. No information would be lost when
          // moving to a parent equivalent position, including affinity
          // information. Otherwise, we should decide whether to set the parent
          // position to be before or after the child, based on the direction of
          // motion, and also reset the affinity.
          switch (move_direction) {
            case ax::mojom::MoveDirection::kBackward:
              // Keep the offset to be right before the embedded object
              // character.
              break;
            case ax::mojom::MoveDirection::kForward:
              // Set the offset to be after the embedded object character.
              parent_offset += max_text_offset_in_parent;
              break;
          }

          // The original affinity doesn't apply any more. In most cases, it
          // should be downstream, unless there is an ambiguity as to whether
          // the parent position is between the end of one line and the start of
          // the next. We perform this check below.
          parent_affinity = ax::mojom::TextAffinity::kDownstream;
        }

        AXPositionInstance parent_position = CreateTextPosition(
            tree_id, parent_id, parent_offset, parent_affinity);

        // If the current position is pointing at the end of its anchor, we need
        // to check if the parent position has introduced ambiguity as to
        // whether it refers to the end of a line or the start of the next.
        // Ambiguity is only present when the parent position points to a text
        // offset that is neither at the start nor at the end of its anchor. We
        // check for ambiguity by creating the parent position and testing if it
        // is erroneously at the start of the next line. Given that the current
        // position, by the nature of being at the end of its anchor, could only
        // be at end of line, the fact that the parent position is also
        // determined to be at start of line demonstrates the presence of
        // ambiguity which is resolved by setting its affinity to upstream.
        //
        // We could not have
        // checked if the child was at the end of the line, because our
        // "AtEndOfLine" predicate takes into account trailing line breaks,
        // which would create false positives.
        if (text_offset_ == max_text_offset &&
            !parent_position->AtEndOfAnchor() &&
            parent_position->AtStartOfLine()) {
          parent_position->affinity_ = ax::mojom::TextAffinity::kUpstream;
        }
        return parent_position;
      }
    }

    return CreateNullPosition();
  }

  // Creates a tree position using the next text-only node as its anchor.
  // Assumes that text-only nodes are leaf nodes.
  AXPositionInstance CreateNextLeafTreePosition() const {
    return CreateNextLeafTreePosition(&DefaultAbortMovePredicate);
  }

  // Creates a tree position using the previous text-only node as its anchor.
  // Assumes that text-only nodes are leaf nodes.
  AXPositionInstance CreatePreviousLeafTreePosition() const {
    return CreatePreviousLeafTreePosition(&DefaultAbortMovePredicate);
  }

  // Creates the next text position anchored at a leaf node of the AXTree.
  //
  // If a pointer |crossed_line_breaking_object| is provided, it'll be set to
  // |true| if any line breaking object boundary was crossed by moving from this
  // leaf text position to the next (if it exists), |false| otherwise.
  AXPositionInstance CreateNextLeafTextPosition(
      bool* crossed_line_breaking_object = nullptr) const {
    if (crossed_line_breaking_object)
      *crossed_line_breaking_object = false;

    // If this is an ancestor text position, resolve to its leaf text position.
    if (IsTextPosition() && !IsLeaf())
      return AsLeafTextPosition();
    std::function<AbortMovePredicate> abort_move_predicate;
    if (crossed_line_breaking_object) {
      abort_move_predicate = [crossed_line_breaking_object](
                                 const AXPosition& move_from,
                                 const AXPosition& move_to,
                                 const AXMoveType type,
                                 const AXMoveDirection direction) {
        return UpdateCrossedLineBreakingObjectToken(
            *crossed_line_breaking_object, move_from, move_to, type, direction);
      };
    } else {
      abort_move_predicate =
          [](const AXPosition& move_from, const AXPosition& move_to,
             const AXMoveType type, const AXMoveDirection direction) {
            return AXPosition::DefaultAbortMovePredicate(move_from, move_to,
                                                         type, direction);
          };
    }
    return CreateNextLeafTreePosition(abort_move_predicate)->AsTextPosition();
  }

  // Creates a text position using the previous text-only node as its anchor.
  // Assumes that text-only nodes are leaf nodes.
  AXPositionInstance CreatePreviousLeafTextPosition() const {
    return CreatePreviousTextAnchorPosition(DefaultAbortMovePredicate);
  }

  // Returns a text position located right before the next character (from this
  // position) in the tree's text representation, following these conditions:
  //
  //   - If this position is at the end of its anchor, normalize it to the start
  //   of the next text anchor, regardless of the position's affinity.
  //   Both text positions are equal when compared, but we consider the start of
  //   an anchor to be a position BEFORE its first character and the end of the
  //   previous to be AFTER its last character.
  //
  //   - Skip any empty text anchors; they're "invisible" to the text
  //   representation and the next character could be ahead.
  //
  //   - Return a null position if there is no next character forward.
  //
  // If possible, return a position anchored at the current position's anchor;
  // this is necessary because we don't want to return any position that might
  // be located in the shadow DOM or in a position anchored at a node that is
  // not visible to a specific platform's APIs.
  //
  // Also, |text_offset| is adjusted to point to a valid character offset, i.e.
  // it cannot be pointing to a low surrogate pair or to the middle of a
  // grapheme cluster.
  AXPositionInstance AsLeafTextPositionBeforeCharacter() const {
    if (IsNullPosition())
      return Clone();

    AXPositionInstance text_position = AsTextPosition();
    // In case the input affinity is upstream, reset it to downstream.
    //
    // This is to ensure that when we find the equivalent leaf text position, it
    // will be at the start of anchor if the original position is anchored to a
    // node higher up in the tree and pointing to a text offset that falls on
    // the boundary between two leaf nodes. In other words, the returned
    // position will always be "before character".
    text_position->affinity_ = ax::mojom::TextAffinity::kDownstream;
    text_position = text_position->AsLeafTextPosition();
    BASE_DCHECK(!text_position->IsNullPosition())
        << "Adjusting to a leaf position should never turn a non-null position "
           "into a null one.";
    if (!text_position->IsIgnored() && !text_position->AtEndOfAnchor()) {
      BASE_DCHECK(text_position->text_offset_ >= 0);
      return text_position;
    }
    text_position = text_position->CreateNextLeafTextPosition();
    while (!text_position->IsNullPosition() &&
           (text_position->IsIgnored() || !text_position->MaxTextOffset())) {
      text_position = text_position->CreateNextLeafTextPosition();
    }
    return text_position;
  }

  // Returns a text position located right after the previous character (from
  // this position) in the tree's text representation.
  //
  // See `AsLeafTextPositionBeforeCharacter`, as this is its "reversed" version.
  AXPositionInstance AsLeafTextPositionAfterCharacter() const {
    if (IsNullPosition())
      return Clone();

    AXPositionInstance text_position = AsTextPosition();
    // Temporarily set the affinity to upstream.
    //
    // This is to ensure that when we find the equivalent leaf text position, it
    // will be at the end of anchor if the original position is anchored to a
    // node higher up in the tree and pointing to a text offset that falls on
    // the boundary between two leaf nodes. In other words, the returned
    // position will always be "after character".
    text_position->affinity_ = ax::mojom::TextAffinity::kUpstream;
    text_position = text_position->AsLeafTextPosition();
    BASE_DCHECK(!text_position->IsNullPosition())
        << "Adjusting to a leaf position should never turn a non-null position "
           "into a null one.";
    if (!text_position->IsIgnored() && !text_position->AtStartOfAnchor()) {
      // The following situation should not be possible but there are existing
      // crashes in the field.
      //
      // TODO(nektar): Remove this workaround as soon as the source of the bug
      // is identified.
      BASE_DCHECK(text_position->text_offset_ >= 0);
      // TODO(chunhtai): handles grapheme.

      // Reset the affinity to downstream, because an upstream affinity doesn't
      // make sense on a leaf anchor.
      text_position->affinity_ = ax::mojom::TextAffinity::kDownstream;
      return text_position;
    }
    text_position = text_position->CreatePreviousLeafTextPosition();
    while (!text_position->IsNullPosition() &&
           (text_position->IsIgnored() || !text_position->MaxTextOffset())) {
      text_position = text_position->CreatePreviousLeafTextPosition();
    }
    return text_position->CreatePositionAtEndOfAnchor();
  }

  // Creates a position pointing to before the next character, which is defined
  // as the start of the next grapheme cluster. Also, ensures that the created
  // position will not point to a low surrogate pair.
  //
  // A grapheme cluster is what an end-user would consider a character and it
  // could include a letter with additional diacritics. It could be more than
  // one Unicode code unit in length.
  //
  // See also http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries
  AXPositionInstance CreateNextCharacterPosition(
      AXBoundaryBehavior boundary_behavior) const {
    if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary &&
        AtEndOfAnchor()) {
      return Clone();
    }

    // There is no next character position.
    AXPositionInstance text_position = AsLeafTextPositionBeforeCharacter();
    if (text_position->IsNullPosition()) {
      if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary ||
          boundary_behavior == AXBoundaryBehavior::StopAtLastAnchorBoundary) {
        text_position = Clone();
      }
      return text_position;
    }

    if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary &&
        *text_position == *this) {
      return Clone();
    }
    BASE_DCHECK(text_position->text_offset_ < text_position->MaxTextOffset());
    // TODO(chunhtai): Need to consider grapheme cluster.
    ++text_position->text_offset_;
    BASE_DCHECK(text_position->text_offset_ > 0);
    BASE_DCHECK(text_position->text_offset_ <= text_position->MaxTextOffset());
    // If the character boundary is in the same subtree, return a position
    // rooted at this position's anchor. This is necessary because we don't want
    // to return a position that might be in the shadow DOM when this position
    // is not.
    const AXNodeType* common_anchor = text_position->LowestCommonAnchor(*this);
    if (GetAnchor() == common_anchor) {
      text_position = text_position->CreateAncestorPosition(
          common_anchor, ax::mojom::MoveDirection::kForward);
    } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) {
      // If the next character position crosses the current anchor boundary
      // with StopAtAnchorBoundary, snap to the end of the current anchor.
      return CreatePositionAtEndOfAnchor();
    }
    // Even if the resulting position is right on a soft line break, affinity is
    // defaulted to downstream so that this method will always produce the same
    // result regardless of the direction of motion or the input affinity.
    text_position->affinity_ = ax::mojom::TextAffinity::kDownstream;
    if (IsTreePosition())
      return text_position->AsTreePosition();
    return text_position;
  }

  // Creates a position pointing to before the previous character, which is
  // defined as the start of the previous grapheme cluster. Also, ensures that
  // the created position will not point to a low surrogate pair.
  //
  // See the comment above `CreateNextCharacterPosition` for the definition of a
  // grapheme cluster.
  AXPositionInstance CreatePreviousCharacterPosition(
      AXBoundaryBehavior boundary_behavior) const {
    if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary &&
        AtStartOfAnchor()) {
      return Clone();
    }

    // There is no previous character position.
    AXPositionInstance text_position = AsLeafTextPositionAfterCharacter();
    if (text_position->IsNullPosition()) {
      if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary ||
          boundary_behavior == AXBoundaryBehavior::StopAtLastAnchorBoundary) {
        text_position = Clone();
      }
      return text_position;
    }

    if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary &&
        *text_position == *this) {
      return Clone();
    }
    BASE_DCHECK(text_position->text_offset_ > 0);
    // TODO(chunhtai): Need to consider grapheme cluster.
    --text_position->text_offset_;
    BASE_DCHECK(text_position->text_offset_ >= 0);
    BASE_DCHECK(text_position->text_offset_ < text_position->MaxTextOffset());
    // The character boundary should be in the same subtree. Return a position
    // rooted at this position's anchor. This is necessary because we don't want
    // to return a position that might be in the shadow DOM when this position
    // is not.
    const AXNodeType* common_anchor = text_position->LowestCommonAnchor(*this);
    if (GetAnchor() == common_anchor) {
      text_position = text_position->CreateAncestorPosition(
          common_anchor, ax::mojom::MoveDirection::kBackward);
    } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) {
      // If the previous character position crosses the current anchor boundary
      // with StopAtAnchorBoundary, snap to the start of the current anchor.
      return CreatePositionAtStartOfAnchor();
    }
    // Even if the resulting position is right on a soft line break, affinity is
    // defaulted to downstream so that this method will always produce the same
    // result regardless of the direction of motion or the input affinity.
    text_position->affinity_ = ax::mojom::TextAffinity::kDownstream;
    if (IsTreePosition())
      return text_position->AsTreePosition();
    return text_position;
  }

  AXPositionInstance CreateNextWordStartPosition(
      AXBoundaryBehavior boundary_behavior) const {
    return CreateBoundaryStartPosition(
        boundary_behavior, ax::mojom::MoveDirection::kForward,
        &AtStartOfWordPredicate, &AtEndOfWordPredicate,
        &GetWordStartOffsetsFunc);
  }

  AXPositionInstance CreatePreviousWordStartPosition(
      AXBoundaryBehavior boundary_behavior) const {
    return CreateBoundaryStartPosition(
        boundary_behavior, ax::mojom::MoveDirection::kBackward,
        &AtStartOfWordPredicate, &AtEndOfWordPredicate,
        &GetWordStartOffsetsFunc);
  }

  // Word end positions are one past the last character of the word.
  AXPositionInstance CreateNextWordEndPosition(
      AXBoundaryBehavior boundary_behavior) const {
    return CreateBoundaryEndPosition(
        boundary_behavior, ax::mojom::MoveDirection::kForward,
        &AtStartOfWordPredicate, &AtEndOfWordPredicate, &GetWordEndOffsetsFunc);
  }

  // Word end positions are one past the last character of the word.
  AXPositionInstance CreatePreviousWordEndPosition(
      AXBoundaryBehavior boundary_behavior) const {
    return CreateBoundaryEndPosition(
        boundary_behavior, ax::mojom::MoveDirection::kBackward,
        &AtStartOfWordPredicate, &AtEndOfWordPredicate, &GetWordEndOffsetsFunc);
  }

  AXPositionInstance CreateNextLineStartPosition(
      AXBoundaryBehavior boundary_behavior) const {
    return CreateBoundaryStartPosition(
        boundary_behavior, ax::mojom::MoveDirection::kForward,
        &AtStartOfLinePredicate, &AtEndOfLinePredicate);
  }

  AXPositionInstance CreatePreviousLineStartPosition(
      AXBoundaryBehavior boundary_behavior) const {
    return CreateBoundaryStartPosition(
        boundary_behavior, ax::mojom::MoveDirection::kBackward,
        &AtStartOfLinePredicate, &AtEndOfLinePredicate);
  }

  // Line end positions are one past the last character of the line, excluding
  // any white space or newline characters that separate the lines.
  AXPositionInstance CreateNextLineEndPosition(
      AXBoundaryBehavior boundary_behavior) const {
    return CreateBoundaryEndPosition(
        boundary_behavior, ax::mojom::MoveDirection::kForward,
        &AtStartOfLinePredicate, &AtEndOfLinePredicate);
  }

  // Line end positions are one past the last character of the line, excluding
  // any white space or newline characters separating the lines.
  AXPositionInstance CreatePreviousLineEndPosition(
      AXBoundaryBehavior boundary_behavior) const {
    return CreateBoundaryEndPosition(
        boundary_behavior, ax::mojom::MoveDirection::kBackward,
        &AtStartOfLinePredicate, &AtEndOfLinePredicate);
  }

  AXPositionInstance CreatePreviousFormatStartPosition(
      AXBoundaryBehavior boundary_behavior) const {
    if (IsNullPosition())
      return Clone();

    AXBoundaryType boundary_type = GetFormatStartBoundaryType();
    if (boundary_type != AXBoundaryType::kNone) {
      if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary ||
          (boundary_behavior == AXBoundaryBehavior::StopAtLastAnchorBoundary &&
           boundary_type == AXBoundaryType::kDocumentStart)) {
        AXPositionInstance clone = Clone();
        // In order to make equality checks simpler, affinity should be reset so
        // that we would get consistent output from this function regardless of
        // input affinity.
        clone->affinity_ = ax::mojom::TextAffinity::kDownstream;
        return clone;
      } else if (boundary_behavior == AXBoundaryBehavior::CrossBoundary &&
                 boundary_type == AXBoundaryType::kDocumentStart) {
        // If we're at a format boundary and there are no more text positions
        // to traverse, return a null position for cross-boundary moves.
        return CreateNullPosition();
      }
    }

    AXPositionInstance tree_position =
        AsTreePosition()->CreatePositionAtStartOfAnchor();
    AXPositionInstance previous_tree_position =
        tree_position->CreatePreviousLeafTreePosition();

    // If moving to the start of the current anchor hasn't changed our position
    // from the original position, we need to test the previous leaf tree
    // position.
    if (AtStartOfAnchor() &&
        boundary_behavior != AXBoundaryBehavior::StopIfAlreadyAtBoundary) {
      tree_position = std::move(previous_tree_position);
      previous_tree_position = tree_position->CreatePreviousLeafTreePosition();
    }

    // The first position in the document is also a format start boundary, so we
    // should not return NullPosition unless we started from that location.
    while (boundary_type != AXBoundaryType::kDocumentStart &&
           !previous_tree_position->IsNullPosition() &&
           !tree_position->AtStartOfFormat()) {
      tree_position = std::move(previous_tree_position);
      previous_tree_position = tree_position->CreatePreviousLeafTreePosition();
    }

    // If the format boundary is in the same subtree, return a position rooted
    // at the current position.
    // This is necessary because we don't want to return any position that might
    // be in the shadow DOM if the original position was not.
    const AXNodeType* common_anchor = tree_position->LowestCommonAnchor(*this);
    if (GetAnchor() == common_anchor) {
      tree_position = tree_position->CreateAncestorPosition(
          common_anchor, ax::mojom::MoveDirection::kBackward);
    } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) {
      return CreatePositionAtStartOfAnchor();
    }

    if (IsTextPosition())
      return tree_position->AsTextPosition();
    return tree_position;
  }

  AXPositionInstance CreateNextFormatEndPosition(
      AXBoundaryBehavior boundary_behavior) const {
    if (IsNullPosition())
      return Clone();

    AXBoundaryType boundary_type = GetFormatEndBoundaryType();
    if (boundary_type != AXBoundaryType::kNone) {
      if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary ||
          (boundary_behavior == AXBoundaryBehavior::StopAtLastAnchorBoundary &&
           boundary_type == AXBoundaryType::kDocumentEnd)) {
        AXPositionInstance clone = Clone();
        // In order to make equality checks simpler, affinity should be reset so
        // that we would get consistent output from this function regardless of
        // input affinity.
        clone->affinity_ = ax::mojom::TextAffinity::kDownstream;
        return clone;
      } else if (boundary_behavior == AXBoundaryBehavior::CrossBoundary &&
                 boundary_type == AXBoundaryType::kDocumentEnd) {
        // If we're at a format boundary and there are no more text positions
        // to traverse, return a null position for cross-boundary moves.
        return CreateNullPosition();
      }
    }

    AXPositionInstance tree_position =
        AsTreePosition()->CreatePositionAtEndOfAnchor();
    AXPositionInstance next_tree_position =
        tree_position->CreateNextLeafTreePosition()
            ->CreatePositionAtEndOfAnchor();

    // If moving to the end of the current anchor hasn't changed our original
    // position, we need to test the next leaf tree position.
    if (AtEndOfAnchor() &&
        boundary_behavior != AXBoundaryBehavior::StopIfAlreadyAtBoundary) {
      tree_position = std::move(next_tree_position);
      next_tree_position = tree_position->CreateNextLeafTreePosition()
                               ->CreatePositionAtEndOfAnchor();
    }

    // The last position in the document is also a format end boundary, so we
    // should not return NullPosition unless we started from that location.
    while (boundary_type != AXBoundaryType::kDocumentEnd &&
           !next_tree_position->IsNullPosition() &&
           !tree_position->AtEndOfFormat()) {
      tree_position = std::move(next_tree_position);
      next_tree_position = tree_position->CreateNextLeafTreePosition()
                               ->CreatePositionAtEndOfAnchor();
    }

    // If the format boundary is in the same subtree, return a position
    // rooted at the current position.
    // This is necessary because we don't want to return any position that might
    // be in the shadow DOM if the original position was not.
    const AXNodeType* common_anchor = tree_position->LowestCommonAnchor(*this);
    if (GetAnchor() == common_anchor) {
      tree_position = tree_position->CreateAncestorPosition(
          common_anchor, ax::mojom::MoveDirection::kForward);
    } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) {
      return CreatePositionAtEndOfAnchor();
    }

    if (IsTextPosition())
      return tree_position->AsTextPosition();
    return tree_position;
  }

  AXPositionInstance CreateNextParagraphStartPosition(
      AXBoundaryBehavior boundary_behavior) const {
    return CreateBoundaryStartPosition(
        boundary_behavior, ax::mojom::MoveDirection::kForward,
        &AtStartOfParagraphPredicate, &AtEndOfParagraphPredicate);
  }

  AXPositionInstance CreatePreviousParagraphStartPosition(
      AXBoundaryBehavior boundary_behavior) const {
    return CreateBoundaryStartPosition(
        boundary_behavior, ax::mojom::MoveDirection::kBackward,
        &AtStartOfParagraphPredicate, &AtEndOfParagraphPredicate);
  }

  AXPositionInstance CreateNextParagraphEndPosition(
      AXBoundaryBehavior boundary_behavior) const {
    return CreateBoundaryEndPosition(
        boundary_behavior, ax::mojom::MoveDirection::kForward,
        &AtStartOfParagraphPredicate, &AtEndOfParagraphPredicate);
  }

  AXPositionInstance CreatePreviousParagraphEndPosition(
      AXBoundaryBehavior boundary_behavior) const {
    AXPositionInstance previous_position = CreateBoundaryEndPosition(
        boundary_behavior, ax::mojom::MoveDirection::kBackward,
        &AtStartOfParagraphPredicate, &AtEndOfParagraphPredicate);
    if (boundary_behavior == AXBoundaryBehavior::CrossBoundary ||
        boundary_behavior == AXBoundaryBehavior::StopAtLastAnchorBoundary) {
      // This is asymmetric with CreateNextParagraphEndPosition due to
      // asymmetries in text anchor movement. Consider:
      //
      // ++1 rootWebArea
      // ++++2 staticText name="FIRST"
      // ++++3 genericContainer isLineBreakingObject=true
      // ++++++4 genericContainer isLineBreakingObject=true
      // ++++++5 staticText name="SECOND"
      //
      // Node 2 offset 5 FIRST<> is a paragraph end since node 3 is a line-
      // breaking object that's not collapsible (since it's not a leaf). When
      // looking for the next text anchor position from there, we advance to
      // sibling node 3, then since that node has descendants, we convert to a
      // tree position to find the leaf node that maps to "node 3 offset 0".
      // Since node 4 has no text, we skip it and land on node 5. We end up at
      // node 5 offset 6 SECOND<> as our next paragraph end.
      //
      // The set of paragraph ends should be consistent when moving in the
      // reverse direction. But starting from node 5 offset 6, the previous text
      // anchor position is previous sibling node 4. We'll consider that a
      // paragraph end since it's a leaf line-breaking object and stop.
      //
      // Essentially, we have two consecutive line-breaking objects, each of
      // which stops movement in the "outward" direction, for different reasons.
      //
      // We handle this by looking back one more step after finding a candidate
      // for previous paragraph end, then testing a forward step from the look-
      // back position. That will land us on the candidate position if it's a
      // valid paragraph boundary.
      //
      while (!previous_position->IsNullPosition()) {
        AXPositionInstance look_back_position =
            previous_position->AsLeafTextPosition()
                ->CreatePreviousLeafTextPosition()
                ->CreatePositionAtEndOfAnchor();
        if (look_back_position->IsNullPosition()) {
          // Nowhere to look back to, so our candidate must be a valid paragraph
          // boundary.
          break;
        }
        AXPositionInstance forward_step_position =
            look_back_position->CreateNextLeafTextPosition()
                ->CreatePositionAtEndOfAnchor();
        if (*forward_step_position == *previous_position)
          break;

        previous_position = previous_position->CreateBoundaryEndPosition(
            boundary_behavior, ax::mojom::MoveDirection::kBackward,
            &AtStartOfParagraphPredicate, &AtEndOfParagraphPredicate);
      }
    }

    return previous_position;
  }

  AXPositionInstance CreateNextPageStartPosition(
      AXBoundaryBehavior boundary_behavior) const {
    return CreateBoundaryStartPosition(
        boundary_behavior, ax::mojom::MoveDirection::kForward,
        &AtStartOfPagePredicate, &AtEndOfPagePredicate);
  }

  AXPositionInstance CreatePreviousPageStartPosition(
      AXBoundaryBehavior boundary_behavior) const {
    return CreateBoundaryStartPosition(
        boundary_behavior, ax::mojom::MoveDirection::kBackward,
        &AtStartOfPagePredicate, &AtEndOfPagePredicate);
  }

  AXPositionInstance CreateNextPageEndPosition(
      AXBoundaryBehavior boundary_behavior) const {
    return CreateBoundaryEndPosition(
        boundary_behavior, ax::mojom::MoveDirection::kForward,
        &AtStartOfPagePredicate, &AtEndOfPagePredicate);
  }

  AXPositionInstance CreatePreviousPageEndPosition(
      AXBoundaryBehavior boundary_behavior) const {
    return CreateBoundaryEndPosition(
        boundary_behavior, ax::mojom::MoveDirection::kBackward,
        &AtStartOfPagePredicate, &AtEndOfPagePredicate);
  }

  AXPositionInstance CreateBoundaryStartPosition(
      AXBoundaryBehavior boundary_behavior,
      ax::mojom::MoveDirection move_direction,
      BoundaryConditionPredicate at_start_condition,
      BoundaryConditionPredicate at_end_condition,
      BoundaryTextOffsetsFunc get_start_offsets = {}) const {
    AXPositionInstance text_position = AsLeafTextPosition();
    if (text_position->IsNullPosition())
      return text_position;

    if (boundary_behavior != AXBoundaryBehavior::StopIfAlreadyAtBoundary) {
      text_position =
          text_position->CreateAdjacentLeafTextPosition(move_direction);
      if (text_position->IsNullPosition()) {
        // There is no adjacent position to move to; in such case, CrossBoundary
        // behavior shall return a null position, while any other behavior shall
        // fallback to return the initial position.
        if (boundary_behavior == AXBoundaryBehavior::CrossBoundary)
          return text_position;
        return Clone();
      }
    }

    if (!at_start_condition(text_position)) {
      text_position = text_position->CreatePositionAtNextOffsetBoundary(
          move_direction, get_start_offsets);

      while (!at_start_condition(text_position)) {
        AXPositionInstance next_position;
        if (move_direction == ax::mojom::MoveDirection::kForward) {
          next_position = text_position->CreateNextLeafTextPosition();
        } else {
          if (text_position->AtStartOfAnchor()) {
            next_position = text_position->CreatePreviousLeafTextPosition();
          } else {
            text_position = text_position->CreatePositionAtStartOfAnchor();
            BASE_DCHECK(!text_position->IsNullPosition());
            continue;
          }
        }

        if (next_position->IsNullPosition()) {
          if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) {
            switch (move_direction) {
              case ax::mojom::MoveDirection::kForward:
                return CreatePositionAtEndOfAnchor()->AsUnignoredPosition(
                    AXPositionAdjustmentBehavior::kMoveForward);
              case ax::mojom::MoveDirection::kBackward:
                return CreatePositionAtStartOfAnchor()->AsUnignoredPosition(
                    AXPositionAdjustmentBehavior::kMoveBackward);
            }
          }

          if (boundary_behavior ==
              AXBoundaryBehavior::StopAtLastAnchorBoundary) {
            // We can't simply return the following position; break and after
            // this loop we'll try to do some adjustments to text_position.
            switch (move_direction) {
              case ax::mojom::MoveDirection::kForward:
                text_position = text_position->CreatePositionAtEndOfAnchor();
                break;
              case ax::mojom::MoveDirection::kBackward:
                text_position = text_position->CreatePositionAtStartOfAnchor();
                break;
            }

            break;
          }

          return next_position->AsUnignoredPosition(
              AdjustmentBehaviorFromBoundaryDirection(move_direction));
        }

        // Continue searching for the next boundary start in the specified
        // direction until the next logical text position is reached.
        text_position = next_position->CreatePositionAtFirstOffsetBoundary(
            move_direction, get_start_offsets);
      }
    }

    // If the boundary is in the same subtree, return a position rooted at this
    // position's anchor. This is necessary because we don't want to return a
    // position that might be in the shadow DOM when this position is not.
    const AXNodeType* common_anchor = text_position->LowestCommonAnchor(*this);
    if (GetAnchor() == common_anchor) {
      text_position =
          text_position->CreateAncestorPosition(common_anchor, move_direction);
    } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) {
      switch (move_direction) {
        case ax::mojom::MoveDirection::kForward:
          return CreatePositionAtEndOfAnchor()->AsUnignoredPosition(
              AXPositionAdjustmentBehavior::kMoveForward);
        case ax::mojom::MoveDirection::kBackward:
          return CreatePositionAtStartOfAnchor()->AsUnignoredPosition(
              AXPositionAdjustmentBehavior::kMoveBackward);
      }
    }

    // Affinity is only upstream at the end of a line, and so a start boundary
    // will never have an upstream affinity.
    text_position->affinity_ = ax::mojom::TextAffinity::kDownstream;
    if (IsTreePosition())
      text_position = text_position->AsTreePosition();
    AXPositionInstance unignored_position = text_position->AsUnignoredPosition(
        AdjustmentBehaviorFromBoundaryDirection(move_direction));
    // If there are no unignored positions in |move_direction| then
    // |text_position| is anchored in ignored content at the start or end
    // of the document.
    // For StopAtLastAnchorBoundary, try to adjust in the opposite direction
    // to return a position within the document just before crossing into
    // the ignored content. This will be the last unignored anchor boundary.
    if (unignored_position->IsNullPosition() &&
        boundary_behavior == AXBoundaryBehavior::StopAtLastAnchorBoundary) {
      unignored_position =
          text_position->AsUnignoredPosition(OppositeAdjustmentBehavior(
              AdjustmentBehaviorFromBoundaryDirection(move_direction)));
    }
    return unignored_position;
  }

  AXPositionInstance CreateBoundaryEndPosition(
      AXBoundaryBehavior boundary_behavior,
      ax::mojom::MoveDirection move_direction,
      BoundaryConditionPredicate at_start_condition,
      BoundaryConditionPredicate at_end_condition,
      BoundaryTextOffsetsFunc get_end_offsets = {}) const {
    AXPositionInstance text_position = AsLeafTextPosition();
    if (text_position->IsNullPosition())
      return text_position;

    if (boundary_behavior != AXBoundaryBehavior::StopIfAlreadyAtBoundary) {
      text_position =
          text_position->CreateAdjacentLeafTextPosition(move_direction);
      if (text_position->IsNullPosition()) {
        // There is no adjacent position to move to; in such case, CrossBoundary
        // behavior shall return a null position, while any other behavior shall
        // fallback to return the initial position.
        if (boundary_behavior == AXBoundaryBehavior::CrossBoundary)
          return text_position;
        return Clone();
      }
    }

    if (!at_end_condition(text_position)) {
      text_position = text_position->CreatePositionAtNextOffsetBoundary(
          move_direction, get_end_offsets);

      while (!at_end_condition(text_position)) {
        AXPositionInstance next_position;
        if (move_direction == ax::mojom::MoveDirection::kForward) {
          if (text_position->AtEndOfAnchor()) {
            next_position = text_position->CreateNextLeafTextPosition();
          } else {
            text_position = text_position->CreatePositionAtEndOfAnchor();
            BASE_DCHECK(!text_position->IsNullPosition());
            continue;
          }
        } else {
          next_position = text_position->CreatePreviousLeafTextPosition()
                              ->CreatePositionAtEndOfAnchor();
        }

        if (next_position->IsNullPosition()) {
          if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) {
            switch (move_direction) {
              case ax::mojom::MoveDirection::kForward:
                return CreatePositionAtEndOfAnchor()->AsUnignoredPosition(
                    AXPositionAdjustmentBehavior::kMoveForward);
              case ax::mojom::MoveDirection::kBackward:
                return CreatePositionAtStartOfAnchor()->AsUnignoredPosition(
                    AXPositionAdjustmentBehavior::kMoveBackward);
            }
          }

          if (boundary_behavior ==
              AXBoundaryBehavior::StopAtLastAnchorBoundary) {
            // We can't simply return the following position; break and after
            // this loop we'll try to do some adjustments to text_position.
            switch (move_direction) {
              case ax::mojom::MoveDirection::kForward:
                text_position = text_position->CreatePositionAtEndOfAnchor();
                break;
              case ax::mojom::MoveDirection::kBackward:
                text_position = text_position->CreatePositionAtStartOfAnchor();
                break;
            }

            break;
          }

          return next_position->AsUnignoredPosition(
              AdjustmentBehaviorFromBoundaryDirection(move_direction));
        }

        // Continue searching for the next boundary end in the specified
        // direction until the next logical text position is reached.
        text_position = next_position->CreatePositionAtFirstOffsetBoundary(
            move_direction, get_end_offsets);
      }
    }

    // If the boundary is in the same subtree, return a position rooted at this
    // position's anchor. This is necessary because we don't want to return a
    // position that might be in the shadow DOM when this position is not.
    const AXNodeType* common_anchor = text_position->LowestCommonAnchor(*this);
    if (GetAnchor() == common_anchor) {
      text_position =
          text_position->CreateAncestorPosition(common_anchor, move_direction);
    } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) {
      switch (move_direction) {
        case ax::mojom::MoveDirection::kForward:
          return CreatePositionAtEndOfAnchor()->AsUnignoredPosition(
              AXPositionAdjustmentBehavior::kMoveForward);
        case ax::mojom::MoveDirection::kBackward:
          return CreatePositionAtStartOfAnchor()->AsUnignoredPosition(
              AXPositionAdjustmentBehavior::kMoveBackward);
      }
    }

    // If there is no ambiguity as to whether the position is at the end of
    // the current boundary or the start of the next boundary, an upstream
    // affinity should be reset to downstream in order to get consistent output
    // from this method, regardless of input affinity.
    //
    // Note that there could be no ambiguity if the boundary is either at the
    // start or the end of the current anchor, so we should always reset to
    // downstream affinity in those cases.
    if (text_position->affinity_ == ax::mojom::TextAffinity::kUpstream) {
      AXPositionInstance downstream_position = text_position->Clone();
      downstream_position->affinity_ = ax::mojom::TextAffinity::kDownstream;
      if (downstream_position->AtStartOfAnchor() ||
          downstream_position->AtEndOfAnchor() ||
          !at_start_condition(downstream_position)) {
        text_position->affinity_ = ax::mojom::TextAffinity::kDownstream;
      }
    }

    if (IsTreePosition())
      text_position = text_position->AsTreePosition();
    AXPositionInstance unignored_position = text_position->AsUnignoredPosition(
        AdjustmentBehaviorFromBoundaryDirection(move_direction));
    // If there are no unignored positions in |move_direction| then
    // |text_position| is anchored in ignored content at the start or end
    // of the document.
    // For StopAtLastAnchorBoundary, try to adjust in the opposite direction
    // to return a position within the document just before crossing into
    // the ignored content. This will be the last unignored anchor boundary.
    if (unignored_position->IsNullPosition() &&
        boundary_behavior == AXBoundaryBehavior::StopAtLastAnchorBoundary) {
      unignored_position =
          text_position->AsUnignoredPosition(OppositeAdjustmentBehavior(
              AdjustmentBehaviorFromBoundaryDirection(move_direction)));
    }
    return unignored_position;
  }

  // TODO(nektar): Add sentence navigation methods.

  // Uses depth-first pre-order traversal.
  AXPositionInstance CreateNextAnchorPosition() const {
    return CreateNextAnchorPosition(&DefaultAbortMovePredicate);
  }

  // Uses depth-first pre-order traversal.
  AXPositionInstance CreatePreviousAnchorPosition() const {
    return CreatePreviousAnchorPosition(&DefaultAbortMovePredicate);
  }

  // Returns an optional integer indicating the logical order of this position
  // compared to another position or returns an empty optional if the positions
  // are not comparable. Any text position at the same character location is
  // logically equivalent although they may be on different anchors or have
  // different text offsets. Positions are not comparable when one position is
  // null and the other is not or if the positions do not have any common
  // ancestor.
  //    0: if this position is logically equivalent to the other position
  //   <0: if this position is logically less than the other position
  //   >0: if this position is logically greater than the other position
  std::optional<int> CompareTo(const AXPosition& other) const {
    if (this->IsNullPosition() && other.IsNullPosition())
      return std::optional<int>(0);
    if (this->IsNullPosition() || other.IsNullPosition())
      return std::optional<int>(std::nullopt);

    // If both positions share an anchor and are of the same type, we can do a
    // straight compare of text offsets or child indices.
    if (GetAnchor() == other.GetAnchor()) {
      if (IsTextPosition() && other.IsTextPosition())
        return text_offset() - other.text_offset();
      if (IsTreePosition() && other.IsTreePosition())
        return child_index() - other.child_index();
    }

    // Ancestor positions are expensive to compute. If possible, we will avoid
    // doing so by computing the ancestor chain of the two positions' anchors.
    // If the lowest common ancestor is neither position's anchor, we can use
    // the order of the first uncommon ancestors as a proxy for the order of the
    // positions.
    //
    // In order to do that, we need to normalize text positions at the end of an
    // anchor to equivalent positions at the start of the next anchor. Ignored
    // positions are a special case in that they need to be shifted to the
    // nearest unignored position in order to be normalized. That shifting can
    // change the comparison result, so if we have an ignored position, we must
    // use the slow path.
    if (IsIgnored() || other.IsIgnored())
      return SlowCompareTo(other);

    // Normalize any text positions at the end of an anchor to equivalent
    // positions at the start of the next anchor.
    AXPositionInstance normalized_this_position = Clone();
    if (normalized_this_position->IsTextPosition()) {
      normalized_this_position =
          normalized_this_position->AsLeafTextPositionBeforeCharacter();
    }

    AXPositionInstance normalized_other_position = other.Clone();
    if (normalized_other_position->IsTextPosition()) {
      normalized_other_position =
          normalized_other_position->AsLeafTextPositionBeforeCharacter();
    }

    if (normalized_this_position->IsNullPosition()) {
      if (normalized_other_position->IsNullPosition()) {
        // Both positions normalized to a position past the end of the document.
        BASE_DCHECK(SlowCompareTo(other).value() == 0);
        return 0;
      }
      // |this| normalized to a position past the end of the document.
      BASE_DCHECK(SlowCompareTo(other).value() > 0);
      return 1;
    } else if (normalized_other_position->IsNullPosition()) {
      // |other| normalized to a position past the end of the document.
      BASE_DCHECK(SlowCompareTo(other).value() < 0);
      return -1;
    }

    // Compute the ancestor stacks of both positions and walk them ourselves
    // rather than calling LowestCommonAnchor(). That way, we can discover the
    // first uncommon ancestors.
    const AXNodeType* common_anchor = nullptr;
    std::stack<AXNodeType*> our_ancestors =
        normalized_this_position->GetAncestorAnchors();
    std::stack<AXNodeType*> other_ancestors =
        normalized_other_position->GetAncestorAnchors();
    while (!our_ancestors.empty() && !other_ancestors.empty() &&
           our_ancestors.top() == other_ancestors.top()) {
      common_anchor = our_ancestors.top();
      our_ancestors.pop();
      other_ancestors.pop();
    }

    if (!common_anchor)
      return std::optional<int>(std::nullopt);

    // If each position has an uncommon ancestor node, we can compare those
    // instead of needing to compute ancestor positions.
    if (!our_ancestors.empty() && !other_ancestors.empty()) {
      AXPositionInstance this_uncommon_tree_position = CreateTreePosition(
          GetTreeID(our_ancestors.top()), GetAnchorID(our_ancestors.top()),
          0 /*child_index*/);
      int this_uncommon_ancestor_index =
          this_uncommon_tree_position->AnchorIndexInParent();
      AXPositionInstance other_uncommon_tree_position = CreateTreePosition(
          GetTreeID(other_ancestors.top()), GetAnchorID(other_ancestors.top()),
          0 /*child_index*/);
      int other_uncommon_ancestor_index =
          other_uncommon_tree_position->AnchorIndexInParent();
      BASE_DCHECK(this_uncommon_ancestor_index !=
                  other_uncommon_ancestor_index);
      int result = this_uncommon_ancestor_index - other_uncommon_ancestor_index;

      // On platforms that support embedded objects, if a text position is
      // within an embedded object and if it is not at the start of that object,
      // the resulting ancestor position should be adjusted to point after the
      // embedded object. Otherwise, assistive software will not be able to get
      // out of the embedded object if its text is not editable when navigating
      // by character.
      //
      // For example, look at the following accessibility tree and the two
      // example text positions together with their equivalent ancestor
      // positions.
      // ++1 kRootWebArea
      // ++++2 kTextField "Before<embedded_object>after"
      // ++++++3 kStaticText "Before"
      // ++++++++4 kInlineTextBox "Before"
      // ++++++5 kImage "Test image"
      // ++++++6 kStaticText "after"
      // ++++++++7 kInlineTextBox "after"
      //
      // Note that the alt text of an image cannot be navigated with cursor
      // left/right, even when the rest of the contents are in a
      // contenteditable.
      //
      // Ancestor position should not be adjusted:
      // TextPosition anchor_id=kImage text_offset=0 affinity=downstream
      // annotated_text=<T>est image AncestorTextPosition anchor_id=kTextField
      // text_offset=6 affinity=downstream
      // annotated_text=Before<embedded_object>after
      //
      // Ancestor position should be adjusted:
      // TextPosition anchor_id=kImage text_offset=1 affinity=downstream
      // annotated_text=T<e>st image AncestorTextPosition anchor_id=kTextField
      // text_offset=7 affinity=downstream
      // annotated_text=Beforeembedded_object<a>fter
      //
      // Note that since the adjustment to the distance between the ancestor
      // positions could at most be by one, we skip doing this check if the
      // ancestor positions have a distance of more than one since it can never
      // change the outcome of the comparison. Note too that if both ancestor
      // positions need to be adjusted, the adjustments will cancel out.
      if (abs(result) == 1) {
        if (!normalized_this_position->AtStartOfAnchor() &&
            this_uncommon_tree_position->IsEmbeddedObjectInParent()) {
          result += 1;
        }
        if (!normalized_other_position->AtStartOfAnchor() &&
            other_uncommon_tree_position->IsEmbeddedObjectInParent()) {
          result -= 1;
        }
      }

#ifndef NDEBUG
      // Validate the optimization.
      int slow_result = SlowCompareTo(other).value();
      BASE_DCHECK((result == 0 && slow_result == 0) ||
                  (result < 0 && slow_result < 0) ||
                  (result > 0 && slow_result > 0));
#endif

      return result;
    }

    return SlowCompareTo(other);
  }

  std::optional<int> SlowCompareTo(const AXPosition& other) const {
    // It is potentially costly to compute the parent position of a text
    // position, whilst computing the parent position of a tree position is
    // really inexpensive. In order to find the lowest common ancestor,
    // especially if that ancestor is all the way up to the root of the tree,
    // this will need to be done repeatedly. We avoid the performance hit by
    // converting both positions to tree positions and only falling back to text
    // positions if both are text positions and the lowest common ancestor is
    // not one of their anchors. Essentially, the question we need to answer is:
    // "When are two non equivalent positions going to have the same lowest
    // common ancestor position when converted to tree positions?" The answer is
    // when they are both text positions and they either have the same anchor,
    // or one is the ancestor of the other.
    const AXNodeType* common_anchor = this->LowestCommonAnchor(other);
    if (!common_anchor)
      return std::optional<int>(std::nullopt);

    // Attempt to avoid recomputing the lowest common ancestor because we may
    // already have its anchor in which case just find the text offset.
    if (this->IsTextPosition() && other.IsTextPosition()) {
      // This text position's anchor is the common ancestor of the other text
      // position's anchor.
      if (this->GetAnchor() == common_anchor) {
        AXPositionInstance other_text_position =
            other.CreateAncestorPosition(common_anchor);
        return std::optional<int>(this->text_offset_ -
                                  other_text_position->text_offset_);
      }

      // The other text position's anchor is the common ancestor of this text
      // position's anchor.
      if (other.GetAnchor() == common_anchor) {
        AXPositionInstance this_text_position =
            this->CreateAncestorPosition(common_anchor);
        return std::optional<int>(this_text_position->text_offset_ -
                                  other.text_offset_);
      }

      // All optimizations failed. Fall back to comparing text positions with
      // the common text position ancestor.
      AXPositionInstance this_text_position_ancestor =
          this->CreateAncestorPosition(common_anchor);
      AXPositionInstance other_text_position_ancestor =
          other.CreateAncestorPosition(common_anchor);
      BASE_DCHECK(this_text_position_ancestor->IsTextPosition());
      BASE_DCHECK(other_text_position_ancestor->IsTextPosition());
      BASE_DCHECK(common_anchor == this_text_position_ancestor->GetAnchor());
      BASE_DCHECK(common_anchor == other_text_position_ancestor->GetAnchor());

      // TODO - This does not take into account |affinity_|, so we may return
      // a false positive when comparing at the end of a line.
      // For example :
      // ++1 kRootWebArea
      // ++++2 kTextField "Line 1\nLine 2"
      // ++++++3 kStaticText "Line 1"
      // ++++++++4 kInlineTextBox "Line 1"
      // ++++++5 kLineBreak "\n"
      // ++++++6 kStaticText "Line 2"
      // ++++++++7 kInlineTextBox "Line 2"
      //
      // TextPosition anchor_id=5 text_offset=1
      // affinity=downstream annotated_text=\n<>
      //
      // TextPosition anchor_id=7 text_offset=0
      // affinity=downstream annotated_text=<L>ine 2
      //
      // |LowestCommonAncestor| for both will be :
      // TextPosition anchor_id=2 text_offset=7
      // ... except anchor_id=5 creates a kUpstream position, while
      // anchor_id=7 creates a kDownstream position.
      return std::optional<int>(this_text_position_ancestor->text_offset_ -
                                other_text_position_ancestor->text_offset_);
    }

    // All optimizations failed. Fall back to comparing child index with
    // the common tree position ancestor.
    AXPositionInstance this_tree_position_ancestor =
        this->AsTreePosition()->CreateAncestorPosition(common_anchor);
    AXPositionInstance other_tree_position_ancestor =
        other.AsTreePosition()->CreateAncestorPosition(common_anchor);
    BASE_DCHECK(this_tree_position_ancestor->IsTreePosition());
    BASE_DCHECK(other_tree_position_ancestor->IsTreePosition());
    BASE_DCHECK(common_anchor == this_tree_position_ancestor->GetAnchor());
    BASE_DCHECK(common_anchor == other_tree_position_ancestor->GetAnchor());

    return std::optional<int>(this_tree_position_ancestor->child_index() -
                              other_tree_position_ancestor->child_index());
  }

  // A valid position can become invalid if the underlying tree structure
  // changes. This is expected behavior, but it is sometimes necessary to
  // maintain valid positions. This method modifies an invalid position that is
  // beyond MaxTextOffset to snap to MaxTextOffset.
  void SnapToMaxTextOffsetIfBeyond() {
    int max_text_offset = MaxTextOffset();
    if (text_offset_ > max_text_offset)
      text_offset_ = max_text_offset;
  }

  // Returns true if this position is on an empty object node that needs to
  // be represented by an empty object replacement character. It does when the
  // node is a collapsed menu list popup button or has no unignored child and is
  // not a text object. This feature is only enabled on some platforms.
  bool IsEmptyObjectReplacedByCharacter() const {
    if (g_ax_embedded_object_behavior ==
            AXEmbeddedObjectBehavior::kSuppressCharacter ||
        IsNullPosition()) {
      return false;
    }

    // A collapsed popup button that contains a menu list popup (i.e, the exact
    // subtree representation we get from a collapsed <select> element on
    // Windows) should not expose its children even though they are not ignored.
    if (GetAnchor()->IsCollapsedMenuListPopUpButton())
      return true;

    // All other elements that have unignored descendants should not be treated
    // as empty objects.
    if (AnchorUnignoredChildCount())
      return false;

    // All unignored leaf nodes in the AXTree except document and text
    // nodes should be replaced by the embedded object character. Also, nodes
    // that only have ignored children (e.g., a button that contains only an
    // empty div) need to be treated as leaf nodes.
    //
    // Calling AXPosition::IsIgnored here is not possible as it would create an
    // infinite loop. However, GetAnchor()->IsIgnored() is sufficient here
    // because we know that the anchor at this position doesn't have an
    // unignored child, making this a leaf tree or text position.
    return !GetAnchor()->IsIgnored() && !IsDocument(GetAnchorRole()) &&
           !IsInTextObject() && !IsIframe(GetAnchorRole());
  }

  bool IsInDescendantOfEmptyObject() const {
    if (g_ax_embedded_object_behavior ==
            AXEmbeddedObjectBehavior::kSuppressCharacter ||
        IsNullPosition()) {
      return false;
    }

    // Empty objects are only possible on a collapsed popup button parent of a
    // menu list popup or a node that only has ignored descendants. If it has no
    // empty object ancestor, it can't be inside of an empty object.
    return GetEmptyObjectAncestorNode();
  }

  AXNodeType* GetEmptyObjectAncestorNode() const {
    if (g_ax_embedded_object_behavior ==
            AXEmbeddedObjectBehavior::kSuppressCharacter ||
        !GetAnchor()) {
      return nullptr;
    }

    if (!GetAnchor()->IsIgnored()) {
      // The only case where a descendant of an empty object can be unignored is
      // when we are inside of a collapsed popup button parent of a menu list
      // popup.
      if (AXNodeType* popup_button =
              GetAnchor()->GetCollapsedMenuListPopUpButtonAncestor()) {
        return popup_button;
      }
      return nullptr;
    }

    // The first unignored ancestor is necessarily the empty object if this node
    // is the descendant of an empty object.
    AXNodeType* ancestor_node = GetLowestUnignoredAncestor();
    if (!ancestor_node)
      return nullptr;

    AXPositionInstance position = CreateTextPosition(
        tree_id_, GetAnchorID(ancestor_node), 0 /* text_offset */,
        ax::mojom::TextAffinity::kDownstream);
    if (position && position->IsEmptyObjectReplacedByCharacter())
      return ancestor_node;

    return nullptr;
  }

  void swap(AXPosition& other) {
    std::swap(kind_, other.kind_);
    std::swap(tree_id_, other.tree_id_);
    std::swap(anchor_id_, other.anchor_id_);
    std::swap(child_index_, other.child_index_);
    std::swap(text_offset_, other.text_offset_);
    std::swap(affinity_, other.affinity_);
  }

  // Abstract methods.

  // Returns the text that is present inside the anchor node, including any text
  // found in descendant text nodes, based on the platform's text
  // representation. Some platforms use an embedded object replacement character
  // that replaces the text coming from each child node.
  virtual std::u16string GetText() const = 0;

  // Determines if the anchor containing this position is a <br> or a text
  // object whose parent's anchor is an enclosing <br>.
  virtual bool IsInLineBreak() const = 0;

  // Determines if the anchor containing this position is a text object.
  virtual bool IsInTextObject() const = 0;

  // Determines if the text representation of this position's anchor contains
  // only whitespace characters; <br> objects span a single '\n' character, so
  // positions inside line breaks are also considered "in whitespace".
  virtual bool IsInWhiteSpace() const = 0;

  // Returns the length of the text that is present inside the anchor node,
  // including any text found in descendant text nodes. This is based on the
  // platform's text representation. Some platforms use an embedded object
  // character that replaces the text coming from each child node.
  //
  // Similar to "text_offset_", the length of the text is in UTF16 code units,
  // not in grapheme clusters.
  virtual int MaxTextOffset() const {
    if (IsNullPosition())
      return INVALID_OFFSET;
    return static_cast<int>(GetText().length());
  }

 protected:
  AXPosition()
      : kind_(AXPositionKind::NULL_POSITION),
        tree_id_(AXTreeIDUnknown()),
        anchor_id_(AXNode::kInvalidAXID),
        child_index_(INVALID_INDEX),
        text_offset_(INVALID_OFFSET),
        affinity_(ax::mojom::TextAffinity::kDownstream) {}

  // We explicitly don't copy any cached members.
  AXPosition(const AXPosition& other)
      : kind_(other.kind_),
        tree_id_(other.tree_id_),
        anchor_id_(other.anchor_id_),
        child_index_(other.child_index_),
        text_offset_(other.text_offset_),
        affinity_(other.affinity_) {}

  // Returns the character offset inside our anchor's parent at which our text
  // starts.
  int AnchorTextOffsetInParent() const {
    if (IsNullPosition())
      return INVALID_OFFSET;

    // Calculate how much text there is to the left of this anchor.
    AXPositionInstance tree_position = AsTreePosition();
    BASE_DCHECK(tree_position);
    AXPositionInstance parent_position = tree_position->CreateParentPosition();
    BASE_DCHECK(parent_position);
    if (parent_position->IsNullPosition())
      return 0;

    int offset_in_parent = 0;
    for (int i = 0; i < parent_position->child_index(); ++i) {
      AXPositionInstance child = parent_position->CreateChildPositionAt(i);
      BASE_DCHECK(child);
      offset_in_parent += child->MaxTextOffsetInParent();
    }
    return offset_in_parent;
  }

  void Initialize(AXPositionKind kind,
                  AXTreeID tree_id,
                  int32_t anchor_id,
                  int child_index,
                  int text_offset,
                  ax::mojom::TextAffinity affinity) {
    kind_ = kind;
    tree_id_ = tree_id;
    anchor_id_ = anchor_id;
    child_index_ = child_index;
    text_offset_ = text_offset;
    affinity_ = affinity;

    if (!IsValid()) {
      // Reset to the null position.
      kind_ = AXPositionKind::NULL_POSITION;
      tree_id_ = AXTreeIDUnknown();
      anchor_id_ = AXNode::kInvalidAXID;
      child_index_ = INVALID_INDEX;
      text_offset_ = INVALID_OFFSET;
      affinity_ = ax::mojom::TextAffinity::kDownstream;
    }
  }

  // Abstract methods.
  virtual void AnchorChild(int child_index,
                           AXTreeID* tree_id,
                           int32_t* child_id) const = 0;
  virtual int AnchorChildCount() const = 0;
  // When a child is ignored, it looks for unignored nodes of that child's
  // children until there are no more descendants.
  //
  // E.g.
  // ++TextField
  // ++++GenericContainer ignored
  // ++++++StaticText "Hello"
  // When we call the following method on TextField, it would return 1.
  virtual int AnchorUnignoredChildCount() const = 0;
  virtual int AnchorIndexInParent() const = 0;
  virtual int AnchorSiblingCount() const = 0;
  virtual std::stack<AXNodeType*> GetAncestorAnchors() const = 0;
  virtual AXNodeType* GetLowestUnignoredAncestor() const = 0;
  virtual void AnchorParent(AXTreeID* tree_id, int32_t* parent_id) const = 0;
  virtual AXNodeType* GetNodeInTree(AXTreeID tree_id,
                                    int32_t node_id) const = 0;
  virtual int32_t GetAnchorID(AXNodeType* node) const = 0;
  virtual AXTreeID GetTreeID(AXNodeType* node) const = 0;

  // Returns the length of text that this anchor node takes up in its parent.
  // On some platforms, embedded objects are represented in their parent with a
  // single embedded object character.
  int MaxTextOffsetInParent() const {
    return IsEmbeddedObjectInParent() ? 1 : MaxTextOffset();
  }

  // Returns whether or not this anchor is represented in their parent with a
  // single embedded object character.
  virtual bool IsEmbeddedObjectInParent() const = 0;

  // Determines if the anchor containing this position produces a hard line
  // break in the text representation, e.g. a block level element or a <br>.
  virtual bool IsInLineBreakingObject() const = 0;

  virtual ax::mojom::Role GetAnchorRole() const = 0;
  virtual ax::mojom::Role GetRole(AXNodeType* node) const = 0;
  virtual AXNodeTextStyles GetTextStyles() const = 0;
  virtual std::vector<int32_t> GetWordStartOffsets() const = 0;
  virtual std::vector<int32_t> GetWordEndOffsets() const = 0;
  virtual int32_t GetNextOnLineID(int32_t node_id) const = 0;
  virtual int32_t GetPreviousOnLineID(int32_t node_id) const = 0;

 private:
  // Defines the relationship between positions during traversal.
  // For example, moving from a descendant to an ancestor, is a kAncestor move.
  enum class AXMoveType {
    kAncestor,
    kDescendant,
    kSibling,
  };

  // Defines the direction of position movement, either next / previous in tree.
  enum class AXMoveDirection {
    kNextInTree,
    kPreviousInTree,
  };

  // Type of predicate function called during anchor navigation.
  // When the predicate returns |true|, the navigation stops and returns a
  // null position object.
  typedef bool AbortMovePredicate(const AXPosition& move_from,
                                  const AXPosition& move_to,
                                  const AXMoveType type,
                                  const AXMoveDirection direction);

  // A text span is defined by a series of inline text boxes that make up a
  // single static text object.
  bool AtEndOfTextSpan() const {
    if (GetAnchorRole() != ax::mojom::Role::kInlineTextBox || !AtEndOfAnchor())
      return false;

    // We are at the end of text span if |this| position has
    // role::kInlineTextBox, the parent of |this| has role::kStaticText, and the
    // anchor node of |this| is the last child of parent's children.
    const bool is_last_child =
        AnchorIndexInParent() == (AnchorSiblingCount() - 1);

    return is_last_child && GetRole(GetLowestUnignoredAncestor()) ==
                                ax::mojom::Role::kStaticText;
  }

  // Uses depth-first pre-order traversal.
  AXPositionInstance CreateNextAnchorPosition(
      std::function<AbortMovePredicate> abort_predicate) const {
    if (IsNullPosition())
      return Clone();

    AXPositionInstance current_position = AsTreePosition();
    BASE_DCHECK(!current_position->IsNullPosition());

    if (!IsLeaf()) {
      const int child_index = current_position->child_index_;
      if (child_index < current_position->AnchorChildCount()) {
        AXPositionInstance child_position =
            current_position->CreateChildPositionAt(child_index);

        if (abort_predicate(*current_position, *child_position,
                            AXMoveType::kDescendant,
                            AXMoveDirection::kNextInTree)) {
          return CreateNullPosition();
        }
        return child_position;
      }
    }

    AXPositionInstance parent_position =
        current_position->CreateParentPosition();

    // Get the next sibling if it exists, otherwise move up the AXTree to the
    // lowest next sibling of this position's ancestors.
    while (!parent_position->IsNullPosition()) {
      const int index_in_parent = current_position->AnchorIndexInParent();
      if (index_in_parent + 1 < parent_position->AnchorChildCount()) {
        AXPositionInstance next_sibling =
            parent_position->CreateChildPositionAt(index_in_parent + 1);
        BASE_DCHECK(!next_sibling->IsNullPosition());

        if (abort_predicate(*current_position, *next_sibling,
                            AXMoveType::kSibling,
                            AXMoveDirection::kNextInTree)) {
          return CreateNullPosition();
        }
        return next_sibling;
      }

      if (abort_predicate(*current_position, *parent_position,
                          AXMoveType::kAncestor,
                          AXMoveDirection::kNextInTree)) {
        return CreateNullPosition();
      }

      current_position = std::move(parent_position);
      parent_position = current_position->CreateParentPosition();
    }
    return CreateNullPosition();
  }

  // Uses depth-first pre-order traversal.
  AXPositionInstance CreatePreviousAnchorPosition(
      std::function<AbortMovePredicate> abort_predicate) const {
    if (IsNullPosition())
      return Clone();

    AXPositionInstance current_position = AsTreePosition();
    BASE_DCHECK(!current_position->IsNullPosition());

    AXPositionInstance parent_position =
        current_position->CreateParentPosition();
    if (parent_position->IsNullPosition())
      return parent_position;

    // If there is no previous sibling, move up to the parent.
    const int index_in_parent = current_position->AnchorIndexInParent();
    if (index_in_parent <= 0) {
      if (abort_predicate(*current_position, *parent_position,
                          AXMoveType::kAncestor,
                          AXMoveDirection::kPreviousInTree)) {
        return CreateNullPosition();
      }
      return parent_position;
    }

    // Get the previous sibling's deepest last child.
    AXPositionInstance rightmost_leaf =
        parent_position->CreateChildPositionAt(index_in_parent - 1);
    BASE_DCHECK(!rightmost_leaf->IsNullPosition());

    if (abort_predicate(*current_position, *rightmost_leaf,
                        AXMoveType::kSibling,
                        AXMoveDirection::kPreviousInTree)) {
      return CreateNullPosition();
    }

    while (!rightmost_leaf->IsLeaf()) {
      parent_position = std::move(rightmost_leaf);
      rightmost_leaf = parent_position->CreateChildPositionAt(
          parent_position->AnchorChildCount() - 1);
      BASE_DCHECK(!rightmost_leaf->IsNullPosition());

      if (abort_predicate(*parent_position, *rightmost_leaf,
                          AXMoveType::kDescendant,
                          AXMoveDirection::kPreviousInTree)) {
        return CreateNullPosition();
      }
    }
    return rightmost_leaf;
  }

  // Creates a position using the next text-only node as its anchor.
  // Assumes that text-only nodes are leaf nodes.
  AXPositionInstance CreateNextTextAnchorPosition(
      std::function<AbortMovePredicate> abort_predicate) const {
    // If this is an ancestor text position, resolve to its leaf text position.
    if (IsTextPosition() && !IsLeaf())
      return AsLeafTextPosition();

    AXPositionInstance next_leaf = CreateNextAnchorPosition(abort_predicate);
    while (!next_leaf->IsNullPosition() && !next_leaf->IsLeaf())
      next_leaf = next_leaf->CreateNextAnchorPosition(abort_predicate);

    BASE_DCHECK(next_leaf);
    return next_leaf->AsLeafTextPosition();
  }

  // Creates a position using the previous text-only node as its anchor.
  // Assumes that text-only nodes are leaf nodes.
  AXPositionInstance CreatePreviousTextAnchorPosition(
      std::function<AbortMovePredicate> abort_predicate) const {
    // If this is an ancestor text position, resolve to its leaf text position.
    if (IsTextPosition() && !IsLeaf())
      return AsLeafTextPosition();

    AXPositionInstance previous_leaf =
        CreatePreviousAnchorPosition(abort_predicate);
    while (!previous_leaf->IsNullPosition() && !previous_leaf->IsLeaf()) {
      previous_leaf =
          previous_leaf->CreatePreviousAnchorPosition(abort_predicate);
    }

    BASE_DCHECK(previous_leaf);
    return previous_leaf->AsLeafTextPosition();
  }

  // Creates a tree position using the next text-only node as its anchor.
  // Assumes that text-only nodes are leaf nodes.
  AXPositionInstance CreateNextLeafTreePosition(
      std::function<AbortMovePredicate> abort_predicate) const {
    AXPositionInstance next_leaf =
        AsTreePosition()->CreateNextAnchorPosition(abort_predicate);
    while (!next_leaf->IsNullPosition() && !next_leaf->IsLeaf())
      next_leaf = next_leaf->CreateNextAnchorPosition(abort_predicate);

    BASE_DCHECK(next_leaf);
    return next_leaf;
  }

  // Creates a tree position using the previous text-only node as its anchor.
  // Assumes that text-only nodes are leaf nodes.
  AXPositionInstance CreatePreviousLeafTreePosition(
      std::function<AbortMovePredicate> abort_predicate) const {
    AXPositionInstance previous_leaf =
        AsTreePosition()->CreatePreviousAnchorPosition(abort_predicate);
    while (!previous_leaf->IsNullPosition() && !previous_leaf->IsLeaf()) {
      previous_leaf =
          previous_leaf->CreatePreviousAnchorPosition(abort_predicate);
    }

    BASE_DCHECK(previous_leaf);
    return previous_leaf;
  }

  //
  // Static helpers for lambda usage.
  //

  static bool AtStartOfPagePredicate(const AXPositionInstance& position) {
    // If a page boundary is ignored, then it should not be exposed to assistive
    // software.
    return !position->IsIgnored() && position->AtStartOfPage();
  }

  static bool AtEndOfPagePredicate(const AXPositionInstance& position) {
    // If a page boundary is ignored, then it should not be exposed to assistive
    // software.
    return !position->IsIgnored() && position->AtEndOfPage();
  }

  static bool AtStartOfParagraphPredicate(const AXPositionInstance& position) {
    // The "AtStartOfParagraph" method already excludes ignored nodes.
    return position->AtStartOfParagraph();
  }

  static bool AtEndOfParagraphPredicate(const AXPositionInstance& position) {
    // The "AtEndOfParagraph" method already excludes ignored nodes.
    return position->AtEndOfParagraph();
  }

  static bool AtStartOfLinePredicate(const AXPositionInstance& position) {
    // Sometimes, nodes that are used to signify line boundaries are ignored.
    return position->AtStartOfLine();
  }

  static bool AtEndOfLinePredicate(const AXPositionInstance& position) {
    // Sometimes, nodes that are used to signify line boundaries are ignored.
    return position->AtEndOfLine();
  }

  static bool AtStartOfWordPredicate(const AXPositionInstance& position) {
    // Word boundaries should be at specific text offsets that are "visible" to
    // assistive software, hence not ignored. Ignored nodes are often used for
    // additional layout information, such as line and paragraph boundaries.
    // Their text is not currently processed.
    return !position->IsIgnored() && position->AtStartOfWord();
  }

  static bool AtEndOfWordPredicate(const AXPositionInstance& position) {
    // Word boundaries should be at specific text offsets that are "visible" to
    // assistive software, hence not ignored. Ignored nodes are often used for
    // additional layout information, such as line and paragraph boundaries.
    // Their text is not currently processed.
    return !position->IsIgnored() && position->AtEndOfWord();
  }

  static bool DefaultAbortMovePredicate(const AXPosition& move_from,
                                        const AXPosition& move_to,
                                        const AXMoveType move_type,
                                        const AXMoveDirection direction) {
    // Default behavior is to never abort.
    return false;
  }

  // AbortMovePredicate function used to detect format boundaries.
  static bool AbortMoveAtFormatBoundary(const AXPosition& move_from,
                                        const AXPosition& move_to,
                                        const AXMoveType move_type,
                                        const AXMoveDirection direction) {
    if (move_from.IsNullPosition() || move_to.IsNullPosition() ||
        move_from.IsEmptyObjectReplacedByCharacter() ||
        move_to.IsEmptyObjectReplacedByCharacter()) {
      return true;
    }

    // Treat moving into or out of nodes with certain roles as a format break.
    ax::mojom::Role from_role = move_from.GetAnchorRole();
    ax::mojom::Role to_role = move_to.GetAnchorRole();
    if (from_role != to_role) {
      if (IsFormatBoundary(from_role) || IsFormatBoundary(to_role))
        return true;
    }

    // Stop moving when text styles differ.
    return move_from.AsLeafTreePosition()->GetTextStyles() !=
           move_to.AsLeafTreePosition()->GetTextStyles();
  }

  static bool MoveCrossesLineBreakingObject(const AXPosition& move_from,
                                            const AXPosition& move_to,
                                            const AXMoveType move_type,
                                            const AXMoveDirection direction) {
    const bool move_from_break = move_from.IsInLineBreakingObject();
    const bool move_to_break = move_to.IsInLineBreakingObject();

    switch (move_type) {
      case AXMoveType::kAncestor:
        // For Ancestor moves, only abort when exiting a block descendant.
        // We don't care if the ancestor is a block or not, since the
        // descendant is contained by it.
        return move_from_break;
      case AXMoveType::kDescendant:
        // For Descendant moves, only abort when entering a block descendant.
        // We don't care if the ancestor is a block or not, since the
        // descendant is contained by it.
        return move_to_break;
      case AXMoveType::kSibling:
        // For Sibling moves, abort if at least one of the siblings are a block,
        // because that would mean exiting and/or entering a block.
        return move_from_break || move_to_break;
    }
    BASE_UNREACHABLE();
    return false;
  }

  // AbortMovePredicate function used to detect paragraph boundaries.
  // We don't want to abort immediately after crossing a line breaking object
  // boundary if the anchor we're moving to is not a leaf, this is necessary to
  // avoid aborting if the next leaf position is whitespace-only; update
  // |crossed_line_breaking_object_token| and wait until a leaf anchor is
  // reached in order to correctly determine paragraph boundaries.
  static bool AbortMoveAtParagraphBoundary(
      bool& crossed_line_breaking_object_token,
      const AXPosition& move_from,
      const AXPosition& move_to,
      const AXMoveType move_type,
      const AXMoveDirection direction) {
    if (move_from.IsNullPosition() || move_to.IsNullPosition() ||
        move_from.IsEmptyObjectReplacedByCharacter() ||
        move_to.IsEmptyObjectReplacedByCharacter()) {
      return true;
    }

    if (!crossed_line_breaking_object_token) {
      crossed_line_breaking_object_token = MoveCrossesLineBreakingObject(
          move_from, move_to, move_type, direction);
    }

    if (crossed_line_breaking_object_token && move_to.IsLeaf()) {
      // If there's a sequence of whitespace-only anchors, collapse so only the
      // last whitespace-only anchor is considered a paragraph boundary.
      return direction != AXMoveDirection::kNextInTree ||
             !move_to.IsInWhiteSpace();
    }
    return false;
  }

  // This AbortMovePredicate never aborts, but detects whether a sequence of
  // consecutive moves cross any line breaking object boundary.
  static bool UpdateCrossedLineBreakingObjectToken(
      bool& crossed_line_breaking_object_token,
      const AXPosition& move_from,
      const AXPosition& move_to,
      const AXMoveType move_type,
      const AXMoveDirection direction) {
    if (!crossed_line_breaking_object_token) {
      crossed_line_breaking_object_token = MoveCrossesLineBreakingObject(
          move_from, move_to, move_type, direction);
    }
    return false;
  }

  // AbortMovePredicate function used to detect page boundaries.
  static bool AbortMoveAtPageBoundary(const AXPosition& move_from,
                                      const AXPosition& move_to,
                                      const AXMoveType move_type,
                                      const AXMoveDirection direction) {
    if (move_from.IsNullPosition() || move_to.IsNullPosition())
      return true;

    const bool move_from_break = move_from.GetAnchor()->GetBoolAttribute(
        ax::mojom::BoolAttribute::kIsPageBreakingObject);
    const bool move_to_break = move_to.GetAnchor()->GetBoolAttribute(
        ax::mojom::BoolAttribute::kIsPageBreakingObject);

    switch (move_type) {
      case AXMoveType::kAncestor:
        // For Ancestor moves, only abort when exiting a page break.
        // We don't care if the ancestor is a page break or not, since the
        // descendant is contained by it.
        return move_from_break;
      case AXMoveType::kDescendant:
        // For Descendant moves, only abort when entering a page break
        // descendant. We don't care if the ancestor is a page break  or not,
        // since the descendant is contained by it.
        return move_to_break;
      case AXMoveType::kSibling:
        // For Sibling moves, abort if at both of the siblings are a page
        // break, because that would mean exiting and/or entering a page break.
        return move_from_break && move_to_break;
    }
    BASE_UNREACHABLE();
    return false;
  }

  static bool AbortMoveAtStartOfInlineBlock(const AXPosition& move_from,
                                            const AXPosition& move_to,
                                            const AXMoveType move_type,
                                            const AXMoveDirection direction) {
    if (move_from.IsNullPosition() || move_to.IsNullPosition())
      return true;

    // These will only be available if AXMode has kHTML set.
    const bool move_from_is_inline_block =
        move_from.GetAnchor()->GetStringAttribute(
            ax::mojom::StringAttribute::kDisplay) == "inline-block";
    const bool move_to_is_inline_block =
        move_to.GetAnchor()->GetStringAttribute(
            ax::mojom::StringAttribute::kDisplay) == "inline-block";

    switch (direction) {
      case AXMoveDirection::kNextInTree:
        // When moving forward, break if we enter an inline block.
        return move_to_is_inline_block &&
               (move_type == AXMoveType::kDescendant ||
                move_type == AXMoveType::kSibling);
      case AXMoveDirection::kPreviousInTree:
        // When moving backward, break if we exit an inline block.
        return move_from_is_inline_block &&
               (move_type == AXMoveType::kAncestor ||
                move_type == AXMoveType::kSibling);
    }
    BASE_UNREACHABLE();
    return false;
  }

  static AXPositionAdjustmentBehavior AdjustmentBehaviorFromBoundaryDirection(
      ax::mojom::MoveDirection move_direction) {
    switch (move_direction) {
      case ax::mojom::MoveDirection::kForward:
        return AXPositionAdjustmentBehavior::kMoveForward;
      case ax::mojom::MoveDirection::kBackward:
        return AXPositionAdjustmentBehavior::kMoveBackward;
    }
  }

  static AXPositionAdjustmentBehavior OppositeAdjustmentBehavior(
      AXPositionAdjustmentBehavior adjustment_behavior) {
    switch (adjustment_behavior) {
      case AXPositionAdjustmentBehavior::kMoveForward:
        return AXPositionAdjustmentBehavior::kMoveBackward;
      case AXPositionAdjustmentBehavior::kMoveBackward:
        return AXPositionAdjustmentBehavior::kMoveForward;
    }
  }

  static std::vector<int32_t> GetWordStartOffsetsFunc(
      const AXPositionInstance& position) {
    return position->GetWordStartOffsets();
  }

  static std::vector<int32_t> GetWordEndOffsetsFunc(
      const AXPositionInstance& position) {
    return position->GetWordEndOffsets();
  }

  AXPositionInstance CreateDocumentAncestorPosition() const {
    AXPositionInstance iterator = Clone();
    while (!iterator->IsNullPosition()) {
      if (IsDocument(iterator->GetAnchorRole()) &&
          iterator->CreateParentPosition()->IsNullPosition()) {
        break;
      }
      iterator = iterator->CreateParentPosition();
    }
    return iterator;
  }

  // Creates a text position that is in the same anchor as the current
  // position, but starting from the current text offset, adjusts to the next
  // or the previous boundary offset depending on the boundary direction. If
  // there is no next / previous offset, the current text offset is unchanged.
  AXPositionInstance CreatePositionAtNextOffsetBoundary(
      ax::mojom::MoveDirection move_direction,
      BoundaryTextOffsetsFunc get_offsets) const {
    if (IsNullPosition() || !get_offsets)
      return Clone();

    AXPositionInstance text_position = AsTextPosition();
    const std::vector<int32_t> boundary_offsets = get_offsets(text_position);
    if (boundary_offsets.empty())
      return text_position;

    switch (move_direction) {
      case ax::mojom::MoveDirection::kForward: {
        const auto offsets_iterator =
            std::upper_bound(boundary_offsets.begin(), boundary_offsets.end(),
                             int32_t{text_position->text_offset_});
        // If there is no next offset, the current offset should be unchanged.
        if (offsets_iterator < boundary_offsets.end()) {
          text_position->text_offset_ = static_cast<int>(*offsets_iterator);
          text_position->affinity_ = ax::mojom::TextAffinity::kDownstream;
        }
        break;
      }
      case ax::mojom::MoveDirection::kBackward: {
        auto offsets_iterator =
            std::lower_bound(boundary_offsets.begin(), boundary_offsets.end(),
                             int32_t{text_position->text_offset_});
        // If there is no previous offset, the current offset should be
        // unchanged.
        if (offsets_iterator > boundary_offsets.begin()) {
          // Since we already checked if "boundary_offsets" are non-empty, we
          // can safely move the iterator one position back, even if it's
          // currently at the vector's end.
          --offsets_iterator;
          text_position->text_offset_ = static_cast<int>(*offsets_iterator);
          text_position->affinity_ = ax::mojom::TextAffinity::kDownstream;
        }
        break;
      }
    }

    return text_position;
  }

  // Creates a text position that is in the same anchor as the current
  // position, but adjusts its text offset to be either at the first or last
  // offset boundary, based on the boundary direction. When moving forward,
  // the text position is adjusted to point to the first offset boundary, or
  // to the end of its anchor if there are no offset boundaries. When moving
  // backward, it is adjusted to point to the last offset boundary, or to the
  // start of its anchor if there are no offset boundaries.
  AXPositionInstance CreatePositionAtFirstOffsetBoundary(
      ax::mojom::MoveDirection move_direction,
      BoundaryTextOffsetsFunc get_offsets) const {
    if (IsNullPosition() || !get_offsets)
      return Clone();

    AXPositionInstance text_position = AsTextPosition();
    const std::vector<int32_t> boundary_offsets = get_offsets(text_position);
    switch (move_direction) {
      case ax::mojom::MoveDirection::kForward:
        if (boundary_offsets.empty()) {
          return text_position->CreatePositionAtEndOfAnchor();
        } else {
          text_position->text_offset_ = static_cast<int>(boundary_offsets[0]);
          return text_position;
        }
        break;
      case ax::mojom::MoveDirection::kBackward:
        if (boundary_offsets.empty()) {
          return text_position->CreatePositionAtStartOfAnchor();
        } else {
          text_position->text_offset_ =
              static_cast<int>(boundary_offsets[boundary_offsets.size() - 1]);
          return text_position;
        }
        break;
    }
  }

  // Returns the next leaf text position in the specified direction ensuring
  // that *AsLeafTextPosition() != *CreateAdjacentLeafTextPosition() is true;
  // returns a null position if no adjacent position exists.
  //
  // This method is the first step for CreateBoundary[Start|End]Position to
  // guarantee that the resulting position when using a boundary behavior other
  // than StopIfAlreadyAtBoundary is not equivalent to the initial position.
  //
  // Note that using CompareTo with text positions does not take into account
  // position affinity or tree pre-order, two text positions are considered
  // equivalent if their offsets in the text representation of the entire AXTree
  // are the same. As such, using Create[Next|Previous]LeafTextPosition is not
  // enough to create adjacent positions, e.g. the end of an anchor and the
  // start of the next one are equivalent; furthermore, there could be nodes
  // with no text representation between them, all of them being equivalent too.
  //
  // IMPORTANT: This method basically moves the given position one character
  // forward/backward, but it could end up at the middle of a grapheme cluster,
  // so it shouldn't be used to move by ax::mojom::TextBoundary::kCharacter (for
  // such purpose use Create[Next|Previous]CharacterPosition instead).
  AXPositionInstance CreateAdjacentLeafTextPosition(
      ax::mojom::MoveDirection move_direction) const {
    AXPositionInstance text_position = AsLeafTextPosition();

    switch (move_direction) {
      case ax::mojom::MoveDirection::kForward:
        // If we are at a text offset less than MaxTextOffset, we will simply
        // increase the offset by one; otherwise, create a position at the start
        // of the next leaf node with non-empty text and increase its offset.
        //
        // Note that a position located at offset 0 of an empty text node is
        // considered both, at the start and at the end of its anchor, so the
        // following loop skips over empty text leaf nodes, which is expected
        // since those positions are equivalent to both, the previous non-empty
        // leaf node's end and the next non-empty leaf node's start.
        while (text_position->AtEndOfAnchor()) {
          text_position = text_position->CreateNextLeafTextPosition();
        }
        if (!text_position->IsNullPosition())
          ++text_position->text_offset_;
        break;
      case ax::mojom::MoveDirection::kBackward:
        // If we are at a text offset greater than 0, we will simply decrease
        // the offset by one; otherwise, create a position at the end of the
        // previous leaf node with non-empty text and decrease its offset.
        //
        // Same as the comment above, using AtStartOfAnchor is enough to skip
        // empty text nodes that are equivalent to the initial position.
        while (text_position->AtStartOfAnchor()) {
          text_position = text_position->CreatePreviousLeafTextPosition()
                              ->CreatePositionAtEndOfAnchor();
        }
        if (!text_position->IsNullPosition())
          --text_position->text_offset_;
        break;
    }

    BASE_DCHECK(text_position->IsValid());
    return text_position;
  }

  AXPositionKind kind_;
  AXTreeID tree_id_;
  AXNode::AXID anchor_id_;

  // For text positions, |child_index_| is initially set to |-1| and only
  // computed on demand. The same with tree positions and |text_offset_|.
  int child_index_;
  // "text_offset_" represents the number of UTF16 code units before this
  // position. It doesn't count grapheme clusters.
  int text_offset_;

  // Affinity is used to distinguish between two text positions that point to
  // the same text offset, but which happens to fall on a soft line break. A
  // soft line break doesn't insert any white space in the accessibility tree,
  // so without affinity there would be no way to determine whether a text
  // position is before or after the soft line break. An upstream affinity
  // means that the position is before the soft line break, whilst a
  // downstream affinity means that the position is after the soft line break.
  //
  // Please note that affinity could only be set to upstream for positions
  // that are anchored to non-leaf nodes. When on a leaf node, there could
  // never be an ambiguity as to which line a position points to because Blink
  // creates separate inline text boxes for each line of text. Therefore, a
  // leaf text position before the soft line break would be pointing to the
  // end of its anchor node, whilst a leaf text position after the soft line
  // break would be pointing to the start of the next node.
  ax::mojom::TextAffinity affinity_;
};

template <class AXPositionType, class AXNodeType>
const int AXPosition<AXPositionType, AXNodeType>::BEFORE_TEXT;
template <class AXPositionType, class AXNodeType>
const int AXPosition<AXPositionType, AXNodeType>::INVALID_INDEX;
template <class AXPositionType, class AXNodeType>
const int AXPosition<AXPositionType, AXNodeType>::INVALID_OFFSET;

template <class AXPositionType, class AXNodeType>
bool operator==(const AXPosition<AXPositionType, AXNodeType>& first,
                const AXPosition<AXPositionType, AXNodeType>& second) {
  const std::optional<int> compare_to_optional = first.CompareTo(second);
  return compare_to_optional.has_value() && compare_to_optional.value() == 0;
}

template <class AXPositionType, class AXNodeType>
bool operator!=(const AXPosition<AXPositionType, AXNodeType>& first,
                const AXPosition<AXPositionType, AXNodeType>& second) {
  const std::optional<int> compare_to_optional = first.CompareTo(second);
  return compare_to_optional.has_value() && compare_to_optional.value() != 0;
}

template <class AXPositionType, class AXNodeType>
bool operator<(const AXPosition<AXPositionType, AXNodeType>& first,
               const AXPosition<AXPositionType, AXNodeType>& second) {
  const std::optional<int> compare_to_optional = first.CompareTo(second);
  return compare_to_optional.has_value() && compare_to_optional.value() < 0;
}

template <class AXPositionType, class AXNodeType>
bool operator<=(const AXPosition<AXPositionType, AXNodeType>& first,
                const AXPosition<AXPositionType, AXNodeType>& second) {
  const std::optional<int> compare_to_optional = first.CompareTo(second);
  return compare_to_optional.has_value() && compare_to_optional.value() <= 0;
}

template <class AXPositionType, class AXNodeType>
bool operator>(const AXPosition<AXPositionType, AXNodeType>& first,
               const AXPosition<AXPositionType, AXNodeType>& second) {
  const std::optional<int> compare_to_optional = first.CompareTo(second);
  return compare_to_optional.has_value() && compare_to_optional.value() > 0;
}

template <class AXPositionType, class AXNodeType>
bool operator>=(const AXPosition<AXPositionType, AXNodeType>& first,
                const AXPosition<AXPositionType, AXNodeType>& second) {
  const std::optional<int> compare_to_optional = first.CompareTo(second);
  return compare_to_optional.has_value() && compare_to_optional.value() >= 0;
}

template <class AXPositionType, class AXNodeType>
void swap(AXPosition<AXPositionType, AXNodeType>& first,
          AXPosition<AXPositionType, AXNodeType>& second) {
  first.swap(second);
}

template <class AXPositionType, class AXNodeType>
std::ostream& operator<<(
    std::ostream& stream,
    const AXPosition<AXPositionType, AXNodeType>& position) {
  return stream << position.ToString();
}

}  // namespace ui

#endif  // UI_ACCESSIBILITY_AX_POSITION_H_
