AX: in an aria-labelledby computation, do not traverse into elements whose nameFrom...
[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 "AccessibilityListBox.h"
35 #include "AccessibilitySpinButton.h"
36 #include "AccessibilityTable.h"
37 #include "ElementIterator.h"
38 #include "EventNames.h"
39 #include "FloatRect.h"
40 #include "Frame.h"
41 #include "FrameLoader.h"
42 #include "FrameSelection.h"
43 #include "FrameView.h"
44 #include "HTMLAreaElement.h"
45 #include "HTMLFieldSetElement.h"
46 #include "HTMLFormElement.h"
47 #include "HTMLFrameElementBase.h"
48 #include "HTMLImageElement.h"
49 #include "HTMLInputElement.h"
50 #include "HTMLLabelElement.h"
51 #include "HTMLLegendElement.h"
52 #include "HTMLMapElement.h"
53 #include "HTMLNames.h"
54 #include "HTMLOptGroupElement.h"
55 #include "HTMLOptionElement.h"
56 #include "HTMLOptionsCollection.h"
57 #include "HTMLParserIdioms.h"
58 #include "HTMLPlugInImageElement.h"
59 #include "HTMLSelectElement.h"
60 #include "HTMLTextAreaElement.h"
61 #include "HTMLTextFormControlElement.h"
62 #include "HitTestRequest.h"
63 #include "HitTestResult.h"
64 #include "LabelableElement.h"
65 #include "LocalizedStrings.h"
66 #include "MathMLNames.h"
67 #include "NodeList.h"
68 #include "NodeTraversal.h"
69 #include "Page.h"
70 #include "ProgressTracker.h"
71 #include "RenderImage.h"
72 #include "RenderView.h"
73 #include "SVGElement.h"
74 #include "SVGNames.h"
75 #include "Text.h"
76 #include "TextControlInnerElements.h"
77 #include "UserGestureIndicator.h"
78 #include "VisibleUnits.h"
79 #include "Widget.h"
80 #include "htmlediting.h"
81 #include <wtf/StdLibExtras.h>
82 #include <wtf/text/StringBuilder.h>
83 #include <wtf/unicode/CharacterNames.h>
84
85 namespace WebCore {
86
87 using namespace HTMLNames;
88
89 static String accessibleNameForNode(Node*);
90
91 AccessibilityNodeObject::AccessibilityNodeObject(Node* node)
92     : AccessibilityObject()
93     , m_ariaRole(UnknownRole)
94     , m_childrenDirty(false)
95     , m_roleForMSAA(UnknownRole)
96 #ifndef NDEBUG
97     , m_initialized(false)
98 #endif
99     , m_node(node)
100 {
101 }
102
103 AccessibilityNodeObject::~AccessibilityNodeObject()
104 {
105     ASSERT(isDetached());
106 }
107
108 void AccessibilityNodeObject::init()
109 {
110 #ifndef NDEBUG
111     ASSERT(!m_initialized);
112     m_initialized = true;
113 #endif
114     m_role = determineAccessibilityRole();
115 }
116
117 PassRefPtr<AccessibilityNodeObject> AccessibilityNodeObject::create(Node* node)
118 {
119     return adoptRef(new AccessibilityNodeObject(node));
120 }
121
122 void AccessibilityNodeObject::detach(AccessibilityDetachmentType detachmentType, AXObjectCache* cache)
123 {
124     // AccessibilityObject calls clearChildren.
125     AccessibilityObject::detach(detachmentType, cache);
126     m_node = nullptr;
127 }
128
129 void AccessibilityNodeObject::childrenChanged()
130 {
131     // This method is meant as a quick way of marking a portion of the accessibility tree dirty.
132     if (!node() && !renderer())
133         return;
134
135     AXObjectCache* cache = axObjectCache();
136     if (!cache)
137         return;
138     cache->postNotification(this, document(), AXObjectCache::AXChildrenChanged);
139
140     // Go up the accessibility parent chain, but only if the element already exists. This method is
141     // called during render layouts, minimal work should be done. 
142     // If AX elements are created now, they could interrogate the render tree while it's in a funky state.
143     // At the same time, process ARIA live region changes.
144     for (AccessibilityObject* parent = this; parent; parent = parent->parentObjectIfExists()) {
145         parent->setNeedsToUpdateChildren();
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         if (parent->supportsARIALiveRegion())
152             cache->postNotification(parent, parent->document(), AXObjectCache::AXLiveRegionChanged);
153         
154         // If this element is an ARIA text control, notify the AT of changes.
155         if ((parent->isARIATextControl() || parent->hasContentEditableAttributeSet()) && !parent->isNativeTextControl())
156             cache->postNotification(parent, parent->document(), AXObjectCache::AXValueChanged);
157     }
158 }
159
160 void AccessibilityNodeObject::updateAccessibilityRole()
161 {
162     bool ignoredStatus = accessibilityIsIgnored();
163     m_role = determineAccessibilityRole();
164     
165     // The AX hierarchy only needs to be updated if the ignored status of an element has changed.
166     if (ignoredStatus != accessibilityIsIgnored())
167         childrenChanged();
168 }
169     
170 AccessibilityObject* AccessibilityNodeObject::firstChild() const
171 {
172     if (!node())
173         return nullptr;
174     
175     Node* firstChild = node()->firstChild();
176
177     if (!firstChild)
178         return nullptr;
179     
180     return axObjectCache()->getOrCreate(firstChild);
181 }
182
183 AccessibilityObject* AccessibilityNodeObject::lastChild() const
184 {
185     if (!node())
186         return nullptr;
187     
188     Node* lastChild = node()->lastChild();
189     if (!lastChild)
190         return nullptr;
191     
192     return axObjectCache()->getOrCreate(lastChild);
193 }
194
195 AccessibilityObject* AccessibilityNodeObject::previousSibling() const
196 {
197     if (!node())
198         return nullptr;
199
200     Node* previousSibling = node()->previousSibling();
201     if (!previousSibling)
202         return nullptr;
203
204     return axObjectCache()->getOrCreate(previousSibling);
205 }
206
207 AccessibilityObject* AccessibilityNodeObject::nextSibling() const
208 {
209     if (!node())
210         return nullptr;
211
212     Node* nextSibling = node()->nextSibling();
213     if (!nextSibling)
214         return nullptr;
215
216     return axObjectCache()->getOrCreate(nextSibling);
217 }
218     
219 AccessibilityObject* AccessibilityNodeObject::parentObjectIfExists() const
220 {
221     return parentObject();
222 }
223     
224 AccessibilityObject* AccessibilityNodeObject::parentObject() const
225 {
226     if (!node())
227         return nullptr;
228
229     Node* parentObj = node()->parentNode();
230     if (!parentObj)
231         return nullptr;
232     
233     if (AXObjectCache* cache = axObjectCache())
234         return cache->getOrCreate(parentObj);
235     
236     return nullptr;
237 }
238
239 LayoutRect AccessibilityNodeObject::elementRect() const
240 {
241     return boundingBoxRect();
242 }
243     
244 LayoutRect AccessibilityNodeObject::boundingBoxRect() const
245 {
246     // AccessibilityNodeObjects have no mechanism yet to return a size or position.
247     // For now, let's return the position of the ancestor that does have a position,
248     // 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.
249     
250     LayoutRect boundingBox;
251     
252     for (AccessibilityObject* positionProvider = parentObject(); positionProvider; positionProvider = positionProvider->parentObject()) {
253         if (positionProvider->isAccessibilityRenderObject()) {
254             LayoutRect parentRect = positionProvider->elementRect();
255             boundingBox.setSize(LayoutSize(parentRect.width(), LayoutUnit(std::min(10.0f, parentRect.height().toFloat()))));
256             boundingBox.setLocation(parentRect.location());
257             break;
258         }
259     }
260     
261     return boundingBox;
262 }
263
264 void AccessibilityNodeObject::setNode(Node* node)
265 {
266     m_node = node;
267 }
268
269 Document* AccessibilityNodeObject::document() const
270 {
271     if (!node())
272         return nullptr;
273     return &node()->document();
274 }
275
276 AccessibilityRole AccessibilityNodeObject::determineAccessibilityRole()
277 {
278     if (!node())
279         return UnknownRole;
280
281     m_ariaRole = determineAriaRoleAttribute();
282     
283     AccessibilityRole ariaRole = ariaRoleAttribute();
284     if (ariaRole != UnknownRole)
285         return ariaRole;
286
287     if (node()->isLink())
288         return WebCoreLinkRole;
289     if (node()->isTextNode())
290         return StaticTextRole;
291     if (node()->hasTagName(buttonTag))
292         return buttonRoleType();
293     if (is<HTMLInputElement>(node())) {
294         HTMLInputElement& input = downcast<HTMLInputElement>(*node());
295         if (input.isCheckbox())
296             return CheckBoxRole;
297         if (input.isRadioButton())
298             return RadioButtonRole;
299         if (input.isTextButton())
300             return buttonRoleType();
301         if (input.isRangeControl())
302             return SliderRole;
303
304 #if ENABLE(INPUT_TYPE_COLOR)
305         const AtomicString& type = input.getAttribute(typeAttr);
306         if (equalIgnoringCase(type, "color"))
307             return ColorWellRole;
308 #endif
309
310         return TextFieldRole;
311     }
312     if (node()->hasTagName(selectTag)) {
313         HTMLSelectElement& selectElement = downcast<HTMLSelectElement>(*node());
314         return selectElement.multiple() ? ListBoxRole : PopUpButtonRole;
315     }
316     if (is<HTMLTextAreaElement>(node()))
317         return TextAreaRole;
318     if (headingLevel())
319         return HeadingRole;
320     if (node()->hasTagName(divTag))
321         return DivRole;
322     if (node()->hasTagName(pTag))
323         return ParagraphRole;
324     if (is<HTMLLabelElement>(node()))
325         return LabelRole;
326     if (node()->isElementNode() && toElement(node())->isFocusable())
327         return GroupRole;
328     
329     return UnknownRole;
330 }
331
332 void AccessibilityNodeObject::insertChild(AccessibilityObject* child, unsigned index)
333 {
334     if (!child)
335         return;
336     
337     // If the parent is asking for this child's children, then either it's the first time (and clearing is a no-op),
338     // or its visibility has changed. In the latter case, this child may have a stale child cached.
339     // This can prevent aria-hidden changes from working correctly. Hence, whenever a parent is getting children, ensure data is not stale.
340     child->clearChildren();
341     
342     if (child->accessibilityIsIgnored()) {
343         const auto& children = child->children();
344         size_t length = children.size();
345         for (size_t i = 0; i < length; ++i)
346             m_children.insert(index + i, children[i]);
347     } else {
348         ASSERT(child->parentObject() == this);
349         m_children.insert(index, child);
350     }
351 }
352
353 void AccessibilityNodeObject::addChild(AccessibilityObject* child)
354 {
355     insertChild(child, m_children.size());
356 }
357
358 void AccessibilityNodeObject::addChildren()
359 {
360     // If the need to add more children in addition to existing children arises, 
361     // childrenChanged should have been called, leaving the object with no children.
362     ASSERT(!m_haveChildren); 
363     
364     if (!m_node)
365         return;
366
367     m_haveChildren = true;
368
369     // The only time we add children from the DOM tree to a node with a renderer is when it's a canvas.
370     if (renderer() && !m_node->hasTagName(canvasTag))
371         return;
372     
373     for (Node* child = m_node->firstChild(); child; child = child->nextSibling())
374         addChild(axObjectCache()->getOrCreate(child));
375 }
376
377 bool AccessibilityNodeObject::canHaveChildren() const
378 {
379     // If this is an AccessibilityRenderObject, then it's okay if this object
380     // doesn't have a node - there are some renderers that don't have associated
381     // nodes, like scroll areas and css-generated text.
382     if (!node() && !isAccessibilityRenderObject())
383         return false;
384
385     // When <noscript> is not being used (its renderer() == 0), ignore its children.
386     if (node() && !renderer() && node()->hasTagName(noscriptTag))
387         return false;
388     
389     // Elements that should not have children
390     switch (roleValue()) {
391     case ImageRole:
392     case ButtonRole:
393     case PopUpButtonRole:
394     case CheckBoxRole:
395     case RadioButtonRole:
396     case TabRole:
397     case ToggleButtonRole:
398     case StaticTextRole:
399     case ListBoxOptionRole:
400     case ScrollBarRole:
401     case ProgressIndicatorRole:
402         return false;
403     default:
404         return true;
405     }
406 }
407
408 bool AccessibilityNodeObject::computeAccessibilityIsIgnored() const
409 {
410 #ifndef NDEBUG
411     // Double-check that an AccessibilityObject is never accessed before
412     // it's been initialized.
413     ASSERT(m_initialized);
414 #endif
415
416     // Handle non-rendered text that is exposed through aria-hidden=false.
417     if (m_node && m_node->isTextNode() && !renderer()) {
418         // Fallback content in iframe nodes should be ignored.
419         if (m_node->parentNode() && m_node->parentNode()->hasTagName(iframeTag) && m_node->parentNode()->renderer())
420             return true;
421
422         // Whitespace only text elements should be ignored when they have no renderer.
423         String string = stringValue().stripWhiteSpace().simplifyWhiteSpace();
424         if (!string.length())
425             return true;
426     }
427
428     AccessibilityObjectInclusion decision = defaultObjectInclusion();
429     if (decision == IncludeObject)
430         return false;
431     if (decision == IgnoreObject)
432         return true;
433     // If this element is within a parent that cannot have children, it should not be exposed.
434     if (isDescendantOfBarrenParent())
435         return true;
436
437     return m_role == UnknownRole;
438 }
439
440 bool AccessibilityNodeObject::canvasHasFallbackContent() const
441 {
442     Node* node = this->node();
443     if (!node || !node->hasTagName(canvasTag))
444         return false;
445     Element& canvasElement = toElement(*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::isAnchor() const
458 {
459     return !isNativeImage() && isLink();
460 }
461
462 bool AccessibilityNodeObject::isNativeTextControl() const
463 {
464     Node* node = this->node();
465     if (!node)
466         return false;
467
468     if (is<HTMLTextAreaElement>(node))
469         return true;
470
471     if (is<HTMLInputElement>(node)) {
472         HTMLInputElement& input = downcast<HTMLInputElement>(*node);
473         return input.isText() || input.isNumberField();
474     }
475
476     return false;
477 }
478
479 bool AccessibilityNodeObject::isSearchField() const
480 {
481     Node* node = this->node();
482     if (!node)
483         return false;
484
485     HTMLInputElement* inputElement = node->toInputElement();
486     if (!inputElement)
487         return false;
488
489     if (inputElement->isSearchField())
490         return true;
491
492     // Some websites don't label their search fields as such. However, they will
493     // use the word "search" in either the form or input type. This won't catch every case,
494     // but it will catch google.com for example.
495
496     // Check the node name of the input type, sometimes it's "search".
497     const AtomicString& nameAttribute = getAttribute(nameAttr);
498     if (nameAttribute.contains("search", false))
499         return true;
500
501     // Check the form action and the name, which will sometimes be "search".
502     HTMLFormElement* form = inputElement->form();
503     if (form && (form->name().contains("search", false) || form->action().contains("search", false)))
504         return true;
505
506     return false;
507 }
508
509 bool AccessibilityNodeObject::isNativeImage() const
510 {
511     Node* node = this->node();
512     if (!node)
513         return false;
514
515     if (is<HTMLImageElement>(node))
516         return true;
517
518     if (node->hasTagName(appletTag) || node->hasTagName(embedTag) || node->hasTagName(objectTag))
519         return true;
520
521     if (is<HTMLInputElement>(node)) {
522         HTMLInputElement& input = downcast<HTMLInputElement>(*node);
523         return input.isImageButton();
524     }
525
526     return false;
527 }
528
529 bool AccessibilityNodeObject::isImage() const
530 {
531     return roleValue() == ImageRole;
532 }
533
534 bool AccessibilityNodeObject::isPasswordField() const
535 {
536     Node* node = this->node();
537     if (!node || !node->isHTMLElement())
538         return false;
539
540     if (ariaRoleAttribute() != UnknownRole)
541         return false;
542
543     HTMLInputElement* inputElement = node->toInputElement();
544     if (!inputElement)
545         return false;
546
547     return inputElement->isPasswordField();
548 }
549
550 bool AccessibilityNodeObject::isInputImage() const
551 {
552     Node* node = this->node();
553     if (!node)
554         return false;
555  
556     if (roleValue() == ButtonRole && is<HTMLInputElement>(node)) {
557         HTMLInputElement& input = downcast<HTMLInputElement>(*node);
558         return input.isImageButton();
559     }
560
561     return false;
562 }
563
564 bool AccessibilityNodeObject::isProgressIndicator() const
565 {
566     return roleValue() == ProgressIndicatorRole;
567 }
568
569 bool AccessibilityNodeObject::isSlider() const
570 {
571     return roleValue() == SliderRole;
572 }
573
574 bool AccessibilityNodeObject::isMenuRelated() const
575 {
576     switch (roleValue()) {
577     case MenuRole:
578     case MenuBarRole:
579     case MenuButtonRole:
580     case MenuItemRole:
581     case MenuItemCheckboxRole:
582     case MenuItemRadioRole:
583         return true;
584     default:
585         return false;
586     }
587 }
588
589 bool AccessibilityNodeObject::isMenu() const
590 {
591     return roleValue() == MenuRole;
592 }
593
594 bool AccessibilityNodeObject::isMenuBar() const
595 {
596     return roleValue() == MenuBarRole;
597 }
598
599 bool AccessibilityNodeObject::isMenuButton() const
600 {
601     return roleValue() == MenuButtonRole;
602 }
603
604 bool AccessibilityNodeObject::isMenuItem() const
605 {
606     switch (roleValue()) {
607     case MenuItemRole:
608     case MenuItemRadioRole:
609     case MenuItemCheckboxRole:
610         return true;
611     default:
612         return false;
613     }
614 }
615
616 bool AccessibilityNodeObject::isNativeCheckboxOrRadio() const
617 {
618     Node* node = this->node();
619     if (!node)
620         return false;
621
622     HTMLInputElement* input = node->toInputElement();
623     if (input)
624         return input->isCheckbox() || input->isRadioButton();
625
626     return false;
627 }
628
629 bool AccessibilityNodeObject::isEnabled() const
630 {
631     // ARIA says that the disabled status applies to the current element and all descendant elements.
632     for (AccessibilityObject* object = const_cast<AccessibilityNodeObject*>(this); object; object = object->parentObject()) {
633         const AtomicString& disabledStatus = object->getAttribute(aria_disabledAttr);
634         if (equalIgnoringCase(disabledStatus, "true"))
635             return false;
636         if (equalIgnoringCase(disabledStatus, "false"))
637             break;
638     }
639     
640     if (roleValue() == HorizontalRuleRole)
641         return false;
642     
643     Node* node = this->node();
644     if (!node || !node->isElementNode())
645         return true;
646
647     return !toElement(node)->isDisabledFormControl();
648 }
649
650 bool AccessibilityNodeObject::isIndeterminate() const
651 {
652     Node* node = this->node();
653     if (!node)
654         return false;
655
656     HTMLInputElement* inputElement = node->toInputElement();
657     if (!inputElement)
658         return false;
659
660     return inputElement->shouldAppearIndeterminate();
661 }
662
663 bool AccessibilityNodeObject::isPressed() const
664 {
665     if (!isButton())
666         return false;
667
668     Node* node = this->node();
669     if (!node)
670         return false;
671
672     // If this is an ARIA button, check the aria-pressed attribute rather than node()->active()
673     if (ariaRoleAttribute() == ButtonRole) {
674         if (equalIgnoringCase(getAttribute(aria_pressedAttr), "true"))
675             return true;
676         return false;
677     }
678
679     if (!node->isElementNode())
680         return false;
681     return toElement(node)->active();
682 }
683
684 bool AccessibilityNodeObject::isChecked() const
685 {
686     Node* node = this->node();
687     if (!node)
688         return false;
689
690     // First test for native checkedness semantics
691     HTMLInputElement* inputElement = node->toInputElement();
692     if (inputElement)
693         return inputElement->shouldAppearChecked();
694
695     // Else, if this is an ARIA checkbox or radio, respect the aria-checked attribute
696     bool validRole = false;
697     switch (ariaRoleAttribute()) {
698     case RadioButtonRole:
699     case CheckBoxRole:
700     case MenuItemRole:
701     case MenuItemCheckboxRole:
702     case MenuItemRadioRole:
703         validRole = true;
704         break;
705     default:
706         break;
707     }
708     
709     if (validRole && equalIgnoringCase(getAttribute(aria_checkedAttr), "true"))
710         return true;
711
712     return false;
713 }
714
715 bool AccessibilityNodeObject::isHovered() const
716 {
717     Node* node = this->node();
718     if (!node)
719         return false;
720
721     return node->isElementNode() && toElement(node)->hovered();
722 }
723
724 bool AccessibilityNodeObject::isMultiSelectable() const
725 {
726     const AtomicString& ariaMultiSelectable = getAttribute(aria_multiselectableAttr);
727     if (equalIgnoringCase(ariaMultiSelectable, "true"))
728         return true;
729     if (equalIgnoringCase(ariaMultiSelectable, "false"))
730         return false;
731     
732     return node() && node()->hasTagName(selectTag) && downcast<HTMLSelectElement>(*node()).multiple();
733 }
734
735 bool AccessibilityNodeObject::isReadOnly() const
736 {
737     Node* node = this->node();
738     if (!node)
739         return true;
740
741     if (is<HTMLTextAreaElement>(node))
742         return downcast<HTMLTextAreaElement>(node)->isReadOnly();
743
744     if (is<HTMLInputElement>(node)) {
745         HTMLInputElement& input = downcast<HTMLInputElement>(*node);
746         if (input.isTextField())
747             return input.isReadOnly();
748     }
749
750     return !node->hasEditableStyle();
751 }
752
753 bool AccessibilityNodeObject::isRequired() const
754 {
755     // Explicit aria-required values should trump native required attributes.
756     const AtomicString& requiredValue = getAttribute(aria_requiredAttr);
757     if (equalIgnoringCase(requiredValue, "true"))
758         return true;
759     if (equalIgnoringCase(requiredValue, "false"))
760         return false;
761
762     Node* n = this->node();
763     if (n && is<HTMLFormControlElement>(n))
764         return downcast<HTMLFormControlElement>(n)->isRequired();
765
766     return false;
767 }
768
769 bool AccessibilityNodeObject::supportsRequiredAttribute() const
770 {
771     switch (roleValue()) {
772     case ButtonRole:
773         return isFileUploadButton();
774     case CellRole:
775     case CheckBoxRole:
776     case ComboBoxRole:
777     case GridRole:
778     case IncrementorRole:
779     case ListBoxRole:
780     case PopUpButtonRole:
781     case RadioButtonRole:
782     case RadioGroupRole:
783     case RowHeaderRole:
784     case SliderRole:
785     case SpinButtonRole:
786     case TableHeaderContainerRole:
787     case TextAreaRole:
788     case TextFieldRole:
789     case ToggleButtonRole:
790         return true;
791     default:
792         return false;
793     }
794 }
795
796 int AccessibilityNodeObject::headingLevel() const
797 {
798     // headings can be in block flow and non-block flow
799     Node* node = this->node();
800     if (!node)
801         return false;
802
803     if (isHeading()) {
804         int ariaLevel = getAttribute(aria_levelAttr).toInt();
805         if (ariaLevel > 0)
806             return ariaLevel;
807     }
808
809     if (node->hasTagName(h1Tag))
810         return 1;
811
812     if (node->hasTagName(h2Tag))
813         return 2;
814
815     if (node->hasTagName(h3Tag))
816         return 3;
817
818     if (node->hasTagName(h4Tag))
819         return 4;
820
821     if (node->hasTagName(h5Tag))
822         return 5;
823
824     if (node->hasTagName(h6Tag))
825         return 6;
826
827     return 0;
828 }
829
830 String AccessibilityNodeObject::valueDescription() const
831 {
832     if (!isRangeControl())
833         return String();
834
835     return getAttribute(aria_valuetextAttr).string();
836 }
837
838 float AccessibilityNodeObject::valueForRange() const
839 {
840     if (node() && is<HTMLInputElement>(node())) {
841         HTMLInputElement& input = downcast<HTMLInputElement>(*node());
842         if (input.isRangeControl())
843             return input.valueAsNumber();
844     }
845
846     if (!isRangeControl())
847         return 0.0f;
848
849     return getAttribute(aria_valuenowAttr).toFloat();
850 }
851
852 float AccessibilityNodeObject::maxValueForRange() const
853 {
854     if (node() && is<HTMLInputElement>(node())) {
855         HTMLInputElement& input = downcast<HTMLInputElement>(*node());
856         if (input.isRangeControl())
857             return input.maximum();
858     }
859
860     if (!isRangeControl())
861         return 0.0f;
862
863     return getAttribute(aria_valuemaxAttr).toFloat();
864 }
865
866 float AccessibilityNodeObject::minValueForRange() const
867 {
868     if (node() && is<HTMLInputElement>(node())) {
869         HTMLInputElement& input = downcast<HTMLInputElement>(*node());
870         if (input.isRangeControl())
871             return input.minimum();
872     }
873
874     if (!isRangeControl())
875         return 0.0f;
876
877     return getAttribute(aria_valueminAttr).toFloat();
878 }
879
880 float AccessibilityNodeObject::stepValueForRange() const
881 {
882     return getAttribute(stepAttr).toFloat();
883 }
884
885 bool AccessibilityNodeObject::isHeading() const
886 {
887     return roleValue() == HeadingRole;
888 }
889
890 bool AccessibilityNodeObject::isLink() const
891 {
892     return roleValue() == WebCoreLinkRole;
893 }
894
895 bool AccessibilityNodeObject::isControl() const
896 {
897     Node* node = this->node();
898     if (!node)
899         return false;
900
901     return is<HTMLFormControlElement>(node) || AccessibilityObject::isARIAControl(ariaRoleAttribute());
902 }
903
904 bool AccessibilityNodeObject::isFieldset() const
905 {
906     Node* node = this->node();
907     if (!node)
908         return false;
909
910     return node->hasTagName(fieldsetTag);
911 }
912
913 bool AccessibilityNodeObject::isGroup() const
914 {
915     return roleValue() == GroupRole;
916 }
917
918 AccessibilityObject* AccessibilityNodeObject::selectedRadioButton()
919 {
920     if (!isRadioGroup())
921         return nullptr;
922
923     // Find the child radio button that is selected (ie. the intValue == 1).
924     for (const auto& child : children()) {
925         if (child->roleValue() == RadioButtonRole && child->checkboxOrRadioValue() == ButtonStateOn)
926             return child.get();
927     }
928     return nullptr;
929 }
930
931 AccessibilityObject* AccessibilityNodeObject::selectedTabItem()
932 {
933     if (!isTabList())
934         return nullptr;
935
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())
942             return child.get();
943     }
944     return nullptr;
945 }
946
947 AccessibilityButtonState AccessibilityNodeObject::checkboxOrRadioValue() const
948 {
949     if (isNativeCheckboxOrRadio())
950         return 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())->isAnchor()))
967             return toElement(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 toElement(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 toElement(node);
1012     
1013     if (AccessibilityObject::isARIAInput(ariaRoleAttribute()))
1014         return toElement(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 toElement(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(node->isElementNode() ? toElement(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(DefinitelyProcessingUserGesture);
1084     alterSliderValue(true);
1085 }
1086
1087 void AccessibilityNodeObject::decrement()
1088 {
1089     UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture);
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(String role, Node* node)
1188 {
1189     ContainerNode* parent = node->parentNode();
1190     if (!parent)
1191         return nullptr;
1192
1193     for (auto& sibling : childrenOfType<Element>(*parent)) {
1194         const AtomicString& siblingAriaRole = sibling.fastGetAttribute(roleAttr);
1195         if (equalIgnoringCase(siblingAriaRole, role))
1196             return &sibling;
1197     }
1198
1199     return nullptr;
1200 }
1201
1202 Element* AccessibilityNodeObject::menuElementForMenuButton() const
1203 {
1204     if (ariaRoleAttribute() != MenuButtonRole)
1205         return nullptr;
1206
1207     return siblingWithAriaRole("menu", node());
1208 }
1209
1210 AccessibilityObject* AccessibilityNodeObject::menuForMenuButton() const
1211 {
1212     if (AXObjectCache* cache = axObjectCache())
1213         return cache->getOrCreate(menuElementForMenuButton());
1214     return nullptr;
1215 }
1216
1217 Element* AccessibilityNodeObject::menuItemElementForMenu() const
1218 {
1219     if (ariaRoleAttribute() != MenuRole)
1220         return nullptr;
1221     
1222     return siblingWithAriaRole("menuitem", node());    
1223 }
1224
1225 AccessibilityObject* AccessibilityNodeObject::menuButtonForMenu() const
1226 {
1227     AXObjectCache* cache = axObjectCache();
1228     if (!cache)
1229         return nullptr;
1230
1231     Element* menuItem = menuItemElementForMenu();
1232
1233     if (menuItem) {
1234         // ARIA just has generic menu items. AppKit needs to know if this is a top level items like MenuBarButton or MenuBarItem
1235         AccessibilityObject* menuItemAX = cache->getOrCreate(menuItem);
1236         if (menuItemAX && menuItemAX->isMenuButton())
1237             return menuItemAX;
1238     }
1239     return nullptr;
1240 }
1241
1242 bool AccessibilityNodeObject::usesAltTagForTextComputation() const
1243 {
1244     return isImage() || isInputImage() || isNativeImage() || isCanvas() || (node() && node()->hasTagName(imgTag));
1245 }
1246     
1247 void AccessibilityNodeObject::titleElementText(Vector<AccessibilityText>& textOrder) const
1248 {
1249     Node* node = this->node();
1250     if (!node)
1251         return;
1252     
1253     bool isInputTag = is<HTMLInputElement>(node);
1254     if (isInputTag || AccessibilityObject::isARIAInput(ariaRoleAttribute()) || isControl()) {
1255         HTMLLabelElement* label = labelForElement(toElement(node));
1256         if (label) {
1257             AccessibilityObject* labelObject = axObjectCache()->getOrCreate(label);
1258             String innerText = label->innerText();
1259             // Only use the <label> text if there's no ARIA override.
1260             if (!innerText.isEmpty() && !ariaAccessibilityDescription())
1261                 textOrder.append(AccessibilityText(innerText, LabelByElementText, labelObject));
1262             return;
1263         }
1264     }
1265     
1266     AccessibilityObject* titleUIElement = this->titleUIElement();
1267     if (titleUIElement)
1268         textOrder.append(AccessibilityText(String(), LabelByElementText, titleUIElement));
1269 }
1270
1271 void AccessibilityNodeObject::alternativeText(Vector<AccessibilityText>& textOrder) const
1272 {
1273     if (isWebArea()) {
1274         String webAreaText = alternativeTextForWebArea();
1275         if (!webAreaText.isEmpty())
1276             textOrder.append(AccessibilityText(webAreaText, AlternativeText));
1277         return;
1278     }
1279     
1280     ariaLabeledByText(textOrder);
1281     
1282     const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
1283     if (!ariaLabel.isEmpty())
1284         textOrder.append(AccessibilityText(ariaLabel, AlternativeText));
1285     
1286     if (usesAltTagForTextComputation()) {
1287         if (renderer() && renderer()->isRenderImage()) {
1288             String renderAltText = toRenderImage(renderer())->altText();
1289
1290             // RenderImage will return title as a fallback from altText, but we don't want title here because we consider that in helpText.
1291             if (!renderAltText.isEmpty() && renderAltText != getAttribute(titleAttr)) {
1292                 textOrder.append(AccessibilityText(renderAltText, AlternativeText));
1293                 return;
1294             }
1295         }
1296         // Images should use alt as long as the attribute is present, even if empty.
1297         // Otherwise, it should fallback to other methods, like the title attribute.
1298         const AtomicString& alt = getAttribute(altAttr);
1299         if (!alt.isEmpty())
1300             textOrder.append(AccessibilityText(alt, AlternativeText));
1301     }
1302     
1303     Node* node = this->node();
1304     if (!node)
1305         return;
1306     
1307     // The fieldset element derives its alternative text from the first associated legend element if one is available.
1308     if (is<HTMLFieldSetElement>(node)) {
1309         AccessibilityObject* object = axObjectCache()->getOrCreate(downcast<HTMLFieldSetElement>(*node).legend());
1310         if (object && !object->isHidden())
1311             textOrder.append(AccessibilityText(accessibleNameForNode(object->node()), AlternativeText));
1312     }
1313     
1314     // SVG elements all can have a <svg:title> element inside which should act as the descriptive text.
1315     if (node->isSVGElement())
1316         textOrder.append(AccessibilityText(downcast<SVGElement>(*node).title(), AlternativeText));
1317     
1318 #if ENABLE(MATHML)
1319     if (node->isMathMLElement())
1320         textOrder.append(AccessibilityText(getAttribute(MathMLNames::alttextAttr), AlternativeText));
1321 #endif
1322 }
1323
1324 void AccessibilityNodeObject::visibleText(Vector<AccessibilityText>& textOrder) const
1325 {
1326     Node* node = this->node();
1327     if (!node)
1328         return;
1329     
1330     bool isInputTag = is<HTMLInputElement>(node);
1331     if (isInputTag) {
1332         HTMLInputElement& input = downcast<HTMLInputElement>(*node);
1333         if (input.isTextButton()) {
1334             textOrder.append(AccessibilityText(input.valueWithDefault(), VisibleText));
1335             return;
1336         }
1337     }
1338     
1339     // If this node isn't rendered, there's no inner text we can extract from a select element.
1340     if (!isAccessibilityRenderObject() && node->hasTagName(selectTag))
1341         return;
1342     
1343     bool useTextUnderElement = false;
1344     
1345     switch (roleValue()) {
1346     case PopUpButtonRole:
1347         // Native popup buttons should not use their button children's text as a title. That value is retrieved through stringValue().
1348         if (node->hasTagName(selectTag))
1349             break;
1350         FALLTHROUGH;
1351     case ButtonRole:
1352     case ToggleButtonRole:
1353     case CheckBoxRole:
1354     case ListBoxOptionRole:
1355     // MacOS does not expect native <li> elements to expose label information, it only expects leaf node elements to do that.
1356 #if !PLATFORM(COCOA)
1357     case ListItemRole:
1358 #endif
1359     case MenuButtonRole:
1360     case MenuItemRole:
1361     case MenuItemCheckboxRole:
1362     case MenuItemRadioRole:
1363     case RadioButtonRole:
1364     case TabRole:
1365     case ProgressIndicatorRole:
1366         useTextUnderElement = true;
1367         break;
1368     default:
1369         break;
1370     }
1371     
1372     // If it's focusable but it's not content editable or a known control type, then it will appear to
1373     // the user as a single atomic object, so we should use its text as the default title.
1374     if (isHeading() || isLink())
1375         useTextUnderElement = true;
1376     
1377     if (useTextUnderElement) {
1378         AccessibilityTextUnderElementMode mode;
1379         
1380         // Headings often include links as direct children. Those links need to be included in text under element.
1381         if (isHeading())
1382             mode.includeFocusableContent = true;
1383
1384         String text = textUnderElement(mode);
1385         if (!text.isEmpty())
1386             textOrder.append(AccessibilityText(text, ChildrenText));
1387     }
1388 }
1389
1390 void AccessibilityNodeObject::helpText(Vector<AccessibilityText>& textOrder) const
1391 {
1392     const AtomicString& ariaHelp = getAttribute(aria_helpAttr);
1393     if (!ariaHelp.isEmpty())
1394         textOrder.append(AccessibilityText(ariaHelp, HelpText));
1395     
1396     String describedBy = ariaDescribedByAttribute();
1397     if (!describedBy.isEmpty())
1398         textOrder.append(AccessibilityText(describedBy, SummaryText));
1399
1400     // Summary attribute used as help text on tables.
1401     const AtomicString& summary = getAttribute(summaryAttr);
1402     if (!summary.isEmpty())
1403         textOrder.append(AccessibilityText(summary, SummaryText));
1404
1405     // The title attribute should be used as help text unless it is already being used as descriptive text.
1406     const AtomicString& title = getAttribute(titleAttr);
1407     if (!title.isEmpty())
1408         textOrder.append(AccessibilityText(title, TitleTagText));
1409 }
1410
1411 void AccessibilityNodeObject::accessibilityText(Vector<AccessibilityText>& textOrder)
1412 {
1413     titleElementText(textOrder);
1414     alternativeText(textOrder);
1415     visibleText(textOrder);
1416     helpText(textOrder);
1417     
1418     String placeholder = placeholderValue();
1419     if (!placeholder.isEmpty())
1420         textOrder.append(AccessibilityText(placeholder, PlaceholderText));
1421 }
1422     
1423 void AccessibilityNodeObject::ariaLabeledByText(Vector<AccessibilityText>& textOrder) const
1424 {
1425     String ariaLabeledBy = ariaLabeledByAttribute();
1426     if (!ariaLabeledBy.isEmpty()) {
1427         Vector<Element*> elements;
1428         ariaLabeledByElements(elements);
1429         
1430         Vector<RefPtr<AccessibilityObject>> axElements;
1431         for (const auto& element : elements) {
1432             RefPtr<AccessibilityObject> axElement = axObjectCache()->getOrCreate(element);
1433             axElements.append(axElement);
1434         }
1435         
1436         textOrder.append(AccessibilityText(ariaLabeledBy, AlternativeText, WTF::move(axElements)));
1437     }
1438 }
1439     
1440 String AccessibilityNodeObject::alternativeTextForWebArea() const
1441 {
1442     // The WebArea description should follow this order:
1443     //     aria-label on the <html>
1444     //     title on the <html>
1445     //     <title> inside the <head> (of it was set through JS)
1446     //     name on the <html>
1447     // For iframes:
1448     //     aria-label on the <iframe>
1449     //     title on the <iframe>
1450     //     name on the <iframe>
1451     
1452     Document* document = this->document();
1453     if (!document)
1454         return String();
1455     
1456     // Check if the HTML element has an aria-label for the webpage.
1457     if (Element* documentElement = document->documentElement()) {
1458         const AtomicString& ariaLabel = documentElement->fastGetAttribute(aria_labelAttr);
1459         if (!ariaLabel.isEmpty())
1460             return ariaLabel;
1461     }
1462     
1463     if (auto* owner = document->ownerElement()) {
1464         if (owner->hasTagName(frameTag) || owner->hasTagName(iframeTag)) {
1465             const AtomicString& title = owner->fastGetAttribute(titleAttr);
1466             if (!title.isEmpty())
1467                 return title;
1468         }
1469         return owner->getNameAttribute();
1470     }
1471     
1472     String documentTitle = document->title();
1473     if (!documentTitle.isEmpty())
1474         return documentTitle;
1475     
1476     if (auto* body = document->body())
1477         return body->getNameAttribute();
1478     
1479     return String();
1480 }
1481     
1482 String AccessibilityNodeObject::accessibilityDescription() const
1483 {
1484     // Static text should not have a description, it should only have a stringValue.
1485     if (roleValue() == StaticTextRole)
1486         return String();
1487
1488     String ariaDescription = ariaAccessibilityDescription();
1489     if (!ariaDescription.isEmpty())
1490         return ariaDescription;
1491
1492     if (usesAltTagForTextComputation()) {
1493         // Images should use alt as long as the attribute is present, even if empty.                    
1494         // Otherwise, it should fallback to other methods, like the title attribute.                    
1495         const AtomicString& alt = getAttribute(altAttr);
1496         if (!alt.isNull())
1497             return alt;
1498     }
1499
1500     // SVG elements all can have a <svg:title> element inside which should act as the descriptive text.
1501     if (m_node && m_node->isSVGElement())
1502         return downcast<SVGElement>(*m_node).title();
1503     
1504 #if ENABLE(MATHML)
1505     if (m_node && m_node->isMathMLElement())
1506         return getAttribute(MathMLNames::alttextAttr);
1507 #endif
1508
1509     // An element's descriptive text is comprised of title() (what's visible on the screen) and accessibilityDescription() (other descriptive text).
1510     // Both are used to generate what a screen reader speaks.                                                           
1511     // If this point is reached (i.e. there's no accessibilityDescription) and there's no title(), we should fallback to using the title attribute.
1512     // 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).
1513     if (title().isEmpty())
1514         return getAttribute(titleAttr);
1515
1516     return String();
1517 }
1518
1519 String AccessibilityNodeObject::helpText() const
1520 {
1521     Node* node = this->node();
1522     if (!node)
1523         return String();
1524     
1525     const AtomicString& ariaHelp = getAttribute(aria_helpAttr);
1526     if (!ariaHelp.isEmpty())
1527         return ariaHelp;
1528     
1529     String describedBy = ariaDescribedByAttribute();
1530     if (!describedBy.isEmpty())
1531         return describedBy;
1532     
1533     String description = accessibilityDescription();
1534     for (Node* curr = node; curr; curr = curr->parentNode()) {
1535         if (curr->isHTMLElement()) {
1536             const AtomicString& summary = toElement(curr)->getAttribute(summaryAttr);
1537             if (!summary.isEmpty())
1538                 return summary;
1539             
1540             // The title attribute should be used as help text unless it is already being used as descriptive text.
1541             const AtomicString& title = toElement(curr)->getAttribute(titleAttr);
1542             if (!title.isEmpty() && description != title)
1543                 return title;
1544         }
1545         
1546         // Only take help text from an ancestor element if its a group or an unknown role. If help was 
1547         // added to those kinds of elements, it is likely it was meant for a child element.
1548         AccessibilityObject* axObj = axObjectCache()->getOrCreate(curr);
1549         if (axObj) {
1550             AccessibilityRole role = axObj->roleValue();
1551             if (role != GroupRole && role != UnknownRole)
1552                 break;
1553         }
1554     }
1555     
1556     return String();
1557 }
1558     
1559 unsigned AccessibilityNodeObject::hierarchicalLevel() const
1560 {
1561     Node* node = this->node();
1562     if (!node || !node->isElementNode())
1563         return 0;
1564     Element* element = toElement(node);
1565     const AtomicString& ariaLevel = element->fastGetAttribute(aria_levelAttr);
1566     if (!ariaLevel.isEmpty())
1567         return ariaLevel.toInt();
1568     
1569     // Only tree item will calculate its level through the DOM currently.
1570     if (roleValue() != TreeItemRole)
1571         return 0;
1572     
1573     // Hierarchy leveling starts at 1, to match the aria-level spec.
1574     // We measure tree hierarchy by the number of groups that the item is within.
1575     unsigned level = 1;
1576     for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) {
1577         AccessibilityRole parentRole = parent->roleValue();
1578         if (parentRole == GroupRole)
1579             level++;
1580         else if (parentRole == TreeRole)
1581             break;
1582     }
1583     
1584     return level;
1585 }
1586
1587 // When building the textUnderElement for an object, determine whether or not
1588 // we should include the inner text of this given descendant object or skip it.
1589 static bool shouldUseAccessiblityObjectInnerText(AccessibilityObject* obj, AccessibilityTextUnderElementMode mode)
1590 {
1591     // Do not use any heuristic if we are explicitly asking to include all the children.
1592     if (mode.childrenInclusion == AccessibilityTextUnderElementMode::TextUnderElementModeIncludeAllChildren)
1593         return true;
1594
1595     // Consider this hypothetical example:
1596     // <div tabindex=0>
1597     //   <h2>
1598     //     Table of contents
1599     //   </h2>
1600     //   <a href="#start">Jump to start of book</a>
1601     //   <ul>
1602     //     <li><a href="#1">Chapter 1</a></li>
1603     //     <li><a href="#1">Chapter 2</a></li>
1604     //   </ul>
1605     // </div>
1606     //
1607     // The goal is to return a reasonable title for the outer container div, because
1608     // it's focusable - but without making its title be the full inner text, which is
1609     // quite long. As a heuristic, skip links, controls, and elements that are usually
1610     // containers with lots of children.
1611
1612     // ARIA states that certain elements are not allowed to expose their children content for name calculation.
1613     if (mode.childrenInclusion == AccessibilityTextUnderElementMode::TextUnderElementModeIncludeNameFromContentsChildren
1614         && !obj->accessibleNameDerivesFromContent())
1615         return false;
1616     
1617     if (equalIgnoringCase(obj->getAttribute(aria_hiddenAttr), "true"))
1618         return false;
1619     
1620     // If something doesn't expose any children, then we can always take the inner text content.
1621     // This is what we want when someone puts an <a> inside a <button> for example.
1622     if (obj->isDescendantOfBarrenParent())
1623         return true;
1624     
1625     // Skip focusable children, so we don't include the text of links and controls.
1626     if (obj->canSetFocusAttribute() && !mode.includeFocusableContent)
1627         return false;
1628
1629     // Skip big container elements like lists, tables, etc.
1630     if (obj->isList() || obj->isAccessibilityTable() || obj->isTree() || obj->isCanvas())
1631         return false;
1632
1633     return true;
1634 }
1635
1636 static bool shouldAddSpaceBeforeAppendingNextElement(StringBuilder& builder, const String& childText)
1637 {
1638     if (!builder.length() || !childText.length())
1639         return false;
1640
1641     // We don't need to add an additional space before or after a line break.
1642     return !(isHTMLLineBreak(childText[0]) || isHTMLLineBreak(builder[builder.length() - 1]));
1643 }
1644     
1645 static void appendNameToStringBuilder(StringBuilder& builder, const String& text)
1646 {
1647     if (shouldAddSpaceBeforeAppendingNextElement(builder, text))
1648         builder.append(' ');
1649     builder.append(text);
1650 }
1651
1652 String AccessibilityNodeObject::textUnderElement(AccessibilityTextUnderElementMode mode) const
1653 {
1654     Node* node = this->node();
1655     if (node && is<Text>(node))
1656         return downcast<Text>(*node).wholeText();
1657
1658     // The render tree should be stable before going ahead. Otherwise, further uses of the
1659     // TextIterator will force a layout update, potentially altering the accessibility tree
1660     // and leading to crashes in the loop that computes the result text from the children.
1661     ASSERT(!document()->renderView()->layoutState());
1662     ASSERT(!document()->childNeedsStyleRecalc());
1663
1664     StringBuilder builder;
1665     for (AccessibilityObject* child = firstChild(); child; child = child->nextSibling()) {
1666         
1667         bool shouldDeriveNameFromAuthor = (mode.childrenInclusion == AccessibilityTextUnderElementMode::TextUnderElementModeIncludeNameFromContentsChildren && !child->accessibleNameDerivesFromContent());
1668         if (shouldDeriveNameFromAuthor) {
1669             appendNameToStringBuilder(builder, accessibleNameForNode(child->node()));
1670             continue;
1671         }
1672         
1673         if (!shouldUseAccessiblityObjectInnerText(child, mode))
1674             continue;
1675
1676         if (child->isAccessibilityNodeObject()) {
1677             Vector<AccessibilityText> textOrder;
1678             toAccessibilityNodeObject(child)->alternativeText(textOrder);
1679             if (textOrder.size() > 0 && textOrder[0].text.length()) {
1680                 appendNameToStringBuilder(builder, textOrder[0].text);
1681                 continue;
1682             }
1683         }
1684         
1685         String childText = child->textUnderElement(mode);
1686         if (childText.length())
1687             appendNameToStringBuilder(builder, childText);
1688     }
1689
1690     return builder.toString().stripWhiteSpace().simplifyWhiteSpace(isHTMLSpaceButNotLineBreak);
1691 }
1692
1693 String AccessibilityNodeObject::title() const
1694 {
1695     Node* node = this->node();
1696     if (!node)
1697         return String();
1698
1699     bool isInputTag = is<HTMLInputElement>(node);
1700     if (isInputTag) {
1701         HTMLInputElement& input = downcast<HTMLInputElement>(*node);
1702         if (input.isTextButton())
1703             return input.valueWithDefault();
1704     }
1705
1706     if (isInputTag || AccessibilityObject::isARIAInput(ariaRoleAttribute()) || isControl()) {
1707         HTMLLabelElement* label = labelForElement(toElement(node));
1708         // Use the label text as the title if 1) the title element is NOT an exposed element and 2) there's no ARIA override.
1709         if (label && !exposesTitleUIElement() && !ariaAccessibilityDescription().length())
1710             return label->innerText();
1711     }
1712
1713     // If this node isn't rendered, there's no inner text we can extract from a select element.
1714     if (!isAccessibilityRenderObject() && node->hasTagName(selectTag))
1715         return String();
1716
1717     switch (roleValue()) {
1718     case PopUpButtonRole:
1719         // Native popup buttons should not use their button children's text as a title. That value is retrieved through stringValue().
1720         if (node->hasTagName(selectTag))
1721             return String();
1722         FALLTHROUGH;
1723     case ButtonRole:
1724     case ToggleButtonRole:
1725     case CheckBoxRole:
1726     case ListBoxOptionRole:
1727     case ListItemRole:
1728     case MenuButtonRole:
1729     case MenuItemRole:
1730     case MenuItemCheckboxRole:
1731     case MenuItemRadioRole:
1732     case RadioButtonRole:
1733     case TabRole:
1734         return textUnderElement();
1735     // SVGRoots should not use the text under itself as a title. That could include the text of objects like <text>.
1736     case SVGRootRole:
1737         return String();
1738     default:
1739         break;
1740     }
1741
1742     if (isLink())
1743         return textUnderElement();
1744     if (isHeading())
1745         return textUnderElement(AccessibilityTextUnderElementMode(AccessibilityTextUnderElementMode::TextUnderElementModeSkipIgnoredChildren, true));
1746
1747     return String();
1748 }
1749
1750 String AccessibilityNodeObject::text() const
1751 {
1752     // If this is a user defined static text, use the accessible name computation.                                      
1753     if (ariaRoleAttribute() == StaticTextRole) {
1754         Vector<AccessibilityText> textOrder;
1755         alternativeText(textOrder);
1756         if (textOrder.size() > 0 && textOrder[0].text.length())
1757             return textOrder[0].text;
1758     }
1759
1760     if (!isTextControl())
1761         return String();
1762
1763     Node* node = this->node();
1764     if (!node)
1765         return String();
1766
1767     if (isNativeTextControl() && is<HTMLTextFormControlElement>(*node))
1768         return downcast<HTMLTextFormControlElement>(*node).value();
1769
1770     if (!node->isElementNode())
1771         return String();
1772
1773     return toElement(node)->innerText();
1774 }
1775
1776 String AccessibilityNodeObject::stringValue() const
1777 {
1778     Node* node = this->node();
1779     if (!node)
1780         return String();
1781
1782     if (ariaRoleAttribute() == StaticTextRole) {
1783         String staticText = text();
1784         if (!staticText.length())
1785             staticText = textUnderElement();
1786         return staticText;
1787     }
1788
1789     if (node->isTextNode())
1790         return textUnderElement();
1791
1792     if (node->hasTagName(selectTag)) {
1793         HTMLSelectElement& selectElement = downcast<HTMLSelectElement>(*node);
1794         int selectedIndex = selectElement.selectedIndex();
1795         const Vector<HTMLElement*>& listItems = selectElement.listItems();
1796         if (selectedIndex >= 0 && static_cast<size_t>(selectedIndex) < listItems.size()) {
1797             const AtomicString& overriddenDescription = listItems[selectedIndex]->fastGetAttribute(aria_labelAttr);
1798             if (!overriddenDescription.isNull())
1799                 return overriddenDescription;
1800         }
1801         if (!selectElement.multiple())
1802             return selectElement.value();
1803         return String();
1804     }
1805
1806     if (isTextControl())
1807         return text();
1808
1809     // FIXME: We might need to implement a value here for more types
1810     // FIXME: It would be better not to advertise a value at all for the types for which we don't implement one;
1811     // this would require subclassing or making accessibilityAttributeNames do something other than return a
1812     // single static array.
1813     return String();
1814 }
1815
1816 void AccessibilityNodeObject::colorValue(int& r, int& g, int& b) const
1817 {
1818     r = 0;
1819     g = 0;
1820     b = 0;
1821
1822     if (!isColorWell())
1823         return;
1824
1825     if (!node() || !is<HTMLInputElement>(node()))
1826         return;
1827
1828     HTMLInputElement& input = downcast<HTMLInputElement>(*node());
1829     const AtomicString& type = input.getAttribute(typeAttr);
1830     if (!equalIgnoringCase(type, "color"))
1831         return;
1832
1833     // HTMLInputElement::value always returns a string parseable by Color().
1834     Color color(input.value());
1835     r = color.red();
1836     g = color.green();
1837     b = color.blue();
1838 }
1839
1840 // This function implements the ARIA accessible name as described by the Mozilla                                        
1841 // ARIA Implementer's Guide.                                                                                            
1842 static String accessibleNameForNode(Node* node)
1843 {
1844     ASSERT(node);
1845     if (!node || !node->isElementNode())
1846         return String();
1847     
1848     Element* element = toElement(node);
1849     const AtomicString& ariaLabel = element->fastGetAttribute(aria_labelAttr);
1850     if (!ariaLabel.isEmpty())
1851         return ariaLabel;
1852     
1853     const AtomicString& alt = element->fastGetAttribute(altAttr);
1854     if (!alt.isEmpty())
1855         return alt;
1856
1857     // If the node can be turned into an AX object, we can use standard name computation rules.
1858     // If however, the node cannot (because there's no renderer e.g.) fallback to using the basic text underneath.
1859     AccessibilityObject* axObject = node->document().axObjectCache()->getOrCreate(node);
1860     if (axObject) {
1861         String valueDescription = axObject->valueDescription();
1862         if (!valueDescription.isEmpty())
1863             return valueDescription;
1864     }
1865     
1866     if (is<HTMLInputElement>(node))
1867         return downcast<HTMLInputElement>(*node).value();
1868     
1869     String text;
1870     if (axObject) {
1871         if (axObject->accessibleNameDerivesFromContent())
1872             text = axObject->textUnderElement(AccessibilityTextUnderElementMode(AccessibilityTextUnderElementMode::TextUnderElementModeIncludeNameFromContentsChildren, true));
1873     } else
1874         text = element->innerText();
1875
1876     if (!text.isEmpty())
1877         return text;
1878     
1879     const AtomicString& title = element->fastGetAttribute(titleAttr);
1880     if (!title.isEmpty())
1881         return title;
1882     
1883     return String();
1884 }
1885
1886 String AccessibilityNodeObject::accessibilityDescriptionForElements(Vector<Element*> &elements) const
1887 {
1888     StringBuilder builder;
1889     unsigned size = elements.size();
1890     for (unsigned i = 0; i < size; ++i)
1891         appendNameToStringBuilder(builder, accessibleNameForNode(elements[i]));
1892     return builder.toString();
1893 }
1894
1895 String AccessibilityNodeObject::ariaDescribedByAttribute() const
1896 {
1897     Vector<Element*> elements;
1898     elementsFromAttribute(elements, aria_describedbyAttr);
1899     
1900     return accessibilityDescriptionForElements(elements);
1901 }
1902
1903 void AccessibilityNodeObject::ariaLabeledByElements(Vector<Element*>& elements) const
1904 {
1905     elementsFromAttribute(elements, aria_labelledbyAttr);
1906     if (!elements.size())
1907         elementsFromAttribute(elements, aria_labeledbyAttr);
1908 }
1909
1910
1911 String AccessibilityNodeObject::ariaLabeledByAttribute() const
1912 {
1913     Vector<Element*> elements;
1914     ariaLabeledByElements(elements);
1915
1916     return accessibilityDescriptionForElements(elements);
1917 }
1918
1919 bool AccessibilityNodeObject::hasAttributesRequiredForInclusion() const
1920 {
1921     if (AccessibilityObject::hasAttributesRequiredForInclusion())
1922         return true;
1923
1924     if (!ariaAccessibilityDescription().isEmpty())
1925         return true;
1926
1927     return false;
1928 }
1929
1930 bool AccessibilityNodeObject::canSetFocusAttribute() const
1931 {
1932     Node* node = this->node();
1933     if (!node)
1934         return false;
1935
1936     if (isWebArea())
1937         return true;
1938     
1939     // NOTE: It would be more accurate to ask the document whether setFocusedElement() would
1940     // do anything. For example, setFocusedElement() will do nothing if the current focused
1941     // node will not relinquish the focus.
1942     if (!node)
1943         return false;
1944
1945     if (!node->isElementNode())
1946         return false;
1947
1948     Element* element = toElement(node);
1949
1950     if (element->isDisabledFormControl())
1951         return false;
1952
1953     return element->supportsFocus();
1954 }
1955
1956 AccessibilityRole AccessibilityNodeObject::determineAriaRoleAttribute() const
1957 {
1958     const AtomicString& ariaRole = getAttribute(roleAttr);
1959     if (ariaRole.isNull() || ariaRole.isEmpty())
1960         return UnknownRole;
1961     
1962     AccessibilityRole role = ariaRoleToWebCoreRole(ariaRole);
1963
1964     // ARIA states if an item can get focus, it should not be presentational.
1965     if (role == PresentationalRole && canSetFocusAttribute())
1966         return UnknownRole;
1967
1968     if (role == ButtonRole)
1969         role = buttonRoleType();
1970
1971     if (role == TextAreaRole && !ariaIsMultiline())
1972         role = TextFieldRole;
1973
1974     role = remapAriaRoleDueToParent(role);
1975     
1976     // Presentational roles are invalidated by the presence of ARIA attributes.
1977     if (role == PresentationalRole && supportsARIAAttributes())
1978         role = UnknownRole;
1979     
1980     if (role)
1981         return role;
1982
1983     return UnknownRole;
1984 }
1985
1986 AccessibilityRole AccessibilityNodeObject::ariaRoleAttribute() const
1987 {
1988     return m_ariaRole;
1989 }
1990
1991 AccessibilityRole AccessibilityNodeObject::remapAriaRoleDueToParent(AccessibilityRole role) const
1992 {
1993     // Some objects change their role based on their parent.
1994     // However, asking for the unignoredParent calls accessibilityIsIgnored(), which can trigger a loop. 
1995     // While inside the call stack of creating an element, we need to avoid accessibilityIsIgnored().
1996     // https://bugs.webkit.org/show_bug.cgi?id=65174
1997
1998     if (role != ListBoxOptionRole && role != MenuItemRole)
1999         return role;
2000     
2001     for (AccessibilityObject* parent = parentObject(); parent && !parent->accessibilityIsIgnored(); parent = parent->parentObject()) {
2002         AccessibilityRole parentAriaRole = parent->ariaRoleAttribute();
2003
2004         // Selects and listboxes both have options as child roles, but they map to different roles within WebCore.
2005         if (role == ListBoxOptionRole && parentAriaRole == MenuRole)
2006             return MenuItemRole;
2007         // An aria "menuitem" may map to MenuButton or MenuItem depending on its parent.
2008         if (role == MenuItemRole && parentAriaRole == GroupRole)
2009             return MenuButtonRole;
2010         
2011         // If the parent had a different role, then we don't need to continue searching up the chain.
2012         if (parentAriaRole)
2013             break;
2014     }
2015     
2016     return role;
2017 }   
2018
2019 bool AccessibilityNodeObject::canSetSelectedAttribute() const
2020 {
2021     // Elements that can be selected
2022     switch (roleValue()) {
2023     case CellRole:
2024     case RadioButtonRole:
2025     case RowHeaderRole:
2026     case RowRole:
2027     case TabListRole:
2028     case TabRole:
2029     case TreeGridRole:
2030     case TreeItemRole:
2031     case TreeRole:
2032         return isEnabled();
2033     default:
2034         return false;
2035     }
2036 }
2037
2038 } // namespace WebCore