Make it possible to test rubber-banding in overflow scroll
[WebKit-https.git] / Source / WebCore / accessibility / AccessibilityRenderObject.cpp
index 5d2e86b..6159ee3 100644 (file)
@@ -36,9 +36,8 @@
 #include "AccessibilitySpinButton.h"
 #include "AccessibilityTable.h"
 #include "CachedImage.h"
 #include "AccessibilitySpinButton.h"
 #include "AccessibilityTable.h"
 #include "CachedImage.h"
-#include "Chrome.h"
+#include "Editing.h"
 #include "ElementIterator.h"
 #include "ElementIterator.h"
-#include "EventNames.h"
 #include "FloatRect.h"
 #include "Frame.h"
 #include "FrameLoader.h"
 #include "FloatRect.h"
 #include "Frame.h"
 #include "FrameLoader.h"
@@ -54,7 +53,6 @@
 #include "HTMLMapElement.h"
 #include "HTMLMeterElement.h"
 #include "HTMLNames.h"
 #include "HTMLMapElement.h"
 #include "HTMLMeterElement.h"
 #include "HTMLNames.h"
-#include "HTMLOptGroupElement.h"
 #include "HTMLOptionElement.h"
 #include "HTMLOptionsCollection.h"
 #include "HTMLSelectElement.h"
 #include "HTMLOptionElement.h"
 #include "HTMLOptionsCollection.h"
 #include "HTMLSelectElement.h"
@@ -70,7 +68,6 @@
 #include "Page.h"
 #include "ProgressTracker.h"
 #include "RenderButton.h"
 #include "Page.h"
 #include "ProgressTracker.h"
 #include "RenderButton.h"
-#include "RenderFieldset.h"
 #include "RenderFileUploadControl.h"
 #include "RenderHTMLCanvas.h"
 #include "RenderImage.h"
 #include "RenderFileUploadControl.h"
 #include "RenderHTMLCanvas.h"
 #include "RenderImage.h"
 #include "RenderedPosition.h"
 #include "SVGDocument.h"
 #include "SVGImage.h"
 #include "RenderedPosition.h"
 #include "SVGDocument.h"
 #include "SVGImage.h"
-#include "SVGNames.h"
 #include "SVGSVGElement.h"
 #include "Text.h"
 #include "TextControlInnerElements.h"
 #include "TextIterator.h"
 #include "VisibleUnits.h"
 #include "SVGSVGElement.h"
 #include "Text.h"
 #include "TextControlInnerElements.h"
 #include "TextIterator.h"
 #include "VisibleUnits.h"
-#include "htmlediting.h"
 #include <wtf/NeverDestroyed.h>
 #include <wtf/StdLibExtras.h>
 #include <wtf/unicode/CharacterNames.h>
 #include <wtf/NeverDestroyed.h>
 #include <wtf/StdLibExtras.h>
 #include <wtf/unicode/CharacterNames.h>
@@ -113,7 +108,7 @@ using namespace HTMLNames;
 
 AccessibilityRenderObject::AccessibilityRenderObject(RenderObject* renderer)
     : AccessibilityNodeObject(renderer->node())
 
 AccessibilityRenderObject::AccessibilityRenderObject(RenderObject* renderer)
     : AccessibilityNodeObject(renderer->node())
