text: /*
   * Copyright (C) 2008, 2009, 2011 Apple Inc. All rights reserved.
   * Copyright (C) 2008 Nuanti Ltd.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1.  Redistributions of source code must retain the above copyright
   *     notice, this list of conditions and the following disclaimer.
   * 2.  Redistributions in binary form must reproduce the above copyright
   *     notice, this list of conditions and the following disclaimer in the
   *     documentation and/or other materials provided with the distribution.
   * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
   *     its contributors may be used to endorse or promote products derived
   *     from this software without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
   * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   */
  
  #ifndef AXObject_h
  #define AXObject_h
  
  #include "core/editing/VisiblePosition.h"
  #include "core/editing/markers/DocumentMarker.h"
  #include "core/inspector/protocol/Accessibility.h"
  #include "modules/ModulesExport.h"
  #include "platform/geometry/FloatQuad.h"
  #include "platform/geometry/LayoutRect.h"
  #include "platform/graphics/Color.h"
  #include "wtf/Forward.h"
  #include "wtf/Vector.h"
  
  class SkMatrix44;
  
  namespace blink {
  
  class AXObject;
  class AXObjectCache;
  class AXObjectCacheImpl;
  class Element;
  class FrameView;
  class IntPoint;
  class Node;
  class LayoutObject;
  class ScrollableArea;
  
  typedef unsigned AXID;
  
  enum AccessibilityRole {
    UnknownRole = 0,
    AbbrRole,  // No mapping to ARIA role.
    AlertDialogRole,
    AlertRole,
    AnnotationRole,  // No mapping to ARIA role.
    ApplicationRole,
    ArticleRole,
    AudioRole,  // No mapping to ARIA role.
    BannerRole,
    BlockquoteRole,     // No mapping to ARIA role.
    BusyIndicatorRole,  // No mapping to ARIA role.
    ButtonRole,
    CanvasRole,   // No mapping to ARIA role.
    CaptionRole,  // No mapping to ARIA role.
    CellRole,
    CheckBoxRole,
    ColorWellRole,  // No mapping to ARIA role.
    ColumnHeaderRole,
    ColumnRole,  // No mapping to ARIA role.
    ComboBoxRole,
    ComplementaryRole,
    ContentInfoRole,
    DateRole,      // No mapping to ARIA role.
    DateTimeRole,  // No mapping to ARIA role.
    DefinitionRole,
    DescriptionListDetailRole,  // No mapping to ARIA role.
    DescriptionListRole,        // No mapping to ARIA role.
    DescriptionListTermRole,    // No mapping to ARIA role.
    DetailsRole,                // No mapping to ARIA role.
    DialogRole,
    DirectoryRole,
    DisclosureTriangleRole,  // No mapping to ARIA role.
    DivRole,                 // No mapping to ARIA role.
    DocumentRole,
    EmbeddedObjectRole,  // No mapping to ARIA role.
    FigcaptionRole,      // No mapping to ARIA role.
    FigureRole,          // No mapping to ARIA role.
    FooterRole,
    FormRole,
    GridRole,
    GroupRole,
    HeadingRole,
    IframePresentationalRole,  // No mapping to ARIA role.
    IframeRole,                // No mapping to ARIA role.
    IgnoredRole,               // No mapping to ARIA role.
    ImageMapLinkRole,          // No mapping to ARIA role.
    ImageMapRole,              // No mapping to ARIA role.
    ImageRole,
    InlineTextBoxRole,  // No mapping to ARIA role.
    InputTimeRole,      // No mapping to ARIA role.
    LabelRole,
    LegendRole,     // No mapping to ARIA role.
    LineBreakRole,  // No mapping to ARIA role.
    LinkRole,
    ListBoxOptionRole,
    ListBoxRole,
    ListItemRole,
    ListMarkerRole,  // No mapping to ARIA role.
    ListRole,
    LogRole,
    MainRole,
    MarkRole,  // No mapping to ARIA role.
    MarqueeRole,
    MathRole,
    MenuBarRole,
    MenuButtonRole,
    MenuItemRole,
    MenuItemCheckBoxRole,
    MenuItemRadioRole,
    MenuListOptionRole,
    MenuListPopupRole,
    MenuRole,
    MeterRole,
    NavigationRole,
    NoneRole,  // No mapping to ARIA role.
    NoteRole,
    OutlineRole,    // No mapping to ARIA role.
    ParagraphRole,  // No mapping to ARIA role.
    PopUpButtonRole,
    PreRole,  // No mapping to ARIA role.
    PresentationalRole,
    ProgressIndicatorRole,
    RadioButtonRole,
    RadioGroupRole,
    RegionRole,
    RootWebAreaRole,  // No mapping to ARIA role.
    RowHeaderRole,
    RowRole,
    RubyRole,        // No mapping to ARIA role.
    RulerRole,       // No mapping to ARIA role.
    SVGRootRole,     // No mapping to ARIA role.
    ScrollAreaRole,  // No mapping to ARIA role.
    ScrollBarRole,
    SeamlessWebAreaRole,  // No mapping to ARIA role.
    SearchRole,
    SearchBoxRole,
    SliderRole,
    SliderThumbRole,     // No mapping to ARIA role.
    SpinButtonPartRole,  // No mapping to ARIA role.
    SpinButtonRole,
    SplitterRole,
    StaticTextRole,  // No mapping to ARIA role.
    StatusRole,
    SwitchRole,
    TabGroupRole,  // No mapping to ARIA role.
    TabListRole,
    TabPanelRole,
    TabRole,
    TableHeaderContainerRole,  // No mapping to ARIA role.
    TableRole,
    TextFieldRole,
    TimeRole,  // No mapping to ARIA role.
    TimerRole,
    ToggleButtonRole,
    ToolbarRole,
    TreeGridRole,
    TreeItemRole,
    TreeRole,
    UserInterfaceTooltipRole,
    VideoRole,    // No mapping to ARIA role.
    WebAreaRole,  // No mapping to ARIA role.
    WindowRole,   // No mapping to ARIA role.
    NumRoles
  };
  
  enum AccessibilityTextSource {
    AlternativeText,
    ChildrenText,
    SummaryText,
    HelpText,
    VisibleText,
    TitleTagText,
    PlaceholderText,
    LabelByElementText,
  };
  
  enum AccessibilityState {
    AXBusyState,
    AXCheckedState,
    AXEnabledState,
    AXExpandedState,
    AXFocusableState,
    AXFocusedState,
    AXHaspopupState,
    AXHoveredState,
    AXInvisibleState,
    AXLinkedState,
    AXMultilineState,
    AXMultiselectableState,
    AXOffscreenState,
    AXPressedState,
    AXProtectedState,
    AXReadonlyState,
    AXRequiredState,
    AXSelectableState,
    AXSelectedState,
    AXVerticalState,
    AXVisitedState
  };
  
  class AccessibilityText final
      : public GarbageCollectedFinalized<AccessibilityText> {
    WTF_MAKE_NONCOPYABLE(AccessibilityText);
  
   public:
    DEFINE_INLINE_TRACE() { visitor->trace(m_textElement); }
  
   private:
    AccessibilityText(const String& text,
                      const AccessibilityTextSource& source,
                      AXObject* element)
        : m_text(text), m_textElement(element) {}
  
    String m_text;
    Member<AXObject> m_textElement;
  };
  
  enum AccessibilityOrientation {
    AccessibilityOrientationUndefined = 0,
    AccessibilityOrientationVertical,
    AccessibilityOrientationHorizontal,
  };
  
  enum AXObjectInclusion {
    IncludeObject,
    IgnoreObject,
    DefaultBehavior,
  };
  
  enum AccessibilityButtonState {
    ButtonStateOff = 0,
    ButtonStateOn,
    ButtonStateMixed,
  };
  
  enum AccessibilityTextDirection {
    AccessibilityTextDirectionLTR,
    AccessibilityTextDirectionRTL,
    AccessibilityTextDirectionTTB,
    AccessibilityTextDirectionBTT
  };
  
  enum SortDirection {
    SortDirectionUndefined = 0,
    SortDirectionNone,
    SortDirectionAscending,
    SortDirectionDescending,
    SortDirectionOther
  };
  
  enum AccessibilityExpanded {
    ExpandedUndefined = 0,
    ExpandedCollapsed,
    ExpandedExpanded,
  };
  
  enum AccessibilityOptionalBool {
    OptionalBoolUndefined = 0,
    OptionalBoolTrue,
    OptionalBoolFalse
  };
  
  enum AriaCurrentState {
    AriaCurrentStateUndefined = 0,
    AriaCurrentStateFalse,
    AriaCurrentStateTrue,
    AriaCurrentStatePage,
    AriaCurrentStateStep,
    AriaCurrentStateLocation,
    AriaCurrentStateDate,
    AriaCurrentStateTime
  };
  
  enum InvalidState {
    InvalidStateUndefined = 0,
    InvalidStateFalse,
    InvalidStateTrue,
    InvalidStateSpelling,
    InvalidStateGrammar,
    InvalidStateOther
  };
  
  enum TextStyle {
    TextStyleNone = 0,
    TextStyleBold = 1 << 0,
    TextStyleItalic = 1 << 1,
    TextStyleUnderline = 1 << 2,
    TextStyleLineThrough = 1 << 3
  };
  
  enum TextUnderElementMode {
    TextUnderElementAll,
    TextUnderElementAny  // If the text is unimportant, just whether or not it's
                         // present
  };
  
  // The source of the accessible name of an element. This is needed
  // because on some platforms this determines how the accessible name
  // is exposed.
  enum AXNameFrom {
    AXNameFromUninitialized = -1,
    AXNameFromAttribute = 0,
    AXNameFromCaption,
    AXNameFromContents,
    AXNameFromPlaceholder,
    AXNameFromRelatedElement,
    AXNameFromValue,
    AXNameFromTitle,
  };
  
  // The potential native HTML-based text (name, description or placeholder)
  // sources for an element.  See
  // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessible-name-and-description-calculation
  enum AXTextFromNativeHTML {
    AXTextFromNativeHTMLUninitialized = -1,
    AXTextFromNativeHTMLFigcaption,
    AXTextFromNativeHTMLLabel,
    AXTextFromNativeHTMLLabelFor,
    AXTextFromNativeHTMLLabelWrapped,
    AXTextFromNativeHTMLLegend,
    AXTextFromNativeHTMLTableCaption,
    AXTextFromNativeHTMLTitleElement,
  };
  
  // The source of the accessible description of an element. This is needed
  // because on some platforms this determines how the accessible description
  // is exposed.
  enum AXDescriptionFrom {
    AXDescriptionFromUninitialized = -1,
    AXDescriptionFromAttribute = 0,
    AXDescriptionFromContents,
    AXDescriptionFromPlaceholder,
    AXDescriptionFromRelatedElement,
  };
  
  enum AXIgnoredReason {
    AXActiveModalDialog,
    AXAncestorDisallowsChild,
    AXAncestorIsLeafNode,
    AXAriaHidden,
    AXAriaHiddenRoot,
    AXEmptyAlt,
    AXEmptyText,
    AXInert,
    AXInheritsPresentation,
    AXLabelContainer,
    AXLabelFor,
    AXNotRendered,
    AXNotVisible,
    AXPresentationalRole,
    AXProbablyPresentational,
    AXStaticTextUsedAsNameFor,
    AXUninteresting
  };
  
  class IgnoredReason {
    DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  
   public:
    AXIgnoredReason reason;
    Member<const AXObject> relatedObject;
  
    explicit IgnoredReason(AXIgnoredReason reason)
        : reason(reason), relatedObject(nullptr) {}
  
    IgnoredReason(AXIgnoredReason r, const AXObject* obj)
        : reason(r), relatedObject(obj) {}
  
    DEFINE_INLINE_TRACE() { visitor->trace(relatedObject); }
  };
  
  class NameSourceRelatedObject
      : public GarbageCollectedFinalized<NameSourceRelatedObject> {
    WTF_MAKE_NONCOPYABLE(NameSourceRelatedObject);
  
   public:
    WeakMember<AXObject> object;
    String text;
  
    NameSourceRelatedObject(AXObject* object, String text)
        : object(object), text(text) {}
  
    DEFINE_INLINE_TRACE() { visitor->trace(object); }
  };
  
  typedef HeapVector<Member<NameSourceRelatedObject>> AXRelatedObjectVector;
  class NameSource {
    DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  
   public:
    String text;
    bool superseded = false;
    bool invalid = false;
    AXNameFrom type = AXNameFromUninitialized;
    const QualifiedName& attribute;
    AtomicString attributeValue;
    AXTextFromNativeHTML nativeSource = AXTextFromNativeHTMLUninitialized;
    AXRelatedObjectVector relatedObjects;
  
    NameSource(bool superseded, const QualifiedName& attr)
        : superseded(superseded), attribute(attr) {}
  
    explicit NameSource(bool superseded)
        : superseded(superseded), attribute(QualifiedName::null()) {}
  
    DEFINE_INLINE_TRACE() { visitor->trace(relatedObjects); }
  };
  
  class DescriptionSource {
    DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  
   public:
    String text;
    bool superseded = false;
    bool invalid = false;
    AXDescriptionFrom type = AXDescriptionFromUninitialized;
    const QualifiedName& attribute;
    AtomicString attributeValue;
    AXTextFromNativeHTML nativeSource = AXTextFromNativeHTMLUninitialized;
    AXRelatedObjectVector relatedObjects;
  
    DescriptionSource(bool superseded, const QualifiedName& attr)
        : superseded(superseded), attribute(attr) {}
  
    explicit DescriptionSource(bool superseded)
        : superseded(superseded), attribute(QualifiedName::null()) {}
  
    DEFINE_INLINE_TRACE() { visitor->trace(relatedObjects); }
  };
  
  }  // namespace blink
  
  WTF_ALLOW_INIT_WITH_MEM_FUNCTIONS(blink::IgnoredReason);
  WTF_ALLOW_INIT_WITH_MEM_FUNCTIONS(blink::NameSource);
  WTF_ALLOW_INIT_WITH_MEM_FUNCTIONS(blink::DescriptionSource);
  
  namespace blink {
  
  class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
    WTF_MAKE_NONCOPYABLE(AXObject);
  
   public:
    typedef HeapVector<Member<AXObject>> AXObjectVector;
  
    struct AXRange {
      DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
      // The deepest descendant in which the range starts.
      // (nullptr means the current object.)
      Persistent<AXObject> anchorObject;
      // The number of characters and child objects in the anchor object
      // before the range starts.
      int anchorOffset;
      // When the same character offset could correspond to two possible
      // cursor positions, upstream means it's on the previous line rather
      // than the next line.
      TextAffinity anchorAffinity;
  
      // The deepest descendant in which the range ends.
      // (nullptr means the current object.)
      Persistent<AXObject> focusObject;
      // The number of characters and child objects in the focus object
      // before the range ends.
      int focusOffset;
      // When the same character offset could correspond to two possible
      // cursor positions, upstream means it's on the previous line rather
      // than the next line.
      TextAffinity focusAffinity;
  
      AXRange()
          : anchorObject(nullptr),
            anchorOffset(-1),
            anchorAffinity(TextAffinity::Upstream),
            focusObject(nullptr),
            focusOffset(-1),
            focusAffinity(TextAffinity::Downstream) {}
  
      AXRange(int startOffset, int endOffset)
          : anchorObject(nullptr),
            anchorOffset(startOffset),
            anchorAffinity(TextAffinity::Upstream),
            focusObject(nullptr),
            focusOffset(endOffset),
            focusAffinity(TextAffinity::Downstream) {}
  
      AXRange(AXObject* anchorObject,
              int anchorOffset,
              TextAffinity anchorAffinity,
              AXObject* focusObject,
              int focusOffset,
              TextAffinity focusAffinity)
          : anchorObject(anchorObject),
            anchorOffset(anchorOffset),
            anchorAffinity(anchorAffinity),
            focusObject(focusObject),
            focusOffset(focusOffset),
            focusAffinity(focusAffinity) {}
  
      bool isValid() const {
        return ((anchorObject && focusObject) ||
                (!anchorObject && !focusObject)) &&
               anchorOffset >= 0 && focusOffset >= 0;
      }
  
      // Determines if the range only refers to text offsets under the current
      // object.
      bool isSimple() const {
        return anchorObject == focusObject || !anchorObject || !focusObject;
      }
    };
  
   protected:
    AXObject(AXObjectCacheImpl&);
  
   public:
    virtual ~AXObject();
    DECLARE_VIRTUAL_TRACE();
  
    static unsigned numberOfLiveAXObjects() { return s_numberOfLiveAXObjects; }
  
    // After constructing an AXObject, it must be given a
    // unique ID, then added to AXObjectCacheImpl, and finally init() must
    // be called last.
    void setAXObjectID(AXID axObjectID) { m_id = axObjectID; }
    virtual void init() {}
  
    // When the corresponding WebCore object that this AXObject
    // wraps is deleted, it must be detached.
    virtual void detach();
    virtual bool isDetached() const;
  
    // If the parent of this object is known, this can be faster than using
    // computeParent().
    virtual void setParent(AXObject* parent) { m_parent = parent; }
  
    // The AXObjectCacheImpl that owns this object, and its unique ID within this
    // cache.
    AXObjectCacheImpl& axObjectCache() const {
      ASSERT(m_axObjectCache);
      return *m_axObjectCache;
    }
  
    AXID axObjectID() const { return m_id; }
  
    // Determine subclass type.
    virtual bool isAXNodeObject() const { return false; }
    virtual bool isAXLayoutObject() const { return false; }
    virtual bool isAXListBox() const { return false; }
    virtual bool isAXListBoxOption() const { return false; }
    virtual bool isAXRadioInput() const { return false; }
    virtual bool isAXSVGRoot() const { return false; }
  
    // Check object role or purpose.
    virtual AccessibilityRole roleValue() const { return m_role; }
    bool isARIATextControl() const;
    virtual bool isARIATreeGridRow() const { return false; }
    virtual bool isAXTable() const { return false; }
    virtual bool isAnchor() const { return false; }
    bool isButton() const;
    bool isCanvas() const { return roleValue() == CanvasRole; }
    bool isCheckbox() const { return roleValue() == CheckBoxRole; }
    bool isCheckboxOrRadio() const { return isCheckbox() || isRadioButton(); }
    bool isColorWell() const { return roleValue() == ColorWellRole; }
    bool isComboBox() const { return roleValue() == ComboBoxRole; }
    virtual bool isControl() const { return false; }
    virtual bool isDataTable() const { return false; }
    virtual bool isEmbeddedObject() const { return false; }
    virtual bool isFieldset() const { return false; }
    virtual bool isHeading() const { return false; }
    virtual bool isImage() const { return false; }
    virtual bool isImageMapLink() const { return false; }
    virtual bool isInputImage() const { return false; }
    bool isLandmarkRelated() const;
    virtual bool isLink() const { return false; }
    virtual bool isList() const { return false; }
    virtual bool isMenu() const { return false; }
    virtual bool isMenuButton() const { return false; }
    virtual bool isMenuList() const { return false; }
    virtual bool isMenuListOption() const { return false; }
    virtual bool isMenuListPopup() const { return false; }
    bool isMenuRelated() const;
    virtual bool isMeter() const { return false; }
    virtual bool isMockObject() const { return false; }
    virtual bool isNativeSpinButton() const { return false; }
    virtual bool isNativeTextControl() const {
      return false;
    }  // input or textarea
    virtual bool isNonNativeTextControl() const {
      return false;
    }  // contenteditable or role=textbox
    virtual bool isPasswordField() const { return false; }
    virtual bool isPasswordFieldAndShouldHideValue() const;
    bool isPresentational() const {
      return roleValue() == NoneRole || roleValue() == PresentationalRole;
    }
    virtual bool isProgressIndicator() const { return false; }
    bool isRadioButton() const { return roleValue() == RadioButtonRole; }
    bool isRange() const {
      return roleValue() == ProgressIndicatorRole ||
             roleValue() == ScrollBarRole || roleValue() == SliderRole ||
             roleValue() == SpinButtonRole;
    }
    bool isScrollbar() const { return roleValue() == ScrollBarRole; }
    virtual bool isSlider() const { return false; }
    virtual bool isNativeSlider() const { return false; }
    virtual bool isSpinButton() const { return roleValue() == SpinButtonRole; }
    virtual bool isSpinButtonPart() const { return false; }
    bool isTabItem() const { return roleValue() == TabRole; }
    virtual bool isTableCell() const { return false; }
    virtual bool isTableRow() const { return false; }
    virtual bool isTextControl() const { return false; }
    virtual bool isTableCol() const { return false; }
    bool isTree() const { return roleValue() == TreeRole; }
    bool isWebArea() const { return roleValue() == WebAreaRole; }
  
    // Check object state.
    virtual bool isChecked() const { return false; }
    virtual bool isClickable() const;
    virtual bool isCollapsed() const { return false; }
    virtual bool isEnabled() const { return false; }
    virtual AccessibilityExpanded isExpanded() const { return ExpandedUndefined; }
    virtual bool isFocused() const { return false; }
    virtual bool isHovered() const { return false; }
    virtual bool isLinked() const { return false; }
    virtual bool isLoaded() const { return false; }
    virtual bool isMultiSelectable() const { return false; }
    virtual bool isOffScreen() const { return false; }
    virtual bool isPressed() const { return false; }
    virtual bool isReadOnly() const { return false; }
    virtual bool isRequired() const { return false; }
    virtual bool isSelected() const { return false; }
    virtual bool isSelectedOptionActive() const { return false; }
    virtual bool isVisible() const { return true; }
    virtual bool isVisited() const { return false; }
  
    // Check whether certain properties can be modified.
    virtual bool canSetFocusAttribute() const { return false; }
    virtual bool canSetValueAttribute() const { return false; }
    virtual bool canSetSelectedAttribute() const { return false; }
  
    // Whether objects are ignored, i.e. not included in the tree.
    bool accessibilityIsIgnored() const;
    typedef HeapVector<IgnoredReason> IgnoredReasons;
    virtual bool computeAccessibilityIsIgnored(IgnoredReasons* = nullptr) const {
      return true;
    }
    bool accessibilityIsIgnoredByDefault(IgnoredReasons* = nullptr) const;
    AXObjectInclusion accessibilityPlatformIncludesObject() const;
    virtual AXObjectInclusion defaultObjectInclusion(
        IgnoredReasons* = nullptr) const;
    bool isInertOrAriaHidden() const;
    const AXObject* ariaHiddenRoot() const;
    bool computeIsInertOrAriaHidden(IgnoredReasons* = nullptr) const;
    bool isDescendantOfLeafNode() const;
    AXObject* leafNodeAncestor() const;
    bool isDescendantOfDisabledNode() const;
    const AXObject* disabledAncestor() const;
    bool lastKnownIsIgnoredValue();
    void setLastKnownIsIgnoredValue(bool);
    bool hasInheritedPresentationalRole() const;
    bool isPresentationalChild() const;
    bool ancestorExposesActiveDescendant() const;
    bool computeAncestorExposesActiveDescendant() const;
  
    //
    // Accessible name calculation
    //
  
    // Retrieves the accessible name of the object, an enum indicating where the
    // name was derived from, and a list of objects that were used to derive the
    // name, if any.
    virtual String name(AXNameFrom&, AXObjectVector* nameObjects) const;
  
    typedef HeapVector<NameSource> NameSources;
    // Retrieves the accessible name of the object and a list of all potential
    // sources for the name, indicating which were used.
    virtual String name(NameSources*) const;
  
    typedef HeapVector<DescriptionSource> DescriptionSources;
    // Takes the result of nameFrom from calling |name|, above, and retrieves the
    // accessible description of the object, which is secondary to |name|, an enum
    // indicating where the description was derived from, and a list of objects
    // that were used to derive the description, if any.
    virtual String description(AXNameFrom,
                               AXDescriptionFrom&,
                               AXObjectVector* descriptionObjects) const {
      return String();
    }
  
    // Same as above, but returns a list of all potential sources for the
    // description, indicating which were used.
    virtual String description(AXNameFrom,
                               AXDescriptionFrom&,
                               DescriptionSources*,
                               AXRelatedObjectVector*) const {
      return String();
    }
  
    // Takes the result of nameFrom and descriptionFrom from calling |name| and
    // |description|, above, and retrieves the placeholder of the object, if
    // present and if it wasn't already exposed by one of the two functions above.
    virtual String placeholder(AXNameFrom, AXDescriptionFrom) const {
      return String();
    }
  
    // Internal functions used by name and description, above.
    typedef HeapHashSet<Member<const AXObject>> AXObjectSet;
    virtual String textAlternative(bool recursive,
                                   bool inAriaLabelledByTraversal,
                                   AXObjectSet& visited,
                                   AXNameFrom& nameFrom,
                                   AXRelatedObjectVector* relatedObjects,
                                   NameSources* nameSources) const {
      return String();
    }
    virtual String textFromDescendants(AXObjectSet& visited,
                                       bool recursive) const {
      return String();
    }
  
    // Returns result of Accessible Name Calculation algorithm.
    // This is a simpler high-level interface to |name| used by Inspector.
    String computedName() const;
  
    // Internal function used to determine whether the result of calling |name| on
    // this object would return text that came from the an HTML label element or
    // not. This is intended to be faster than calling |name| or
    // |textAlternative|, and without side effects (it won't call
    // axObjectCache->getOrCreate).
    virtual bool nameFromLabelElement() const { return false; }
  
    //
    // Properties of static elements.
    //
  
    virtual const AtomicString& accessKey() const { return nullAtom; }
    RGBA32 backgroundColor() const;
    virtual RGBA32 computeBackgroundColor() const { return Color::transparent; }
    virtual RGBA32 color() const { return Color::black; }
    // Used by objects of role ColorWellRole.
    virtual RGBA32 colorValue() const { return Color::transparent; }
    virtual bool canvasHasFallbackContent() const { return false; }
    virtual String fontFamily() const { return nullAtom; }
    // Font size is in pixels.
    virtual float fontSize() const { return 0.0f; }
    // Value should be 1-based. 0 means not supported.
    virtual int headingLevel() const { return 0; }
    // Value should be 1-based. 0 means not supported.
    virtual unsigned hierarchicalLevel() const { return 0; }
    virtual AccessibilityOrientation orientation() const;
    virtual String text() const { return String(); }
    virtual AccessibilityTextDirection textDirection() const {
      return AccessibilityTextDirectionLTR;
    }
    virtual int textLength() const { return 0; }
    virtual TextStyle getTextStyle() const { return TextStyleNone; }
    virtual KURL url() const { return KURL(); }
  
    // Load inline text boxes for just this node, even if
    // settings->inlineTextBoxAccessibilityEnabled() is false.
    virtual void loadInlineTextBoxes() {}
  
    // Walk the AXObjects on the same line. This is supported on any
    // object type but primarily intended to be used for inline text boxes.
    virtual AXObject* nextOnLine() const { return nullptr; }
    virtual AXObject* previousOnLine() const { return nullptr; }
  
    // For all node objects. The start and end character offset of each
    // marker, such as spelling or grammar error.
    virtual void markers(Vector<DocumentMarker::MarkerType>&,
                         Vector<AXRange>&) const {}
    // For an inline text box.
    // The integer horizontal pixel offset of each character in the string;
    // negative values for RTL.
    virtual void textCharacterOffsets(Vector<int>&) const {}
    // The start and end character offset of each word in the object's text.
    virtual void wordBoundaries(Vector<AXRange>&) const {}
  
    // Properties of interactive elements.
    String actionVerb() const;
    virtual AccessibilityButtonState checkboxOrRadioValue() const;
    virtual AriaCurrentState ariaCurrentState() const {
      return AriaCurrentStateUndefined;
    }
    virtual InvalidState getInvalidState() const { return InvalidStateUndefined; }
    // Only used when invalidState() returns InvalidStateOther.
    virtual String ariaInvalidValue() const { return String(); }
    virtual String valueDescription() const { return String(); }
    virtual float valueForRange() const { return 0.0f; }
    virtual float maxValueForRange() const { return 0.0f; }
    virtual float minValueForRange() const { return 0.0f; }
    virtual String stringValue() const { return String(); }
  
    // ARIA attributes.
    virtual AXObject* activeDescendant() { return nullptr; }
    virtual String ariaAutoComplete() const { return String(); }
    virtual String ariaDescribedByAttribute() const { return String(); }
    virtual void ariaFlowToElements(AXObjectVector&) const {}
    virtual void ariaControlsElements(AXObjectVector&) const {}
    virtual void ariaOwnsElements(AXObjectVector& owns) const {}
    virtual void ariaDescribedbyElements(AXObjectVector&) const {}
    virtual void ariaLabelledbyElements(AXObjectVector&) const {}
    virtual bool ariaHasPopup() const { return false; }
    virtual bool isEditable() const { return false; }
    bool isMultiline() const;
    virtual bool isRichlyEditable() const { return false; }
    virtual String ariaLabelledbyAttribute() const { return String(); }
    bool ariaPressedIsPresent() const;
    virtual AccessibilityRole ariaRoleAttribute() const { return UnknownRole; }
    virtual bool ariaRoleHasPresentationalChildren() const { return false; }
    virtual AXObject* ancestorForWhichThisIsAPresentationalChild() const {
      return 0;
    }
    bool supportsActiveDescendant() const;
    bool supportsARIAAttributes() const;
    virtual bool supportsARIADragging() const { return false; }
    virtual bool supportsARIADropping() const { return false; }
    virtual bool supportsARIAFlowTo() const { return false; }
    virtual bool supportsARIAOwns() const { return false; }
    bool supportsRangeValue() const;
    virtual SortDirection getSortDirection() const {
      return SortDirectionUndefined;
    }
  
    // Returns 0-based index.
    int indexInParent() const;
  
    // Value should be 1-based. 0 means not supported.
    virtual int posInSet() const { return 0; }
    virtual int setSize() const { return 0; }
    bool supportsSetSizeAndPosInSet() const;
  
    // ARIA live-region features.
    bool isLiveRegion() const;
    AXObject* liveRegionRoot() const;
    virtual const AtomicString& liveRegionStatus() const { return nullAtom; }
    virtual const AtomicString& liveRegionRelevant() const { return nullAtom; }
    virtual bool liveRegionAtomic() const { return false; }
    virtual bool liveRegionBusy() const { return false; }
  
    const AtomicString& containerLiveRegionStatus() const;
    const AtomicString& containerLiveRegionRelevant() const;
    bool containerLiveRegionAtomic() const;
    bool containerLiveRegionBusy() const;
  
    // Every object's bounding box is returned relative to a
    // container object (which is guaranteed to be an ancestor) and
    // optionally a transformation matrix that needs to be applied too.
    // To compute the absolute bounding box of an element, start with its
    // boundsInContainer and apply the transform. Then as long as its container is
    // not null, walk up to its container and offset by the container's offset
    // from origin, the container's scroll position if any, and apply the
    // container's transform.  Do this until you reach the root of the tree.
    virtual void getRelativeBounds(AXObject** outContainer,
                                   FloatRect& outBoundsInContainer,
                                   SkMatrix44& outContainerTransform) const;
  
    // Get the bounds in frame-relative coordinates as a LayoutRect.
    LayoutRect getBoundsInFrameCoordinates() const;
  
    // Explicitly set an object's bounding rect and offset container.
    void setElementRect(LayoutRect r, AXObject* container) {
      m_explicitElementRect = r;
      m_explicitContainerID = container->axObjectID();
    }
  
    // Hit testing.
    // Called on the root AX object to return the deepest available element.
    virtual AXObject* accessibilityHitTest(const IntPoint&) const { return 0; }
    // Called on the AX object after the layout tree determines which is the right
    // AXLayoutObject.
    virtual AXObject* elementAccessibilityHitTest(const IntPoint&) const;
  
    // High-level accessibility tree access. Other modules should only use these
    // functions.
    const AXObjectVector& children();
    AXObject* parentObject() const;
    AXObject* parentObjectIfExists() const;
    virtual AXObject* computeParent() const = 0;
    virtual AXObject* computeParentIfExists() const { return 0; }
    AXObject* cachedParentObject() const { return m_parent; }
    AXObject* parentObjectUnignored() const;
  
    // Low-level accessibility tree exploration, only for use within the
    // accessibility module.
    virtual AXObject* rawFirstChild() const { return 0; }
    virtual AXObject* rawNextSibling() const { return 0; }
    virtual void addChildren() {}
    virtual bool canHaveChildren() const { return true; }
    bool hasChildren() const { return m_haveChildren; }
    virtual void updateChildrenIfNecessary();
    virtual bool needsToUpdateChildren() const { return false; }
    virtual void setNeedsToUpdateChildren() {}
    virtual void clearChildren();
    virtual void detachFromParent() { m_parent = 0; }
    virtual AXObject* scrollBar(AccessibilityOrientation) { return 0; }
  
    // Properties of the object's owning document or page.
    virtual double estimatedLoadingProgress() const { return 0; }
  
    // DOM and layout tree access.
    virtual Node* getNode() const { return 0; }
    virtual LayoutObject* getLayoutObject() const { return 0; }
    virtual Document* getDocument() const;
    virtual FrameView* documentFrameView() const;
    virtual Element* anchorElement() const { return 0; }
    virtual Element* actionElement() const { return 0; }
    String language() const;
    bool hasAttribute(const QualifiedName&) const;
    const AtomicString& getAttribute(const QualifiedName&) const;
  
    // Methods that retrieve or manipulate the current selection.
  
    // Get the current selection from anywhere in the accessibility tree.
    virtual AXRange selection() const { return AXRange(); }
    // Gets only the start and end offsets of the selection computed using the
    // current object as the starting point. Returns a null selection if there is
    // no selection in the subtree rooted at this object.
    virtual AXRange selectionUnderObject() const { return AXRange(); }
    virtual void setSelection(const AXRange&) {}
  
    // Scrollable containers.
    bool isScrollableContainer() const;
    IntPoint scrollOffset() const;
    IntPoint minimumScrollOffset() const;
    IntPoint maximumScrollOffset() const;
    void setScrollOffset(const IntPoint&) const;
  
    // If this object itself scrolls, return its ScrollableArea.
    virtual ScrollableArea* getScrollableAreaIfScrollable() const { return 0; }
  
    // Modify or take an action on an object.
    virtual void increment() {}
    virtual void decrement() {}
    bool performDefaultAction() const { return press(); }
    virtual bool press() const;
    // Make this object visible by scrolling as many nested scrollable views as
    // needed.
    void scrollToMakeVisible() const;
    // Same, but if the whole object can't be made visible, try for this subrect,
    // in local coordinates.
    void scrollToMakeVisibleWithSubFocus(const IntRect&) const;
    // Scroll this object to a given point in global coordinates of the top-level
    // window.
    void scrollToGlobalPoint(const IntPoint&) const;
    virtual void setFocused(bool) {}
    virtual void setSelected(bool) {}
    virtual void setSequentialFocusNavigationStartingPoint();
    virtual void setValue(const String&) {}
    virtual void setValue(float) {}
  
    // Notifications that this object may have changed.
    virtual void childrenChanged() {}
    virtual void handleActiveDescendantChanged() {}
    virtual void handleAriaExpandedChanged() {}
    void notifyIfIgnoredValueChanged();
    virtual void selectionChanged();
    virtual void textChanged() {}
    virtual void updateAccessibilityRole() {}
  
    // Text metrics. Most of these should be deprecated, needs major cleanup.
    virtual VisiblePosition visiblePositionForIndex(int) const {
      return VisiblePosition();
    }
    int lineForPosition(const VisiblePosition&) const;
    virtual int index(const VisiblePosition&) const { return -1; }
    virtual void lineBreaks(Vector<int>&) const {}
  
    // Static helper functions.
    static bool isARIAControl(AccessibilityRole);
    static bool isARIAInput(AccessibilityRole);
    static AccessibilityRole ariaRoleToWebCoreRole(const String&);
    static const AtomicString& roleName(AccessibilityRole);
    static const AtomicString& internalRoleName(AccessibilityRole);
    static bool isInsideFocusableElementOrARIAWidget(const Node&);
  
   protected:
    AXID m_id;
    AXObjectVector m_children;
    mutable bool m_haveChildren;
    AccessibilityRole m_role;
    AXObjectInclusion m_lastKnownIsIgnoredValue;
    LayoutRect m_explicitElementRect;
    AXID m_explicitContainerID;
  
    // Used only inside textAlternative():
    static String collapseWhitespace(const String&);
    static String recursiveTextAlternative(const AXObject&,
                                           bool inAriaLabelledByTraversal,
                                           AXObjectSet& visited);
    bool isHiddenForTextAlternativeCalculation() const;
    String ariaTextAlternative(bool recursive,
                               bool inAriaLabelledByTraversal,
                               AXObjectSet& visited,
                               AXNameFrom&,
                               AXRelatedObjectVector*,
                               NameSources*,
                               bool* foundTextAlternative) const;
    String textFromElements(bool inAriaLabelledByTraversal,
                            AXObjectSet& visited,
                            HeapVector<Member<Element>>& elements,
                            AXRelatedObjectVector* relatedObjects) const;
    void tokenVectorFromAttribute(Vector<String>&, const QualifiedName&) const;
    void elementsFromAttribute(HeapVector<Member<Element>>& elements,
                               const QualifiedName&) const;
    void ariaLabelledbyElementVector(HeapVector<Member<Element>>& elements) const;
    String textFromAriaLabelledby(AXObjectSet& visited,
                                  AXRelatedObjectVector* relatedObjects) const;
    String textFromAriaDescribedby(AXRelatedObjectVector* relatedObjects) const;
  
    virtual const AXObject* inheritsPresentationalRoleFrom() const { return 0; }
  
    virtual bool nameFromContents() const;
  
    AccessibilityRole buttonRoleType() const;
  
    virtual LayoutObject* layoutObjectForRelativeBounds() const {
      return nullptr;
    }
  
    mutable Member<AXObject> m_parent;
  
    // The following cached attribute values (the ones starting with m_cached*)
    // are only valid if m_lastModificationCount matches
    // AXObjectCacheImpl::modificationCount().
    mutable int m_lastModificationCount;
    mutable RGBA32 m_cachedBackgroundColor;
    mutable bool m_cachedIsIgnored : 1;
    mutable bool m_cachedIsInertOrAriaHidden : 1;
    mutable bool m_cachedIsDescendantOfLeafNode : 1;
    mutable bool m_cachedIsDescendantOfDisabledNode : 1;
    mutable bool m_cachedHasInheritedPresentationalRole : 1;
    mutable bool m_cachedIsPresentationalChild : 1;
    mutable bool m_cachedAncestorExposesActiveDescendant : 1;
    mutable Member<AXObject> m_cachedLiveRegionRoot;
  
    Member<AXObjectCacheImpl> m_axObjectCache;
  
    // Updates the cached attribute values. This may be recursive, so to prevent
    // deadlocks,
    // functions called here may only search up the tree (ancestors), not down.
    void updateCachedAttributeValuesIfNeeded() const;
  
   private:
    static bool includesARIAWidgetRole(const String&);
    static bool hasInteractiveARIAAttribute(const Element&);
  
    static unsigned s_numberOfLiveAXObjects;
  };
  
  #define DEFINE_AX_OBJECT_TYPE_CASTS(thisType, predicate)           \
    DEFINE_TYPE_CASTS(thisType, AXObject, object, object->predicate, \
                      object.predicate)
  
  }  // namespace blink
  
  #endif  // AXObject_h
  