| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2012, Google Inc. All rights reserved. | 2 * Copyright (C) 2012, Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 #include "core/layout/LayoutObject.h" | 52 #include "core/layout/LayoutObject.h" |
| 53 #include "modules/accessibility/AXObjectCacheImpl.h" | 53 #include "modules/accessibility/AXObjectCacheImpl.h" |
| 54 #include "platform/UserGestureIndicator.h" | 54 #include "platform/UserGestureIndicator.h" |
| 55 #include "wtf/text/StringBuilder.h" | 55 #include "wtf/text/StringBuilder.h" |
| 56 | 56 |
| 57 | 57 |
| 58 namespace blink { | 58 namespace blink { |
| 59 | 59 |
| 60 using namespace HTMLNames; | 60 using namespace HTMLNames; |
| 61 | 61 |
| 62 AXNodeObject::AXNodeObject(Node* node, AXObjectCacheImpl* axObjectCache) | 62 AXNodeObject::AXNodeObject(Node* node, AXObjectCacheImpl& axObjectCache) |
| 63 : AXObject(axObjectCache) | 63 : AXObject(axObjectCache) |
| 64 , m_ariaRole(UnknownRole) | 64 , m_ariaRole(UnknownRole) |
| 65 , m_childrenDirty(false) | 65 , m_childrenDirty(false) |
| 66 #if ENABLE(ASSERT) | 66 #if ENABLE(ASSERT) |
| 67 , m_initialized(false) | 67 , m_initialized(false) |
| 68 #endif | 68 #endif |
| 69 , m_node(node) | 69 , m_node(node) |
| 70 { | 70 { |
| 71 } | 71 } |
| 72 | 72 |
| 73 PassRefPtr<AXNodeObject> AXNodeObject::create(Node* node, AXObjectCacheImpl* axO
bjectCache) | 73 PassRefPtr<AXNodeObject> AXNodeObject::create(Node* node, AXObjectCacheImpl& axO
bjectCache) |
| 74 { | 74 { |
| 75 return adoptRef(new AXNodeObject(node, axObjectCache)); | 75 return adoptRef(new AXNodeObject(node, axObjectCache)); |
| 76 } | 76 } |
| 77 | 77 |
| 78 AXNodeObject::~AXNodeObject() | 78 AXNodeObject::~AXNodeObject() |
| 79 { | 79 { |
| 80 ASSERT(isDetached()); | 80 ASSERT(isDetached()); |
| 81 } | 81 } |
| 82 | 82 |
| 83 // This function implements the ARIA accessible name as described by the Mozilla | 83 // This function implements the ARIA accessible name as described by the Mozilla |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 { | 127 { |
| 128 if (roleValue() != SliderRole) | 128 if (roleValue() != SliderRole) |
| 129 return; | 129 return; |
| 130 | 130 |
| 131 float value = valueForRange(); | 131 float value = valueForRange(); |
| 132 float step = stepValueForRange(); | 132 float step = stepValueForRange(); |
| 133 | 133 |
| 134 value += increase ? step : -step; | 134 value += increase ? step : -step; |
| 135 | 135 |
| 136 setValue(String::number(value)); | 136 setValue(String::number(value)); |
| 137 axObjectCache()->postNotification(node(), AXObjectCacheImpl::AXValueChanged)
; | 137 axObjectCache().postNotification(node(), AXObjectCacheImpl::AXValueChanged); |
| 138 } | 138 } |
| 139 | 139 |
| 140 String AXNodeObject::ariaAccessibilityDescription() const | 140 String AXNodeObject::ariaAccessibilityDescription() const |
| 141 { | 141 { |
| 142 String ariaLabeledBy = ariaLabeledByAttribute(); | 142 String ariaLabeledBy = ariaLabeledByAttribute(); |
| 143 if (!ariaLabeledBy.isEmpty()) | 143 if (!ariaLabeledBy.isEmpty()) |
| 144 return ariaLabeledBy; | 144 return ariaLabeledBy; |
| 145 | 145 |
| 146 const AtomicString& ariaLabel = getAttribute(aria_labelAttr); | 146 const AtomicString& ariaLabel = getAttribute(aria_labelAttr); |
| 147 if (!ariaLabel.isEmpty()) | 147 if (!ariaLabel.isEmpty()) |
| (...skipping 24 matching lines...) Expand all Loading... |
| 172 ignoredReasons->append(IgnoredReason(AXAncestorIsLeafNode, leafNodeA
ncestor())); | 172 ignoredReasons->append(IgnoredReason(AXAncestorIsLeafNode, leafNodeA
ncestor())); |
| 173 return true; | 173 return true; |
| 174 } | 174 } |
| 175 | 175 |
| 176 // Ignore labels that are already referenced by a control's title UI element
. | 176 // Ignore labels that are already referenced by a control's title UI element
. |
| 177 AXObject* controlObject = correspondingControlForLabelElement(); | 177 AXObject* controlObject = correspondingControlForLabelElement(); |
| 178 if (controlObject && !controlObject->deprecatedExposesTitleUIElement() && co
ntrolObject->isCheckboxOrRadio()) { | 178 if (controlObject && !controlObject->deprecatedExposesTitleUIElement() && co
ntrolObject->isCheckboxOrRadio()) { |
| 179 if (ignoredReasons) { | 179 if (ignoredReasons) { |
| 180 HTMLLabelElement* label = labelElementContainer(); | 180 HTMLLabelElement* label = labelElementContainer(); |
| 181 if (label && !label->isSameNode(node())) { | 181 if (label && !label->isSameNode(node())) { |
| 182 AXObject* labelAXObject = axObjectCache()->getOrCreate(label); | 182 AXObject* labelAXObject = axObjectCache().getOrCreate(label); |
| 183 ignoredReasons->append(IgnoredReason(AXLabelContainer, labelAXOb
ject)); | 183 ignoredReasons->append(IgnoredReason(AXLabelContainer, labelAXOb
ject)); |
| 184 } | 184 } |
| 185 | 185 |
| 186 ignoredReasons->append(IgnoredReason(AXLabelFor, controlObject)); | 186 ignoredReasons->append(IgnoredReason(AXLabelFor, controlObject)); |
| 187 } | 187 } |
| 188 return true; | 188 return true; |
| 189 } | 189 } |
| 190 | 190 |
| 191 Element* element = node()->isElementNode() ? toElement(node()) : node()->par
entElement(); | 191 Element* element = node()->isElementNode() ? toElement(node()) : node()->par
entElement(); |
| 192 if (!layoutObject() | 192 if (!layoutObject() |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 568 if (Element* idElement = scope.getElementById(AtomicString(id))) | 568 if (Element* idElement = scope.getElementById(AtomicString(id))) |
| 569 elements.append(idElement); | 569 elements.append(idElement); |
| 570 } | 570 } |
| 571 } | 571 } |
| 572 | 572 |
| 573 void AXNodeObject::accessibilityChildrenFromAttribute(QualifiedName attr, Access
ibilityChildrenVector& children) const | 573 void AXNodeObject::accessibilityChildrenFromAttribute(QualifiedName attr, Access
ibilityChildrenVector& children) const |
| 574 { | 574 { |
| 575 WillBeHeapVector<RawPtrWillBeMember<Element>> elements; | 575 WillBeHeapVector<RawPtrWillBeMember<Element>> elements; |
| 576 elementsFromAttribute(elements, attr); | 576 elementsFromAttribute(elements, attr); |
| 577 | 577 |
| 578 AXObjectCacheImpl* cache = axObjectCache(); | 578 AXObjectCacheImpl& cache = axObjectCache(); |
| 579 for (const auto& element : elements) { | 579 for (const auto& element : elements) { |
| 580 if (AXObject* child = cache->getOrCreate(element)) | 580 if (AXObject* child = cache.getOrCreate(element)) |
| 581 children.append(child); | 581 children.append(child); |
| 582 } | 582 } |
| 583 } | 583 } |
| 584 | 584 |
| 585 // This only returns true if this is the element that actually has the | 585 // This only returns true if this is the element that actually has the |
| 586 // contentEditable attribute set, unlike node->hasEditableStyle() which will | 586 // contentEditable attribute set, unlike node->hasEditableStyle() which will |
| 587 // also return true if an ancestor is editable. | 587 // also return true if an ancestor is editable. |
| 588 bool AXNodeObject::hasContentEditableAttributeSet() const | 588 bool AXNodeObject::hasContentEditableAttributeSet() const |
| 589 { | 589 { |
| 590 if (!hasAttribute(contenteditableAttr)) | 590 if (!hasAttribute(contenteditableAttr)) |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 | 657 |
| 658 return Traversal<HTMLLabelElement>::firstAncestor(*element); | 658 return Traversal<HTMLLabelElement>::firstAncestor(*element); |
| 659 } | 659 } |
| 660 | 660 |
| 661 AXObject* AXNodeObject::menuButtonForMenu() const | 661 AXObject* AXNodeObject::menuButtonForMenu() const |
| 662 { | 662 { |
| 663 Element* menuItem = menuItemElementForMenu(); | 663 Element* menuItem = menuItemElementForMenu(); |
| 664 | 664 |
| 665 if (menuItem) { | 665 if (menuItem) { |
| 666 // ARIA just has generic menu items. AppKit needs to know if this is a t
op level items like MenuBarButton or MenuBarItem | 666 // ARIA just has generic menu items. AppKit needs to know if this is a t
op level items like MenuBarButton or MenuBarItem |
| 667 AXObject* menuItemAX = axObjectCache()->getOrCreate(menuItem); | 667 AXObject* menuItemAX = axObjectCache().getOrCreate(menuItem); |
| 668 if (menuItemAX && menuItemAX->isMenuButton()) | 668 if (menuItemAX && menuItemAX->isMenuButton()) |
| 669 return menuItemAX; | 669 return menuItemAX; |
| 670 } | 670 } |
| 671 return 0; | 671 return 0; |
| 672 } | 672 } |
| 673 | 673 |
| 674 static Element* siblingWithAriaRole(String role, Node* node) | 674 static Element* siblingWithAriaRole(String role, Node* node) |
| 675 { | 675 { |
| 676 Node* parent = node->parentNode(); | 676 Node* parent = node->parentNode(); |
| 677 if (!parent) | 677 if (!parent) |
| (...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1272 | 1272 |
| 1273 return toElement(node)->innerText(); | 1273 return toElement(node)->innerText(); |
| 1274 } | 1274 } |
| 1275 | 1275 |
| 1276 AXObject* AXNodeObject::deprecatedTitleUIElement() const | 1276 AXObject* AXNodeObject::deprecatedTitleUIElement() const |
| 1277 { | 1277 { |
| 1278 if (!node() || !node()->isElementNode()) | 1278 if (!node() || !node()->isElementNode()) |
| 1279 return 0; | 1279 return 0; |
| 1280 | 1280 |
| 1281 if (isFieldset()) | 1281 if (isFieldset()) |
| 1282 return axObjectCache()->getOrCreate(toHTMLFieldSetElement(node())->legen
d()); | 1282 return axObjectCache().getOrCreate(toHTMLFieldSetElement(node())->legend
()); |
| 1283 | 1283 |
| 1284 HTMLLabelElement* label = labelForElement(toElement(node())); | 1284 HTMLLabelElement* label = labelForElement(toElement(node())); |
| 1285 if (label) | 1285 if (label) |
| 1286 return axObjectCache()->getOrCreate(label); | 1286 return axObjectCache().getOrCreate(label); |
| 1287 | 1287 |
| 1288 return 0; | 1288 return 0; |
| 1289 } | 1289 } |
| 1290 | 1290 |
| 1291 AccessibilityButtonState AXNodeObject::checkboxOrRadioValue() const | 1291 AccessibilityButtonState AXNodeObject::checkboxOrRadioValue() const |
| 1292 { | 1292 { |
| 1293 if (isNativeCheckboxOrRadio()) | 1293 if (isNativeCheckboxOrRadio()) |
| 1294 return isChecked() ? ButtonStateOn : ButtonStateOff; | 1294 return isChecked() ? ButtonStateOn : ButtonStateOff; |
| 1295 | 1295 |
| 1296 return AXObject::checkboxOrRadioValue(); | 1296 return AXObject::checkboxOrRadioValue(); |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1752 return summary; | 1752 return summary; |
| 1753 | 1753 |
| 1754 // The title attribute should be used as help text unless it is alre
ady being used as descriptive text. | 1754 // The title attribute should be used as help text unless it is alre
ady being used as descriptive text. |
| 1755 const AtomicString& title = toElement(curr)->getAttribute(titleAttr)
; | 1755 const AtomicString& title = toElement(curr)->getAttribute(titleAttr)
; |
| 1756 if (!title.isEmpty() && description != title) | 1756 if (!title.isEmpty() && description != title) |
| 1757 return title; | 1757 return title; |
| 1758 } | 1758 } |
| 1759 | 1759 |
| 1760 // Only take help text from an ancestor element if its a group or an unk
nown role. If help was | 1760 // Only take help text from an ancestor element if its a group or an unk
nown role. If help was |
| 1761 // added to those kinds of elements, it is likely it was meant for a chi
ld element. | 1761 // added to those kinds of elements, it is likely it was meant for a chi
ld element. |
| 1762 AXObject* axObj = axObjectCache()->getOrCreate(curr); | 1762 AXObject* axObj = axObjectCache().getOrCreate(curr); |
| 1763 if (axObj) { | 1763 if (axObj) { |
| 1764 AccessibilityRole role = axObj->roleValue(); | 1764 AccessibilityRole role = axObj->roleValue(); |
| 1765 if (role != GroupRole && role != UnknownRole) | 1765 if (role != GroupRole && role != UnknownRole) |
| 1766 break; | 1766 break; |
| 1767 } | 1767 } |
| 1768 } | 1768 } |
| 1769 | 1769 |
| 1770 return String(); | 1770 return String(); |
| 1771 } | 1771 } |
| 1772 | 1772 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1822 } | 1822 } |
| 1823 | 1823 |
| 1824 // Step 2B from: http://www.w3.org/TR/accname-aam-1.1 | 1824 // Step 2B from: http://www.w3.org/TR/accname-aam-1.1 |
| 1825 if (!inAriaLabelledByTraversal && hasAttribute(aria_labelledbyAttr) && !alre
adyVisited) { | 1825 if (!inAriaLabelledByTraversal && hasAttribute(aria_labelledbyAttr) && !alre
adyVisited) { |
| 1826 if (nameFrom) | 1826 if (nameFrom) |
| 1827 *nameFrom = AXNameFromRelatedElement; | 1827 *nameFrom = AXNameFromRelatedElement; |
| 1828 WillBeHeapVector<RawPtrWillBeMember<Element>> elements; | 1828 WillBeHeapVector<RawPtrWillBeMember<Element>> elements; |
| 1829 ariaLabeledByElements(elements); | 1829 ariaLabeledByElements(elements); |
| 1830 StringBuilder accumulatedText; | 1830 StringBuilder accumulatedText; |
| 1831 for (const auto& element : elements) { | 1831 for (const auto& element : elements) { |
| 1832 RefPtr<AXObject> axElement = axObjectCache()->getOrCreate(element); | 1832 RefPtr<AXObject> axElement = axObjectCache().getOrCreate(element); |
| 1833 if (axElement) { | 1833 if (axElement) { |
| 1834 if (nameObjects) | 1834 if (nameObjects) |
| 1835 nameObjects->append(axElement.get()); | 1835 nameObjects->append(axElement.get()); |
| 1836 String result = axElement->textAlternative(true, true, visited,
nullptr, nullptr); | 1836 String result = axElement->textAlternative(true, true, visited,
nullptr, nullptr); |
| 1837 if (!result.isEmpty()) { | 1837 if (!result.isEmpty()) { |
| 1838 if (!accumulatedText.isEmpty()) | 1838 if (!accumulatedText.isEmpty()) |
| 1839 accumulatedText.append(" "); | 1839 accumulatedText.append(" "); |
| 1840 accumulatedText.append(result); | 1840 accumulatedText.append(result); |
| 1841 } | 1841 } |
| 1842 } | 1842 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1895 if (!m_explicitElementRect.isEmpty()) | 1895 if (!m_explicitElementRect.isEmpty()) |
| 1896 return m_explicitElementRect; | 1896 return m_explicitElementRect; |
| 1897 | 1897 |
| 1898 // FIXME: If there are a lot of elements in the canvas, it will be inefficie
nt. | 1898 // FIXME: If there are a lot of elements in the canvas, it will be inefficie
nt. |
| 1899 // We can avoid the inefficient calculations by using AXComputedObjectAttrib
uteCache. | 1899 // We can avoid the inefficient calculations by using AXComputedObjectAttrib
uteCache. |
| 1900 if (node()->parentElement()->isInCanvasSubtree()) { | 1900 if (node()->parentElement()->isInCanvasSubtree()) { |
| 1901 LayoutRect rect; | 1901 LayoutRect rect; |
| 1902 | 1902 |
| 1903 for (Node& child : NodeTraversal::childrenOf(*node())) { | 1903 for (Node& child : NodeTraversal::childrenOf(*node())) { |
| 1904 if (child.isHTMLElement()) { | 1904 if (child.isHTMLElement()) { |
| 1905 if (AXObject* obj = axObjectCache()->get(&child)) { | 1905 if (AXObject* obj = axObjectCache().get(&child)) { |
| 1906 if (rect.isEmpty()) | 1906 if (rect.isEmpty()) |
| 1907 rect = obj->elementRect(); | 1907 rect = obj->elementRect(); |
| 1908 else | 1908 else |
| 1909 rect.unite(obj->elementRect()); | 1909 rect.unite(obj->elementRect()); |
| 1910 } | 1910 } |
| 1911 } | 1911 } |
| 1912 } | 1912 } |
| 1913 | 1913 |
| 1914 if (!rect.isEmpty()) | 1914 if (!rect.isEmpty()) |
| 1915 return rect; | 1915 return rect; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1946 | 1946 |
| 1947 if (!parentNode) | 1947 if (!parentNode) |
| 1948 parentNode = node->parentNode(); | 1948 parentNode = node->parentNode(); |
| 1949 | 1949 |
| 1950 return parentNode; | 1950 return parentNode; |
| 1951 } | 1951 } |
| 1952 | 1952 |
| 1953 AXObject* AXNodeObject::computeParent() const | 1953 AXObject* AXNodeObject::computeParent() const |
| 1954 { | 1954 { |
| 1955 if (Node* parentNode = getParentNodeForComputeParent(node())) | 1955 if (Node* parentNode = getParentNodeForComputeParent(node())) |
| 1956 return axObjectCache()->getOrCreate(parentNode); | 1956 return axObjectCache().getOrCreate(parentNode); |
| 1957 | 1957 |
| 1958 return nullptr; | 1958 return nullptr; |
| 1959 } | 1959 } |
| 1960 | 1960 |
| 1961 AXObject* AXNodeObject::computeParentIfExists() const | 1961 AXObject* AXNodeObject::computeParentIfExists() const |
| 1962 { | 1962 { |
| 1963 if (Node* parentNode = getParentNodeForComputeParent(node())) | 1963 if (Node* parentNode = getParentNodeForComputeParent(node())) |
| 1964 return axObjectCache()->get(parentNode); | 1964 return axObjectCache().get(parentNode); |
| 1965 | 1965 |
| 1966 return nullptr; | 1966 return nullptr; |
| 1967 } | 1967 } |
| 1968 | 1968 |
| 1969 AXObject* AXNodeObject::firstChild() const | 1969 AXObject* AXNodeObject::firstChild() const |
| 1970 { | 1970 { |
| 1971 if (!node()) | 1971 if (!node()) |
| 1972 return 0; | 1972 return 0; |
| 1973 | 1973 |
| 1974 Node* firstChild = node()->firstChild(); | 1974 Node* firstChild = node()->firstChild(); |
| 1975 | 1975 |
| 1976 if (!firstChild) | 1976 if (!firstChild) |
| 1977 return 0; | 1977 return 0; |
| 1978 | 1978 |
| 1979 return axObjectCache()->getOrCreate(firstChild); | 1979 return axObjectCache().getOrCreate(firstChild); |
| 1980 } | 1980 } |
| 1981 | 1981 |
| 1982 AXObject* AXNodeObject::nextSibling() const | 1982 AXObject* AXNodeObject::nextSibling() const |
| 1983 { | 1983 { |
| 1984 if (!node()) | 1984 if (!node()) |
| 1985 return 0; | 1985 return 0; |
| 1986 | 1986 |
| 1987 Node* nextSibling = node()->nextSibling(); | 1987 Node* nextSibling = node()->nextSibling(); |
| 1988 if (!nextSibling) | 1988 if (!nextSibling) |
| 1989 return 0; | 1989 return 0; |
| 1990 | 1990 |
| 1991 return axObjectCache()->getOrCreate(nextSibling); | 1991 return axObjectCache().getOrCreate(nextSibling); |
| 1992 } | 1992 } |
| 1993 | 1993 |
| 1994 void AXNodeObject::addChildren() | 1994 void AXNodeObject::addChildren() |
| 1995 { | 1995 { |
| 1996 // If the need to add more children in addition to existing children arises, | 1996 // If the need to add more children in addition to existing children arises, |
| 1997 // childrenChanged should have been called, leaving the object with no child
ren. | 1997 // childrenChanged should have been called, leaving the object with no child
ren. |
| 1998 ASSERT(!m_haveChildren); | 1998 ASSERT(!m_haveChildren); |
| 1999 | 1999 |
| 2000 if (!m_node) | 2000 if (!m_node) |
| 2001 return; | 2001 return; |
| 2002 | 2002 |
| 2003 m_haveChildren = true; | 2003 m_haveChildren = true; |
| 2004 | 2004 |
| 2005 // The only time we add children from the DOM tree to a node with a layoutOb
ject is when it's a canvas. | 2005 // The only time we add children from the DOM tree to a node with a layoutOb
ject is when it's a canvas. |
| 2006 if (layoutObject() && !isHTMLCanvasElement(*m_node)) | 2006 if (layoutObject() && !isHTMLCanvasElement(*m_node)) |
| 2007 return; | 2007 return; |
| 2008 | 2008 |
| 2009 Vector<AXObject*> ownedChildren; | 2009 Vector<AXObject*> ownedChildren; |
| 2010 computeAriaOwnsChildren(ownedChildren); | 2010 computeAriaOwnsChildren(ownedChildren); |
| 2011 | 2011 |
| 2012 for (Node& child : NodeTraversal::childrenOf(*m_node)) { | 2012 for (Node& child : NodeTraversal::childrenOf(*m_node)) { |
| 2013 AXObject* childObj = axObjectCache()->getOrCreate(&child); | 2013 AXObject* childObj = axObjectCache().getOrCreate(&child); |
| 2014 if (!axObjectCache()->isAriaOwned(childObj)) | 2014 if (!axObjectCache().isAriaOwned(childObj)) |
| 2015 addChild(childObj); | 2015 addChild(childObj); |
| 2016 } | 2016 } |
| 2017 | 2017 |
| 2018 for (const auto& ownedChild : ownedChildren) | 2018 for (const auto& ownedChild : ownedChildren) |
| 2019 addChild(ownedChild); | 2019 addChild(ownedChild); |
| 2020 | 2020 |
| 2021 for (const auto& child : m_children) | 2021 for (const auto& child : m_children) |
| 2022 child->setParent(this); | 2022 child->setParent(this); |
| 2023 } | 2023 } |
| 2024 | 2024 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2063 case PopUpButtonRole: | 2063 case PopUpButtonRole: |
| 2064 case CheckBoxRole: | 2064 case CheckBoxRole: |
| 2065 case RadioButtonRole: | 2065 case RadioButtonRole: |
| 2066 case SwitchRole: | 2066 case SwitchRole: |
| 2067 case TabRole: | 2067 case TabRole: |
| 2068 case ToggleButtonRole: | 2068 case ToggleButtonRole: |
| 2069 case ListBoxOptionRole: | 2069 case ListBoxOptionRole: |
| 2070 case ScrollBarRole: | 2070 case ScrollBarRole: |
| 2071 return false; | 2071 return false; |
| 2072 case StaticTextRole: | 2072 case StaticTextRole: |
| 2073 if (!axObjectCache()->inlineTextBoxAccessibilityEnabled()) | 2073 if (!axObjectCache().inlineTextBoxAccessibilityEnabled()) |
| 2074 return false; | 2074 return false; |
| 2075 default: | 2075 default: |
| 2076 return true; | 2076 return true; |
| 2077 } | 2077 } |
| 2078 } | 2078 } |
| 2079 | 2079 |
| 2080 Element* AXNodeObject::actionElement() const | 2080 Element* AXNodeObject::actionElement() const |
| 2081 { | 2081 { |
| 2082 Node* node = this->node(); | 2082 Node* node = this->node(); |
| 2083 if (!node) | 2083 if (!node) |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2120 elt = mouseButtonListener(); | 2120 elt = mouseButtonListener(); |
| 2121 return elt; | 2121 return elt; |
| 2122 } | 2122 } |
| 2123 | 2123 |
| 2124 Element* AXNodeObject::anchorElement() const | 2124 Element* AXNodeObject::anchorElement() const |
| 2125 { | 2125 { |
| 2126 Node* node = this->node(); | 2126 Node* node = this->node(); |
| 2127 if (!node) | 2127 if (!node) |
| 2128 return 0; | 2128 return 0; |
| 2129 | 2129 |
| 2130 AXObjectCacheImpl* cache = axObjectCache(); | 2130 AXObjectCacheImpl& cache = axObjectCache(); |
| 2131 | 2131 |
| 2132 // search up the DOM tree for an anchor element | 2132 // search up the DOM tree for an anchor element |
| 2133 // NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElem
ent | 2133 // NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElem
ent |
| 2134 for ( ; node; node = node->parentNode()) { | 2134 for ( ; node; node = node->parentNode()) { |
| 2135 if (isHTMLAnchorElement(*node) || (node->layoutObject() && cache->getOrC
reate(node->layoutObject())->isAnchor())) | 2135 if (isHTMLAnchorElement(*node) || (node->layoutObject() && cache.getOrCr
eate(node->layoutObject())->isAnchor())) |
| 2136 return toElement(node); | 2136 return toElement(node); |
| 2137 } | 2137 } |
| 2138 | 2138 |
| 2139 return 0; | 2139 return 0; |
| 2140 } | 2140 } |
| 2141 | 2141 |
| 2142 Document* AXNodeObject::document() const | 2142 Document* AXNodeObject::document() const |
| 2143 { | 2143 { |
| 2144 if (!node()) | 2144 if (!node()) |
| 2145 return 0; | 2145 return 0; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2159 | 2159 |
| 2160 HTMLElement* correspondingControl = labelElement->control(); | 2160 HTMLElement* correspondingControl = labelElement->control(); |
| 2161 if (!correspondingControl) | 2161 if (!correspondingControl) |
| 2162 return 0; | 2162 return 0; |
| 2163 | 2163 |
| 2164 // Make sure the corresponding control isn't a descendant of this label | 2164 // Make sure the corresponding control isn't a descendant of this label |
| 2165 // that's in the middle of being destroyed. | 2165 // that's in the middle of being destroyed. |
| 2166 if (correspondingControl->layoutObject() && !correspondingControl->layoutObj
ect()->parent()) | 2166 if (correspondingControl->layoutObject() && !correspondingControl->layoutObj
ect()->parent()) |
| 2167 return 0; | 2167 return 0; |
| 2168 | 2168 |
| 2169 return axObjectCache()->getOrCreate(correspondingControl); | 2169 return axObjectCache().getOrCreate(correspondingControl); |
| 2170 } | 2170 } |
| 2171 | 2171 |
| 2172 HTMLLabelElement* AXNodeObject::labelElementContainer() const | 2172 HTMLLabelElement* AXNodeObject::labelElementContainer() const |
| 2173 { | 2173 { |
| 2174 if (!node()) | 2174 if (!node()) |
| 2175 return 0; | 2175 return 0; |
| 2176 | 2176 |
| 2177 // the control element should not be considered part of the label | 2177 // the control element should not be considered part of the label |
| 2178 if (isControl()) | 2178 if (isControl()) |
| 2179 return 0; | 2179 return 0; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2229 return; | 2229 return; |
| 2230 | 2230 |
| 2231 // If this is not part of the accessibility tree because an ancestor | 2231 // If this is not part of the accessibility tree because an ancestor |
| 2232 // has only presentational children, invalidate this object's children but | 2232 // has only presentational children, invalidate this object's children but |
| 2233 // skip sending a notification and skip walking up the ancestors. | 2233 // skip sending a notification and skip walking up the ancestors. |
| 2234 if (ancestorForWhichThisIsAPresentationalChild()) { | 2234 if (ancestorForWhichThisIsAPresentationalChild()) { |
| 2235 setNeedsToUpdateChildren(); | 2235 setNeedsToUpdateChildren(); |
| 2236 return; | 2236 return; |
| 2237 } | 2237 } |
| 2238 | 2238 |
| 2239 axObjectCache()->postNotification(this, AXObjectCacheImpl::AXChildrenChanged
); | 2239 axObjectCache().postNotification(this, AXObjectCacheImpl::AXChildrenChanged)
; |
| 2240 | 2240 |
| 2241 // Go up the accessibility parent chain, but only if the element already exi
sts. This method is | 2241 // Go up the accessibility parent chain, but only if the element already exi
sts. This method is |
| 2242 // called during layout, minimal work should be done. | 2242 // called during layout, minimal work should be done. |
| 2243 // If AX elements are created now, they could interrogate the layout tree wh
ile it's in a funky state. | 2243 // If AX elements are created now, they could interrogate the layout tree wh
ile it's in a funky state. |
| 2244 // At the same time, process ARIA live region changes. | 2244 // At the same time, process ARIA live region changes. |
| 2245 for (AXObject* parent = this; parent; parent = parent->parentObjectIfExists(
)) { | 2245 for (AXObject* parent = this; parent; parent = parent->parentObjectIfExists(
)) { |
| 2246 parent->setNeedsToUpdateChildren(); | 2246 parent->setNeedsToUpdateChildren(); |
| 2247 | 2247 |
| 2248 // These notifications always need to be sent because screenreaders are
reliant on them to perform. | 2248 // These notifications always need to be sent because screenreaders are
reliant on them to perform. |
| 2249 // In other words, they need to be sent even when the screen reader has
not accessed this live region since the last update. | 2249 // In other words, they need to be sent even when the screen reader has
not accessed this live region since the last update. |
| 2250 | 2250 |
| 2251 // If this element supports ARIA live regions, then notify the AT of cha
nges. | 2251 // If this element supports ARIA live regions, then notify the AT of cha
nges. |
| 2252 if (parent->isLiveRegion()) | 2252 if (parent->isLiveRegion()) |
| 2253 axObjectCache()->postNotification(parent, AXObjectCacheImpl::AXLiveR
egionChanged); | 2253 axObjectCache().postNotification(parent, AXObjectCacheImpl::AXLiveRe
gionChanged); |
| 2254 | 2254 |
| 2255 // If this element is an ARIA text box or content editable, post a "valu
e changed" notification on it | 2255 // If this element is an ARIA text box or content editable, post a "valu
e changed" notification on it |
| 2256 // so that it behaves just like a native input element or textarea. | 2256 // so that it behaves just like a native input element or textarea. |
| 2257 if (isNonNativeTextControl()) | 2257 if (isNonNativeTextControl()) |
| 2258 axObjectCache()->postNotification(parent, AXObjectCacheImpl::AXValue
Changed); | 2258 axObjectCache().postNotification(parent, AXObjectCacheImpl::AXValueC
hanged); |
| 2259 } | 2259 } |
| 2260 } | 2260 } |
| 2261 | 2261 |
| 2262 void AXNodeObject::selectionChanged() | 2262 void AXNodeObject::selectionChanged() |
| 2263 { | 2263 { |
| 2264 // Post the selected text changed event on the first ancestor that's | 2264 // Post the selected text changed event on the first ancestor that's |
| 2265 // focused (to handle form controls, ARIA text boxes and contentEditable), | 2265 // focused (to handle form controls, ARIA text boxes and contentEditable), |
| 2266 // or the web area if the selection is just in the document somewhere. | 2266 // or the web area if the selection is just in the document somewhere. |
| 2267 if (isFocused() || isWebArea()) | 2267 if (isFocused() || isWebArea()) |
| 2268 axObjectCache()->postNotification(this, AXObjectCacheImpl::AXSelectedTex
tChanged); | 2268 axObjectCache().postNotification(this, AXObjectCacheImpl::AXSelectedText
Changed); |
| 2269 else | 2269 else |
| 2270 AXObject::selectionChanged(); // Calls selectionChanged on parent. | 2270 AXObject::selectionChanged(); // Calls selectionChanged on parent. |
| 2271 } | 2271 } |
| 2272 | 2272 |
| 2273 void AXNodeObject::textChanged() | 2273 void AXNodeObject::textChanged() |
| 2274 { | 2274 { |
| 2275 // If this element supports ARIA live regions, or is part of a region with a
n ARIA editable role, | 2275 // If this element supports ARIA live regions, or is part of a region with a
n ARIA editable role, |
| 2276 // then notify the AT of changes. | 2276 // then notify the AT of changes. |
| 2277 AXObjectCacheImpl* cache = axObjectCache(); | 2277 AXObjectCacheImpl& cache = axObjectCache(); |
| 2278 for (Node* parentNode = node(); parentNode; parentNode = parentNode->parentN
ode()) { | 2278 for (Node* parentNode = node(); parentNode; parentNode = parentNode->parentN
ode()) { |
| 2279 AXObject* parent = cache->get(parentNode); | 2279 AXObject* parent = cache.get(parentNode); |
| 2280 if (!parent) | 2280 if (!parent) |
| 2281 continue; | 2281 continue; |
| 2282 | 2282 |
| 2283 if (parent->isLiveRegion()) | 2283 if (parent->isLiveRegion()) |
| 2284 cache->postNotification(parentNode, AXObjectCacheImpl::AXLiveRegionC
hanged); | 2284 cache.postNotification(parentNode, AXObjectCacheImpl::AXLiveRegionCh
anged); |
| 2285 | 2285 |
| 2286 // If this element is an ARIA text box or content editable, post a "valu
e changed" notification on it | 2286 // If this element is an ARIA text box or content editable, post a "valu
e changed" notification on it |
| 2287 // so that it behaves just like a native input element or textarea. | 2287 // so that it behaves just like a native input element or textarea. |
| 2288 if (parent->isNonNativeTextControl()) | 2288 if (parent->isNonNativeTextControl()) |
| 2289 cache->postNotification(parentNode, AXObjectCacheImpl::AXValueChange
d); | 2289 cache.postNotification(parentNode, AXObjectCacheImpl::AXValueChanged
); |
| 2290 } | 2290 } |
| 2291 } | 2291 } |
| 2292 | 2292 |
| 2293 void AXNodeObject::updateAccessibilityRole() | 2293 void AXNodeObject::updateAccessibilityRole() |
| 2294 { | 2294 { |
| 2295 bool ignoredStatus = accessibilityIsIgnored(); | 2295 bool ignoredStatus = accessibilityIsIgnored(); |
| 2296 m_role = determineAccessibilityRole(); | 2296 m_role = determineAccessibilityRole(); |
| 2297 | 2297 |
| 2298 // The AX hierarchy only needs to be updated if the ignored status of an ele
ment has changed. | 2298 // The AX hierarchy only needs to be updated if the ignored status of an ele
ment has changed. |
| 2299 if (ignoredStatus != accessibilityIsIgnored()) | 2299 if (ignoredStatus != accessibilityIsIgnored()) |
| 2300 childrenChanged(); | 2300 childrenChanged(); |
| 2301 } | 2301 } |
| 2302 | 2302 |
| 2303 void AXNodeObject::computeAriaOwnsChildren(Vector<AXObject*>& ownedChildren) | 2303 void AXNodeObject::computeAriaOwnsChildren(Vector<AXObject*>& ownedChildren) |
| 2304 { | 2304 { |
| 2305 if (!hasAttribute(aria_ownsAttr)) | 2305 if (!hasAttribute(aria_ownsAttr)) |
| 2306 return; | 2306 return; |
| 2307 | 2307 |
| 2308 Vector<String> idVector; | 2308 Vector<String> idVector; |
| 2309 tokenVectorFromAttribute(idVector, aria_ownsAttr); | 2309 tokenVectorFromAttribute(idVector, aria_ownsAttr); |
| 2310 | 2310 |
| 2311 axObjectCache()->updateAriaOwns(this, idVector, ownedChildren); | 2311 axObjectCache().updateAriaOwns(this, idVector, ownedChildren); |
| 2312 } | 2312 } |
| 2313 | 2313 |
| 2314 String AXNodeObject::alternativeTextForWebArea() const | 2314 String AXNodeObject::alternativeTextForWebArea() const |
| 2315 { | 2315 { |
| 2316 // The WebArea description should follow this order: | 2316 // The WebArea description should follow this order: |
| 2317 // aria-label on the <html> | 2317 // aria-label on the <html> |
| 2318 // title on the <html> | 2318 // title on the <html> |
| 2319 // <title> inside the <head> (of it was set through JS) | 2319 // <title> inside the <head> (of it was set through JS) |
| 2320 // name on the <html> | 2320 // name on the <html> |
| 2321 // For iframes: | 2321 // For iframes: |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2378 } | 2378 } |
| 2379 | 2379 |
| 2380 void AXNodeObject::ariaLabeledByText(Vector<AccessibilityText>& textOrder) const | 2380 void AXNodeObject::ariaLabeledByText(Vector<AccessibilityText>& textOrder) const |
| 2381 { | 2381 { |
| 2382 String ariaLabeledBy = ariaLabeledByAttribute(); | 2382 String ariaLabeledBy = ariaLabeledByAttribute(); |
| 2383 if (!ariaLabeledBy.isEmpty()) { | 2383 if (!ariaLabeledBy.isEmpty()) { |
| 2384 WillBeHeapVector<RawPtrWillBeMember<Element>> elements; | 2384 WillBeHeapVector<RawPtrWillBeMember<Element>> elements; |
| 2385 ariaLabeledByElements(elements); | 2385 ariaLabeledByElements(elements); |
| 2386 | 2386 |
| 2387 for (const auto& element : elements) { | 2387 for (const auto& element : elements) { |
| 2388 RefPtr<AXObject> axElement = axObjectCache()->getOrCreate(element); | 2388 RefPtr<AXObject> axElement = axObjectCache().getOrCreate(element); |
| 2389 textOrder.append(AccessibilityText(ariaLabeledBy, AlternativeText, a
xElement)); | 2389 textOrder.append(AccessibilityText(ariaLabeledBy, AlternativeText, a
xElement)); |
| 2390 } | 2390 } |
| 2391 } | 2391 } |
| 2392 } | 2392 } |
| 2393 | 2393 |
| 2394 } // namespace blink | 2394 } // namespace blink |
| OLD | NEW |