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