-    , m_renderer(renderer)
+    , m_renderer(makeWeakPtr(renderer))
 {
 #ifndef NDEBUG
     m_renderer->setHasAXObject(true);
 {
 #ifndef NDEBUG
     m_renderer->setHasAXObject(true);
@@ -150,14 +145,14 @@ void AccessibilityRenderObject::detach(AccessibilityDetachmentType detachmentTyp
 
 RenderBoxModelObject* AccessibilityRenderObject::renderBoxModelObject() const
 {
 
 RenderBoxModelObject* AccessibilityRenderObject::renderBoxModelObject() const
 {
-    if (!is<RenderBoxModelObject>(m_renderer))
+    if (!is<RenderBoxModelObject>(renderer()))
         return nullptr;
         return nullptr;
-    return downcast<RenderBoxModelObject>(m_renderer);
+    return downcast<RenderBoxModelObject>(renderer());
 }
 
 void AccessibilityRenderObject::setRenderer(RenderObject* renderer)
 {
 }
 
 void AccessibilityRenderObject::setRenderer(RenderObject* renderer)
 {
-    m_renderer = renderer;
+    m_renderer = makeWeakPtr(renderer);
     setNode(renderer->node());
 }
 
     setNode(renderer->node());
 }
 
@@ -188,7 +183,7 @@ static inline RenderObject* firstChildConsideringContinuation(RenderObject& rend
     // We don't want to include the end of a continuation as the firstChild of the
     // anonymous parent, because everything has already been linked up via continuation.
     // CSS first-letter selector is an example of this case.
     // We don't want to include the end of a continuation as the firstChild of the
     // anonymous parent, because everything has already been linked up via continuation.
     // CSS first-letter selector is an example of this case.
-    if (renderer.isAnonymous() && firstChild && firstChild->isInlineElementContinuation())
+    if (renderer.isAnonymous() && is<RenderElement>(firstChild) && downcast<RenderElement>(*firstChild).isInlineElementContinuation())
         firstChild = nullptr;
     
     if (!firstChild && isInlineWithContinuation(renderer))
         firstChild = nullptr;
     
     if (!firstChild && isInlineWithContinuation(renderer))
@@ -253,12 +248,15 @@ AccessibilityObject* AccessibilityRenderObject::lastChild() const
 
 static inline RenderInline* startOfContinuations(RenderObject& renderer)
 {
 
 static inline RenderInline* startOfContinuations(RenderObject& renderer)
 {
-    if (renderer.isInlineElementContinuation() && is<RenderInline>(renderer.node()->renderer()))
+    if (!is<RenderElement>(renderer))
+        return nullptr;
+    auto& renderElement = downcast<RenderElement>(renderer);
+    if (renderElement.isInlineElementContinuation() && is<RenderInline>(renderElement.element()->renderer()))
         return downcast<RenderInline>(renderer.node()->renderer());
 
     // Blocks with a previous continuation always have a next continuation
         return downcast<RenderInline>(renderer.node()->renderer());
 
     // Blocks with a previous continuation always have a next continuation
-    if (is<RenderBlock>(renderer) && downcast<RenderBlock>(renderer).inlineElementContinuation())
-        return downcast<RenderInline>(downcast<RenderBlock>(renderer).inlineElementContinuation()->element()->renderer());
+    if (is<RenderBlock>(renderElement) && downcast<RenderBlock>(renderElement).inlineElementContinuation())
+        return downcast<RenderInline>(downcast<RenderBlock>(renderElement).inlineElementContinuation()->element()->renderer());
 
     return nullptr;
 }
 
     return nullptr;
 }
@@ -312,7 +310,7 @@ static inline RenderObject* childBeforeConsideringContinuations(RenderInline* re
 static inline bool firstChildIsInlineContinuation(RenderElement& renderer)
 {
     RenderObject* child = renderer.firstChild();
 static inline bool firstChildIsInlineContinuation(RenderElement& renderer)
 {
     RenderObject* child = renderer.firstChild();
-    return child && child->isInlineElementContinuation();
+    return is<RenderElement>(child) && downcast<RenderElement>(*child).isInlineElementContinuation();
 }
 
 AccessibilityObject* AccessibilityRenderObject::previousSibling() const
 }
 
 AccessibilityObject* AccessibilityRenderObject::previousSibling() const
@@ -326,7 +324,7 @@ AccessibilityObject* AccessibilityRenderObject::previousSibling() const
     // last child is our previous sibling (or further back in the continuation chain)
     RenderInline* startOfConts;
     if (is<RenderBox>(*m_renderer) && (startOfConts = startOfContinuations(*m_renderer)))
     // last child is our previous sibling (or further back in the continuation chain)
     RenderInline* startOfConts;
     if (is<RenderBox>(*m_renderer) && (startOfConts = startOfContinuations(*m_renderer)))
-        previousSibling = childBeforeConsideringContinuations(startOfConts, m_renderer);
+        previousSibling = childBeforeConsideringContinuations(startOfConts, renderer());
 
     // Case 2: Anonymous block parent of the end of a continuation - skip all the way to before
     // the parent of the start, since everything in between will be linked up via the continuation.
 
     // Case 2: Anonymous block parent of the end of a continuation - skip all the way to before
     // the parent of the start, since everything in between will be linked up via the continuation.
@@ -415,7 +413,12 @@ AccessibilityObject* AccessibilityRenderObject::nextSibling() const
     if (!nextSibling)
         return nullptr;
     
     if (!nextSibling)
         return nullptr;
     
-    return axObjectCache()->getOrCreate(nextSibling);
+    // Make sure next sibling has the same parent.
+    AccessibilityObject* nextObj = axObjectCache()->getOrCreate(nextSibling);
+    if (nextObj && nextObj->parentObject() != this->parentObject())
+        return nullptr;
+    
+    return nextObj;
 }
 
 static RenderBoxModelObject* nextContinuation(RenderObject& renderer)
 }
 
 static RenderBoxModelObject* nextContinuation(RenderObject& renderer)
@@ -488,11 +491,11 @@ AccessibilityObject* AccessibilityRenderObject::parentObject() const
     if (!m_renderer)
         return nullptr;
     
     if (!m_renderer)
         return nullptr;
     
-    if (ariaRoleAttribute() == MenuBarRole)
+    if (ariaRoleAttribute() == AccessibilityRole::MenuBar)
         return axObjectCache()->getOrCreate(m_renderer->parent());
 
     // menuButton and its corresponding menu are DOM siblings, but Accessibility needs them to be parent/child
         return axObjectCache()->getOrCreate(m_renderer->parent());
 
     // menuButton and its corresponding menu are DOM siblings, but Accessibility needs them to be parent/child
-    if (ariaRoleAttribute() == MenuRole) {
+    if (ariaRoleAttribute() == AccessibilityRole::Menu) {
         AccessibilityObject* parent = menuButtonForMenu();
         if (parent)
             return parent;
         AccessibilityObject* parent = menuButtonForMenu();
         if (parent)
             return parent;
@@ -521,7 +524,7 @@ bool AccessibilityRenderObject::isAttachment() const
     // Widgets are the replaced elements that we represent to AX as attachments
     bool isWidget = renderer->isWidget();
 
     // Widgets are the replaced elements that we represent to AX as attachments
     bool isWidget = renderer->isWidget();
 
-    return isWidget && ariaRoleAttribute() == UnknownRole;
+    return isWidget && ariaRoleAttribute() == AccessibilityRole::Unknown;
 }
 
 bool AccessibilityRenderObject::isFileUploadButton() const
 }
 
 bool AccessibilityRenderObject::isFileUploadButton() const
@@ -536,7 +539,9 @@ bool AccessibilityRenderObject::isFileUploadButton() const
 
 bool AccessibilityRenderObject::isOffScreen() const
 {
 
 bool AccessibilityRenderObject::isOffScreen() const
 {
-    ASSERT(m_renderer);
+    if (!m_renderer)
+        return true;
+
     IntRect contentRect = snappedIntRect(m_renderer->absoluteClippedOverflowRect());
     // FIXME: unclear if we need LegacyIOSDocumentVisibleRect.
     IntRect viewRect = m_renderer->view().frameView().visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect);
     IntRect contentRect = snappedIntRect(m_renderer->absoluteClippedOverflowRect());
     // FIXME: unclear if we need LegacyIOSDocumentVisibleRect.
     IntRect viewRect = m_renderer->view().frameView().visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect);
@@ -556,7 +561,7 @@ Element* AccessibilityRenderObject::anchorElement() const
     RenderObject* currentRenderer;
     
     // Search up the render tree for a RenderObject with a DOM node.  Defer to an earlier continuation, though.
     RenderObject* currentRenderer;
     
     // Search up the render tree for a RenderObject with a DOM node.  Defer to an earlier continuation, though.
-    for (currentRenderer = m_renderer; currentRenderer && !currentRenderer->node(); currentRenderer = currentRenderer->parent()) {
+    for (currentRenderer = renderer(); currentRenderer && !currentRenderer->node(); currentRenderer = currentRenderer->parent()) {
         if (currentRenderer->isAnonymousBlock()) {
             if (RenderObject* continuation = downcast<RenderBlock>(*currentRenderer).continuation())
                 return cache->getOrCreate(continuation)->anchorElement();
         if (currentRenderer->isAnonymousBlock()) {
             if (RenderObject* continuation = downcast<RenderBlock>(*currentRenderer).continuation())
                 return cache->getOrCreate(continuation)->anchorElement();
@@ -591,7 +596,7 @@ String AccessibilityRenderObject::helpText() const
         return describedBy;
     
     String description = accessibilityDescription();
         return describedBy;
     
     String description = accessibilityDescription();
-    for (RenderObject* ancestor = m_renderer; ancestor; ancestor = ancestor->parent()) {
+    for (RenderObject* ancestor = renderer(); ancestor; ancestor = ancestor->parent()) {
         if (is<HTMLElement>(ancestor->node())) {
             HTMLElement& element = downcast<HTMLElement>(*ancestor->node());
             const AtomicString& summary = element.getAttribute(summaryAttr);
         if (is<HTMLElement>(ancestor->node())) {
             HTMLElement& element = downcast<HTMLElement>(*ancestor->node());
             const AtomicString& summary = element.getAttribute(summaryAttr);
@@ -606,10 +611,8 @@ String AccessibilityRenderObject::helpText() const
         
         // Only take help text from an ancestor element if its a group or an unknown role. If help was 
         // added to those kinds of elements, it is likely it was meant for a child element.
         
         // Only take help text from an ancestor element if its a group or an unknown role. If help was 
         // added to those kinds of elements, it is likely it was meant for a child element.
-        AccessibilityObject* axObj = axObjectCache()->getOrCreate(ancestor);
-        if (axObj) {
-            AccessibilityRole role = axObj->roleValue();
-            if (role != GroupRole && role != UnknownRole)
+        if (AccessibilityObject* axObj = axObjectCache()->getOrCreate(ancestor)) {
+            if (!axObj->isGroup() && axObj->roleValue() != AccessibilityRole::Unknown)
                 break;
         }
     }
                 break;
         }
     }
@@ -629,15 +632,12 @@ String AccessibilityRenderObject::textUnderElement(AccessibilityTextUnderElement
     if (m_renderer->isBR())
         return ASCIILiteral("\n");
 
     if (m_renderer->isBR())
         return ASCIILiteral("\n");
 
-    bool isRenderText = is<RenderText>(*m_renderer);
-
     if (shouldGetTextFromNode(mode))
         return AccessibilityNodeObject::textUnderElement(mode);
 
     // We use a text iterator for text objects AND for those cases where we are
     // explicitly asking for the full text under a given element.
     if (shouldGetTextFromNode(mode))
         return AccessibilityNodeObject::textUnderElement(mode);
 
     // We use a text iterator for text objects AND for those cases where we are
     // explicitly asking for the full text under a given element.
-    bool shouldIncludeAllChildren = mode.childrenInclusion == AccessibilityTextUnderElementMode::TextUnderElementModeIncludeAllChildren;
-    if (isRenderText || shouldIncludeAllChildren) {
+    if (is<RenderText>(*m_renderer) || mode.childrenInclusion == AccessibilityTextUnderElementMode::TextUnderElementModeIncludeAllChildren) {
         // If possible, use a text iterator to get the text, so that whitespace
         // is handled consistently.
         Document* nodeDocument = nullptr;
         // If possible, use a text iterator to get the text, so that whitespace
         // is handled consistently.
         Document* nodeDocument = nullptr;
@@ -671,11 +671,10 @@ String AccessibilityRenderObject::textUnderElement(AccessibilityTextUnderElement
                 if (frame->document() != nodeDocument)
                     return String();
 
                 if (frame->document() != nodeDocument)
                     return String();
 
-                // The tree should be stable before looking through the children of a non-Render Text object.
-                // Otherwise, further uses of TextIterator will force a layout update, potentially altering
-                // the accessibility tree and causing crashes in the loop that computes the result text.
-                ASSERT((isRenderText || !shouldIncludeAllChildren) || (!nodeDocument->renderView()->layoutState() && !nodeDocument->childNeedsStyleRecalc()));
-
+                // Renders referenced by accessibility objects could get destroyed, if TextIterator ends up triggering
+                // style update/layout here. See also AXObjectCache::deferTextChangedIfNeeded().
+                ASSERT_WITH_SECURITY_IMPLICATION(!nodeDocument->childNeedsStyleRecalc());
+                ASSERT_WITH_SECURITY_IMPLICATION(!nodeDocument->view()->layoutContext().isInRenderTreeLayout());
                 return plainText(textRange.get(), textIteratorBehaviorForTextRange());
             }
         }
                 return plainText(textRange.get(), textIteratorBehaviorForTextRange());
             }
         }
@@ -744,7 +743,7 @@ String AccessibilityRenderObject::stringValue() const
 
     RenderBoxModelObject* cssBox = renderBoxModelObject();
 
 
     RenderBoxModelObject* cssBox = renderBoxModelObject();
 
-    if (ariaRoleAttribute() == StaticTextRole) {
+    if (ariaRoleAttribute() == AccessibilityRole::StaticText) {
         String staticText = text();
         if (!staticText.length())
             staticText = textUnderElement();
         String staticText = text();
         if (!staticText.length())
             staticText = textUnderElement();
@@ -777,6 +776,11 @@ String AccessibilityRenderObject::stringValue() const
     if (isTextControl())
         return text();
     
     if (isTextControl())
         return text();
     
+#if PLATFORM(IOS)
+    if (isInputTypePopupButton())
+        return textUnderElement();
+#endif
+    
     if (is<RenderFileUploadControl>(*m_renderer))
         return downcast<RenderFileUploadControl>(*m_renderer).fileTextValue();
     
     if (is<RenderFileUploadControl>(*m_renderer))
         return downcast<RenderFileUploadControl>(*m_renderer).fileTextValue();
     
@@ -819,7 +823,7 @@ void AccessibilityRenderObject::offsetBoundingBoxForRemoteSVGElement(LayoutRect&
     
 LayoutRect AccessibilityRenderObject::boundingBoxRect() const
 {
     
 LayoutRect AccessibilityRenderObject::boundingBoxRect() const
 {
-    RenderObject* obj = m_renderer;
+    RenderObject* obj = renderer();
     
     if (!obj)
         return LayoutRect();
     
     if (!obj)
         return LayoutRect();
@@ -881,12 +885,12 @@ LayoutRect AccessibilityRenderObject::elementRect() const
     
 bool AccessibilityRenderObject::supportsPath() const
 {
     
 bool AccessibilityRenderObject::supportsPath() const
 {
-    return is<RenderSVGShape>(m_renderer);
+    return is<RenderSVGShape>(renderer());
 }
 
 Path AccessibilityRenderObject::elementPath() const
 {
 }
 
 Path AccessibilityRenderObject::elementPath() const
 {
-    if (is<RenderSVGShape>(m_renderer) && downcast<RenderSVGShape>(*m_renderer).hasPath()) {
+    if (is<RenderSVGShape>(renderer()) && downcast<RenderSVGShape>(*m_renderer).hasPath()) {
         Path path = downcast<RenderSVGShape>(*m_renderer).path();
         
         // The SVG path is in terms of the parent's bounding box. The path needs to be offset to frame coordinates.
         Path path = downcast<RenderSVGShape>(*m_renderer).path();
         
         // The SVG path is in terms of the parent's bounding box. The path needs to be offset to frame coordinates.
@@ -957,7 +961,7 @@ ESpeak AccessibilityRenderObject::speakProperty() const
 void AccessibilityRenderObject::addRadioButtonGroupChildren(AccessibilityObject* parent, AccessibilityChildrenVector& linkedUIElements) const
 {
     for (const auto& child : parent->children()) {
 void AccessibilityRenderObject::addRadioButtonGroupChildren(AccessibilityObject* parent, AccessibilityChildrenVector& linkedUIElements) const
 {
     for (const auto& child : parent->children()) {
-        if (child->roleValue() == RadioButtonRole)
+        if (child->roleValue() == AccessibilityRole::RadioButton)
             linkedUIElements.append(child);
         else
             addRadioButtonGroupChildren(child.get(), linkedUIElements);
             linkedUIElements.append(child);
         else
             addRadioButtonGroupChildren(child.get(), linkedUIElements);
@@ -966,7 +970,7 @@ void AccessibilityRenderObject::addRadioButtonGroupChildren(AccessibilityObject*
     
 void AccessibilityRenderObject::addRadioButtonGroupMembers(AccessibilityChildrenVector& linkedUIElements) const
 {
     
 void AccessibilityRenderObject::addRadioButtonGroupMembers(AccessibilityChildrenVector& linkedUIElements) const
 {
-    if (roleValue() != RadioButtonRole)
+    if (roleValue() != AccessibilityRole::RadioButton)
         return;
     
     Node* node = this->node();
         return;
     
     Node* node = this->node();
@@ -979,7 +983,7 @@ void AccessibilityRenderObject::addRadioButtonGroupMembers(AccessibilityChildren
     } else {
         // If we didn't find any radio button siblings with the traditional naming, lets search for a radio group role and find its children.
         for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) {
     } else {
         // If we didn't find any radio button siblings with the traditional naming, lets search for a radio group role and find its children.
         for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) {
-            if (parent->roleValue() == RadioGroupRole)
+            if (parent->roleValue() == AccessibilityRole::RadioGroup)
                 addRadioButtonGroupChildren(parent, linkedUIElements);
         }
     }
                 addRadioButtonGroupChildren(parent, linkedUIElements);
         }
     }
@@ -997,7 +1001,7 @@ void AccessibilityRenderObject::linkedUIElements(AccessibilityChildrenVector& li
             linkedUIElements.append(linkedAXElement);
     }
 
             linkedUIElements.append(linkedAXElement);
     }
 
-    if (roleValue() == RadioButtonRole)
+    if (roleValue() == AccessibilityRole::RadioButton)
         addRadioButtonGroupMembers(linkedUIElements);
 }
 
         addRadioButtonGroupMembers(linkedUIElements);
 }
 
@@ -1010,7 +1014,7 @@ bool AccessibilityRenderObject::hasTextAlternative() const
     
 bool AccessibilityRenderObject::ariaHasPopup() const
 {
     
 bool AccessibilityRenderObject::ariaHasPopup() const
 {
-    return elementAttributeValue(aria_haspopupAttr);
+    return !equalLettersIgnoringASCIICase(ariaPopupValue(), "false");
 }
 
 bool AccessibilityRenderObject::supportsARIADropping() const 
 }
 
 bool AccessibilityRenderObject::supportsARIADropping() const 
@@ -1045,7 +1049,7 @@ void AccessibilityRenderObject::determineARIADropEffects(Vector<String>& effects
     
 bool AccessibilityRenderObject::exposesTitleUIElement() const
 {
     
 bool AccessibilityRenderObject::exposesTitleUIElement() const
 {
-    if (!isControl() && !isFigure())
+    if (!isControl() && !isFigureElement())
         return false;
 
     // If this control is ignored (because it's invisible), 
         return false;
 
     // If this control is ignored (because it's invisible), 
@@ -1080,9 +1084,9 @@ AccessibilityObject* AccessibilityRenderObject::titleUIElement() const
     
     // if isFieldset is true, the renderer is guaranteed to be a RenderFieldset
     if (isFieldset())
     
     // if isFieldset is true, the renderer is guaranteed to be a RenderFieldset
     if (isFieldset())
-        return axObjectCache()->getOrCreate(downcast<RenderFieldset>(*m_renderer).findLegend(RenderFieldset::IncludeFloatingOrOutOfFlow));
+        return axObjectCache()->getOrCreate(downcast<RenderBlock>(*m_renderer).findFieldsetLegend(RenderBlock::FieldsetIncludeFloatingOrOutOfFlow));
     
     
-    if (isFigure())
+    if (isFigureElement())
         return captionForFigure();
     
     Node* node = m_renderer->node();
         return captionForFigure();
     
     Node* node = m_renderer->node();
@@ -1102,7 +1106,7 @@ bool AccessibilityRenderObject::isAllowedChildOfTree() const
     bool isInTree = false;
     bool isTreeItemDescendant = false;
     while (axObj) {
     bool isInTree = false;
     bool isTreeItemDescendant = false;
     while (axObj) {
-        if (axObj->roleValue() == TreeItemRole)
+        if (axObj->roleValue() == AccessibilityRole::TreeItem)
             isTreeItemDescendant = true;
         if (axObj->isTree()) {
             isInTree = true;
             isTreeItemDescendant = true;
         if (axObj->isTree()) {
             isInTree = true;
@@ -1114,7 +1118,7 @@ bool AccessibilityRenderObject::isAllowedChildOfTree() const
     // If the object is in a tree, only tree items should be exposed (and the children of tree items).
     if (isInTree) {
         AccessibilityRole role = roleValue();
     // If the object is in a tree, only tree items should be exposed (and the children of tree items).
     if (isInTree) {
         AccessibilityRole role = roleValue();
-        if (role != TreeItemRole && role != StaticTextRole && !isTreeItemDescendant)
+        if (role != AccessibilityRole::TreeItem && role != AccessibilityRole::StaticText && !isTreeItemDescendant)
             return false;
     }
     return true;
             return false;
     }
     return true;
@@ -1124,13 +1128,13 @@ static AccessibilityObjectInclusion objectInclusionFromAltText(const String& alt
 {
     // Don't ignore an image that has an alt tag.
     if (!altText.containsOnlyWhitespace())
 {
     // Don't ignore an image that has an alt tag.
     if (!altText.containsOnlyWhitespace())
-        return IncludeObject;
+        return AccessibilityObjectInclusion::IncludeObject;
     
     // The informal standard is to ignore images with zero-length alt strings.
     if (!altText.isNull())
     
     // The informal standard is to ignore images with zero-length alt strings.
     if (!altText.isNull())
-        return IgnoreObject;
+        return AccessibilityObjectInclusion::IgnoreObject;
     
     
-    return DefaultBehavior;
+    return AccessibilityObjectInclusion::DefaultBehavior;
 }
 
 AccessibilityObjectInclusion AccessibilityRenderObject::defaultObjectInclusion() const
 }
 
 AccessibilityObjectInclusion AccessibilityRenderObject::defaultObjectInclusion() const
@@ -1138,19 +1142,30 @@ AccessibilityObjectInclusion AccessibilityRenderObject::defaultObjectInclusion()
     // The following cases can apply to any element that's a subclass of AccessibilityRenderObject.
     
     if (!m_renderer)
     // The following cases can apply to any element that's a subclass of AccessibilityRenderObject.
     
     if (!m_renderer)
-        return IgnoreObject;
+        return AccessibilityObjectInclusion::IgnoreObject;
 
     if (m_renderer->style().visibility() != VISIBLE) {
         // aria-hidden is meant to override visibility as the determinant in AX hierarchy inclusion.
         if (equalLettersIgnoringASCIICase(getAttribute(aria_hiddenAttr), "false"))
 
     if (m_renderer->style().visibility() != VISIBLE) {
         // aria-hidden is meant to override visibility as the determinant in AX hierarchy inclusion.
         if (equalLettersIgnoringASCIICase(getAttribute(aria_hiddenAttr), "false"))
-            return DefaultBehavior;
+            return AccessibilityObjectInclusion::DefaultBehavior;
         
         
-        return IgnoreObject;
+        return AccessibilityObjectInclusion::IgnoreObject;
     }
 
     return AccessibilityObject::defaultObjectInclusion();
 }
     }
 
     return AccessibilityObject::defaultObjectInclusion();
 }
-
+    
+static bool webAreaIsPresentational(RenderObject* renderer)
+{
+    if (!is<RenderView>(*renderer))
+        return false;
+    
+    if (auto ownerElement = renderer->document().ownerElement())
+        return nodeHasPresentationRole(ownerElement);
+    
+    return false;
+}
+    
 bool AccessibilityRenderObject::computeAccessibilityIsIgnored() const
 {
 #ifndef NDEBUG
 bool AccessibilityRenderObject::computeAccessibilityIsIgnored() const
 {
 #ifndef NDEBUG
@@ -1164,21 +1179,25 @@ bool AccessibilityRenderObject::computeAccessibilityIsIgnored() const
     // Then process other use cases that need to be applied to all the various roles
     // that AccessibilityRenderObjects take on.
     AccessibilityObjectInclusion decision = defaultObjectInclusion();
     // Then process other use cases that need to be applied to all the various roles
     // that AccessibilityRenderObjects take on.
     AccessibilityObjectInclusion decision = defaultObjectInclusion();
-    if (decision == IncludeObject)
+    if (decision == AccessibilityObjectInclusion::IncludeObject)
         return false;
         return false;
-    if (decision == IgnoreObject)
+    if (decision == AccessibilityObjectInclusion::IgnoreObject)
         return true;
     
     // If this element is within a parent that cannot have children, it should not be exposed.
     if (isDescendantOfBarrenParent())
         return true;    
     
         return true;
     
     // If this element is within a parent that cannot have children, it should not be exposed.
     if (isDescendantOfBarrenParent())
         return true;    
     
-    if (roleValue() == IgnoredRole)
+    if (roleValue() == AccessibilityRole::Ignored)
         return true;
     
         return true;
     
-    if (roleValue() == PresentationalRole || inheritsPresentationalRole())
+    if (roleValue() == AccessibilityRole::Presentational || inheritsPresentationalRole())
         return true;
     
         return true;
     
+    // WebAreas should be ignored if their iframe container is marked as presentational.
+    if (webAreaIsPresentational(renderer()))
+        return true;
+
     // An ARIA tree can only have tree items and static text as children.
     if (!isAllowedChildOfTree())
         return true;
     // An ARIA tree can only have tree items and static text as children.
     if (!isAllowedChildOfTree())
         return true;
@@ -1207,7 +1226,7 @@ bool AccessibilityRenderObject::computeAccessibilityIsIgnored() const
     if (is<RenderText>(*m_renderer)) {
         // static text beneath MenuItems and MenuButtons are just reported along with the menu item, so it's ignored on an individual level
         AccessibilityObject* parent = parentObjectUnignored();
     if (is<RenderText>(*m_renderer)) {
         // static text beneath MenuItems and MenuButtons are just reported along with the menu item, so it's ignored on an individual level
         AccessibilityObject* parent = parentObjectUnignored();
-        if (parent && (parent->isMenuItem() || parent->ariaRoleAttribute() == MenuButtonRole))
+        if (parent && (parent->isMenuItem() || parent->ariaRoleAttribute() == AccessibilityRole::MenuButton))
             return true;
         auto& renderText = downcast<RenderText>(*m_renderer);
         if (!renderText.hasRenderedText())
             return true;
         auto& renderText = downcast<RenderText>(*m_renderer);
         if (!renderText.hasRenderedText())
@@ -1215,7 +1234,7 @@ bool AccessibilityRenderObject::computeAccessibilityIsIgnored() const
 
         // static text beneath TextControls is reported along with the text control text so it's ignored.
         for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) { 
 
         // static text beneath TextControls is reported along with the text control text so it's ignored.
         for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) { 
-            if (parent->roleValue() == TextFieldRole)
+            if (parent->roleValue() == AccessibilityRole::TextField)
                 return true;
         }
         
                 return true;
         }
         
@@ -1226,10 +1245,12 @@ bool AccessibilityRenderObject::computeAccessibilityIsIgnored() const
         // The alt attribute may be set on a text fragment through CSS, which should be honored.
         if (is<RenderTextFragment>(renderText)) {
             AccessibilityObjectInclusion altTextInclusion = objectInclusionFromAltText(downcast<RenderTextFragment>(renderText).altText());
         // The alt attribute may be set on a text fragment through CSS, which should be honored.
         if (is<RenderTextFragment>(renderText)) {
             AccessibilityObjectInclusion altTextInclusion = objectInclusionFromAltText(downcast<RenderTextFragment>(renderText).altText());
-            if (altTextInclusion == IgnoreObject)
+            if (altTextInclusion == AccessibilityObjectInclusion::IgnoreObject)
                 return true;
                 return true;
-            if (altTextInclusion == IncludeObject)
+            if (altTextInclusion == AccessibilityObjectInclusion::IncludeObject)
                 return false;
                 return false;
+            if (downcast<RenderTextFragment>(renderText).firstLetter())
+                return true;
         }
 
         // text elements that are just empty whitespace should not be returned
         }
 
         // text elements that are just empty whitespace should not be returned
@@ -1249,27 +1270,28 @@ bool AccessibilityRenderObject::computeAccessibilityIsIgnored() const
     if (isControl())
         return false;
     
     if (isControl())
         return false;
     
-    if (isFigure())
+    if (isFigureElement())
         return false;
 
     switch (roleValue()) {
         return false;
 
     switch (roleValue()) {
-    case AudioRole:
-    case DescriptionListTermRole:
-    case DescriptionListDetailRole:
-    case DetailsRole:
-    case DocumentArticleRole:
-    case LandmarkRegionRole:
-    case ListItemRole:
-    case VideoRole:
+    case AccessibilityRole::Audio:
+    case AccessibilityRole::DescriptionListTerm:
+    case AccessibilityRole::DescriptionListDetail:
+    case AccessibilityRole::Details:
+    case AccessibilityRole::DocumentArticle:
+    case AccessibilityRole::LandmarkRegion:
+    case AccessibilityRole::ListItem:
+    case AccessibilityRole::Time:
+    case AccessibilityRole::Video:
         return false;
     default:
         break;
     }
     
         return false;
     default:
         break;
     }
     
-    if (ariaRoleAttribute() != UnknownRole)
+    if (ariaRoleAttribute() != AccessibilityRole::Unknown)
         return false;
     
         return false;
     
-    if (roleValue() == HorizontalRuleRole)
+    if (roleValue() == AccessibilityRole::HorizontalRule)
         return false;
     
     // don't ignore labels, because they serve as TitleUIElements
         return false;
     
     // don't ignore labels, because they serve as TitleUIElements
@@ -1309,16 +1331,16 @@ bool AccessibilityRenderObject::computeAccessibilityIsIgnored() const
         
         // First check the RenderImage's altText (which can be set through a style sheet, or come from the Element).
         // However, if this is not a native image, fallback to the attribute on the Element.
         
         // First check the RenderImage's altText (which can be set through a style sheet, or come from the Element).
         // However, if this is not a native image, fallback to the attribute on the Element.
-        AccessibilityObjectInclusion altTextInclusion = DefaultBehavior;
-        bool isRenderImage = is<RenderImage>(m_renderer);
+        AccessibilityObjectInclusion altTextInclusion = AccessibilityObjectInclusion::DefaultBehavior;
+        bool isRenderImage = is<RenderImage>(renderer());
         if (isRenderImage)
             altTextInclusion = objectInclusionFromAltText(downcast<RenderImage>(*m_renderer).altText());
         else
             altTextInclusion = objectInclusionFromAltText(getAttribute(altAttr).string());
 
         if (isRenderImage)
             altTextInclusion = objectInclusionFromAltText(downcast<RenderImage>(*m_renderer).altText());
         else
             altTextInclusion = objectInclusionFromAltText(getAttribute(altAttr).string());
 
-        if (altTextInclusion == IgnoreObject)
+        if (altTextInclusion == AccessibilityObjectInclusion::IgnoreObject)
             return true;
             return true;
-        if (altTextInclusion == IncludeObject)
+        if (altTextInclusion == AccessibilityObjectInclusion::IncludeObject)
             return false;
         
         // If an image has a title attribute on it, accessibility should be lenient and allow it to appear in the hierarchy (according to WAI-ARIA).
             return false;
         
         // If an image has a title attribute on it, accessibility should be lenient and allow it to appear in the hierarchy (according to WAI-ARIA).
@@ -1381,7 +1403,7 @@ bool AccessibilityRenderObject::computeAccessibilityIsIgnored() const
 
     // <span> tags are inline tags and not meant to convey information if they have no other aria
     // information on them. If we don't ignore them, they may emit signals expected to come from
 
     // <span> tags are inline tags and not meant to convey information if they have no other aria
     // information on them. If we don't ignore them, they may emit signals expected to come from
-    // their parent. In addition, because included spans are GroupRole objects, and GroupRole
+    // their parent. In addition, because included spans are AccessibilityRole::Group objects, and AccessibilityRole::Group
     // objects are often containers with meaningful information, the inclusion of a span can have
     // the side effect of causing the immediate parent accessible to be ignored. This is especially
     // problematic for platforms which have distinct roles for textual block elements.
     // objects are often containers with meaningful information, the inclusion of a span can have
     // the side effect of causing the immediate parent accessible to be ignored. This is especially
     // problematic for platforms which have distinct roles for textual block elements.
@@ -1417,18 +1439,14 @@ double AccessibilityRenderObject::estimatedLoadingProgress() const
     if (isLoaded())
         return 1.0;
     
     if (isLoaded())
         return 1.0;
     
-    Page* page = m_renderer->document().page();
-    if (!page)
-        return 0;
-    
-    return page->progress().estimatedProgress();
+    return m_renderer->page().progress().estimatedProgress();
 }
     
 int AccessibilityRenderObject::layoutCount() const
 {
     if (!is<RenderView>(*m_renderer))
         return 0;
 }
     
 int AccessibilityRenderObject::layoutCount() const
 {
     if (!is<RenderView>(*m_renderer))
         return 0;
-    return downcast<RenderView>(*m_renderer).frameView().layoutCount();
+    return downcast<RenderView>(*m_renderer).frameView().layoutContext().layoutCount();
 }
 
 String AccessibilityRenderObject::text() const
 }
 
 String AccessibilityRenderObject::text() const
@@ -1454,15 +1472,22 @@ PlainTextRange AccessibilityRenderObject::documentBasedSelectedTextRange() const
     Node* node = m_renderer->node();
     if (!node)
         return PlainTextRange();
     Node* node = m_renderer->node();
     if (!node)
         return PlainTextRange();
-    
+
     VisibleSelection visibleSelection = selection();
     RefPtr<Range> currentSelectionRange = visibleSelection.toNormalizedRange();
     VisibleSelection visibleSelection = selection();
     RefPtr<Range> currentSelectionRange = visibleSelection.toNormalizedRange();
-    if (!currentSelectionRange || !currentSelectionRange->intersectsNode(*node, IGNORE_EXCEPTION))
+    if (!currentSelectionRange)
         return PlainTextRange();
         return PlainTextRange();
-    
+    // FIXME: The reason this does the correct thing when the selection is in the
+    // shadow tree of an input element is that we get an exception below, and we
+    // choose to interpret all exceptions as "does not intersect". Seems likely
+    // that does not handle all cases correctly.
+    auto intersectsResult = currentSelectionRange->intersectsNode(*node);
+    if (!intersectsResult.hasException() && !intersectsResult.releaseReturnValue())
+        return PlainTextRange();
+
     int start = indexForVisiblePosition(visibleSelection.start());
     int end = indexForVisiblePosition(visibleSelection.end());
     int start = indexForVisiblePosition(visibleSelection.start());
     int end = indexForVisiblePosition(visibleSelection.end());
-    
+
     return PlainTextRange(start, end - start);
 }
 
     return PlainTextRange(start, end - start);
 }
 
@@ -1485,7 +1510,7 @@ const AtomicString& AccessibilityRenderObject::accessKey() const
 {
     Node* node = m_renderer->node();
     if (!is<Element>(node))
 {
     Node* node = m_renderer->node();
     if (!is<Element>(node))
-        return nullAtom;
+        return nullAtom();
     return downcast<Element>(*node).getAttribute(accesskeyAttr);
 }
 
     return downcast<Element>(*node).getAttribute(accesskeyAttr);
 }
 
@@ -1503,7 +1528,7 @@ PlainTextRange AccessibilityRenderObject::selectedTextRange() const
     
     AccessibilityRole ariaRole = ariaRoleAttribute();
     // Use the text control native range if it's a native object and it has no ARIA role (or has a text based ARIA role).
     
     AccessibilityRole ariaRole = ariaRoleAttribute();
     // Use the text control native range if it's a native object and it has no ARIA role (or has a text based ARIA role).
-    if (isNativeTextControl() && (ariaRole == UnknownRole || isARIATextControl())) {
+    if (isNativeTextControl() && (ariaRole == AccessibilityRole::Unknown || isARIATextControl())) {
         HTMLTextFormControlElement& textControl = downcast<RenderTextControl>(*m_renderer).textFormControlElement();
         return PlainTextRange(textControl.selectionStart(), textControl.selectionEnd() - textControl.selectionStart());
     }
         HTMLTextFormControlElement& textControl = downcast<RenderTextControl>(*m_renderer).textFormControlElement();
         return PlainTextRange(textControl.selectionStart(), textControl.selectionEnd() - textControl.selectionStart());
     }
@@ -1566,12 +1591,18 @@ URL AccessibilityRenderObject::url() const
 
 bool AccessibilityRenderObject::isUnvisited() const
 {
 
 bool AccessibilityRenderObject::isUnvisited() const
 {
+    if (!m_renderer)
+        return true;
+
     // FIXME: Is it a privacy violation to expose unvisited information to accessibility APIs?
     return m_renderer->style().isLink() && m_renderer->style().insideLink() == InsideUnvisitedLink;
 }
 
 bool AccessibilityRenderObject::isVisited() const
 {
     // FIXME: Is it a privacy violation to expose unvisited information to accessibility APIs?
     return m_renderer->style().isLink() && m_renderer->style().insideLink() == InsideUnvisitedLink;
 }
 
 bool AccessibilityRenderObject::isVisited() const
 {
+    if (!m_renderer)
+        return false;
+
     // FIXME: Is it a privacy violation to expose visited information to accessibility APIs?
     return m_renderer->style().isLink() && m_renderer->style().insideLink() == InsideVisitedLink;
 }
     // FIXME: Is it a privacy violation to expose visited information to accessibility APIs?
     return m_renderer->style().isLink() && m_renderer->style().insideLink() == InsideVisitedLink;
 }
@@ -1610,6 +1641,10 @@ bool AccessibilityRenderObject::isSelected() const
     if (isTabItem() && isTabItemSelected())
         return true;
 
     if (isTabItem() && isTabItemSelected())
         return true;
 
+    // Menu items are considered selectable by assistive technologies
+    if (isMenuItem())
+        return isFocused() || parentObjectUnignored()->activeDescendant() == this;
+
     return false;
 }
 
     return false;
 }
 
@@ -1640,7 +1675,7 @@ bool AccessibilityRenderObject::isTabItemSelected() const
         AccessibilityObject* tabPanel = cache->getOrCreate(element);
 
         // A tab item should only control tab panels.
         AccessibilityObject* tabPanel = cache->getOrCreate(element);
 
         // A tab item should only control tab panels.
-        if (!tabPanel || tabPanel->roleValue() != TabPanelRole)
+        if (!tabPanel || tabPanel->roleValue() != AccessibilityRole::TabPanel)
             continue;
         
         AccessibilityObject* checkFocusElement = focusedElement;
             continue;
         
         AccessibilityObject* checkFocusElement = focusedElement;
@@ -1669,7 +1704,7 @@ bool AccessibilityRenderObject::isFocused() const
     // A web area is represented by the Document node in the DOM tree, which isn't focusable.
     // Check instead if the frame's selection controller is focused
     if (focusedElement == m_renderer->node()
     // A web area is represented by the Document node in the DOM tree, which isn't focusable.
     // Check instead if the frame's selection controller is focused
     if (focusedElement == m_renderer->node()
-        || (roleValue() == WebAreaRole && document.frame()->selection().isFocusedAndActive()))
+        || (roleValue() == AccessibilityRole::WebArea && document.frame()->selection().isFocusedAndActive()))
         return true;
     
     return false;
         return true;
     
     return false;
@@ -1711,7 +1746,7 @@ void AccessibilityRenderObject::setSelectedRows(AccessibilityChildrenVector& sel
 {
     // Setting selected only makes sense in trees and tables (and tree-tables).
     AccessibilityRole role = roleValue();
 {
     // Setting selected only makes sense in trees and tables (and tree-tables).
     AccessibilityRole role = roleValue();
-    if (role != TreeRole && role != TreeGridRole && role != TableRole && role != GridRole)
+    if (role != AccessibilityRole::Tree && role != AccessibilityRole::TreeGrid && role != AccessibilityRole::Table && role != AccessibilityRole::Grid)
         return;
     
     bool isMulti = isMultiSelectable();
         return;
     
     bool isMulti = isMultiSelectable();
@@ -1728,16 +1763,15 @@ void AccessibilityRenderObject::setValue(const String& string)
     if (!m_renderer || !is<Element>(m_renderer->node()))
         return;
     Element& element = downcast<Element>(*m_renderer->node());
     if (!m_renderer || !is<Element>(m_renderer->node()))
         return;
     Element& element = downcast<Element>(*m_renderer->node());
-
-    if (!is<RenderBoxModelObject>(*m_renderer))
-        return;
-    RenderBoxModelObject& renderer = downcast<RenderBoxModelObject>(*m_renderer);
-
+    RenderObject& renderer = *m_renderer;
+    
     // FIXME: Do we want to do anything here for ARIA textboxes?
     if (renderer.isTextField() && is<HTMLInputElement>(element))
         downcast<HTMLInputElement>(element).setValue(string);
     else if (renderer.isTextArea() && is<HTMLTextAreaElement>(element))
         downcast<HTMLTextAreaElement>(element).setValue(string);
     // FIXME: Do we want to do anything here for ARIA textboxes?
     if (renderer.isTextField() && is<HTMLInputElement>(element))
         downcast<HTMLInputElement>(element).setValue(string);
     else if (renderer.isTextArea() && is<HTMLTextAreaElement>(element))
         downcast<HTMLTextAreaElement>(element).setValue(string);
+    else if (is<HTMLElement>(element) && contentEditableAttributeIsEnabled(&element))
+        downcast<HTMLElement>(element).setInnerText(string);
 }
 
 bool AccessibilityRenderObject::supportsARIAOwns() const
 }
 
 bool AccessibilityRenderObject::supportsARIAOwns() const
@@ -1801,7 +1835,7 @@ void AccessibilityRenderObject::getDocumentLinks(AccessibilityChildrenVector& re
         } else {
             auto* parent = current->parentNode();
             if (is<HTMLAreaElement>(*current) && is<HTMLMapElement>(parent)) {
         } else {
             auto* parent = current->parentNode();
             if (is<HTMLAreaElement>(*current) && is<HTMLMapElement>(parent)) {
-                auto& areaObject = downcast<AccessibilityImageMapLink>(*axObjectCache()->getOrCreate(ImageMapLinkRole));
+                auto& areaObject = downcast<AccessibilityImageMapLink>(*axObjectCache()->getOrCreate(AccessibilityRole::ImageMapLink));
                 HTMLMapElement& map = downcast<HTMLMapElement>(*parent);
                 areaObject.setHTMLAreaElement(downcast<HTMLAreaElement>(current));
                 areaObject.setHTMLMapElement(&map);
                 HTMLMapElement& map = downcast<HTMLMapElement>(*parent);
                 areaObject.setHTMLAreaElement(downcast<HTMLAreaElement>(current));
                 areaObject.setHTMLMapElement(&map);
@@ -2163,7 +2197,7 @@ int AccessibilityRenderObject::index(const VisiblePosition& position) const
     if (position.isNull() || !isTextControl())
         return -1;
 
     if (position.isNull() || !isTextControl())
         return -1;
 
-    if (renderObjectContainsPosition(m_renderer, position.deepEquivalent()))
+    if (renderObjectContainsPosition(renderer(), position.deepEquivalent()))
         return indexForVisiblePosition(position);
     
     return -1;
         return indexForVisiblePosition(position);
     
     return -1;
@@ -2361,6 +2395,11 @@ AccessibilityObject* AccessibilityRenderObject::accessibilityHitTest(const IntPo
 
 bool AccessibilityRenderObject::shouldNotifyActiveDescendant() const
 {
 
 bool AccessibilityRenderObject::shouldNotifyActiveDescendant() const
 {
+#if PLATFORM(GTK)
+    // According to the Core AAM spec, ATK expects object:state-changed:focused notifications
+    // whenever the active descendant changes.
+    return true;
+#endif
     // We want to notify that the combo box has changed its active descendant,
     // but we do not want to change the focus, because focus should remain with the combo box.
     if (isComboBox())
     // We want to notify that the combo box has changed its active descendant,
     // but we do not want to change the focus, because focus should remain with the combo box.
     if (isComboBox())
@@ -2372,18 +2411,18 @@ bool AccessibilityRenderObject::shouldNotifyActiveDescendant() const
 bool AccessibilityRenderObject::shouldFocusActiveDescendant() const
 {
     switch (ariaRoleAttribute()) {
 bool AccessibilityRenderObject::shouldFocusActiveDescendant() const
 {
     switch (ariaRoleAttribute()) {
-    case GroupRole:
-    case ListBoxRole:
-    case MenuRole:
-    case MenuBarRole:
-    case RadioGroupRole:
-    case RowRole:
-    case PopUpButtonRole:
-    case ProgressIndicatorRole:
-    case ToolbarRole:
-    case OutlineRole:
-    case TreeRole:
-    case GridRole:
+    case AccessibilityRole::ApplicationGroup:
+    case AccessibilityRole::ListBox:
+    case AccessibilityRole::Menu:
+    case AccessibilityRole::MenuBar:
+    case AccessibilityRole::RadioGroup:
+    case AccessibilityRole::Row:
+    case AccessibilityRole::PopUpButton:
+    case AccessibilityRole::ProgressIndicator:
+    case AccessibilityRole::Toolbar:
+    case AccessibilityRole::Outline:
+    case AccessibilityRole::Tree:
+    case AccessibilityRole::Grid:
     /* FIXME: replace these with actual roles when they are added to AccessibilityRole
     composite
     alert
     /* FIXME: replace these with actual roles when they are added to AccessibilityRole
     composite
     alert
@@ -2426,17 +2465,20 @@ AccessibilityObject* AccessibilityRenderObject::activeDescendant() const
 
 void AccessibilityRenderObject::handleAriaExpandedChanged()
 {
 
 void AccessibilityRenderObject::handleAriaExpandedChanged()
 {
+    // This object might be deleted under the call to the parentObject() method.
+    auto protectedThis = makeRef(*this);
+    
     // Find if a parent of this object should handle aria-expanded changes.
     AccessibilityObject* containerParent = this->parentObject();
     while (containerParent) {
         bool foundParent = false;
         
         switch (containerParent->roleValue()) {
     // Find if a parent of this object should handle aria-expanded changes.
     AccessibilityObject* containerParent = this->parentObject();
     while (containerParent) {
         bool foundParent = false;
         
         switch (containerParent->roleValue()) {
-        case TreeRole:
-        case TreeGridRole:
-        case GridRole:
-        case TableRole:
-        case BrowserRole:
+        case AccessibilityRole::Tree:
+        case AccessibilityRole::TreeGrid:
+        case AccessibilityRole::Grid:
+        case AccessibilityRole::Table:
+        case AccessibilityRole::Browser:
             foundParent = true;
             break;
         default:
             foundParent = true;
             break;
         default:
@@ -2458,7 +2500,7 @@ void AccessibilityRenderObject::handleAriaExpandedChanged()
         cache->postNotification(containerParent, document(), AXObjectCache::AXRowCountChanged);
 
     // Post that the specific row either collapsed or expanded.
         cache->postNotification(containerParent, document(), AXObjectCache::AXRowCountChanged);
 
     // Post that the specific row either collapsed or expanded.
-    if (roleValue() == RowRole || roleValue() == TreeItemRole)
+    if (roleValue() == AccessibilityRole::Row || roleValue() == AccessibilityRole::TreeItem)
         cache->postNotification(this, document(), isExpanded() ? AXObjectCache::AXRowExpanded : AXObjectCache::AXRowCollapsed);
     else
         cache->postNotification(this, document(), AXObjectCache::AXExpandedChanged);
         cache->postNotification(this, document(), isExpanded() ? AXObjectCache::AXRowExpanded : AXObjectCache::AXRowCollapsed);
     else
         cache->postNotification(this, document(), AXObjectCache::AXExpandedChanged);
@@ -2473,7 +2515,7 @@ void AccessibilityRenderObject::handleActiveDescendantChanged()
         return;
 
     if (activeDescendant() && shouldNotifyActiveDescendant())
         return;
 
     if (activeDescendant() && shouldNotifyActiveDescendant())
-        renderer()->document().axObjectCache()->postNotification(m_renderer, AXObjectCache::AXActiveDescendantChanged);
+        renderer()->document().axObjectCache()->postNotification(renderer(), AXObjectCache::AXActiveDescendantChanged);
 }
 
 AccessibilityObject* AccessibilityRenderObject::correspondingControlForLabelElement() const
 }
 
 AccessibilityObject* AccessibilityRenderObject::correspondingControlForLabelElement() const
@@ -2536,7 +2578,7 @@ bool AccessibilityRenderObject::renderObjectIsObservable(RenderObject& renderer)
 AccessibilityObject* AccessibilityRenderObject::observableObject() const
 {
     // Find the object going up the parent chain that is used in accessibility to monitor certain notifications.
 AccessibilityObject* AccessibilityRenderObject::observableObject() const
 {
     // Find the object going up the parent chain that is used in accessibility to monitor certain notifications.
-    for (RenderObject* renderer = m_renderer; renderer && renderer->node(); renderer = renderer->parent()) {
+    for (RenderObject* renderer = this->renderer(); renderer && renderer->node(); renderer = renderer->parent()) {
         if (renderObjectIsObservable(*renderer)) {
             if (AXObjectCache* cache = axObjectCache())
                 return cache->getOrCreate(renderer);
         if (renderObjectIsObservable(*renderer)) {
             if (AXObjectCache* cache = axObjectCache())
                 return cache->getOrCreate(renderer);
@@ -2567,7 +2609,7 @@ String AccessibilityRenderObject::expandedTextValue() const
 
 bool AccessibilityRenderObject::supportsExpandedTextValue() const
 {
 
 bool AccessibilityRenderObject::supportsExpandedTextValue() const
 {
-    if (roleValue() == StaticTextRole) {
+    if (roleValue() == AccessibilityRole::StaticText) {
         if (AccessibilityObject* parent = parentObject())
             return parent->hasTagName(abbrTag) || parent->hasTagName(acronymTag);
     }
         if (AccessibilityObject* parent = parentObject())
             return parent->hasTagName(abbrTag) || parent->hasTagName(acronymTag);
     }
@@ -2578,251 +2620,255 @@ bool AccessibilityRenderObject::supportsExpandedTextValue() const
 AccessibilityRole AccessibilityRenderObject::determineAccessibilityRole()
 {
     if (!m_renderer)
 AccessibilityRole AccessibilityRenderObject::determineAccessibilityRole()
 {
     if (!m_renderer)
-        return UnknownRole;
+        return AccessibilityRole::Unknown;
 
     // Sometimes we need to ignore the attribute role. Like if a tree is malformed,
     // we want to ignore the treeitem's attribute role.
 
     // Sometimes we need to ignore the attribute role. Like if a tree is malformed,
     // we want to ignore the treeitem's attribute role.
-    if ((m_ariaRole = determineAriaRoleAttribute()) != UnknownRole && !shouldIgnoreAttributeRole())
+    if ((m_ariaRole = determineAriaRoleAttribute()) != AccessibilityRole::Unknown && !shouldIgnoreAttributeRole())
         return m_ariaRole;
     
     Node* node = m_renderer->node();
     RenderBoxModelObject* cssBox = renderBoxModelObject();
 
     if (node && node->isLink())
         return m_ariaRole;
     
     Node* node = m_renderer->node();
     RenderBoxModelObject* cssBox = renderBoxModelObject();
 
     if (node && node->isLink())
-        return WebCoreLinkRole;
+        return AccessibilityRole::WebCoreLink;
     if (node && is<HTMLImageElement>(*node) && downcast<HTMLImageElement>(*node).hasAttributeWithoutSynchronization(usemapAttr))
     if (node && is<HTMLImageElement>(*node) && downcast<HTMLImageElement>(*node).hasAttributeWithoutSynchronization(usemapAttr))
-        return ImageMapRole;
+        return AccessibilityRole::ImageMap;
     if ((cssBox && cssBox->isListItem()) || (node && node->hasTagName(liTag)))
     if ((cssBox && cssBox->isListItem()) || (node && node->hasTagName(liTag)))
-        return ListItemRole;
+        return AccessibilityRole::ListItem;
     if (m_renderer->isListMarker())
     if (m_renderer->isListMarker())
-        return ListMarkerRole;
+        return AccessibilityRole::ListMarker;
     if (node && node->hasTagName(buttonTag))
         return buttonRoleType();
     if (node && node->hasTagName(legendTag))
     if (node && node->hasTagName(buttonTag))
         return buttonRoleType();
     if (node && node->hasTagName(legendTag))
-        return LegendRole;
+        return AccessibilityRole::Legend;
     if (m_renderer->isText())
     if (m_renderer->isText())
-        return StaticTextRole;
+        return AccessibilityRole::StaticText;
     if (cssBox && cssBox->isImage()) {
         if (is<HTMLInputElement>(node))
     if (cssBox && cssBox->isImage()) {
         if (is<HTMLInputElement>(node))
-            return ariaHasPopup() ? PopUpButtonRole : ButtonRole;
+            return ariaHasPopup() ? AccessibilityRole::PopUpButton : AccessibilityRole::Button;
         if (isSVGImage())
         if (isSVGImage())
-            return SVGRootRole;
-        return ImageRole;
+            return AccessibilityRole::SVGRoot;
+        return AccessibilityRole::Image;
     }
     
     if (node && node->hasTagName(canvasTag))
     }
     
     if (node && node->hasTagName(canvasTag))
-        return CanvasRole;
+        return AccessibilityRole::Canvas;
 
     if (cssBox && cssBox->isRenderView())
 
     if (cssBox && cssBox->isRenderView())
-        return WebAreaRole;
+        return AccessibilityRole::WebArea;
     
     if (cssBox && cssBox->isTextField()) {
         if (is<HTMLInputElement>(node))
     
     if (cssBox && cssBox->isTextField()) {
         if (is<HTMLInputElement>(node))
-            return downcast<HTMLInputElement>(*node).isSearchField() ? SearchFieldRole : TextFieldRole;
+            return downcast<HTMLInputElement>(*node).isSearchField() ? AccessibilityRole::SearchField : AccessibilityRole::TextField;
     }
     
     if (cssBox && cssBox->isTextArea())
     }
     
     if (cssBox && cssBox->isTextArea())
-        return TextAreaRole;
+        return AccessibilityRole::TextArea;
 
     if (is<HTMLInputElement>(node)) {
         HTMLInputElement& input = downcast<HTMLInputElement>(*node);
         if (input.isCheckbox())
 
     if (is<HTMLInputElement>(node)) {
         HTMLInputElement& input = downcast<HTMLInputElement>(*node);
         if (input.isCheckbox())
-            return CheckBoxRole;
+            return AccessibilityRole::CheckBox;
         if (input.isRadioButton())
         if (input.isRadioButton())
-            return RadioButtonRole;
+            return AccessibilityRole::RadioButton;
         if (input.isTextButton())
             return buttonRoleType();
         // On iOS, the date field and time field are popup buttons. On other platforms they are text fields.
 #if PLATFORM(IOS)
         if (input.isDateField() || input.isTimeField())
         if (input.isTextButton())
             return buttonRoleType();
         // On iOS, the date field and time field are popup buttons. On other platforms they are text fields.
 #if PLATFORM(IOS)
         if (input.isDateField() || input.isTimeField())
-            return PopUpButtonRole;
+            return AccessibilityRole::PopUpButton;
 #endif
 #if ENABLE(INPUT_TYPE_COLOR)
         if (input.isColorControl())
 #endif
 #if ENABLE(INPUT_TYPE_COLOR)
         if (input.isColorControl())
-            return ColorWellRole;
+            return AccessibilityRole::ColorWell;
 #endif
     }
     
     if (hasContentEditableAttributeSet())
 #endif
     }
     
     if (hasContentEditableAttributeSet())
-        return TextAreaRole;
+        return AccessibilityRole::TextArea;
     
     if (isFileUploadButton())
     
     if (isFileUploadButton())
-        return ButtonRole;
+        return AccessibilityRole::Button;
     
     if (cssBox && cssBox->isMenuList())
     
     if (cssBox && cssBox->isMenuList())
-        return PopUpButtonRole;
+        return AccessibilityRole::PopUpButton;
     
     if (headingLevel())
     
     if (headingLevel())
-        return HeadingRole;
+        return AccessibilityRole::Heading;
     
     if (m_renderer->isSVGRoot())
     
     if (m_renderer->isSVGRoot())
-        return SVGRootRole;
+        return AccessibilityRole::SVGRoot;
     
     if (isStyleFormatGroup())
     
     if (isStyleFormatGroup())
-        return is<RenderInline>(*m_renderer) ? InlineRole : GroupRole;
+        return is<RenderInline>(*m_renderer) ? AccessibilityRole::Inline : AccessibilityRole::TextGroup;
     
     if (node && node->hasTagName(ddTag))
     
     if (node && node->hasTagName(ddTag))
-        return DescriptionListDetailRole;
+        return AccessibilityRole::DescriptionListDetail;
     
     if (node && node->hasTagName(dtTag))
     
     if (node && node->hasTagName(dtTag))
-        return DescriptionListTermRole;
+        return AccessibilityRole::DescriptionListTerm;
 
     if (node && node->hasTagName(dlTag))
 
     if (node && node->hasTagName(dlTag))
-        return DescriptionListRole;
+        return AccessibilityRole::DescriptionList;
+
+    if (node && node->hasTagName(fieldsetTag))
+        return AccessibilityRole::Group;
+
+    if (node && node->hasTagName(figureTag))
+        return AccessibilityRole::Figure;
 
     // Check for Ruby elements
     if (m_renderer->isRubyText())
 
     // Check for Ruby elements
     if (m_renderer->isRubyText())
-        return RubyTextRole;
+        return AccessibilityRole::RubyText;
     if (m_renderer->isRubyBase())
     if (m_renderer->isRubyBase())
-        return RubyBaseRole;
+        return AccessibilityRole::RubyBase;
     if (m_renderer->isRubyRun())
     if (m_renderer->isRubyRun())
-        return RubyRunRole;
+        return AccessibilityRole::RubyRun;
     if (m_renderer->isRubyBlock())
     if (m_renderer->isRubyBlock())
-        return RubyBlockRole;
+        return AccessibilityRole::RubyBlock;
     if (m_renderer->isRubyInline())
     if (m_renderer->isRubyInline())
-        return RubyInlineRole;
+        return AccessibilityRole::RubyInline;
     
     // This return value is what will be used if AccessibilityTableCell determines
     // the cell should not be treated as a cell (e.g. because it is a layout table.
     
     // This return value is what will be used if AccessibilityTableCell determines
     // the cell should not be treated as a cell (e.g. because it is a layout table.
-    // In ATK, there is a distinction between generic text block elements and other
-    // generic containers; AX API does not make this distinction.
-    if (is<RenderTableCell>(m_renderer))
-#if PLATFORM(GTK) || PLATFORM(EFL)
-        return DivRole;
-#else
-        return GroupRole;
-#endif
+    if (is<RenderTableCell>(renderer()))
+        return AccessibilityRole::TextGroup;
 
     // Table sections should be ignored.
     if (m_renderer->isTableSection())
 
     // Table sections should be ignored.
     if (m_renderer->isTableSection())
-        return IgnoredRole;
+        return AccessibilityRole::Ignored;
 
     if (m_renderer->isHR())
 
     if (m_renderer->isHR())
-        return HorizontalRuleRole;
+        return AccessibilityRole::HorizontalRule;
 
     if (node && node->hasTagName(pTag))
 
     if (node && node->hasTagName(pTag))
-        return ParagraphRole;
+        return AccessibilityRole::Paragraph;
 
     if (is<HTMLLabelElement>(node))
 
     if (is<HTMLLabelElement>(node))
-        return LabelRole;
+        return AccessibilityRole::Label;
 
     if (node && node->hasTagName(dfnTag))
 
     if (node && node->hasTagName(dfnTag))
-        return DefinitionRole;
+        return AccessibilityRole::Definition;
 
     if (node && node->hasTagName(divTag))
 
     if (node && node->hasTagName(divTag))
-        return DivRole;
+        return AccessibilityRole::Div;
 
     if (is<HTMLFormElement>(node))
 
     if (is<HTMLFormElement>(node))
-        return FormRole;
+        return AccessibilityRole::Form;
 
     if (node && node->hasTagName(articleTag))
 
     if (node && node->hasTagName(articleTag))
-        return DocumentArticleRole;
+        return AccessibilityRole::DocumentArticle;
 
     if (node && node->hasTagName(mainTag))
 
     if (node && node->hasTagName(mainTag))
-        return LandmarkMainRole;
+        return AccessibilityRole::LandmarkMain;
 
     if (node && node->hasTagName(navTag))
 
     if (node && node->hasTagName(navTag))
-        return LandmarkNavigationRole;
+        return AccessibilityRole::LandmarkNavigation;
 
     if (node && node->hasTagName(asideTag))
 
     if (node && node->hasTagName(asideTag))
-        return LandmarkComplementaryRole;
+        return AccessibilityRole::LandmarkComplementary;
 
     // The default role attribute value for the section element, region, became a landmark in ARIA 1.1.
     // The HTML AAM spec says it is "strongly recommended" that ATs only convey and provide navigation
     // for section elements which have names.
     if (node && node->hasTagName(sectionTag))
 
     // The default role attribute value for the section element, region, became a landmark in ARIA 1.1.
     // The HTML AAM spec says it is "strongly recommended" that ATs only convey and provide navigation
     // for section elements which have names.
     if (node && node->hasTagName(sectionTag))
-        return hasAttribute(aria_labelAttr) || hasAttribute(aria_labelledbyAttr) ? LandmarkRegionRole : GroupRole;
+        return hasAttribute(aria_labelAttr) || hasAttribute(aria_labelledbyAttr) ? AccessibilityRole::LandmarkRegion : AccessibilityRole::TextGroup;
 
     if (node && node->hasTagName(addressTag))
 
     if (node && node->hasTagName(addressTag))
-        return LandmarkContentInfoRole;
+        return AccessibilityRole::LandmarkContentInfo;
 
     if (node && node->hasTagName(blockquoteTag))
 
     if (node && node->hasTagName(blockquoteTag))
-        return BlockquoteRole;
+        return AccessibilityRole::Blockquote;
 
     if (node && node->hasTagName(captionTag))
 
     if (node && node->hasTagName(captionTag))
-        return CaptionRole;
+        return AccessibilityRole::Caption;
     
     if (node && node->hasTagName(markTag))
     
     if (node && node->hasTagName(markTag))
-        return MarkRole;
+        return AccessibilityRole::Mark;
 
     if (node && node->hasTagName(preTag))
 
     if (node && node->hasTagName(preTag))
-        return PreRole;
+        return AccessibilityRole::Pre;
 
     if (is<HTMLDetailsElement>(node))
 
     if (is<HTMLDetailsElement>(node))
-        return DetailsRole;
+        return AccessibilityRole::Details;
     if (is<HTMLSummaryElement>(node))
     if (is<HTMLSummaryElement>(node))
-        return SummaryRole;
+        return AccessibilityRole::Summary;
     
     // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html
     // Output elements should be mapped to status role.
     if (isOutput())
     
     // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html
     // Output elements should be mapped to status role.
     if (isOutput())
-        return ApplicationStatusRole;
+        return AccessibilityRole::ApplicationStatus;
 
 #if ENABLE(VIDEO)
     if (is<HTMLVideoElement>(node))
 
 #if ENABLE(VIDEO)
     if (is<HTMLVideoElement>(node))
-        return VideoRole;
+        return AccessibilityRole::Video;
     if (is<HTMLAudioElement>(node))
     if (is<HTMLAudioElement>(node))
-        return AudioRole;
+        return AccessibilityRole::Audio;
 #endif
     
     // The HTML element should not be exposed as an element. That's what the RenderView element does.
     if (node && node->hasTagName(htmlTag))
 #endif
     
     // The HTML element should not be exposed as an element. That's what the RenderView element does.
     if (node && node->hasTagName(htmlTag))
-        return IgnoredRole;
+        return AccessibilityRole::Ignored;
 
     // There should only be one banner/contentInfo per page. If header/footer are being used within an article or section
     // then it should not be exposed as whole page's banner/contentInfo
     if (node && node->hasTagName(headerTag) && !isDescendantOfElementType(articleTag) && !isDescendantOfElementType(sectionTag))
 
     // There should only be one banner/contentInfo per page. If header/footer are being used within an article or section
     // then it should not be exposed as whole page's banner/contentInfo
     if (node && node->hasTagName(headerTag) && !isDescendantOfElementType(articleTag) && !isDescendantOfElementType(sectionTag))
-        return LandmarkBannerRole;
+        return AccessibilityRole::LandmarkBanner;
     if (node && node->hasTagName(footerTag) && !isDescendantOfElementType(articleTag) && !isDescendantOfElementType(sectionTag))
     if (node && node->hasTagName(footerTag) && !isDescendantOfElementType(articleTag) && !isDescendantOfElementType(sectionTag))
-        return FooterRole;
+        return AccessibilityRole::Footer;
+    
+    // menu tags with toolbar type should have Toolbar role.
+    if (node && node->hasTagName(menuTag) && equalLettersIgnoringASCIICase(getAttribute(typeAttr), "toolbar"))
+        return AccessibilityRole::Toolbar;
+    
+    if (node && node->hasTagName(timeTag))
+        return AccessibilityRole::Time;
     
     // If the element does not have role, but it has ARIA attributes, or accepts tab focus, accessibility should fallback to exposing it as a group.
     if (supportsARIAAttributes() || canSetFocusAttribute())
     
     // If the element does not have role, but it has ARIA attributes, or accepts tab focus, accessibility should fallback to exposing it as a group.
     if (supportsARIAAttributes() || canSetFocusAttribute())
-        return GroupRole;
+        return AccessibilityRole::Group;
 
 
-    if (m_renderer->isRenderBlockFlow()) {
-#if PLATFORM(GTK) || PLATFORM(EFL)
-        // For ATK, GroupRole maps to ATK_ROLE_PANEL. Panels are most commonly found (and hence
-        // expected) in UI elements; not text blocks.
-        return m_renderer->isAnonymousBlock() ? DivRole : GroupRole;
-#else
-        return GroupRole;
-#endif
-    }
+    if (m_renderer->isRenderBlockFlow())
+        return m_renderer->isAnonymousBlock() ? AccessibilityRole::TextGroup : AccessibilityRole::Group;
     
     
-    // InlineRole is the final fallback before assigning UnknownRole to an object. It makes it
+    // InlineRole is the final fallback before assigning AccessibilityRole::Unknown to an object. It makes it
     // possible to distinguish truly unknown objects from non-focusable inline text elements
     // which have an event handler or attribute suggesting possible inclusion by the platform.
     if (is<RenderInline>(*m_renderer)
         && (hasAttributesRequiredForInclusion()
             || (node && node->hasEventListeners())
             || (supportsDatetimeAttribute() && !getAttribute(datetimeAttr).isEmpty())))
     // possible to distinguish truly unknown objects from non-focusable inline text elements
     // which have an event handler or attribute suggesting possible inclusion by the platform.
     if (is<RenderInline>(*m_renderer)
         && (hasAttributesRequiredForInclusion()
             || (node && node->hasEventListeners())
             || (supportsDatetimeAttribute() && !getAttribute(datetimeAttr).isEmpty())))
-        return InlineRole;
+        return AccessibilityRole::Inline;
 
 
-    return UnknownRole;
+    return AccessibilityRole::Unknown;
 }
 
 AccessibilityOrientation AccessibilityRenderObject::orientation() const
 {
     const AtomicString& ariaOrientation = getAttribute(aria_orientationAttr);
     if (equalLettersIgnoringASCIICase(ariaOrientation, "horizontal"))
 }
 
 AccessibilityOrientation AccessibilityRenderObject::orientation() const
 {
     const AtomicString& ariaOrientation = getAttribute(aria_orientationAttr);
     if (equalLettersIgnoringASCIICase(ariaOrientation, "horizontal"))
-        return AccessibilityOrientationHorizontal;
+        return AccessibilityOrientation::Horizontal;
     if (equalLettersIgnoringASCIICase(ariaOrientation, "vertical"))
     if (equalLettersIgnoringASCIICase(ariaOrientation, "vertical"))
-        return AccessibilityOrientationVertical;
+        return AccessibilityOrientation::Vertical;
     if (equalLettersIgnoringASCIICase(ariaOrientation, "undefined"))
     if (equalLettersIgnoringASCIICase(ariaOrientation, "undefined"))
-        return AccessibilityOrientationUndefined;
+        return AccessibilityOrientation::Undefined;
 
 
-    // ARIA 1.1 Implicit defaults are defined on some roles.
-    // http://www.w3.org/TR/wai-aria-1.1/#aria-orientation
-    if (isScrollbar() || isComboBox() || isListBox() || isMenu() || isTree())
-        return AccessibilityOrientationVertical;
+    // In ARIA 1.1, the implicit value of aria-orientation changed from horizontal
+    // to undefined on all roles that don't have their own role-specific values. In
+    // addition, the implicit value of combobox became undefined.
+    if (isComboBox() || isRadioGroup() || isTreeGrid())
+        return AccessibilityOrientation::Undefined;
+
+    if (isScrollbar() || isListBox() || isMenu() || isTree())
+        return AccessibilityOrientation::Vertical;
     
     
-    if (isMenuBar() || isSplitter() || isTabList() || isToolbar())
-        return AccessibilityOrientationHorizontal;
+    if (isMenuBar() || isSplitter() || isTabList() || isToolbar() || isSlider())
+        return AccessibilityOrientation::Horizontal;
     
     return AccessibilityObject::orientation();
 }
     
     return AccessibilityObject::orientation();
 }
-    
+
 bool AccessibilityRenderObject::inheritsPresentationalRole() const
 {
     // ARIA states if an item can get focus, it should not be presentational.
 bool AccessibilityRenderObject::inheritsPresentationalRole() const
 {
     // ARIA states if an item can get focus, it should not be presentational.
@@ -2832,48 +2878,41 @@ bool AccessibilityRenderObject::inheritsPresentationalRole() const
     // ARIA spec says that when a parent object is presentational, and it has required child elements,
     // those child elements are also presentational. For example, <li> becomes presentational from <ul>.
     // http://www.w3.org/WAI/PF/aria/complete#presentation
     // ARIA spec says that when a parent object is presentational, and it has required child elements,
     // those child elements are also presentational. For example, <li> becomes presentational from <ul>.
     // http://www.w3.org/WAI/PF/aria/complete#presentation
-    static NeverDestroyed<HashSet<QualifiedName>> listItemParents;
-    static NeverDestroyed<HashSet<QualifiedName>> tableCellParents;
 
 
-    HashSet<QualifiedName>* possibleParentTagNames = nullptr;
+    const Vector<const HTMLQualifiedName*>* parentTags;
     switch (roleValue()) {
     switch (roleValue()) {
-    case ListItemRole:
-    case ListMarkerRole:
-        if (listItemParents.get().isEmpty()) {
-            listItemParents.get().add(ulTag);
-            listItemParents.get().add(olTag);
-            listItemParents.get().add(dlTag);
-        }
-        possibleParentTagNames = &listItemParents.get();
-        break;
-    case GridCellRole:
-    case CellRole:
-        if (tableCellParents.get().isEmpty())
-            tableCellParents.get().add(tableTag);
-        possibleParentTagNames = &tableCellParents.get();
+    case AccessibilityRole::ListItem:
+    case AccessibilityRole::ListMarker: {
+        static const auto listItemParents = makeNeverDestroyed(Vector<const HTMLQualifiedName*> { &dlTag.get(), &olTag.get(), &ulTag.get() });
+        parentTags = &listItemParents.get();
         break;
         break;
-    default:
+    }
+    case AccessibilityRole::GridCell:
+    case AccessibilityRole::Cell: {
+        static const auto tableCellParents = makeNeverDestroyed(Vector<const HTMLQualifiedName*> { &tableTag.get() });
+        parentTags = &tableCellParents.get();
         break;
     }
         break;
     }
-    
-    // Not all elements need to check for this, only ones that are required children.
-    if (!possibleParentTagNames)
+    default:
+        // Not all elements need to do the following check, only ones that are required children.
         return false;
         return false;
-    
-    for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) { 
+    }
+
+    for (auto* parent = parentObject(); parent; parent = parent->parentObject()) {
         if (!is<AccessibilityRenderObject>(*parent))
             continue;
         if (!is<AccessibilityRenderObject>(*parent))
             continue;
-        
+
         Node* node = downcast<AccessibilityRenderObject>(*parent).node();
         if (!is<Element>(node))
             continue;
         Node* node = downcast<AccessibilityRenderObject>(*parent).node();
         if (!is<Element>(node))
             continue;
-        
+
         // If native tag of the parent element matches an acceptable name, then return
         // based on its presentational status.
         // If native tag of the parent element matches an acceptable name, then return
         // based on its presentational status.
-        if (possibleParentTagNames->contains(downcast<Element>(node)->tagQName()))
-            return parent->roleValue() == PresentationalRole;
+        auto& name = downcast<Element>(*node).tagQName();
+        if (std::any_of(parentTags->begin(), parentTags->end(), [&name] (auto* possibleName) { return *possibleName == name; }))
+            return parent->roleValue() == AccessibilityRole::Presentational;
     }
     }
-    
+
     return false;
 }
     
     return false;
 }
     
@@ -2890,11 +2929,11 @@ bool AccessibilityRenderObject::isPresentationalChildOfAriaRole() const
 bool AccessibilityRenderObject::ariaRoleHasPresentationalChildren() const
 {
     switch (m_ariaRole) {
 bool AccessibilityRenderObject::ariaRoleHasPresentationalChildren() const
 {
     switch (m_ariaRole) {
-    case ButtonRole:
-    case SliderRole:
-    case ImageRole:
-    case ProgressIndicatorRole:
-    case SpinButtonRole:
+    case AccessibilityRole::Button:
+    case AccessibilityRole::Slider:
+    case AccessibilityRole::Image:
+    case AccessibilityRole::ProgressIndicator:
+    case AccessibilityRole::SpinButton:
     // case SeparatorRole:
         return true;
     default:
     // case SeparatorRole:
         return true;
     default:
@@ -2904,7 +2943,7 @@ bool AccessibilityRenderObject::ariaRoleHasPresentationalChildren() const
 
 bool AccessibilityRenderObject::canSetExpandedAttribute() const
 {
 
 bool AccessibilityRenderObject::canSetExpandedAttribute() const
 {
-    if (roleValue() == DetailsRole)
+    if (roleValue() == AccessibilityRole::Details)
         return true;
     
     // An object can be expanded if it aria-expanded is true or false.
         return true;
     
     // An object can be expanded if it aria-expanded is true or false.
@@ -2925,13 +2964,13 @@ void AccessibilityRenderObject::textChanged()
     if (!cache)
         return;
     
     if (!cache)
         return;
     
-    for (RenderObject* renderParent = m_renderer; renderParent; renderParent = renderParent->parent()) {
+    for (RenderObject* renderParent = renderer(); renderParent; renderParent = renderParent->parent()) {
         AccessibilityObject* parent = cache->get(renderParent);
         if (!parent)
             continue;
         
         if (parent->supportsARIALiveRegion())
         AccessibilityObject* parent = cache->get(renderParent);
         if (!parent)
             continue;
         
         if (parent->supportsARIALiveRegion())
-            cache->postNotification(renderParent, AXObjectCache::AXLiveRegionChanged);
+            cache->postLiveRegionChangeNotification(parent);
 
         if (parent->isNonNativeTextControl())
             cache->postNotification(renderParent, AXObjectCache::AXValueChanged);
 
         if (parent->isNonNativeTextControl())
             cache->postNotification(renderParent, AXObjectCache::AXValueChanged);
@@ -2958,7 +2997,7 @@ void AccessibilityRenderObject::addImageMapChildren()
         // add an <area> element for this child if it has a link
         if (!area.isLink())
             continue;
         // add an <area> element for this child if it has a link
         if (!area.isLink())
             continue;
-        auto& areaObject = downcast<AccessibilityImageMapLink>(*axObjectCache()->getOrCreate(ImageMapLinkRole));
+        auto& areaObject = downcast<AccessibilityImageMapLink>(*axObjectCache()->getOrCreate(AccessibilityRole::ImageMapLink));
         areaObject.setHTMLAreaElement(&area);
         areaObject.setHTMLMapElement(map);
         areaObject.setParent(this);
         areaObject.setHTMLAreaElement(&area);
         areaObject.setHTMLMapElement(map);
         areaObject.setParent(this);
@@ -2972,7 +3011,7 @@ void AccessibilityRenderObject::addImageMapChildren()
 void AccessibilityRenderObject::updateChildrenIfNecessary()
 {
     if (needsToUpdateChildren())
 void AccessibilityRenderObject::updateChildrenIfNecessary()
 {
     if (needsToUpdateChildren())
-        clearChildren();        
+        clearChildren();
     
     AccessibilityObject::updateChildrenIfNecessary();
 }
     
     AccessibilityObject::updateChildrenIfNecessary();
 }
@@ -2993,7 +3032,7 @@ void AccessibilityRenderObject::addTextFieldChildren()
     if (!is<SpinButtonElement>(spinButtonElement))
         return;
 
     if (!is<SpinButtonElement>(spinButtonElement))
         return;
 
-    auto& axSpinButton = downcast<AccessibilitySpinButton>(*axObjectCache()->getOrCreate(SpinButtonRole));
+    auto& axSpinButton = downcast<AccessibilitySpinButton>(*axObjectCache()->getOrCreate(AccessibilityRole::SpinButton));
     axSpinButton.setSpinButtonElement(downcast<SpinButtonElement>(spinButtonElement));
     axSpinButton.setParent(this);
     m_children.append(&axSpinButton);
     axSpinButton.setSpinButtonElement(downcast<SpinButtonElement>(spinButtonElement));
     axSpinButton.setParent(this);
     m_children.append(&axSpinButton);
@@ -3012,7 +3051,7 @@ void AccessibilityRenderObject::detachRemoteSVGRoot()
 
 AccessibilitySVGRoot* AccessibilityRenderObject::remoteSVGRootElement(CreationChoice createIfNecessary) const
 {
 
 AccessibilitySVGRoot* AccessibilityRenderObject::remoteSVGRootElement(CreationChoice createIfNecessary) const
 {
-    if (!is<RenderImage>(m_renderer))
+    if (!is<RenderImage>(renderer()))
         return nullptr;
     
     CachedImage* cachedImage = downcast<RenderImage>(*m_renderer).cachedImage();
         return nullptr;
     
     CachedImage* cachedImage = downcast<RenderImage>(*m_renderer).cachedImage();
@@ -3092,9 +3131,7 @@ void AccessibilityRenderObject::addAttachmentChildren()
     if (!widget || !widget->isFrameView())
         return;
     
     if (!widget || !widget->isFrameView())
         return;
     
-    AccessibilityObject* axWidget = axObjectCache()->getOrCreate(widget);
-    if (!axWidget->accessibilityIsIgnored())
-        m_children.append(axWidget);
+    addChild(axObjectCache()->getOrCreate(widget));
 }
 
 #if PLATFORM(COCOA)
 }
 
 #if PLATFORM(COCOA)
@@ -3168,7 +3205,7 @@ void AccessibilityRenderObject::addHiddenChildren()
 void AccessibilityRenderObject::updateRoleAfterChildrenCreation()
 {
     // If a menu does not have valid menuitem children, it should not be exposed as a menu.
 void AccessibilityRenderObject::updateRoleAfterChildrenCreation()
 {
     // If a menu does not have valid menuitem children, it should not be exposed as a menu.
-    if (roleValue() == MenuRole) {
+    if (roleValue() == AccessibilityRole::Menu) {
         // Elements marked as menus must have at least one menu item child.
         size_t menuItemCount = 0;
         for (const auto& child : children()) {
         // Elements marked as menus must have at least one menu item child.
         size_t menuItemCount = 0;
         for (const auto& child : children()) {
@@ -3179,7 +3216,7 @@ void AccessibilityRenderObject::updateRoleAfterChildrenCreation()
         }
 
         if (!menuItemCount)
         }
 
         if (!menuItemCount)
-            m_role = GroupRole;
+            m_role = AccessibilityRole::Group;
     }
 }
     
     }
 }
     
@@ -3197,6 +3234,8 @@ void AccessibilityRenderObject::addChildren()
     for (RefPtr<AccessibilityObject> obj = firstChild(); obj; obj = obj->nextSibling())
         addChild(obj.get());
     
     for (RefPtr<AccessibilityObject> obj = firstChild(); obj; obj = obj->nextSibling())
         addChild(obj.get());
     
+    m_subtreeDirty = false;
+    
     addHiddenChildren();
     addAttachmentChildren();
     addImageMapChildren();
     addHiddenChildren();
     addAttachmentChildren();
     addImageMapChildren();
@@ -3251,18 +3290,38 @@ bool AccessibilityRenderObject::ariaLiveRegionAtomic() const
 
     // WAI-ARIA "alert" and "status" roles have an implicit aria-atomic value of true.
     switch (roleValue()) {
 
     // WAI-ARIA "alert" and "status" roles have an implicit aria-atomic value of true.
     switch (roleValue()) {
-    case ApplicationAlertRole:
-    case ApplicationStatusRole:
+    case AccessibilityRole::ApplicationAlert:
+    case AccessibilityRole::ApplicationStatus:
         return true;
     default:
         return false;
     }
 }
 
         return true;
     default:
         return false;
     }
 }
 
-bool AccessibilityRenderObject::ariaLiveRegionBusy() const
+bool AccessibilityRenderObject::isBusy() const
 {
     return elementAttributeValue(aria_busyAttr);    
 }
 {
     return elementAttributeValue(aria_busyAttr);    
 }
+
+bool AccessibilityRenderObject::canHaveSelectedChildren() const
+{
+    switch (roleValue()) {
+    // These roles are containers whose children support aria-selected:
+    case AccessibilityRole::Grid:
+    case AccessibilityRole::ListBox:
+    case AccessibilityRole::TabList:
+    case AccessibilityRole::Tree:
+    case AccessibilityRole::TreeGrid:
+    // These roles are containers whose children are treated as selected by assistive
+    // technologies. We can get the "selected" item via aria-activedescendant or the
+    // focused element.
+    case AccessibilityRole::Menu:
+    case AccessibilityRole::MenuBar:
+        return true;
+    default:
+        return false;
+    }
+}
     
 void AccessibilityRenderObject::ariaSelectedRows(AccessibilityChildrenVector& result)
 {
     
 void AccessibilityRenderObject::ariaSelectedRows(AccessibilityChildrenVector& result)
 {
@@ -3304,7 +3363,7 @@ void AccessibilityRenderObject::ariaListboxSelectedChildren(AccessibilityChildre
 
     for (const auto& child : children()) {
         // Every child should have aria-role option, and if so, check for selected attribute/state.
 
     for (const auto& child : children()) {
         // Every child should have aria-role option, and if so, check for selected attribute/state.
-        if (child->isSelected() && child->ariaRoleAttribute() == ListBoxOptionRole) {
+        if (child->isSelected() && child->ariaRoleAttribute() == AccessibilityRole::ListBoxOption) {
             result.append(child);
             if (!isMulti)
                 return;
             result.append(child);
             if (!isMulti)
                 return;
@@ -3316,12 +3375,37 @@ void AccessibilityRenderObject::selectedChildren(AccessibilityChildrenVector& re
 {
     ASSERT(result.isEmpty());
 
 {
     ASSERT(result.isEmpty());
 
-    // only listboxes should be asked for their selected children. 
-    AccessibilityRole role = roleValue();
-    if (role == ListBoxRole) // native list boxes would be AccessibilityListBoxes, so only check for aria list boxes
+    if (!canHaveSelectedChildren())
+        return;
+
+    switch (roleValue()) {
+    case AccessibilityRole::ListBox:
+        // native list boxes would be AccessibilityListBoxes, so only check for aria list boxes
         ariaListboxSelectedChildren(result);
         ariaListboxSelectedChildren(result);
-    else if (role == TreeRole || role == TreeGridRole || role == TableRole || role == GridRole)
+        return;
+    case AccessibilityRole::Grid:
+    case AccessibilityRole::Tree:
+    case AccessibilityRole::TreeGrid:
         ariaSelectedRows(result);
         ariaSelectedRows(result);
+        return;
+    case AccessibilityRole::TabList:
+        if (AccessibilityObject* selectedTab = selectedTabItem())
+            result.append(selectedTab);
+        return;
+    case AccessibilityRole::Menu:
+    case AccessibilityRole::MenuBar:
+        if (AccessibilityObject* descendant = activeDescendant()) {
+            result.append(descendant);
+            return;
+        }
+        if (AccessibilityObject* focusedElement = focusedUIElement()) {
+            result.append(focusedElement);
+            return;
+        }
+        return;
+    default:
+        ASSERT_NOT_REACHED();
+    }
 }
 
 void AccessibilityRenderObject::ariaListboxVisibleChildren(AccessibilityChildrenVector& result)      
 }
 
 void AccessibilityRenderObject::ariaListboxVisibleChildren(AccessibilityChildrenVector& result)      
@@ -3340,7 +3424,8 @@ void AccessibilityRenderObject::visibleChildren(AccessibilityChildrenVector& res
     ASSERT(result.isEmpty());
         
     // only listboxes are asked for their visible children. 
     ASSERT(result.isEmpty());
         
     // only listboxes are asked for their visible children. 
-    if (ariaRoleAttribute() != ListBoxRole) { // native list boxes would be AccessibilityListBoxes, so only check for aria list boxes
+    if (ariaRoleAttribute() != AccessibilityRole::ListBox) {
+        // native list boxes would be AccessibilityListBoxes, so only check for aria list boxes
         ASSERT_NOT_REACHED();
         return;
     }
         ASSERT_NOT_REACHED();
         return;
     }
@@ -3349,7 +3434,7 @@ void AccessibilityRenderObject::visibleChildren(AccessibilityChildrenVector& res
  
 void AccessibilityRenderObject::tabChildren(AccessibilityChildrenVector& result)
 {
  
 void AccessibilityRenderObject::tabChildren(AccessibilityChildrenVector& result)
 {
-    ASSERT(roleValue() == TabListRole);
+    ASSERT(roleValue() == AccessibilityRole::TabList);
     
     for (const auto& child : children()) {
         if (child->isTabItem())
     
     for (const auto& child : children()) {
         if (child->isTabItem())
@@ -3369,24 +3454,24 @@ const String& AccessibilityRenderObject::actionVerb() const
     static NeverDestroyed<const String> linkAction(AXLinkActionVerb());
 
     switch (roleValue()) {
     static NeverDestroyed<const String> linkAction(AXLinkActionVerb());
 
     switch (roleValue()) {
-    case ButtonRole:
-    case ToggleButtonRole:
+    case AccessibilityRole::Button:
+    case AccessibilityRole::ToggleButton:
         return buttonAction;
         return buttonAction;
-    case TextFieldRole:
-    case TextAreaRole:
+    case AccessibilityRole::TextField:
+    case AccessibilityRole::TextArea:
         return textFieldAction;
         return textFieldAction;
-    case RadioButtonRole:
+    case AccessibilityRole::RadioButton:
         return radioButtonAction;
         return radioButtonAction;
-    case CheckBoxRole:
+    case AccessibilityRole::CheckBox:
         return isChecked() ? checkedCheckBoxAction : uncheckedCheckBoxAction;
         return isChecked() ? checkedCheckBoxAction : uncheckedCheckBoxAction;
-    case LinkRole:
-    case WebCoreLinkRole:
+    case AccessibilityRole::Link:
+    case AccessibilityRole::WebCoreLink:
         return linkAction;
     default:
         return linkAction;
     default:
-        return nullAtom;
+        return nullAtom();
     }
 #else
     }
 #else
-    return nullAtom;
+    return nullAtom();
 #endif
 }
     
 #endif
 }
     
@@ -3445,7 +3530,7 @@ bool AccessibilityRenderObject::hasBoldFont() const
     if (!m_renderer)
         return false;
     
     if (!m_renderer)
         return false;
     
-    return m_renderer->style().fontDescription().weight() >= FontWeightBold;
+    return isFontWeightBold(m_renderer->style().fontDescription().weight());
 }
 
 bool AccessibilityRenderObject::hasItalicFont() const
 }
 
 bool AccessibilityRenderObject::hasItalicFont() const
@@ -3453,7 +3538,7 @@ bool AccessibilityRenderObject::hasItalicFont() const
     if (!m_renderer)
         return false;
     
     if (!m_renderer)
         return false;
     
-    return m_renderer->style().fontDescription().italic() == FontItalicOn;
+    return isItalic(m_renderer->style().fontDescription().italic());
 }
 
 bool AccessibilityRenderObject::hasPlainText() const
 }
 
 bool AccessibilityRenderObject::hasPlainText() const
@@ -3463,8 +3548,8 @@ bool AccessibilityRenderObject::hasPlainText() const
     
     const RenderStyle& style = m_renderer->style();
     
     
     const RenderStyle& style = m_renderer->style();
     
-    return style.fontDescription().weight() == FontWeightNormal
-        && style.fontDescription().italic() == FontItalicOff
+    return style.fontDescription().weight() == normalWeightValue()
+        && style.fontDescription().italic() == normalItalicValue()
         && style.textDecorationsInEffect() == TextDecorationNone;
 }
 
         && style.textDecorationsInEffect() == TextDecorationNone;
 }
 
@@ -3510,12 +3595,16 @@ String AccessibilityRenderObject::nameForMSAA() const
 
 static bool shouldReturnTagNameAsRoleForMSAA(const Element& element)
 {
 
 static bool shouldReturnTagNameAsRoleForMSAA(const Element& element)
 {
-    // See "document structure",
-    // https://wiki.mozilla.org/Accessibility/AT-Windows-API
-    // FIXME: Add the other tag names that should be returned as the role.
-    return element.hasTagName(h1Tag) || element.hasTagName(h2Tag) 
+    return element.hasTagName(abbrTag) || element.hasTagName(acronymTag)
+        || element.hasTagName(blockquoteTag) || element.hasTagName(ddTag)
+        || element.hasTagName(dlTag) || element.hasTagName(dtTag)
+        || element.hasTagName(formTag) || element.hasTagName(frameTag)
+        || element.hasTagName(h1Tag) || element.hasTagName(h2Tag)
         || element.hasTagName(h3Tag) || element.hasTagName(h4Tag)
         || element.hasTagName(h3Tag) || element.hasTagName(h4Tag)
-        || element.hasTagName(h5Tag) || element.hasTagName(h6Tag);
+        || element.hasTagName(h5Tag) || element.hasTagName(h6Tag)
+        || element.hasTagName(iframeTag) || element.hasTagName(qTag)
+        || element.hasTagName(tbodyTag) || element.hasTagName(tfootTag)
+        || element.hasTagName(theadTag);
 }
 
 String AccessibilityRenderObject::stringRoleForMSAA() const
 }
 
 String AccessibilityRenderObject::stringRoleForMSAA() const
@@ -3567,25 +3656,25 @@ String AccessibilityRenderObject::descriptionForMSAA() const
 static AccessibilityRole msaaRoleForRenderer(const RenderObject* renderer)
 {
     if (!renderer)
 static AccessibilityRole msaaRoleForRenderer(const RenderObject* renderer)
 {
     if (!renderer)
-        return UnknownRole;
+        return AccessibilityRole::Unknown;
 
     if (is<RenderText>(*renderer))
 
     if (is<RenderText>(*renderer))
-        return EditableTextRole;
+        return AccessibilityRole::EditableText;
 
     if (is<RenderListItem>(*renderer))
 
     if (is<RenderListItem>(*renderer))
-        return ListItemRole;
+        return AccessibilityRole::ListItem;
 
 
-    return UnknownRole;
+    return AccessibilityRole::Unknown;
 }
 
 AccessibilityRole AccessibilityRenderObject::roleValueForMSAA() const
 {
 }
 
 AccessibilityRole AccessibilityRenderObject::roleValueForMSAA() const
 {
-    if (m_roleForMSAA != UnknownRole)
+    if (m_roleForMSAA != AccessibilityRole::Unknown)
         return m_roleForMSAA;
 
         return m_roleForMSAA;
 
-    m_roleForMSAA = msaaRoleForRenderer(m_renderer);
+    m_roleForMSAA = msaaRoleForRenderer(renderer());
 
 
-    if (m_roleForMSAA == UnknownRole)
+    if (m_roleForMSAA == AccessibilityRole::Unknown)
         m_roleForMSAA = roleValue();
 
     return m_roleForMSAA;
         m_roleForMSAA = roleValue();
 
     return m_roleForMSAA;
@@ -3613,7 +3702,7 @@ ScrollableArea* AccessibilityRenderObject::getScrollableAreaIfScrollable() const
     if (parentObject() && parentObject()->isAccessibilityScrollView())
         return nullptr;
 
     if (parentObject() && parentObject()->isAccessibilityScrollView())
         return nullptr;
 
-    if (!is<RenderBox>(m_renderer))
+    if (!is<RenderBox>(renderer()))
         return nullptr;
 
     auto& box = downcast<RenderBox>(*m_renderer);
         return nullptr;
 
     auto& box = downcast<RenderBox>(*m_renderer);
@@ -3625,7 +3714,7 @@ ScrollableArea* AccessibilityRenderObject::getScrollableAreaIfScrollable() const
 
 void AccessibilityRenderObject::scrollTo(const IntPoint& point) const
 {
 
 void AccessibilityRenderObject::scrollTo(const IntPoint& point) const
 {
-    if (!is<RenderBox>(m_renderer))
+    if (!is<RenderBox>(renderer()))
         return;
 
     auto& box = downcast<RenderBox>(*m_renderer);
         return;
 
     auto& box = downcast<RenderBox>(*m_renderer);
@@ -3633,7 +3722,7 @@ void AccessibilityRenderObject::scrollTo(const IntPoint& point) const
         return;
 
     // FIXME: is point a ScrollOffset or ScrollPosition? Test in RTL overflow.
         return;
 
     // FIXME: is point a ScrollOffset or ScrollPosition? Test in RTL overflow.
-    box.layer()->scrollToOffset(point, RenderLayer::ScrollOffsetClamped);
+    box.layer()->scrollToOffset(point);
 }
 
 #if ENABLE(MATHML)
 }
 
 #if ENABLE(MATHML)