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