| 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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 #include "core/html/HTMLMediaElement.h" | 45 #include "core/html/HTMLMediaElement.h" |
| 46 #include "core/html/HTMLMeterElement.h" | 46 #include "core/html/HTMLMeterElement.h" |
| 47 #include "core/html/HTMLPlugInElement.h" | 47 #include "core/html/HTMLPlugInElement.h" |
| 48 #include "core/html/HTMLSelectElement.h" | 48 #include "core/html/HTMLSelectElement.h" |
| 49 #include "core/html/HTMLTableCaptionElement.h" | 49 #include "core/html/HTMLTableCaptionElement.h" |
| 50 #include "core/html/HTMLTableCellElement.h" | 50 #include "core/html/HTMLTableCellElement.h" |
| 51 #include "core/html/HTMLTableElement.h" | 51 #include "core/html/HTMLTableElement.h" |
| 52 #include "core/html/HTMLTableRowElement.h" | 52 #include "core/html/HTMLTableRowElement.h" |
| 53 #include "core/html/HTMLTableSectionElement.h" | 53 #include "core/html/HTMLTableSectionElement.h" |
| 54 #include "core/html/HTMLTextAreaElement.h" | 54 #include "core/html/HTMLTextAreaElement.h" |
| 55 #include "core/html/LabelsNodeList.h" |
| 55 #include "core/html/parser/HTMLParserIdioms.h" | 56 #include "core/html/parser/HTMLParserIdioms.h" |
| 56 #include "core/html/shadow/MediaControlElements.h" | 57 #include "core/html/shadow/MediaControlElements.h" |
| 57 #include "core/layout/LayoutBlockFlow.h" | 58 #include "core/layout/LayoutBlockFlow.h" |
| 58 #include "core/layout/LayoutObject.h" | 59 #include "core/layout/LayoutObject.h" |
| 59 #include "core/svg/SVGElement.h" | 60 #include "core/svg/SVGElement.h" |
| 60 #include "modules/accessibility/AXObjectCacheImpl.h" | 61 #include "modules/accessibility/AXObjectCacheImpl.h" |
| 61 #include "platform/UserGestureIndicator.h" | 62 #include "platform/UserGestureIndicator.h" |
| 62 #include "platform/text/PlatformLocale.h" | 63 #include "platform/text/PlatformLocale.h" |
| 63 #include "wtf/text/StringBuilder.h" | 64 #include "wtf/text/StringBuilder.h" |
| 64 | 65 |
| (...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 return false; | 639 return false; |
| 639 | 640 |
| 640 // An SVG root is focusable by default, but it's probably not interactive, s
o don't | 641 // An SVG root is focusable by default, but it's probably not interactive, s
o don't |
| 641 // include it. It can still be made accessible by giving it an ARIA role. | 642 // include it. It can still be made accessible by giving it an ARIA role. |
| 642 if (roleValue() == SVGRootRole) | 643 if (roleValue() == SVGRootRole) |
| 643 return false; | 644 return false; |
| 644 | 645 |
| 645 return true; | 646 return true; |
| 646 } | 647 } |
| 647 | 648 |
| 648 HTMLLabelElement* AXNodeObject::labelForElement(const Element* element) const | |
| 649 { | |
| 650 if (!element->isHTMLElement() || !toHTMLElement(element)->isLabelable()) | |
| 651 return 0; | |
| 652 | |
| 653 const AtomicString& id = element->getIdAttribute(); | |
| 654 if (!id.isEmpty()) { | |
| 655 if (HTMLLabelElement* labelFor = element->treeScope().labelElementForId(
id)) | |
| 656 return labelFor; | |
| 657 } | |
| 658 | |
| 659 HTMLLabelElement* labelWrappedElement = Traversal<HTMLLabelElement>::firstAn
cestor(*element); | |
| 660 if (labelWrappedElement && labelWrappedElement->control() == toLabelableElem
ent(element)) | |
| 661 return labelWrappedElement; | |
| 662 | |
| 663 return 0; | |
| 664 } | |
| 665 | |
| 666 AXObject* AXNodeObject::menuButtonForMenu() const | 649 AXObject* AXNodeObject::menuButtonForMenu() const |
| 667 { | 650 { |
| 668 Element* menuItem = menuItemElementForMenu(); | 651 Element* menuItem = menuItemElementForMenu(); |
| 669 | 652 |
| 670 if (menuItem) { | 653 if (menuItem) { |
| 671 // ARIA just has generic menu items. AppKit needs to know if this is a t
op level items like MenuBarButton or MenuBarItem | 654 // ARIA just has generic menu items. AppKit needs to know if this is a t
op level items like MenuBarButton or MenuBarItem |
| 672 AXObject* menuItemAX = axObjectCache().getOrCreate(menuItem); | 655 AXObject* menuItemAX = axObjectCache().getOrCreate(menuItem); |
| 673 if (menuItemAX && menuItemAX->isMenuButton()) | 656 if (menuItemAX && menuItemAX->isMenuButton()) |
| 674 return menuItemAX; | 657 return menuItemAX; |
| 675 } | 658 } |
| (...skipping 986 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1662 if (nameSources) { | 1645 if (nameSources) { |
| 1663 foundTextAlternative = true; | 1646 foundTextAlternative = true; |
| 1664 nameSources->last().text = textAlternative; | 1647 nameSources->last().text = textAlternative; |
| 1665 } else { | 1648 } else { |
| 1666 return textAlternative; | 1649 return textAlternative; |
| 1667 } | 1650 } |
| 1668 } | 1651 } |
| 1669 | 1652 |
| 1670 nameFrom = AXNameFromUninitialized; | 1653 nameFrom = AXNameFromUninitialized; |
| 1671 | 1654 |
| 1672 if (foundTextAlternative) { | 1655 if (nameSources && foundTextAlternative) { |
| 1673 for (size_t i = 0; i < nameSources->size(); ++i) { | 1656 for (size_t i = 0; i < nameSources->size(); ++i) { |
| 1674 if (!(*nameSources)[i].text.isNull() && !(*nameSources)[i].supersede
d) { | 1657 if (!(*nameSources)[i].text.isNull() && !(*nameSources)[i].supersede
d) { |
| 1675 NameSource& nameSource = (*nameSources)[i]; | 1658 NameSource& nameSource = (*nameSources)[i]; |
| 1676 nameFrom = nameSource.type; | 1659 nameFrom = nameSource.type; |
| 1677 if (!nameSource.relatedObjects.isEmpty()) | 1660 if (!nameSource.relatedObjects.isEmpty()) |
| 1678 *relatedObjects = nameSource.relatedObjects; | 1661 *relatedObjects = nameSource.relatedObjects; |
| 1679 return nameSource.text; | 1662 return nameSource.text; |
| 1680 } | 1663 } |
| 1681 } | 1664 } |
| 1682 } | 1665 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1756 // Step 2C from: http://www.w3.org/TR/accname-aam-1.1 | 1739 // Step 2C from: http://www.w3.org/TR/accname-aam-1.1 |
| 1757 const AtomicString& ariaLabel = getAttribute(aria_labelAttr); | 1740 const AtomicString& ariaLabel = getAttribute(aria_labelAttr); |
| 1758 if (!ariaLabel.isEmpty()) | 1741 if (!ariaLabel.isEmpty()) |
| 1759 return false; | 1742 return false; |
| 1760 | 1743 |
| 1761 // Based on http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessi
ble-name-and-description-calculation | 1744 // Based on http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessi
ble-name-and-description-calculation |
| 1762 // 5.1/5.5 Text inputs, Other labelable Elements | 1745 // 5.1/5.5 Text inputs, Other labelable Elements |
| 1763 HTMLElement* htmlElement = nullptr; | 1746 HTMLElement* htmlElement = nullptr; |
| 1764 if (getNode()->isHTMLElement()) | 1747 if (getNode()->isHTMLElement()) |
| 1765 htmlElement = toHTMLElement(getNode()); | 1748 htmlElement = toHTMLElement(getNode()); |
| 1766 if (htmlElement && htmlElement->isLabelable()) { | 1749 if (htmlElement && isLabelableElement(htmlElement)) { |
| 1767 HTMLLabelElement* label = labelForElement(htmlElement); | 1750 if (toLabelableElement(htmlElement)->labels() && toLabelableElement(html
Element)->labels()->length() > 0) |
| 1768 if (label) | |
| 1769 return true; | 1751 return true; |
| 1770 } | 1752 } |
| 1771 | 1753 |
| 1772 return false; | 1754 return false; |
| 1773 } | 1755 } |
| 1774 | 1756 |
| 1775 LayoutRect AXNodeObject::elementRect() const | 1757 LayoutRect AXNodeObject::elementRect() const |
| 1776 { | 1758 { |
| 1777 // First check if it has a custom rect, for example if this element is tied
to a canvas path. | 1759 // First check if it has a custom rect, for example if this element is tied
to a canvas path. |
| 1778 if (!m_explicitElementRect.isEmpty()) | 1760 if (!m_explicitElementRect.isEmpty()) |
| (...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2225 | 2207 |
| 2226 const HTMLInputElement* inputElement = nullptr; | 2208 const HTMLInputElement* inputElement = nullptr; |
| 2227 if (isHTMLInputElement(getNode())) | 2209 if (isHTMLInputElement(getNode())) |
| 2228 inputElement = toHTMLInputElement(getNode()); | 2210 inputElement = toHTMLInputElement(getNode()); |
| 2229 | 2211 |
| 2230 // 5.1/5.5 Text inputs, Other labelable Elements | 2212 // 5.1/5.5 Text inputs, Other labelable Elements |
| 2231 // If you change this logic, update AXNodeObject::nameFromLabelElement, too. | 2213 // If you change this logic, update AXNodeObject::nameFromLabelElement, too. |
| 2232 HTMLElement* htmlElement = nullptr; | 2214 HTMLElement* htmlElement = nullptr; |
| 2233 if (getNode()->isHTMLElement()) | 2215 if (getNode()->isHTMLElement()) |
| 2234 htmlElement = toHTMLElement(getNode()); | 2216 htmlElement = toHTMLElement(getNode()); |
| 2217 |
| 2235 if (htmlElement && htmlElement->isLabelable()) { | 2218 if (htmlElement && htmlElement->isLabelable()) { |
| 2236 // label | |
| 2237 nameFrom = AXNameFromRelatedElement; | 2219 nameFrom = AXNameFromRelatedElement; |
| 2238 if (nameSources) { | 2220 if (nameSources) { |
| 2239 nameSources->append(NameSource(*foundTextAlternative)); | 2221 nameSources->append(NameSource(*foundTextAlternative)); |
| 2240 nameSources->last().type = nameFrom; | 2222 nameSources->last().type = nameFrom; |
| 2241 nameSources->last().nativeSource = AXTextFromNativeHTMLLabel; | 2223 nameSources->last().nativeSource = AXTextFromNativeHTMLLabel; |
| 2242 } | 2224 } |
| 2243 HTMLLabelElement* label = labelForElement(htmlElement); | |
| 2244 if (label) { | |
| 2245 AXObject* labelAXObject = axObjectCache().getOrCreate(label); | |
| 2246 // Avoid an infinite loop for label wrapped | |
| 2247 if (labelAXObject && !visited.contains(labelAXObject)) { | |
| 2248 textAlternative = recursiveTextAlternative(*labelAXObject, false
, visited); | |
| 2249 | 2225 |
| 2250 if (relatedObjects) { | 2226 LabelsNodeList* labels = toLabelableElement(htmlElement)->labels(); |
| 2251 localRelatedObjects.append(new NameSourceRelatedObject(label
AXObject, textAlternative)); | 2227 if (labels && labels->length() > 0) { |
| 2252 *relatedObjects = localRelatedObjects; | 2228 HeapVector<Member<Element>> labelElements; |
| 2253 localRelatedObjects.clear(); | 2229 for (unsigned labelIndex = 0; labelIndex < labels->length(); ++label
Index) { |
| 2230 Element* label = labels->item(labelIndex); |
| 2231 if (nameSources) { |
| 2232 if (label->getAttribute(forAttr) == htmlElement->getIdAttrib
ute()) |
| 2233 nameSources->last().nativeSource = AXTextFromNativeHTMLL
abelFor; |
| 2234 else |
| 2235 nameSources->last().nativeSource = AXTextFromNativeHTMLL
abelWrapped; |
| 2254 } | 2236 } |
| 2237 labelElements.append(label); |
| 2238 } |
| 2255 | 2239 |
| 2240 textAlternative = textFromElements(false, visited, labelElements, re
latedObjects); |
| 2241 if (!textAlternative.isNull()) { |
| 2242 *foundTextAlternative = true; |
| 2256 if (nameSources) { | 2243 if (nameSources) { |
| 2257 NameSource& source = nameSources->last(); | 2244 NameSource& source = nameSources->last(); |
| 2258 source.relatedObjects = *relatedObjects; | 2245 source.relatedObjects = *relatedObjects; |
| 2259 source.text = textAlternative; | 2246 source.text = textAlternative; |
| 2260 if (label->getAttribute(forAttr) == htmlElement->getIdAttrib
ute()) | |
| 2261 source.nativeSource = AXTextFromNativeHTMLLabelFor; | |
| 2262 else | |
| 2263 source.nativeSource = AXTextFromNativeHTMLLabelWrapped; | |
| 2264 *foundTextAlternative = true; | |
| 2265 } else { | 2247 } else { |
| 2266 return textAlternative; | 2248 return textAlternative; |
| 2267 } | 2249 } |
| 2250 } else if (nameSources) { |
| 2251 nameSources->last().invalid = true; |
| 2268 } | 2252 } |
| 2269 } | 2253 } |
| 2270 } | 2254 } |
| 2271 | 2255 |
| 2272 // 5.2 input type="button", input type="submit" and input type="reset" | 2256 // 5.2 input type="button", input type="submit" and input type="reset" |
| 2273 if (inputElement && inputElement->isTextButton()) { | 2257 if (inputElement && inputElement->isTextButton()) { |
| 2274 // value attribue | 2258 // value attribue |
| 2275 nameFrom = AXNameFromValue; | 2259 nameFrom = AXNameFromValue; |
| 2276 if (nameSources) { | 2260 if (nameSources) { |
| 2277 nameSources->append(NameSource(*foundTextAlternative, valueAttr)); | 2261 nameSources->append(NameSource(*foundTextAlternative, valueAttr)); |
| (...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2847 return placeholder; | 2831 return placeholder; |
| 2848 } | 2832 } |
| 2849 | 2833 |
| 2850 DEFINE_TRACE(AXNodeObject) | 2834 DEFINE_TRACE(AXNodeObject) |
| 2851 { | 2835 { |
| 2852 visitor->trace(m_node); | 2836 visitor->trace(m_node); |
| 2853 AXObject::trace(visitor); | 2837 AXObject::trace(visitor); |
| 2854 } | 2838 } |
| 2855 | 2839 |
| 2856 } // namespace blink | 2840 } // namespace blink |
| OLD | NEW |