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 |