AX: In ARIA 1.1, the implicit value for aria-level on headings is 2
[WebKit-https.git] / Source / WebCore / accessibility / AccessibilityNodeObject.cpp
1 /*
2 * Copyright (C) 2012, Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1.  Redistributions of source code must retain the above copyright
9 *     notice, this list of conditions and the following disclaimer.
10 * 2.  Redistributions in binary form must reproduce the above copyright
11 *     notice, this list of conditions and the following disclaimer in the
12 *     documentation and/or other materials provided with the distribution.
13 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
14 *     its contributors may be used to endorse or promote products derived
15 *     from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "config.h"
30 #include "AccessibilityNodeObject.h"
31
32 #include "AXObjectCache.h"
33 #include "AccessibilityImageMapLink.h"
34 #include "AccessibilityList.h"
35 #include "AccessibilityListBox.h"
36 #include "AccessibilitySpinButton.h"
37 #include "AccessibilityTable.h"
38 #include "ElementIterator.h"
39 #include "EventNames.h"
40 #include "FloatRect.h"
41 #include "Frame.h"
42 #include "FrameLoader.h"
43 #include "FrameSelection.h"
44 #include "FrameView.h"
45 #include "HTMLCanvasElement.h"
46 #include "HTMLDetailsElement.h"
47 #include "HTMLFieldSetElement.h"
48 #include "HTMLFormElement.h"
49 #include "HTMLImageElement.h"
50 #include "HTMLInputElement.h"
51 #include "HTMLLabelElement.h"
52 #include "HTMLLegendElement.h"
53 #include "HTMLNames.h"
54 #include "HTMLParserIdioms.h"
55 #include "HTMLSelectElement.h"
56 #include "HTMLTextAreaElement.h"
57 #include "HTMLTextFormControlElement.h"
58 #include "LabelableElement.h"
59 #include "LocalizedStrings.h"
60 #include "MathMLElement.h"
61 #include "MathMLNames.h"
62 #include "NodeList.h"
63 #include "NodeTraversal.h"
64 #include "Page.h"
65 #include "ProgressTracker.h"
66 #include "RenderImage.h"
67 #include "RenderView.h"
68 #include "SVGElement.h"
69 #include "SVGNames.h"
70 #include "Text.h"
71 #include "TextControlInnerElements.h"
72 #include "UserGestureIndicator.h"
73 #include "VisibleUnits.h"
74 #include "Widget.h"
75 #include "htmlediting.h"
76 #include <wtf/StdLibExtras.h>
77 #include <wtf/text/StringBuilder.h>
78 #include <wtf/unicode/CharacterNames.h>
79
80 namespace WebCore {
81
82 using namespace HTMLNames;
83
84 static String accessibleNameForNode(Node* node, Node* labelledbyNode = nullptr);
85
86 AccessibilityNodeObject::AccessibilityNodeObject(Node* node)
87     : AccessibilityObject()
88     , m_ariaRole(UnknownRole)
89     , m_childrenDirty(false)
90     , m_roleForMSAA(UnknownRole)
91 #ifndef NDEBUG
92     , m_initialized(false)
93 #endif
94     , m_node(node)
95 {
96 }
97
98 AccessibilityNodeObject::~AccessibilityNodeObject()
99 {
100     ASSERT(isDetached());
101 }
102
103 void AccessibilityNodeObject::init()
104 {
105 #ifndef NDEBUG
106     ASSERT(!m_initialized);
107     m_initialized = true;
108 #endif
109     m_role = determineAccessibilityRole();
110 }
111
112 Ref<AccessibilityNodeObject> AccessibilityNodeObject::create(Node* node)
113 {
114     return adoptRef(*new AccessibilityNodeObject(node));
115 }
116
117 void AccessibilityNodeObject::detach(AccessibilityDetachmentType detachmentType, AXObjectCache* cache)
118 {
119     // AccessibilityObject calls clearChildren.
120     AccessibilityObject::detach(detachmentType, cache);
121     m_node = nullptr;
122 }
123
124 void AccessibilityNodeObject::childrenChanged()
125 {
126     // This method is meant as a quick way of marking a portion of the accessibility tree dirty.
127     if (!node() && !renderer())
128         return;
129
130     AXObjectCache* cache = axObjectCache();
131     if (!cache)
132         return;
133     cache->postNotification(this, document(), AXObjectCache::AXChildrenChanged);
134
135     // Go up the accessibility parent chain, but only if the element already exists. This method is
136     // called during render layouts, minimal work should be done. 
137     // If AX elements are created now, they could interrogate the render tree while it's in a funky state.
138     // At the same time, process ARIA live region changes.
139     for (AccessibilityObject* parent = this; parent; parent = parent->parentObjectIfExists()) {
140         parent->setNeedsToUpdateChildren();
141
142         // These notifications always need to be sent because screenreaders are reliant on them to perform. 
143         // In other words, they need to be sent even when the screen reader has not accessed this live region since the last update.
144
145         // If this element supports ARIA live regions, then notify the AT of changes.
146         // Sometimes this function can be called many times within a short period of time, leading to posting too many AXLiveRegionChanged
147         // notifications. To fix this, we used a timer to make sure we only post one notification for the children changes within a pre-defined
148         // time interval.
149         if (parent->supportsARIALiveRegion())
150             cache->postLiveRegionChangeNotification(parent);
151         
152         // If this element is an ARIA text control, notify the AT of changes.
153         if (parent->isNonNativeTextControl())
154             cache->postNotification(parent, parent->document(), AXObjectCache::AXValueChanged);
155     }
156 }
157
158 void AccessibilityNodeObject::updateAccessibilityRole()
159 {
160     bool ignoredStatus = accessibilityIsIgnored();
161     m_role = determineAccessibilityRole();
162     
163     // The AX hierarchy only needs to be updated if the ignored status of an element has changed.
164     if (ignoredStatus != accessibilityIsIgnored())
165         childrenChanged();
166 }
167     
168 AccessibilityObject* AccessibilityNodeObject::firstChild() const
169 {
170     if (!node())
171         return nullptr;
172     
173     Node* firstChild = node()->firstChild();
174
175     if (!firstChild)
176         return nullptr;
177     
178     return axObjectCache()->getOrCreate(firstChild);
179 }
180
181 AccessibilityObject* AccessibilityNodeObject::lastChild() const
182 {
183     if (!node())
184         return nullptr;
185     
186     Node* lastChild = node()->lastChild();
187     if (!lastChild)
188         return nullptr;
189     
190     return axObjectCache()->getOrCreate(lastChild);
191 }
192
193 AccessibilityObject* AccessibilityNodeObject::previousSibling() const
194 {
195     if (!node())
196         return nullptr;
197
198     Node* previousSibling = node()->previousSibling();
199     if (!previousSibling)
200         return nullptr;
201
202     return axObjectCache()->getOrCreate(previousSibling);
203 }
204
205 AccessibilityObject* AccessibilityNodeObject::nextSibling() const
206 {
207     if (!node())
208         return nullptr;
209
210     Node* nextSibling = node()->nextSibling();
211     if (!nextSibling)
212         return nullptr;
213
214     return axObjectCache()->getOrCreate(nextSibling);
215 }
216     
217 AccessibilityObject* AccessibilityNodeObject::parentObjectIfExists() const
218 {
219     return parentObject();
220 }
221     
222 AccessibilityObject* AccessibilityNodeObject::parentObject() const
223 {
224     if (!node())
225         return nullptr;
226
227     Node* parentObj = node()->parentNode();
228     if (!parentObj)
229         return nullptr;
230     
231     if (AXObjectCache* cache = axObjectCache())
232         return cache->getOrCreate(parentObj);
233     
234     return nullptr;
235 }
236
237 LayoutRect AccessibilityNodeObject::elementRect() const
238 {
239     return boundingBoxRect();
240 }
241
242 LayoutRect AccessibilityNodeObject::boundingBoxRect() const
243 {
244     // AccessibilityNodeObjects have no mechanism yet to return a size or position.
245     // For now, let's return the position of the ancestor that does have a position,
246     // and make it the width of that parent, and about the height of a line of text, so that it's clear the object is a child of the parent.
247     
248     LayoutRect boundingBox;
249     
250     for (AccessibilityObject* positionProvider = parentObject(); positionProvider; positionProvider = positionProvider->parentObject()) {
251         if (positionProvider->isAccessibilityRenderObject()) {
252             LayoutRect parentRect = positionProvider->elementRect();
253             boundingBox.setSize(LayoutSize(parentRect.width(), LayoutUnit(std::min(10.0f, parentRect.height().toFloat()))));
254             boundingBox.setLocation(parentRect.location());
255             break;
256         }
257     }
258     
259     return boundingBox;
260 }
261
262 void AccessibilityNodeObject::setNode(Node* node)
263 {
264     m_node = node;
265 }
266
267 Document* AccessibilityNodeObject::document() const
268 {
269     if (!node())
270         return nullptr;
271     return &node()->document();
272 }
273
274 AccessibilityRole AccessibilityNodeObject::determineAccessibilityRole()
275 {
276     if (!node())
277         return UnknownRole;
278
279     if ((m_ariaRole = determineAriaRoleAttribute()) != UnknownRole)
280         return m_ariaRole;
281     
282     if (node()->isLink())
283         return WebCoreLinkRole;
284     if (node()->isTextNode())
285         return StaticTextRole;
286     if (node()->hasTagName(buttonTag))
287         return buttonRoleType();
288     if (is<HTMLInputElement>(*node())) {
289         HTMLInputElement& input = downcast<HTMLInputElement>(*node());
290         if (input.isCheckbox())
291             return CheckBoxRole;
292         if (input.isRadioButton())
293             return RadioButtonRole;
294         if (input.isTextButton())
295             return buttonRoleType();
296         if (input.isRangeControl())
297             return SliderRole;
298         if (input.isInputTypeHidden())
299             return IgnoredRole;
300         if (input.isSearchField())
301             return SearchFieldRole;
302 #if ENABLE(INPUT_TYPE_COLOR)
303         if (input.isColorControl())
304             return ColorWellRole;
305 #endif
306         return TextFieldRole;
307     }
308     if (node()->hasTagName(selectTag)) {
309         HTMLSelectElement& selectElement = downcast<HTMLSelectElement>(*node());
310         return selectElement.multiple() ? ListBoxRole : PopUpButtonRole;
311     }
312     if (is<HTMLTextAreaElement>(*node()))
313         return TextAreaRole;
314     if (headingLevel())
315         return HeadingRole;
316     if (node()->hasTagName(blockquoteTag))
317         return BlockquoteRole;
318     if (node()->hasTagName(divTag))
319         return DivRole;
320     if (node()->hasTagName(pTag))
321         return ParagraphRole;
322     if (is<HTMLLabelElement>(*node()))
323         return LabelRole;
324     if (is<Element>(*node()) && downcast<Element>(*node()).isFocusable())
325         return GroupRole;
326     
327     return UnknownRole;
328 }
329
330 void AccessibilityNodeObject::insertChild(AccessibilityObject* child, unsigned index)
331 {
332     if (!child)
333         return;
334     
335     // If the parent is asking for this child's children, then either it's the first time (and clearing is a no-op),
336     // or its visibility has changed. In the latter case, this child may have a stale child cached.
337     // This can prevent aria-hidden changes from working correctly. Hence, whenever a parent is getting children, ensure data is not stale.
338     child->clearChildren();
339     
340     if (child->accessibilityIsIgnored()) {
341         const auto& children = child->children();
342         size_t length = children.size();
343         for (size_t i = 0; i < length; ++i)
344             m_children.insert(index + i, children[i]);
345     } else {
346         ASSERT(child->parentObject() == this);
347         m_children.insert(index, child);
348     }
349 }
350
351 void AccessibilityNodeObject::addChild(AccessibilityObject* child)
352 {
353     insertChild(child, m_children.size());
354 }
355
356 void AccessibilityNodeObject::addChildren()
357 {
358     // If the need to add more children in addition to existing children arises, 
359     // childrenChanged should have been called, leaving the object with no children.
360     ASSERT(!m_haveChildren); 
361     
362     if (!m_node)
363         return;
364
365     m_haveChildren = true;
366
367     // The only time we add children from the DOM tree to a node with a renderer is when it's a canvas.
368     if (renderer() && !m_node->hasTagName(canvasTag))
369         return;
370     
371     for (Node* child = m_node->firstChild(); child; child = child->nextSibling())
372         addChild(axObjectCache()->getOrCreate(child));
373 }
374
375 bool AccessibilityNodeObject::canHaveChildren() const
376 {
377     // If this is an AccessibilityRenderObject, then it's okay if this object
378     // doesn't have a node - there are some renderers that don't have associated
379     // nodes, like scroll areas and css-generated text.
380     if (!node() && !isAccessibilityRenderObject())
381         return false;
382
383     // When <noscript> is not being used (its renderer() == 0), ignore its children.
384     if (node() && !renderer() && node()->hasTagName(noscriptTag))
385         return false;
386     
387     // Elements that should not have children
388     switch (roleValue()) {
389     case ImageRole:
390     case ButtonRole:
391     case PopUpButtonRole:
392     case CheckBoxRole:
393     case RadioButtonRole:
394     case TabRole:
395     case ToggleButtonRole:
396     case StaticTextRole:
397     case ListBoxOptionRole:
398     case ScrollBarRole:
399     case ProgressIndicatorRole:
400     case SwitchRole:
401         return false;
402     default:
403         return true;
404     }
405 }
406
407 bool AccessibilityNodeObject::computeAccessibilityIsIgnored() const
408 {
409 #ifndef NDEBUG
410     // Double-check that an AccessibilityObject is never accessed before
411     // it's been initialized.
412     ASSERT(m_initialized);
413 #endif
414
415     // Handle non-rendered text that is exposed through aria-hidden=false.
416     if (m_node && m_node->isTextNode() && !renderer()) {
417         // Fallback content in iframe nodes should be ignored.
418         if (m_node->parentNode() && m_node->parentNode()->hasTagName(iframeTag) && m_node->parentNode()->renderer())
419             return true;
420
421         // Whitespace only text elements should be ignored when they have no renderer.
422         String string = stringValue().stripWhiteSpace().simplifyWhiteSpace();
423         if (!string.length())
424             return true;
425     }
426
427     AccessibilityObjectInclusion decision = defaultObjectInclusion();
428     if (decision == IncludeObject)
429         return false;
430     if (decision == IgnoreObject)
431         return true;
432     // If this element is within a parent that cannot have children, it should not be exposed.
433     if (isDescendantOfBarrenParent())
434         return true;
435
436     if (roleValue() == IgnoredRole)
437         return true;
438     
439     return m_role == UnknownRole;
440 }
441
442 bool AccessibilityNodeObject::canvasHasFallbackContent() const
443 {
444     Node* node = this->node();
445     if (!is<HTMLCanvasElement>(node))
446         return false;
447     HTMLCanvasElement& canvasElement = downcast<HTMLCanvasElement>(*node);
448     // If it has any children that are elements, we'll assume it might be fallback
449     // content. If it has no children or its only children are not elements
450     // (e.g. just text nodes), it doesn't have fallback content.
451     return childrenOfType<Element>(canvasElement).first();
452 }
453
454 bool AccessibilityNodeObject::isImageButton() const
455 {
456     return isNativeImage() && isButton();
457 }
458
459 bool AccessibilityNodeObject::isNativeTextControl() const
460 {
461     Node* node = this->node();
462     if (!node)
463         return false;
464
465     if (is<HTMLTextAreaElement>(*node))
466         return true;
467
468     if (is<HTMLInputElement>(*node)) {
469         HTMLInputElement& input = downcast<HTMLInputElement>(*node);
470         return input.isText() || input.isNumberField();
471     }
472
473     return false;
474 }
475
476 bool AccessibilityNodeObject::isSearchField() const
477 {
478     Node* node = this->node();
479     if (!node)
480         return false;
481
482     if (roleValue() == SearchFieldRole)
483         return true;
484
485     if (!is<HTMLInputElement>(*node))
486         return false;
487
488     auto& inputElement = downcast<HTMLInputElement>(*node);
489
490     // Some websites don't label their search fields as such. However, they will
491     // use the word "search" in either the form or input type. This won't catch every case,
492     // but it will catch google.com for example.
493
494     // Check the node name of the input type, sometimes it's "search".
495     const AtomicString& nameAttribute = getAttribute(nameAttr);
496     if (nameAttribute.contains("search", false))
497         return true;
498
499     // Check the form action and the name, which will sometimes be "search".
500     auto* form = inputElement.form();
501     if (form && (form->name().contains("search", false) || form->action().contains("search", false)))
502         return true;
503
504     return false;
505 }
506
507 bool AccessibilityNodeObject::isNativeImage() const
508 {
509     Node* node = this->node();
510     if (!node)
511         return false;
512
513     if (is<HTMLImageElement>(*node))
514         return true;
515
516     if (node->hasTagName(appletTag) || node->hasTagName(embedTag) || node->hasTagName(objectTag))
517         return true;
518
519     if (is<HTMLInputElement>(*node)) {
520         HTMLInputElement& input = downcast<HTMLInputElement>(*node);
521         return input.isImageButton();
522     }
523
524     return false;
525 }
526
527 bool AccessibilityNodeObject::isImage() const
528 {
529     return roleValue() == ImageRole;
530 }
531
532 bool AccessibilityNodeObject::isPasswordField() const
533 {
534     auto* node = this->node();
535     if (!is<HTMLInputElement>(node))
536         return false;
537
538     if (ariaRoleAttribute() != UnknownRole)
539         return false;
540
541     return downcast<HTMLInputElement>(*node).isPasswordField();
542 }
543
544 AccessibilityObject* AccessibilityNodeObject::passwordFieldOrContainingPasswordField()
545 {
546     Node* node = this->node();
547     if (!node)
548         return nullptr;
549
550     if (is<HTMLInputElement>(*node) && downcast<HTMLInputElement>(*node).isPasswordField())
551         return this;
552
553     auto* element = node->shadowHost();
554     if (!is<HTMLInputElement>(element))
555         return nullptr;
556
557     if (auto* cache = axObjectCache())
558         return cache->getOrCreate(element);
559
560     return nullptr;
561 }
562
563 bool AccessibilityNodeObject::isInputImage() const
564 {
565     Node* node = this->node();
566     if (is<HTMLInputElement>(node) && roleValue() == ButtonRole) {
567         HTMLInputElement& input = downcast<HTMLInputElement>(*node);
568         return input.isImageButton();
569     }
570
571     return false;
572 }
573
574 bool AccessibilityNodeObject::isProgressIndicator() const
575 {
576     return roleValue() == ProgressIndicatorRole;
577 }
578
579 bool AccessibilityNodeObject::isSlider() const
580 {
581     return roleValue() == SliderRole;
582 }
583
584 bool AccessibilityNodeObject::isMenuRelated() const
585 {
586     switch (roleValue()) {
587     case MenuRole:
588     case MenuBarRole:
589     case MenuButtonRole:
590     case MenuItemRole:
591     case MenuItemCheckboxRole:
592     case MenuItemRadioRole:
593         return true;
594     default:
595         return false;
596     }
597 }
598
599 bool AccessibilityNodeObject::isMenu() const
600 {
601     return roleValue() == MenuRole;
602 }
603
604 bool AccessibilityNodeObject::isMenuBar() const
605 {
606     return roleValue() == MenuBarRole;
607 }
608
609 bool AccessibilityNodeObject::isMenuButton() const
610 {
611     return roleValue() == MenuButtonRole;
612 }
613
614 bool AccessibilityNodeObject::isMenuItem() const
615 {
616     switch (roleValue()) {
617     case MenuItemRole:
618     case MenuItemRadioRole:
619     case MenuItemCheckboxRole:
620         return true;
621     default:
622         return false;
623     }
624 }
625
626 bool AccessibilityNodeObject::isNativeCheckboxOrRadio() const
627 {
628     Node* node = this->node();
629     if (!is<HTMLInputElement>(node))
630         return false;
631
632     auto& input = downcast<HTMLInputElement>(*node);
633     return input.isCheckbox() || input.isRadioButton();
634 }
635
636 bool AccessibilityNodeObject::isEnabled() const
637 {
638     // ARIA says that the disabled status applies to the current element and all descendant elements.
639     for (AccessibilityObject* object = const_cast<AccessibilityNodeObject*>(this); object; object = object->parentObject()) {
640         const AtomicString& disabledStatus = object->getAttribute(aria_disabledAttr);
641         if (equalLettersIgnoringASCIICase(disabledStatus, "true"))
642             return false;
643         if (equalLettersIgnoringASCIICase(disabledStatus, "false"))
644             break;
645     }
646     
647     if (roleValue() == HorizontalRuleRole)
648         return false;
649     
650     Node* node = this->node();
651     if (!is<Element>(node))
652         return true;
653
654     return !downcast<Element>(*node).isDisabledFormControl();
655 }
656
657 bool AccessibilityNodeObject::isIndeterminate() const
658 {
659     return equalLettersIgnoringASCIICase(getAttribute(indeterminateAttr), "true");
660 }
661
662 bool AccessibilityNodeObject::isPressed() const
663 {
664     if (!isButton())
665         return false;
666
667     Node* node = this->node();
668     if (!node)
669         return false;
670
671     // If this is an toggle button, check the aria-pressed attribute rather than node()->active()
672     if (isToggleButton())
673         return equalLettersIgnoringASCIICase(getAttribute(aria_pressedAttr), "true");
674
675     if (!is<Element>(*node))
676         return false;
677     return downcast<Element>(*node).active();
678 }
679
680 bool AccessibilityNodeObject::isChecked() const
681 {
682     Node* node = this->node();
683     if (!node)
684         return false;
685
686     // First test for native checkedness semantics
687     if (is<HTMLInputElement>(*node))
688         return downcast<HTMLInputElement>(*node).shouldAppearChecked();
689
690     // Else, if this is an ARIA checkbox or radio, respect the aria-checked attribute
691     bool validRole = false;
692     switch (ariaRoleAttribute()) {
693     case RadioButtonRole:
694     case CheckBoxRole:
695     case MenuItemRole:
696     case MenuItemCheckboxRole:
697     case MenuItemRadioRole:
698     case SwitchRole:
699         validRole = true;
700         break;
701     default:
702         break;
703     }
704     
705     if (validRole && equalLettersIgnoringASCIICase(getAttribute(aria_checkedAttr), "true"))
706         return true;
707
708     return false;
709 }
710
711 bool AccessibilityNodeObject::isHovered() const
712 {
713     Node* node = this->node();
714     return is<Element>(node) && downcast<Element>(*node).hovered();
715 }
716
717 bool AccessibilityNodeObject::isMultiSelectable() const
718 {
719     const AtomicString& ariaMultiSelectable = getAttribute(aria_multiselectableAttr);
720     if (equalLettersIgnoringASCIICase(ariaMultiSelectable, "true"))
721         return true;
722     if (equalLettersIgnoringASCIICase(ariaMultiSelectable, "false"))
723         return false;
724     
725     return node() && node()->hasTagName(selectTag) && downcast<HTMLSelectElement>(*node()).multiple();
726 }
727
728 bool AccessibilityNodeObject::isRequired() const
729 {
730     // Explicit aria-required values should trump native required attributes.
731     const AtomicString& requiredValue = getAttribute(aria_requiredAttr);
732     if (equalLettersIgnoringASCIICase(requiredValue, "true"))
733         return true;
734     if (equalLettersIgnoringASCIICase(requiredValue, "false"))
735         return false;
736
737     Node* n = this->node();
738     if (is<HTMLFormControlElement>(n))
739         return downcast<HTMLFormControlElement>(*n).isRequired();
740
741     return false;
742 }
743
744 bool AccessibilityNodeObject::supportsRequiredAttribute() const
745 {
746     switch (roleValue()) {
747     case ButtonRole:
748         return isFileUploadButton();
749     case CellRole:
750     case ColumnHeaderRole:
751     case CheckBoxRole:
752     case ComboBoxRole:
753     case GridRole:
754     case GridCellRole:
755     case IncrementorRole:
756     case ListBoxRole:
757     case PopUpButtonRole:
758     case RadioButtonRole:
759     case RadioGroupRole:
760     case RowHeaderRole:
761     case SliderRole:
762     case SpinButtonRole:
763     case TableHeaderContainerRole:
764     case TextAreaRole:
765     case TextFieldRole:
766     case ToggleButtonRole:
767         return true;
768     default:
769         return false;
770     }
771 }
772
773 int AccessibilityNodeObject::headingLevel() const
774 {
775     // headings can be in block flow and non-block flow
776     Node* node = this->node();
777     if (!node)
778         return false;
779
780     if (isHeading()) {
781         int ariaLevel = getAttribute(aria_levelAttr).toInt();
782         if (ariaLevel > 0)
783             return ariaLevel;
784     }
785
786     if (node->hasTagName(h1Tag))
787         return 1;
788
789     if (node->hasTagName(h2Tag))
790         return 2;
791
792     if (node->hasTagName(h3Tag))
793         return 3;
794
795     if (node->hasTagName(h4Tag))
796         return 4;
797
798     if (node->hasTagName(h5Tag))
799         return 5;
800
801     if (node->hasTagName(h6Tag))
802         return 6;
803
804     // The implicit value of aria-level is 2 for the heading role.
805     // https://www.w3.org/TR/wai-aria-1.1/#heading
806     if (ariaRoleAttribute() == HeadingRole)
807         return 2;
808
809     return 0;
810 }
811
812 String AccessibilityNodeObject::valueDescription() const
813 {
814     if (!isRangeControl())
815         return String();
816
817     return getAttribute(aria_valuetextAttr).string();
818 }
819
820 float AccessibilityNodeObject::valueForRange() const
821 {
822     if (is<HTMLInputElement>(node())) {
823         HTMLInputElement& input = downcast<HTMLInputElement>(*node());
824         if (input.isRangeControl())
825             return input.valueAsNumber();
826     }
827
828     if (!isRangeControl())
829         return 0.0f;
830
831     return getAttribute(aria_valuenowAttr).toFloat();
832 }
833
834 float AccessibilityNodeObject::maxValueForRange() const
835 {
836     if (is<HTMLInputElement>(node())) {
837         HTMLInputElement& input = downcast<HTMLInputElement>(*node());
838         if (input.isRangeControl())
839             return input.maximum();
840     }
841
842     if (!isRangeControl())
843         return 0.0f;
844
845     return getAttribute(aria_valuemaxAttr).toFloat();
846 }
847
848 float AccessibilityNodeObject::minValueForRange() const
849 {
850     if (is<HTMLInputElement>(node())) {
851         HTMLInputElement& input = downcast<HTMLInputElement>(*node());
852         if (input.isRangeControl())
853             return input.minimum();
854     }
855
856     if (!isRangeControl())
857         return 0.0f;
858
859     return getAttribute(aria_valueminAttr).toFloat();
860 }
861
862 float AccessibilityNodeObject::stepValueForRange() const
863 {
864     return getAttribute(stepAttr).toFloat();
865 }
866
867 bool AccessibilityNodeObject::isHeading() const
868 {
869     return roleValue() == HeadingRole;
870 }
871
872 bool AccessibilityNodeObject::isLink() const
873 {
874     return roleValue() == WebCoreLinkRole;
875 }
876
877 bool AccessibilityNodeObject::isControl() const
878 {
879     Node* node = this->node();
880     if (!node)
881         return false;
882
883     return is<HTMLFormControlElement>(*node) || AccessibilityObject::isARIAControl(ariaRoleAttribute());
884 }
885
886 bool AccessibilityNodeObject::isFieldset() const
887 {
888     Node* node = this->node();
889     if (!node)
890         return false;
891
892     return node->hasTagName(fieldsetTag);
893 }
894
895 bool AccessibilityNodeObject::isGroup() const
896 {
897     return roleValue() == GroupRole;
898 }
899
900 AccessibilityObject* AccessibilityNodeObject::selectedRadioButton()
901 {
902     if (!isRadioGroup())
903         return nullptr;
904
905     // Find the child radio button that is selected (ie. the intValue == 1).
906     for (const auto& child : children()) {
907         if (child->roleValue() == RadioButtonRole && child->checkboxOrRadioValue() == ButtonStateOn)
908             return child.get();
909     }
910     return nullptr;
911 }
912
913 AccessibilityObject* AccessibilityNodeObject::selectedTabItem()
914 {
915     if (!isTabList())
916         return nullptr;
917
918     // Find the child tab item that is selected (ie. the intValue == 1).
919     AccessibilityObject::AccessibilityChildrenVector tabs;
920     tabChildren(tabs);
921
922     for (const auto& child : children()) {
923         if (child->isTabItem() && child->isChecked())
924             return child.get();
925     }
926     return nullptr;
927 }
928
929 AccessibilityButtonState AccessibilityNodeObject::checkboxOrRadioValue() const
930 {
931     if (isNativeCheckboxOrRadio())
932         return isIndeterminate() ? ButtonStateMixed : isChecked() ? ButtonStateOn : ButtonStateOff;
933
934     return AccessibilityObject::checkboxOrRadioValue();
935 }
936
937 Element* AccessibilityNodeObject::anchorElement() const
938 {
939     Node* node = this->node();
940     if (!node)
941         return nullptr;
942
943     AXObjectCache* cache = axObjectCache();
944
945     // search up the DOM tree for an anchor element
946     // NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElement
947     for ( ; node; node = node->parentNode()) {
948         if (is<HTMLAnchorElement>(*node) || (node->renderer() && cache->getOrCreate(node->renderer())->isLink()))
949             return downcast<Element>(node);
950     }
951
952     return nullptr;
953 }
954
955 static bool isNodeActionElement(Node* node)
956 {
957     if (is<HTMLInputElement>(*node)) {
958         HTMLInputElement& input = downcast<HTMLInputElement>(*node);
959         if (!input.isDisabledFormControl() && (input.isRadioButton() || input.isCheckbox() || input.isTextButton() || input.isFileUpload() || input.isImageButton()))
960             return true;
961     } else if (node->hasTagName(buttonTag) || node->hasTagName(selectTag))
962         return true;
963
964     return false;
965 }
966     
967 static Element* nativeActionElement(Node* start)
968 {
969     if (!start)
970         return nullptr;
971     
972     // Do a deep-dive to see if any nodes should be used as the action element.
973     // We have to look at Nodes, since this method should only be called on objects that do not have children (like buttons).
974     // It solves the problem when authors put role="button" on a group and leave the actual button inside the group.
975     
976     for (Node* child = start->firstChild(); child; child = child->nextSibling()) {
977         if (isNodeActionElement(child))
978             return downcast<Element>(child);
979
980         if (Element* subChild = nativeActionElement(child))
981             return subChild;
982     }
983     return nullptr;
984 }
985     
986 Element* AccessibilityNodeObject::actionElement() const
987 {
988     Node* node = this->node();
989     if (!node)
990         return nullptr;
991
992     if (isNodeActionElement(node))
993         return downcast<Element>(node);
994     
995     if (AccessibilityObject::isARIAInput(ariaRoleAttribute()))
996         return downcast<Element>(node);
997
998     switch (roleValue()) {
999     case ButtonRole:
1000     case PopUpButtonRole:
1001     case ToggleButtonRole:
1002     case TabRole:
1003     case MenuItemRole:
1004     case MenuItemCheckboxRole:
1005     case MenuItemRadioRole:
1006     case ListItemRole:
1007         // Check if the author is hiding the real control element inside the ARIA element.
1008         if (Element* nativeElement = nativeActionElement(node))
1009             return nativeElement;
1010         return downcast<Element>(node);
1011     default:
1012         break;
1013     }
1014     
1015     Element* elt = anchorElement();
1016     if (!elt)
1017         elt = mouseButtonListener();
1018     return elt;
1019 }
1020
1021 Element* AccessibilityNodeObject::mouseButtonListener(MouseButtonListenerResultFilter filter) const
1022 {
1023     Node* node = this->node();
1024     if (!node)
1025         return nullptr;
1026
1027     // check if our parent is a mouse button listener
1028     // FIXME: Do the continuation search like anchorElement does
1029     for (auto& element : elementLineage(is<Element>(*node) ? downcast<Element>(node) : node->parentElement())) {
1030         // If we've reached the body and this is not a control element, do not expose press action for this element unless filter is IncludeBodyElement.
1031         // It can cause false positives, where every piece of text is labeled as accepting press actions.
1032         if (element.hasTagName(bodyTag) && isStaticText() && filter == ExcludeBodyElement)
1033             break;
1034         
1035         if (element.hasEventListeners(eventNames().clickEvent) || element.hasEventListeners(eventNames().mousedownEvent) || element.hasEventListeners(eventNames().mouseupEvent))
1036             return &element;
1037     }
1038
1039     return nullptr;
1040 }
1041
1042 bool AccessibilityNodeObject::isDescendantOfBarrenParent() const
1043 {
1044     for (AccessibilityObject* object = parentObject(); object; object = object->parentObject()) {
1045         if (!object->canHaveChildren())
1046             return true;
1047     }
1048
1049     return false;
1050 }
1051
1052 void AccessibilityNodeObject::alterSliderValue(bool increase)
1053 {
1054     if (roleValue() != SliderRole)
1055         return;
1056
1057     if (!getAttribute(stepAttr).isEmpty())
1058         changeValueByStep(increase);
1059     else
1060         changeValueByPercent(increase ? 5 : -5);
1061 }
1062     
1063 void AccessibilityNodeObject::increment()
1064 {
1065     UserGestureIndicator gestureIndicator(ProcessingUserGesture, document());
1066     alterSliderValue(true);
1067 }
1068
1069 void AccessibilityNodeObject::decrement()
1070 {
1071     UserGestureIndicator gestureIndicator(ProcessingUserGesture, document());
1072     alterSliderValue(false);
1073 }
1074
1075 void AccessibilityNodeObject::changeValueByStep(bool increase)
1076 {
1077     float step = stepValueForRange();
1078     float value = valueForRange();
1079
1080     value += increase ? step : -step;
1081
1082     setValue(String::number(value));
1083
1084     axObjectCache()->postNotification(node(), AXObjectCache::AXValueChanged);
1085 }
1086
1087 void AccessibilityNodeObject::changeValueByPercent(float percentChange)
1088 {
1089     float range = maxValueForRange() - minValueForRange();
1090     float step = range * (percentChange / 100);
1091     float value = valueForRange();
1092
1093     // Make sure the specified percent will cause a change of one integer step or larger.
1094     if (fabs(step) < 1)
1095         step = fabs(percentChange) * (1 / percentChange);
1096
1097     value += step;
1098     setValue(String::number(value));
1099
1100     axObjectCache()->postNotification(node(), AXObjectCache::AXValueChanged);
1101 }
1102
1103 bool AccessibilityNodeObject::isGenericFocusableElement() const
1104 {
1105     if (!canSetFocusAttribute())
1106         return false;
1107
1108     // If it's a control, it's not generic.
1109     if (isControl())
1110         return false;
1111     
1112     AccessibilityRole role = roleValue();
1113     if (role == VideoRole || role == AudioRole)
1114         return false;
1115
1116     // If it has an aria role, it's not generic.
1117     if (m_ariaRole != UnknownRole)
1118         return false;
1119
1120     // If the content editable attribute is set on this element, that's the reason
1121     // it's focusable, and existing logic should handle this case already - so it's not a
1122     // generic focusable element.
1123
1124     if (hasContentEditableAttributeSet())
1125         return false;
1126
1127     // The web area and body element are both focusable, but existing logic handles these
1128     // cases already, so we don't need to include them here.
1129     if (role == WebAreaRole)
1130         return false;
1131     if (node() && node()->hasTagName(bodyTag))
1132         return false;
1133
1134     // An SVG root is focusable by default, but it's probably not interactive, so don't
1135     // include it. It can still be made accessible by giving it an ARIA role.
1136     if (role == SVGRootRole)
1137         return false;
1138
1139     return true;
1140 }
1141
1142 HTMLLabelElement* AccessibilityNodeObject::labelForElement(Element* element) const
1143 {
1144     if (!is<HTMLElement>(*element) || !downcast<HTMLElement>(*element).isLabelable())
1145         return nullptr;
1146
1147     const AtomicString& id = element->getIdAttribute();
1148     if (!id.isEmpty()) {
1149         if (HTMLLabelElement* label = element->treeScope().labelElementForId(id))
1150             return label;
1151     }
1152
1153     return ancestorsOfType<HTMLLabelElement>(*element).first();
1154 }
1155
1156 String AccessibilityNodeObject::ariaAccessibilityDescription() const
1157 {
1158     String ariaLabeledBy = ariaLabeledByAttribute();
1159     if (!ariaLabeledBy.isEmpty())
1160         return ariaLabeledBy;
1161
1162     const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
1163     if (!ariaLabel.isEmpty())
1164         return ariaLabel;
1165
1166     return String();
1167 }
1168
1169 static Element* siblingWithAriaRole(Node* node, const char* role)
1170 {
1171     // FIXME: Either we should add a null check here or change the function to take a reference instead of a pointer.
1172     ContainerNode* parent = node->parentNode();
1173     if (!parent)
1174         return nullptr;
1175
1176     for (auto& sibling : childrenOfType<Element>(*parent)) {
1177         // FIXME: Should skip sibling that is the same as the node.
1178         if (equalIgnoringASCIICase(sibling.attributeWithoutSynchronization(roleAttr), role))
1179             return &sibling;
1180     }
1181
1182     return nullptr;
1183 }
1184
1185 Element* AccessibilityNodeObject::menuElementForMenuButton() const
1186 {
1187     if (ariaRoleAttribute() != MenuButtonRole)
1188         return nullptr;
1189
1190     return siblingWithAriaRole(node(), "menu");
1191 }
1192
1193 AccessibilityObject* AccessibilityNodeObject::menuForMenuButton() const
1194 {
1195     if (AXObjectCache* cache = axObjectCache())
1196         return cache->getOrCreate(menuElementForMenuButton());
1197     return nullptr;
1198 }
1199
1200 Element* AccessibilityNodeObject::menuItemElementForMenu() const
1201 {
1202     if (ariaRoleAttribute() != MenuRole)
1203         return nullptr;
1204     
1205     return siblingWithAriaRole(node(), "menuitem");
1206 }
1207
1208 AccessibilityObject* AccessibilityNodeObject::menuButtonForMenu() const
1209 {
1210     AXObjectCache* cache = axObjectCache();
1211     if (!cache)
1212         return nullptr;
1213
1214     Element* menuItem = menuItemElementForMenu();
1215
1216     if (menuItem) {
1217         // ARIA just has generic menu items. AppKit needs to know if this is a top level items like MenuBarButton or MenuBarItem
1218         AccessibilityObject* menuItemAX = cache->getOrCreate(menuItem);
1219         if (menuItemAX && menuItemAX->isMenuButton())
1220             return menuItemAX;
1221     }
1222     return nullptr;
1223 }
1224
1225 AccessibilityObject* AccessibilityNodeObject::captionForFigure() const
1226 {
1227     if (!isFigure())
1228         return nullptr;
1229     
1230     AXObjectCache* cache = axObjectCache();
1231     if (!cache)
1232         return nullptr;
1233     
1234     Node* node = this->node();
1235     for (Node* child = node->firstChild(); child; child = child->nextSibling()) {
1236         if (child->hasTagName(figcaptionTag))
1237             return cache->getOrCreate(child);
1238     }
1239     return nullptr;
1240 }
1241
1242 bool AccessibilityNodeObject::usesAltTagForTextComputation() const
1243 {
1244     return isImage() || isInputImage() || isNativeImage() || isCanvas() || (node() && node()->hasTagName(imgTag));
1245 }
1246
1247 bool AccessibilityNodeObject::isLabelable() const
1248 {
1249     Node* node = this->node();
1250     if (!node)
1251         return false;
1252     
1253     return is<HTMLInputElement>(*node) || AccessibilityObject::isARIAInput(ariaRoleAttribute()) || isControl() || isProgressIndicator() || isMeter();
1254 }
1255
1256 String AccessibilityNodeObject::textForLabelElement(Element* element) const
1257 {
1258     String result = String();
1259     if (!is<HTMLLabelElement>(*element))
1260         return result;
1261     
1262     HTMLLabelElement* label = downcast<HTMLLabelElement>(element);
1263     // Check to see if there's aria-labelledby attribute on the label element.
1264     if (AccessibilityObject* labelObject = axObjectCache()->getOrCreate(label))
1265         result = labelObject->ariaLabeledByAttribute();
1266     
1267     // Then check for aria-label attribute.
1268     if (result.isEmpty())
1269         result = label->attributeWithoutSynchronization(aria_labelAttr);
1270     
1271     return !result.isEmpty() ? result : label->innerText();
1272 }
1273     
1274 void AccessibilityNodeObject::titleElementText(Vector<AccessibilityText>& textOrder) const
1275 {
1276     Node* node = this->node();
1277     if (!node)
1278         return;
1279     
1280     if (isLabelable()) {
1281         if (HTMLLabelElement* label = labelForElement(downcast<Element>(node))) {
1282             AccessibilityObject* labelObject = axObjectCache()->getOrCreate(label);
1283             String innerText = textForLabelElement(label);
1284             
1285             // Only use the <label> text if there's no ARIA override.
1286             if (!innerText.isEmpty() && !ariaAccessibilityDescription())
1287                 textOrder.append(AccessibilityText(innerText, isMeter() ? AlternativeText : LabelByElementText, labelObject));
1288             return;
1289         }
1290     }
1291     
1292     AccessibilityObject* titleUIElement = this->titleUIElement();
1293     if (titleUIElement)
1294         textOrder.append(AccessibilityText(String(), LabelByElementText, titleUIElement));
1295 }
1296
1297 void AccessibilityNodeObject::alternativeText(Vector<AccessibilityText>& textOrder) const
1298 {
1299     if (isWebArea()) {
1300         String webAreaText = alternativeTextForWebArea();
1301         if (!webAreaText.isEmpty())
1302             textOrder.append(AccessibilityText(webAreaText, AlternativeText));
1303         return;
1304     }
1305     
1306     ariaLabeledByText(textOrder);
1307     
1308     const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
1309     if (!ariaLabel.isEmpty())
1310         textOrder.append(AccessibilityText(ariaLabel, AlternativeText));
1311     
1312     if (usesAltTagForTextComputation()) {
1313         if (is<RenderImage>(renderer())) {
1314             String renderAltText = downcast<RenderImage>(*renderer()).altText();
1315
1316             // RenderImage will return title as a fallback from altText, but we don't want title here because we consider that in helpText.
1317             if (!renderAltText.isEmpty() && renderAltText != getAttribute(titleAttr)) {
1318                 textOrder.append(AccessibilityText(renderAltText, AlternativeText));
1319                 return;
1320             }
1321         }
1322         // Images should use alt as long as the attribute is present, even if empty.
1323         // Otherwise, it should fallback to other methods, like the title attribute.
1324         const AtomicString& alt = getAttribute(altAttr);
1325         if (!alt.isEmpty())
1326             textOrder.append(AccessibilityText(alt, AlternativeText));
1327     }
1328     
1329     Node* node = this->node();
1330     if (!node)
1331         return;
1332     
1333     // The fieldset element derives its alternative text from the first associated legend element if one is available.
1334     if (is<HTMLFieldSetElement>(*node)) {
1335         AccessibilityObject* object = axObjectCache()->getOrCreate(downcast<HTMLFieldSetElement>(*node).legend());
1336         if (object && !object->isHidden())
1337             textOrder.append(AccessibilityText(accessibleNameForNode(object->node()), AlternativeText));
1338     }
1339     
1340     // The figure element derives its alternative text from the first associated figcaption element if one is available.
1341     if (isFigure()) {
1342         AccessibilityObject* captionForFigure = this->captionForFigure();
1343         if (captionForFigure && !captionForFigure->isHidden())
1344             textOrder.append(AccessibilityText(accessibleNameForNode(captionForFigure->node()), AlternativeText));
1345     }
1346     
1347 #if ENABLE(MATHML)
1348     if (node->isMathMLElement())
1349         textOrder.append(AccessibilityText(getAttribute(MathMLNames::alttextAttr), AlternativeText));
1350 #endif
1351 }
1352
1353 void AccessibilityNodeObject::visibleText(Vector<AccessibilityText>& textOrder) const
1354 {
1355     Node* node = this->node();
1356     if (!node)
1357         return;
1358     
1359     bool isInputTag = is<HTMLInputElement>(*node);
1360     if (isInputTag) {
1361         HTMLInputElement& input = downcast<HTMLInputElement>(*node);
1362         if (input.isTextButton()) {
1363             textOrder.append(AccessibilityText(input.valueWithDefault(), VisibleText));
1364             return;
1365         }
1366     }
1367     
1368     // If this node isn't rendered, there's no inner text we can extract from a select element.
1369     if (!isAccessibilityRenderObject() && node->hasTagName(selectTag))
1370         return;
1371     
1372     bool useTextUnderElement = false;
1373     
1374     switch (roleValue()) {
1375     case PopUpButtonRole:
1376         // Native popup buttons should not use their button children's text as a title. That value is retrieved through stringValue().
1377         if (node->hasTagName(selectTag))
1378             break;
1379         FALLTHROUGH;
1380     case ButtonRole:
1381     case ToggleButtonRole:
1382     case CheckBoxRole:
1383     case ListBoxOptionRole:
1384     // MacOS does not expect native <li> elements to expose label information, it only expects leaf node elements to do that.
1385 #if !PLATFORM(COCOA)
1386     case ListItemRole:
1387 #endif
1388     case MenuButtonRole:
1389     case MenuItemRole:
1390     case MenuItemCheckboxRole:
1391     case MenuItemRadioRole:
1392     case RadioButtonRole:
1393     case SwitchRole:
1394     case TabRole:
1395         useTextUnderElement = true;
1396         break;
1397     default:
1398         break;
1399     }
1400     
1401     // If it's focusable but it's not content editable or a known control type, then it will appear to
1402     // the user as a single atomic object, so we should use its text as the default title.
1403     if (isHeading() || isLink())
1404         useTextUnderElement = true;
1405     
1406     if (isOutput())
1407         useTextUnderElement = true;
1408     
1409     if (useTextUnderElement) {
1410         AccessibilityTextUnderElementMode mode;
1411         
1412         // Headings often include links as direct children. Those links need to be included in text under element.
1413         if (isHeading())
1414             mode.includeFocusableContent = true;
1415
1416         String text = textUnderElement(mode);
1417         if (!text.isEmpty())
1418             textOrder.append(AccessibilityText(text, ChildrenText));
1419     }
1420 }
1421
1422 void AccessibilityNodeObject::helpText(Vector<AccessibilityText>& textOrder) const
1423 {
1424     const AtomicString& ariaHelp = getAttribute(aria_helpAttr);
1425     if (!ariaHelp.isEmpty())
1426         textOrder.append(AccessibilityText(ariaHelp, HelpText));
1427     
1428     String describedBy = ariaDescribedByAttribute();
1429     if (!describedBy.isEmpty())
1430         textOrder.append(AccessibilityText(describedBy, SummaryText));
1431
1432     // Summary attribute used as help text on tables.
1433     const AtomicString& summary = getAttribute(summaryAttr);
1434     if (!summary.isEmpty())
1435         textOrder.append(AccessibilityText(summary, SummaryText));
1436
1437     // The title attribute should be used as help text unless it is already being used as descriptive text.
1438     // However, when the title attribute is the only text alternative provided, it may be exposed as the
1439     // descriptive text. This is problematic in the case of meters because the HTML spec suggests authors
1440     // can expose units through this attribute. Therefore, if the element is a meter, change its source
1441     // type to HelpText.
1442     const AtomicString& title = getAttribute(titleAttr);
1443     if (!title.isEmpty()) {
1444         if (!isMeter())
1445             textOrder.append(AccessibilityText(title, TitleTagText));
1446         else
1447             textOrder.append(AccessibilityText(title, HelpText));
1448     }
1449 }
1450
1451 void AccessibilityNodeObject::accessibilityText(Vector<AccessibilityText>& textOrder)
1452 {
1453     titleElementText(textOrder);
1454     alternativeText(textOrder);
1455     visibleText(textOrder);
1456     helpText(textOrder);
1457     
1458     String placeholder = placeholderValue();
1459     if (!placeholder.isEmpty())
1460         textOrder.append(AccessibilityText(placeholder, PlaceholderText));
1461 }
1462     
1463 void AccessibilityNodeObject::ariaLabeledByText(Vector<AccessibilityText>& textOrder) const
1464 {
1465     String ariaLabeledBy = ariaLabeledByAttribute();
1466     if (!ariaLabeledBy.isEmpty()) {
1467         Vector<Element*> elements;
1468         ariaLabeledByElements(elements);
1469         
1470         Vector<RefPtr<AccessibilityObject>> axElements;
1471         for (const auto& element : elements) {
1472             RefPtr<AccessibilityObject> axElement = axObjectCache()->getOrCreate(element);
1473             axElements.append(axElement);
1474         }
1475         
1476         textOrder.append(AccessibilityText(ariaLabeledBy, AlternativeText, WTFMove(axElements)));
1477     }
1478 }
1479     
1480 String AccessibilityNodeObject::alternativeTextForWebArea() const
1481 {
1482     // The WebArea description should follow this order:
1483     //     aria-label on the <html>
1484     //     title on the <html>
1485     //     <title> inside the <head> (of it was set through JS)
1486     //     name on the <html>
1487     // For iframes:
1488     //     aria-label on the <iframe>
1489     //     title on the <iframe>
1490     //     name on the <iframe>
1491     
1492     Document* document = this->document();
1493     if (!document)
1494         return String();
1495     
1496     // Check if the HTML element has an aria-label for the webpage.
1497     if (Element* documentElement = document->documentElement()) {
1498         const AtomicString& ariaLabel = documentElement->attributeWithoutSynchronization(aria_labelAttr);
1499         if (!ariaLabel.isEmpty())
1500             return ariaLabel;
1501     }
1502     
1503     if (auto* owner = document->ownerElement()) {
1504         if (owner->hasTagName(frameTag) || owner->hasTagName(iframeTag)) {
1505             const AtomicString& title = owner->attributeWithoutSynchronization(titleAttr);
1506             if (!title.isEmpty())
1507                 return title;
1508         }
1509         return owner->getNameAttribute();
1510     }
1511     
1512     String documentTitle = document->title();
1513     if (!documentTitle.isEmpty())
1514         return documentTitle;
1515     
1516     if (auto* body = document->bodyOrFrameset())
1517         return body->getNameAttribute();
1518     
1519     return String();
1520 }
1521     
1522 String AccessibilityNodeObject::accessibilityDescription() const
1523 {
1524     // Static text should not have a description, it should only have a stringValue.
1525     if (roleValue() == StaticTextRole)
1526         return String();
1527
1528     String ariaDescription = ariaAccessibilityDescription();
1529     if (!ariaDescription.isEmpty())
1530         return ariaDescription;
1531
1532     if (usesAltTagForTextComputation()) {
1533         // Images should use alt as long as the attribute is present, even if empty.                    
1534         // Otherwise, it should fallback to other methods, like the title attribute.                    
1535         const AtomicString& alt = getAttribute(altAttr);
1536         if (!alt.isNull())
1537             return alt;
1538     }
1539     
1540 #if ENABLE(MATHML)
1541     if (is<MathMLElement>(m_node))
1542         return getAttribute(MathMLNames::alttextAttr);
1543 #endif
1544
1545     // An element's descriptive text is comprised of title() (what's visible on the screen) and accessibilityDescription() (other descriptive text).
1546     // Both are used to generate what a screen reader speaks.                                                           
1547     // If this point is reached (i.e. there's no accessibilityDescription) and there's no title(), we should fallback to using the title attribute.
1548     // The title attribute is normally used as help text (because it is a tooltip), but if there is nothing else available, this should be used (according to ARIA).
1549     if (title().isEmpty())
1550         return getAttribute(titleAttr);
1551
1552     return String();
1553 }
1554
1555 String AccessibilityNodeObject::helpText() const
1556 {
1557     Node* node = this->node();
1558     if (!node)
1559         return String();
1560     
1561     const AtomicString& ariaHelp = getAttribute(aria_helpAttr);
1562     if (!ariaHelp.isEmpty())
1563         return ariaHelp;
1564     
1565     String describedBy = ariaDescribedByAttribute();
1566     if (!describedBy.isEmpty())
1567         return describedBy;
1568     
1569     String description = accessibilityDescription();
1570     for (Node* ancestor = node; ancestor; ancestor = ancestor->parentNode()) {
1571         if (is<HTMLElement>(*ancestor)) {
1572             HTMLElement& element = downcast<HTMLElement>(*ancestor);
1573             const AtomicString& summary = element.getAttribute(summaryAttr);
1574             if (!summary.isEmpty())
1575                 return summary;
1576             
1577             // The title attribute should be used as help text unless it is already being used as descriptive text.
1578             const AtomicString& title = element.getAttribute(titleAttr);
1579             if (!title.isEmpty() && description != title)
1580                 return title;
1581         }
1582         
1583         // Only take help text from an ancestor element if its a group or an unknown role. If help was 
1584         // added to those kinds of elements, it is likely it was meant for a child element.
1585         AccessibilityObject* axObj = axObjectCache()->getOrCreate(ancestor);
1586         if (axObj) {
1587             AccessibilityRole role = axObj->roleValue();
1588             if (role != GroupRole && role != UnknownRole)
1589                 break;
1590         }
1591     }
1592     
1593     return String();
1594 }
1595     
1596 unsigned AccessibilityNodeObject::hierarchicalLevel() const
1597 {
1598     Node* node = this->node();
1599     if (!is<Element>(node))
1600         return 0;
1601     Element& element = downcast<Element>(*node);
1602     const AtomicString& ariaLevel = element.attributeWithoutSynchronization(aria_levelAttr);
1603     if (!ariaLevel.isEmpty())
1604         return ariaLevel.toInt();
1605     
1606     // Only tree item will calculate its level through the DOM currently.
1607     if (roleValue() != TreeItemRole)
1608         return 0;
1609     
1610     // Hierarchy leveling starts at 1, to match the aria-level spec.
1611     // We measure tree hierarchy by the number of groups that the item is within.
1612     unsigned level = 1;
1613     for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) {
1614         AccessibilityRole parentRole = parent->ariaRoleAttribute();
1615         if (parentRole == GroupRole)
1616             level++;
1617         else if (parentRole == TreeRole)
1618             break;
1619     }
1620     
1621     return level;
1622 }
1623
1624 void AccessibilityNodeObject::setIsExpanded(bool expand)
1625 {
1626 #if ENABLE(DETAILS_ELEMENT)
1627     if (is<HTMLDetailsElement>(node())) {
1628         auto& details = downcast<HTMLDetailsElement>(*node());
1629         if (expand != details.isOpen())
1630             details.toggleOpen();
1631     }
1632 #else
1633     UNUSED_PARAM(expand);
1634 #endif
1635 }
1636     
1637 // When building the textUnderElement for an object, determine whether or not
1638 // we should include the inner text of this given descendant object or skip it.
1639 static bool shouldUseAccessibilityObjectInnerText(AccessibilityObject* obj, AccessibilityTextUnderElementMode mode)
1640 {
1641     // Do not use any heuristic if we are explicitly asking to include all the children.
1642     if (mode.childrenInclusion == AccessibilityTextUnderElementMode::TextUnderElementModeIncludeAllChildren)
1643         return true;
1644
1645     // Consider this hypothetical example:
1646     // <div tabindex=0>
1647     //   <h2>
1648     //     Table of contents
1649     //   </h2>
1650     //   <a href="#start">Jump to start of book</a>
1651     //   <ul>
1652     //     <li><a href="#1">Chapter 1</a></li>
1653     //     <li><a href="#1">Chapter 2</a></li>
1654     //   </ul>
1655     // </div>
1656     //
1657     // The goal is to return a reasonable title for the outer container div, because
1658     // it's focusable - but without making its title be the full inner text, which is
1659     // quite long. As a heuristic, skip links, controls, and elements that are usually
1660     // containers with lots of children.
1661
1662     // ARIA states that certain elements are not allowed to expose their children content for name calculation.
1663     if (mode.childrenInclusion == AccessibilityTextUnderElementMode::TextUnderElementModeIncludeNameFromContentsChildren
1664         && !obj->accessibleNameDerivesFromContent())
1665         return false;
1666     
1667     if (equalLettersIgnoringASCIICase(obj->getAttribute(aria_hiddenAttr), "true"))
1668         return false;
1669     
1670     // If something doesn't expose any children, then we can always take the inner text content.
1671     // This is what we want when someone puts an <a> inside a <button> for example.
1672     if (obj->isDescendantOfBarrenParent())
1673         return true;
1674     
1675     // Skip focusable children, so we don't include the text of links and controls.
1676     if (obj->canSetFocusAttribute() && !mode.includeFocusableContent)
1677         return false;
1678
1679     // Skip big container elements like lists, tables, etc.
1680     if (is<AccessibilityList>(*obj))
1681         return false;
1682
1683     if (is<AccessibilityTable>(*obj) && downcast<AccessibilityTable>(*obj).isExposableThroughAccessibility())
1684         return false;
1685
1686     if (obj->isTree() || obj->isCanvas())
1687         return false;
1688
1689     return true;
1690 }
1691
1692 static bool shouldAddSpaceBeforeAppendingNextElement(StringBuilder& builder, const String& childText)
1693 {
1694     if (!builder.length() || !childText.length())
1695         return false;
1696
1697     // We don't need to add an additional space before or after a line break.
1698     return !(isHTMLLineBreak(childText[0]) || isHTMLLineBreak(builder[builder.length() - 1]));
1699 }
1700     
1701 static void appendNameToStringBuilder(StringBuilder& builder, const String& text)
1702 {
1703     if (shouldAddSpaceBeforeAppendingNextElement(builder, text))
1704         builder.append(' ');
1705     builder.append(text);
1706 }
1707
1708 String AccessibilityNodeObject::textUnderElement(AccessibilityTextUnderElementMode mode) const
1709 {
1710     Node* node = this->node();
1711     if (is<Text>(node))
1712         return downcast<Text>(*node).wholeText();
1713
1714     StringBuilder builder;
1715     for (AccessibilityObject* child = firstChild(); child; child = child->nextSibling()) {
1716         if (mode.ignoredChildNode && child->node() == mode.ignoredChildNode)
1717             continue;
1718         
1719         bool shouldDeriveNameFromAuthor = (mode.childrenInclusion == AccessibilityTextUnderElementMode::TextUnderElementModeIncludeNameFromContentsChildren && !child->accessibleNameDerivesFromContent());
1720         if (shouldDeriveNameFromAuthor) {
1721             appendNameToStringBuilder(builder, accessibleNameForNode(child->node()));
1722             continue;
1723         }
1724         
1725         if (!shouldUseAccessibilityObjectInnerText(child, mode))
1726             continue;
1727
1728         if (is<AccessibilityNodeObject>(*child)) {
1729             Vector<AccessibilityText> textOrder;
1730             downcast<AccessibilityNodeObject>(*child).alternativeText(textOrder);
1731             if (textOrder.size() > 0 && textOrder[0].text.length()) {
1732                 appendNameToStringBuilder(builder, textOrder[0].text);
1733                 continue;
1734             }
1735         }
1736         
1737         String childText = child->textUnderElement(mode);
1738         if (childText.length())
1739             appendNameToStringBuilder(builder, childText);
1740     }
1741
1742     return builder.toString().stripWhiteSpace().simplifyWhiteSpace(isHTMLSpaceButNotLineBreak);
1743 }
1744
1745 String AccessibilityNodeObject::title() const
1746 {
1747     Node* node = this->node();
1748     if (!node)
1749         return String();
1750
1751     bool isInputTag = is<HTMLInputElement>(*node);
1752     if (isInputTag) {
1753         HTMLInputElement& input = downcast<HTMLInputElement>(*node);
1754         if (input.isTextButton())
1755             return input.valueWithDefault();
1756     }
1757
1758     if (isLabelable()) {
1759         HTMLLabelElement* label = labelForElement(downcast<Element>(node));
1760         // Use the label text as the title if 1) the title element is NOT an exposed element and 2) there's no ARIA override.
1761         if (label && !exposesTitleUIElement() && !ariaAccessibilityDescription().length())
1762             return textForLabelElement(label);
1763     }
1764
1765     // If this node isn't rendered, there's no inner text we can extract from a select element.
1766     if (!isAccessibilityRenderObject() && node->hasTagName(selectTag))
1767         return String();
1768
1769     switch (roleValue()) {
1770     case PopUpButtonRole:
1771         // Native popup buttons should not use their button children's text as a title. That value is retrieved through stringValue().
1772         if (node->hasTagName(selectTag))
1773             return String();
1774         FALLTHROUGH;
1775     case ButtonRole:
1776     case ToggleButtonRole:
1777     case CheckBoxRole:
1778     case ListBoxOptionRole:
1779     case ListItemRole:
1780     case MenuButtonRole:
1781     case MenuItemRole:
1782     case MenuItemCheckboxRole:
1783     case MenuItemRadioRole:
1784     case RadioButtonRole:
1785     case SwitchRole:
1786     case TabRole:
1787         return textUnderElement();
1788     // SVGRoots should not use the text under itself as a title. That could include the text of objects like <text>.
1789     case SVGRootRole:
1790         return String();
1791     default:
1792         break;
1793     }
1794
1795     if (isLink())
1796         return textUnderElement();
1797     if (isHeading())
1798         return textUnderElement(AccessibilityTextUnderElementMode(AccessibilityTextUnderElementMode::TextUnderElementModeSkipIgnoredChildren, true));
1799
1800     return String();
1801 }
1802
1803 String AccessibilityNodeObject::text() const
1804 {
1805     // If this is a user defined static text, use the accessible name computation.                                      
1806     if (ariaRoleAttribute() == StaticTextRole) {
1807         Vector<AccessibilityText> textOrder;
1808         alternativeText(textOrder);
1809         if (textOrder.size() > 0 && textOrder[0].text.length())
1810             return textOrder[0].text;
1811     }
1812
1813     if (!isTextControl())
1814         return String();
1815
1816     Node* node = this->node();
1817     if (!node)
1818         return String();
1819
1820     if (isNativeTextControl() && is<HTMLTextFormControlElement>(*node))
1821         return downcast<HTMLTextFormControlElement>(*node).value();
1822
1823     if (!node->isElementNode())
1824         return String();
1825
1826     return downcast<Element>(node)->innerText();
1827 }
1828
1829 String AccessibilityNodeObject::stringValue() const
1830 {
1831     Node* node = this->node();
1832     if (!node)
1833         return String();
1834
1835     if (ariaRoleAttribute() == StaticTextRole) {
1836         String staticText = text();
1837         if (!staticText.length())
1838             staticText = textUnderElement();
1839         return staticText;
1840     }
1841
1842     if (node->isTextNode())
1843         return textUnderElement();
1844
1845     if (node->hasTagName(selectTag)) {
1846         HTMLSelectElement& selectElement = downcast<HTMLSelectElement>(*node);
1847         int selectedIndex = selectElement.selectedIndex();
1848         const Vector<HTMLElement*>& listItems = selectElement.listItems();
1849         if (selectedIndex >= 0 && static_cast<size_t>(selectedIndex) < listItems.size()) {
1850             const AtomicString& overriddenDescription = listItems[selectedIndex]->attributeWithoutSynchronization(aria_labelAttr);
1851             if (!overriddenDescription.isNull())
1852                 return overriddenDescription;
1853         }
1854         if (!selectElement.multiple())
1855             return selectElement.value();
1856         return String();
1857     }
1858
1859     if (isTextControl())
1860         return text();
1861
1862     // FIXME: We might need to implement a value here for more types
1863     // FIXME: It would be better not to advertise a value at all for the types for which we don't implement one;
1864     // this would require subclassing or making accessibilityAttributeNames do something other than return a
1865     // single static array.
1866     return String();
1867 }
1868
1869 void AccessibilityNodeObject::colorValue(int& r, int& g, int& b) const
1870 {
1871     r = 0;
1872     g = 0;
1873     b = 0;
1874
1875 #if ENABLE(INPUT_TYPE_COLOR)
1876     if (!isColorWell())
1877         return;
1878
1879     if (!is<HTMLInputElement>(node()))
1880         return;
1881
1882     auto& input = downcast<HTMLInputElement>(*node());
1883     if (!input.isColorControl())
1884         return;
1885
1886     // HTMLInputElement::value always returns a string parseable by Color().
1887     Color color(input.value());
1888     r = color.red();
1889     g = color.green();
1890     b = color.blue();
1891 #endif
1892 }
1893
1894 // This function implements the ARIA accessible name as described by the Mozilla                                        
1895 // ARIA Implementer's Guide.                                                                                            
1896 static String accessibleNameForNode(Node* node, Node* labelledbyNode)
1897 {
1898     ASSERT(node);
1899     if (!is<Element>(node))
1900         return String();
1901     
1902     Element& element = downcast<Element>(*node);
1903     const AtomicString& ariaLabel = element.attributeWithoutSynchronization(aria_labelAttr);
1904     if (!ariaLabel.isEmpty())
1905         return ariaLabel;
1906     
1907     const AtomicString& alt = element.attributeWithoutSynchronization(altAttr);
1908     if (!alt.isEmpty())
1909         return alt;
1910
1911     // If the node can be turned into an AX object, we can use standard name computation rules.
1912     // If however, the node cannot (because there's no renderer e.g.) fallback to using the basic text underneath.
1913     AccessibilityObject* axObject = node->document().axObjectCache()->getOrCreate(node);
1914     if (axObject) {
1915         String valueDescription = axObject->valueDescription();
1916         if (!valueDescription.isEmpty())
1917             return valueDescription;
1918     }
1919     
1920     if (is<HTMLInputElement>(*node))
1921         return downcast<HTMLInputElement>(*node).value();
1922     
1923     String text;
1924     if (axObject) {
1925         if (axObject->accessibleNameDerivesFromContent())
1926             text = axObject->textUnderElement(AccessibilityTextUnderElementMode(AccessibilityTextUnderElementMode::TextUnderElementModeIncludeNameFromContentsChildren, true, labelledbyNode));
1927     } else
1928         text = element.innerText();
1929
1930     if (!text.isEmpty())
1931         return text;
1932     
1933     const AtomicString& title = element.attributeWithoutSynchronization(titleAttr);
1934     if (!title.isEmpty())
1935         return title;
1936     
1937     return String();
1938 }
1939
1940 String AccessibilityNodeObject::accessibilityDescriptionForChildren() const
1941 {
1942     Node* node = this->node();
1943     if (!node)
1944         return String();
1945
1946     AXObjectCache* cache = axObjectCache();
1947     if (!cache)
1948         return String();
1949
1950     StringBuilder builder;
1951     for (Node* child = node->firstChild(); child; child = child->nextSibling()) {
1952         if (!is<Element>(child))
1953             continue;
1954
1955         if (AccessibilityObject* axObject = cache->getOrCreate(child)) {
1956             String description = axObject->ariaLabeledByAttribute();
1957             if (description.isEmpty())
1958                 description = accessibleNameForNode(child);
1959             appendNameToStringBuilder(builder, description);
1960         }
1961     }
1962
1963     return builder.toString();
1964 }
1965
1966 String AccessibilityNodeObject::accessibilityDescriptionForElements(Vector<Element*> &elements) const
1967 {
1968     StringBuilder builder;
1969     unsigned size = elements.size();
1970     for (unsigned i = 0; i < size; ++i)
1971         appendNameToStringBuilder(builder, accessibleNameForNode(elements[i], node()));
1972     return builder.toString();
1973 }
1974
1975 String AccessibilityNodeObject::ariaDescribedByAttribute() const
1976 {
1977     Vector<Element*> elements;
1978     elementsFromAttribute(elements, aria_describedbyAttr);
1979     
1980     return accessibilityDescriptionForElements(elements);
1981 }
1982
1983 void AccessibilityNodeObject::ariaLabeledByElements(Vector<Element*>& elements) const
1984 {
1985     elementsFromAttribute(elements, aria_labelledbyAttr);
1986     if (!elements.size())
1987         elementsFromAttribute(elements, aria_labeledbyAttr);
1988 }
1989
1990
1991 String AccessibilityNodeObject::ariaLabeledByAttribute() const
1992 {
1993     Vector<Element*> elements;
1994     ariaLabeledByElements(elements);
1995
1996     return accessibilityDescriptionForElements(elements);
1997 }
1998
1999 bool AccessibilityNodeObject::hasAttributesRequiredForInclusion() const
2000 {
2001     if (AccessibilityObject::hasAttributesRequiredForInclusion())
2002         return true;
2003
2004     if (!ariaAccessibilityDescription().isEmpty())
2005         return true;
2006
2007     return false;
2008 }
2009
2010 bool AccessibilityNodeObject::canSetFocusAttribute() const
2011 {
2012     Node* node = this->node();
2013     if (!node)
2014         return false;
2015
2016     if (isWebArea())
2017         return true;
2018     
2019     // NOTE: It would be more accurate to ask the document whether setFocusedElement() would
2020     // do anything. For example, setFocusedElement() will do nothing if the current focused
2021     // node will not relinquish the focus.
2022     if (!is<Element>(node))
2023         return false;
2024
2025     Element& element = downcast<Element>(*node);
2026
2027     if (element.isDisabledFormControl())
2028         return false;
2029
2030     return element.supportsFocus();
2031 }
2032
2033 bool AccessibilityNodeObject::canSetValueAttribute() const
2034 {
2035     Node* node = this->node();
2036     if (!node)
2037         return false;
2038
2039     // The host-language readonly attribute trumps aria-readonly.
2040     if (is<HTMLTextAreaElement>(*node))
2041         return !downcast<HTMLTextAreaElement>(*node).isReadOnly();
2042     if (is<HTMLInputElement>(*node)) {
2043         HTMLInputElement& input = downcast<HTMLInputElement>(*node);
2044         if (input.isTextField())
2045             return !input.isReadOnly();
2046     }
2047
2048     String readOnly = ariaReadOnlyValue();
2049     if (!readOnly.isEmpty())
2050         return readOnly == "true" ? false : true;
2051
2052     if (isNonNativeTextControl())
2053         return true;
2054
2055     if (isMeter())
2056         return false;
2057
2058     if (isProgressIndicator() || isSlider())
2059         return true;
2060
2061 #if PLATFORM(GTK) || PLATFORM(EFL)
2062     // In ATK, input types which support aria-readonly are treated as having a
2063     // settable value if the user can modify the widget's value or its state.
2064     if (supportsARIAReadOnly() || isRadioButton())
2065         return true;
2066 #endif
2067
2068     if (isWebArea()) {
2069         Document* document = this->document();
2070         if (!document)
2071             return false;
2072
2073         if (HTMLElement* body = document->bodyOrFrameset()) {
2074             if (body->hasEditableStyle())
2075                 return true;
2076         }
2077
2078         return document->hasEditableStyle();
2079     }
2080
2081     return node->hasEditableStyle();
2082 }
2083
2084 AccessibilityRole AccessibilityNodeObject::determineAriaRoleAttribute() const
2085 {
2086     const AtomicString& ariaRole = getAttribute(roleAttr);
2087     if (ariaRole.isNull() || ariaRole.isEmpty())
2088         return UnknownRole;
2089     
2090     AccessibilityRole role = ariaRoleToWebCoreRole(ariaRole);
2091
2092     // ARIA states if an item can get focus, it should not be presentational.
2093     if (role == PresentationalRole && canSetFocusAttribute())
2094         return UnknownRole;
2095
2096     if (role == ButtonRole)
2097         role = buttonRoleType();
2098
2099     if (role == TextAreaRole && !ariaIsMultiline())
2100         role = TextFieldRole;
2101
2102     role = remapAriaRoleDueToParent(role);
2103     
2104     // Presentational roles are invalidated by the presence of ARIA attributes.
2105     if (role == PresentationalRole && supportsARIAAttributes())
2106         role = UnknownRole;
2107     
2108     if (role)
2109         return role;
2110
2111     return UnknownRole;
2112 }
2113
2114 AccessibilityRole AccessibilityNodeObject::ariaRoleAttribute() const
2115 {
2116     return m_ariaRole;
2117 }
2118
2119 AccessibilityRole AccessibilityNodeObject::remapAriaRoleDueToParent(AccessibilityRole role) const
2120 {
2121     // Some objects change their role based on their parent.
2122     // However, asking for the unignoredParent calls accessibilityIsIgnored(), which can trigger a loop. 
2123     // While inside the call stack of creating an element, we need to avoid accessibilityIsIgnored().
2124     // https://bugs.webkit.org/show_bug.cgi?id=65174
2125
2126     if (role != ListBoxOptionRole && role != MenuItemRole)
2127         return role;
2128     
2129     for (AccessibilityObject* parent = parentObject(); parent && !parent->accessibilityIsIgnored(); parent = parent->parentObject()) {
2130         AccessibilityRole parentAriaRole = parent->ariaRoleAttribute();
2131
2132         // Selects and listboxes both have options as child roles, but they map to different roles within WebCore.
2133         if (role == ListBoxOptionRole && parentAriaRole == MenuRole)
2134             return MenuItemRole;
2135         // An aria "menuitem" may map to MenuButton or MenuItem depending on its parent.
2136         if (role == MenuItemRole && parentAriaRole == GroupRole)
2137             return MenuButtonRole;
2138         
2139         // If the parent had a different role, then we don't need to continue searching up the chain.
2140         if (parentAriaRole)
2141             break;
2142     }
2143     
2144     return role;
2145 }   
2146
2147 bool AccessibilityNodeObject::canSetSelectedAttribute() const
2148 {
2149     // Elements that can be selected
2150     switch (roleValue()) {
2151     case CellRole:
2152     case GridCellRole:
2153     case RadioButtonRole:
2154     case RowHeaderRole:
2155     case RowRole:
2156     case TabListRole:
2157     case TabRole:
2158     case TreeGridRole:
2159     case TreeItemRole:
2160     case TreeRole:
2161         return isEnabled();
2162     default:
2163         return false;
2164     }
2165 }
2166
2167 } // namespace WebCore