AX: Do the early return when role is different than UnknownRole
[WebKit-https.git] / Source / WebCore / accessibility / AccessibilityNodeObject.cpp
1 /*
2 * Copyright (C) 2012, Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1.  Redistributions of source code must retain the above copyright
9 *     notice, this list of conditions and the following disclaimer.
10 * 2.  Redistributions in binary form must reproduce the above copyright
11 *     notice, this list of conditions and the following disclaimer in the
12 *     documentation and/or other materials provided with the distribution.
13 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
14 *     its contributors may be used to endorse or promote products derived
15 *     from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "config.h"
30 #include "AccessibilityNodeObject.h"
31
32 #include "AXObjectCache.h"
33 #include "AccessibilityImageMapLink.h"
34 #include "AccessibilityList.h"
35 #include "AccessibilityListBox.h"
36 #include "AccessibilitySpinButton.h"
37 #include "AccessibilityTable.h"
38 #include "ElementIterator.h"
39 #include "EventNames.h"
40 #include "FloatRect.h"
41 #include "Frame.h"
42 #include "FrameLoader.h"
43 #include "FrameSelection.h"
44 #include "FrameView.h"
45 #include "HTMLAreaElement.h"
46 #include "HTMLCanvasElement.h"
47 #include "HTMLFieldSetElement.h"
48 #include "HTMLFormElement.h"
49 #include "HTMLFrameElementBase.h"
50 #include "HTMLImageElement.h"
51 #include "HTMLInputElement.h"
52 #include "HTMLLabelElement.h"
53 #include "HTMLLegendElement.h"
54 #include "HTMLMapElement.h"
55 #include "HTMLNames.h"
56 #include "HTMLOptGroupElement.h"
57 #include "HTMLOptionElement.h"
58 #include "HTMLOptionsCollection.h"
59 #include "HTMLParserIdioms.h"
60 #include "HTMLPlugInImageElement.h"
61 #include "HTMLSelectElement.h"
62 #include "HTMLTextAreaElement.h"
63 #include "HTMLTextFormControlElement.h"
64 #include "HitTestRequest.h"
65 #include "HitTestResult.h"
66 #include "LabelableElement.h"
67 #include "LocalizedStrings.h"
68 #include "MathMLElement.h"
69 #include "MathMLNames.h"
70 #include "NodeList.h"
71 #include "NodeTraversal.h"
72 #include "Page.h"
73 #include "ProgressTracker.h"
74 #include "RenderImage.h"
75 #include "RenderView.h"
76 #include "SVGElement.h"
77 #include "SVGNames.h"
78 #include "Text.h"
79 #include "TextControlInnerElements.h"
80 #include "UserGestureIndicator.h"
81 #include "VisibleUnits.h"
82 #include "Widget.h"
83 #include "htmlediting.h"
84 #include <wtf/StdLibExtras.h>
85 #include <wtf/text/StringBuilder.h>
86 #include <wtf/unicode/CharacterNames.h>
87
88 namespace WebCore {
89
90 using namespace HTMLNames;
91
92 static String accessibleNameForNode(Node*);
93
94 AccessibilityNodeObject::AccessibilityNodeObject(Node* node)
95     : AccessibilityObject()
96     , m_ariaRole(UnknownRole)
97     , m_childrenDirty(false)
98     , m_roleForMSAA(UnknownRole)
99 #ifndef NDEBUG
100     , m_initialized(false)
101 #endif
102     , m_node(node)
103 {
104 }
105
106 AccessibilityNodeObject::~AccessibilityNodeObject()
107 {
108     ASSERT(isDetached());
109 }
110
111 void AccessibilityNodeObject::init()
112 {
113 #ifndef NDEBUG
114     ASSERT(!m_initialized);
115     m_initialized = true;
116 #endif
117     m_role = determineAccessibilityRole();
118 }
119
120 PassRefPtr<AccessibilityNodeObject> AccessibilityNodeObject::create(Node* node)
121 {
122     return adoptRef(new AccessibilityNodeObject(node));
123 }
124
125 void AccessibilityNodeObject::detach(AccessibilityDetachmentType detachmentType, AXObjectCache* cache)
126 {
127     // AccessibilityObject calls clearChildren.
128     AccessibilityObject::detach(detachmentType, cache);
129     m_node = nullptr;
130 }
131
132 void AccessibilityNodeObject::childrenChanged()
133 {
134     // This method is meant as a quick way of marking a portion of the accessibility tree dirty.
135     if (!node() && !renderer())
136         return;
137
138     AXObjectCache* cache = axObjectCache();
139     if (!cache)
140         return;
141     cache->postNotification(this, document(), AXObjectCache::AXChildrenChanged);
142
143     // Go up the accessibility parent chain, but only if the element already exists. This method is
144     // called during render layouts, minimal work should be done. 
145     // If AX elements are created now, they could interrogate the render tree while it's in a funky state.
146     // At the same time, process ARIA live region changes.
147     for (AccessibilityObject* parent = this; parent; parent = parent->parentObjectIfExists()) {
148         parent->setNeedsToUpdateChildren();
149
150         // These notifications always need to be sent because screenreaders are reliant on them to perform. 
151         // In other words, they need to be sent even when the screen reader has not accessed this live region since the last update.
152
153         // If this element supports ARIA live regions, then notify the AT of changes.
154         if (parent->supportsARIALiveRegion())
155             cache->postNotification(parent, parent->document(), AXObjectCache::AXLiveRegionChanged);
156         
157         // If this element is an ARIA text control, notify the AT of changes.
158         if ((parent->isARIATextControl() || parent->hasContentEditableAttributeSet()) && !parent->isNativeTextControl())
159             cache->postNotification(parent, parent->document(), AXObjectCache::AXValueChanged);
160     }
161 }
162
163 void AccessibilityNodeObject::updateAccessibilityRole()
164 {
165     bool ignoredStatus = accessibilityIsIgnored();
166     m_role = determineAccessibilityRole();
167     
168     // The AX hierarchy only needs to be updated if the ignored status of an element has changed.
169     if (ignoredStatus != accessibilityIsIgnored())
170         childrenChanged();
171 }
172     
173 AccessibilityObject* AccessibilityNodeObject::firstChild() const
174 {
175     if (!node())
176         return nullptr;
177     
178     Node* firstChild = node()->firstChild();
179
180     if (!firstChild)
181         return nullptr;
182     
183     return axObjectCache()->getOrCreate(firstChild);
184 }
185
186 AccessibilityObject* AccessibilityNodeObject::lastChild() const
187 {
188     if (!node())
189         return nullptr;
190     
191     Node* lastChild = node()->lastChild();
192     if (!lastChild)
193         return nullptr;
194     
195     return axObjectCache()->getOrCreate(lastChild);
196 }
197
198 AccessibilityObject* AccessibilityNodeObject::previousSibling() const
199 {
200     if (!node())
201         return nullptr;
202
203     Node* previousSibling = node()->previousSibling();
204     if (!previousSibling)
205         return nullptr;
206
207     return axObjectCache()->getOrCreate(previousSibling);
208 }
209
210 AccessibilityObject* AccessibilityNodeObject::nextSibling() const
211 {
212     if (!node())
213         return nullptr;
214
215     Node* nextSibling = node()->nextSibling();
216     if (!nextSibling)
217         return nullptr;
218
219     return axObjectCache()->getOrCreate(nextSibling);
220 }
221     
222 AccessibilityObject* AccessibilityNodeObject::parentObjectIfExists() const
223 {
224     return parentObject();
225 }
226     
227 AccessibilityObject* AccessibilityNodeObject::parentObject() const
228 {
229     if (!node())
230         return nullptr;
231
232     Node* parentObj = node()->parentNode();
233     if (!parentObj)
234         return nullptr;
235     
236     if (AXObjectCache* cache = axObjectCache())
237         return cache->getOrCreate(parentObj);
238     
239     return nullptr;
240 }
241
242 LayoutRect AccessibilityNodeObject::elementRect() const
243 {
244     return boundingBoxRect();
245 }
246     
247 LayoutRect AccessibilityNodeObject::boundingBoxRect() const
248 {
249     // AccessibilityNodeObjects have no mechanism yet to return a size or position.
250     // For now, let's return the position of the ancestor that does have a position,
251     // 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.
252     
253     LayoutRect boundingBox;
254     
255     for (AccessibilityObject* positionProvider = parentObject(); positionProvider; positionProvider = positionProvider->parentObject()) {
256         if (positionProvider->isAccessibilityRenderObject()) {
257             LayoutRect parentRect = positionProvider->elementRect();
258             boundingBox.setSize(LayoutSize(parentRect.width(), LayoutUnit(std::min(10.0f, parentRect.height().toFloat()))));
259             boundingBox.setLocation(parentRect.location());
260             break;
261         }
262     }
263     
264     return boundingBox;
265 }
266
267 void AccessibilityNodeObject::setNode(Node* node)
268 {
269     m_node = node;
270 }
271
272 Document* AccessibilityNodeObject::document() const
273 {
274     if (!node())
275         return nullptr;
276     return &node()->document();
277 }
278
279 AccessibilityRole AccessibilityNodeObject::determineAccessibilityRole()
280 {
281     if (!node())
282         return UnknownRole;
283
284     if ((m_ariaRole = determineAriaRoleAttribute()) != UnknownRole)
285         return m_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 (is<Element>(*node()) && downcast<Element>(*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 (!is<HTMLCanvasElement>(node))
444         return false;
445     HTMLCanvasElement& canvasElement = downcast<HTMLCanvasElement>(*node);
446     // If it has any children that are elements, we'll assume it might be fallback
447     // content. If it has no children or its only children are not elements
448     // (e.g. just text nodes), it doesn't have fallback content.
449     return childrenOfType<Element>(canvasElement).first();
450 }
451
452 bool AccessibilityNodeObject::isImageButton() const
453 {
454     return isNativeImage() && isButton();
455 }
456
457 bool AccessibilityNodeObject::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 (is<HTMLInputElement>(node) && roleValue() == ButtonRole) {
554         HTMLInputElement& input = downcast<HTMLInputElement>(*node);
555         return input.isImageButton();
556     }
557
558     return false;
559 }
560
561 bool AccessibilityNodeObject::isProgressIndicator() const
562 {
563     return roleValue() == ProgressIndicatorRole;
564 }
565
566 bool AccessibilityNodeObject::isSlider() const
567 {
568     return roleValue() == SliderRole;
569 }
570
571 bool AccessibilityNodeObject::isMenuRelated() const
572 {
573     switch (roleValue()) {
574     case MenuRole:
575     case MenuBarRole:
576     case MenuButtonRole:
577     case MenuItemRole:
578     case MenuItemCheckboxRole:
579     case MenuItemRadioRole:
580         return true;
581     default:
582         return false;
583     }
584 }
585
586 bool AccessibilityNodeObject::isMenu() const
587 {
588     return roleValue() == MenuRole;
589 }
590
591 bool AccessibilityNodeObject::isMenuBar() const
592 {
593     return roleValue() == MenuBarRole;
594 }
595
596 bool AccessibilityNodeObject::isMenuButton() const
597 {
598     return roleValue() == MenuButtonRole;
599 }
600
601 bool AccessibilityNodeObject::isMenuItem() const
602 {
603     switch (roleValue()) {
604     case MenuItemRole:
605     case MenuItemRadioRole:
606     case MenuItemCheckboxRole:
607         return true;
608     default:
609         return false;
610     }
611 }
612
613 bool AccessibilityNodeObject::isNativeCheckboxOrRadio() const
614 {
615     Node* node = this->node();
616     if (!node)
617         return false;
618
619     HTMLInputElement* input = node->toInputElement();
620     if (input)
621         return input->isCheckbox() || input->isRadioButton();
622
623     return false;
624 }
625
626 bool AccessibilityNodeObject::isEnabled() const
627 {
628     // ARIA says that the disabled status applies to the current element and all descendant elements.
629     for (AccessibilityObject* object = const_cast<AccessibilityNodeObject*>(this); object; object = object->parentObject()) {
630         const AtomicString& disabledStatus = object->getAttribute(aria_disabledAttr);
631         if (equalIgnoringCase(disabledStatus, "true"))
632             return false;
633         if (equalIgnoringCase(disabledStatus, "false"))
634             break;
635     }
636     
637     if (roleValue() == HorizontalRuleRole)
638         return false;
639     
640     Node* node = this->node();
641     if (!is<Element>(node))
642         return true;
643
644     return !downcast<Element>(*node).isDisabledFormControl();
645 }
646
647 bool AccessibilityNodeObject::isIndeterminate() const
648 {
649     Node* node = this->node();
650     if (!node)
651         return false;
652
653     HTMLInputElement* inputElement = node->toInputElement();
654     if (!inputElement)
655         return false;
656
657     return inputElement->shouldAppearIndeterminate();
658 }
659
660 bool AccessibilityNodeObject::isPressed() const
661 {
662     if (!isButton())
663         return false;
664
665     Node* node = this->node();
666     if (!node)
667         return false;
668
669     // If this is an ARIA button, check the aria-pressed attribute rather than node()->active()
670     if (ariaRoleAttribute() == ButtonRole) {
671         if (equalIgnoringCase(getAttribute(aria_pressedAttr), "true"))
672             return true;
673         return false;
674     }
675
676     if (!is<Element>(*node))
677         return false;
678     return downcast<Element>(*node).active();
679 }
680
681 bool AccessibilityNodeObject::isChecked() const
682 {
683     Node* node = this->node();
684     if (!node)
685         return false;
686
687     // First test for native checkedness semantics
688     HTMLInputElement* inputElement = node->toInputElement();
689     if (inputElement)
690         return inputElement->shouldAppearChecked();
691
692     // Else, if this is an ARIA checkbox or radio, respect the aria-checked attribute
693     bool validRole = false;
694     switch (ariaRoleAttribute()) {
695     case RadioButtonRole:
696     case CheckBoxRole:
697     case MenuItemRole:
698     case MenuItemCheckboxRole:
699     case MenuItemRadioRole:
700         validRole = true;
701         break;
702     default:
703         break;
704     }
705     
706     if (validRole && equalIgnoringCase(getAttribute(aria_checkedAttr), "true"))
707         return true;
708
709     return false;
710 }
711
712 bool AccessibilityNodeObject::isHovered() const
713 {
714     Node* node = this->node();
715     return is<Element>(node) && downcast<Element>(*node).hovered();
716 }
717
718 bool AccessibilityNodeObject::isMultiSelectable() const
719 {
720     const AtomicString& ariaMultiSelectable = getAttribute(aria_multiselectableAttr);
721     if (equalIgnoringCase(ariaMultiSelectable, "true"))
722         return true;
723     if (equalIgnoringCase(ariaMultiSelectable, "false"))
724         return false;
725     
726     return node() && node()->hasTagName(selectTag) && downcast<HTMLSelectElement>(*node()).multiple();
727 }
728
729 bool AccessibilityNodeObject::isReadOnly() const
730 {
731     Node* node = this->node();
732     if (!node)
733         return true;
734
735     if (is<HTMLTextAreaElement>(*node))
736         return downcast<HTMLTextAreaElement>(*node).isReadOnly();
737
738     if (is<HTMLInputElement>(*node)) {
739         HTMLInputElement& input = downcast<HTMLInputElement>(*node);
740         if (input.isTextField())
741             return input.isReadOnly();
742     }
743
744     return !node->hasEditableStyle();
745 }
746
747 bool AccessibilityNodeObject::isRequired() const
748 {
749     // Explicit aria-required values should trump native required attributes.
750     const AtomicString& requiredValue = getAttribute(aria_requiredAttr);
751     if (equalIgnoringCase(requiredValue, "true"))
752         return true;
753     if (equalIgnoringCase(requiredValue, "false"))
754         return false;
755
756     Node* n = this->node();
757     if (is<HTMLFormControlElement>(n))
758         return downcast<HTMLFormControlElement>(*n).isRequired();
759
760     return false;
761 }
762
763 bool AccessibilityNodeObject::supportsRequiredAttribute() const
764 {
765     switch (roleValue()) {
766     case ButtonRole:
767         return isFileUploadButton();
768     case CellRole:
769     case CheckBoxRole:
770     case ComboBoxRole:
771     case GridRole:
772     case IncrementorRole:
773     case ListBoxRole:
774     case PopUpButtonRole:
775     case RadioButtonRole:
776     case RadioGroupRole:
777     case RowHeaderRole:
778     case SliderRole:
779     case SpinButtonRole:
780     case TableHeaderContainerRole:
781     case TextAreaRole:
782     case TextFieldRole:
783     case ToggleButtonRole:
784         return true;
785     default:
786         return false;
787     }
788 }
789
790 int AccessibilityNodeObject::headingLevel() const
791 {
792     // headings can be in block flow and non-block flow
793     Node* node = this->node();
794     if (!node)
795         return false;
796
797     if (isHeading()) {
798         int ariaLevel = getAttribute(aria_levelAttr).toInt();
799         if (ariaLevel > 0)
800             return ariaLevel;
801     }
802
803     if (node->hasTagName(h1Tag))
804         return 1;
805
806     if (node->hasTagName(h2Tag))
807         return 2;
808
809     if (node->hasTagName(h3Tag))
810         return 3;
811
812     if (node->hasTagName(h4Tag))
813         return 4;
814
815     if (node->hasTagName(h5Tag))
816         return 5;
817
818     if (node->hasTagName(h6Tag))
819         return 6;
820
821     return 0;
822 }
823
824 String AccessibilityNodeObject::valueDescription() const
825 {
826     if (!isRangeControl())
827         return String();
828
829     return getAttribute(aria_valuetextAttr).string();
830 }
831
832 float AccessibilityNodeObject::valueForRange() const
833 {
834     if (is<HTMLInputElement>(node())) {
835         HTMLInputElement& input = downcast<HTMLInputElement>(*node());
836         if (input.isRangeControl())
837             return input.valueAsNumber();
838     }
839
840     if (!isRangeControl())
841         return 0.0f;
842
843     return getAttribute(aria_valuenowAttr).toFloat();
844 }
845
846 float AccessibilityNodeObject::maxValueForRange() const
847 {
848     if (is<HTMLInputElement>(node())) {
849         HTMLInputElement& input = downcast<HTMLInputElement>(*node());
850         if (input.isRangeControl())
851             return input.maximum();
852     }
853
854     if (!isRangeControl())
855         return 0.0f;
856
857     return getAttribute(aria_valuemaxAttr).toFloat();
858 }
859
860 float AccessibilityNodeObject::minValueForRange() const
861 {
862     if (is<HTMLInputElement>(node())) {
863         HTMLInputElement& input = downcast<HTMLInputElement>(*node());
864         if (input.isRangeControl())
865             return input.minimum();
866     }
867
868     if (!isRangeControl())
869         return 0.0f;
870
871     return getAttribute(aria_valueminAttr).toFloat();
872 }
873
874 float AccessibilityNodeObject::stepValueForRange() const
875 {
876     return getAttribute(stepAttr).toFloat();
877 }
878
879 bool AccessibilityNodeObject::isHeading() const
880 {
881     return roleValue() == HeadingRole;
882 }
883
884 bool AccessibilityNodeObject::isLink() const
885 {
886     return roleValue() == WebCoreLinkRole;
887 }
888
889 bool AccessibilityNodeObject::isControl() const
890 {
891     Node* node = this->node();
892     if (!node)
893         return false;
894
895     return is<HTMLFormControlElement>(*node) || AccessibilityObject::isARIAControl(ariaRoleAttribute());
896 }
897
898 bool AccessibilityNodeObject::isFieldset() const
899 {
900     Node* node = this->node();
901     if (!node)
902         return false;
903
904     return node->hasTagName(fieldsetTag);
905 }
906
907 bool AccessibilityNodeObject::isGroup() const
908 {
909     return roleValue() == GroupRole;
910 }
911
912 AccessibilityObject* AccessibilityNodeObject::selectedRadioButton()
913 {
914     if (!isRadioGroup())
915         return nullptr;
916
917     // Find the child radio button that is selected (ie. the intValue == 1).
918     for (const auto& child : children()) {
919         if (child->roleValue() == RadioButtonRole && child->checkboxOrRadioValue() == ButtonStateOn)
920             return child.get();
921     }
922     return nullptr;
923 }
924
925 AccessibilityObject* AccessibilityNodeObject::selectedTabItem()
926 {
927     if (!isTabList())
928         return nullptr;
929
930     // Find the child tab item that is selected (ie. the intValue == 1).
931     AccessibilityObject::AccessibilityChildrenVector tabs;
932     tabChildren(tabs);
933
934     for (const auto& child : children()) {
935         if (child->isTabItem() && child->isChecked())
936             return child.get();
937     }
938     return nullptr;
939 }
940
941 AccessibilityButtonState AccessibilityNodeObject::checkboxOrRadioValue() const
942 {
943     if (isNativeCheckboxOrRadio())
944         return isChecked() ? ButtonStateOn : ButtonStateOff;
945
946     return AccessibilityObject::checkboxOrRadioValue();
947 }
948
949 Element* AccessibilityNodeObject::anchorElement() const
950 {
951     Node* node = this->node();
952     if (!node)
953         return nullptr;
954
955     AXObjectCache* cache = axObjectCache();
956
957     // search up the DOM tree for an anchor element
958     // NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElement
959     for ( ; node; node = node->parentNode()) {
960         if (is<HTMLAnchorElement>(*node) || (node->renderer() && cache->getOrCreate(node->renderer())->isAnchor()))
961             return downcast<Element>(node);
962     }
963
964     return nullptr;
965 }
966
967 static bool isNodeActionElement(Node* node)
968 {
969     if (is<HTMLInputElement>(*node)) {
970         HTMLInputElement& input = downcast<HTMLInputElement>(*node);
971         if (!input.isDisabledFormControl() && (input.isRadioButton() || input.isCheckbox() || input.isTextButton() || input.isFileUpload() || input.isImageButton()))
972             return true;
973     } else if (node->hasTagName(buttonTag) || node->hasTagName(selectTag))
974         return true;
975
976     return false;
977 }
978     
979 static Element* nativeActionElement(Node* start)
980 {
981     if (!start)
982         return nullptr;
983     
984     // Do a deep-dive to see if any nodes should be used as the action element.
985     // We have to look at Nodes, since this method should only be called on objects that do not have children (like buttons).
986     // It solves the problem when authors put role="button" on a group and leave the actual button inside the group.
987     
988     for (Node* child = start->firstChild(); child; child = child->nextSibling()) {
989         if (isNodeActionElement(child))
990             return downcast<Element>(child);
991
992         if (Element* subChild = nativeActionElement(child))
993             return subChild;
994     }
995     return nullptr;
996 }
997     
998 Element* AccessibilityNodeObject::actionElement() const
999 {
1000     Node* node = this->node();
1001     if (!node)
1002         return nullptr;
1003
1004     if (isNodeActionElement(node))
1005         return downcast<Element>(node);
1006     
1007     if (AccessibilityObject::isARIAInput(ariaRoleAttribute()))
1008         return downcast<Element>(node);
1009
1010     switch (roleValue()) {
1011     case ButtonRole:
1012     case PopUpButtonRole:
1013     case ToggleButtonRole:
1014     case TabRole:
1015     case MenuItemRole:
1016     case MenuItemCheckboxRole:
1017     case MenuItemRadioRole:
1018     case ListItemRole:
1019         // Check if the author is hiding the real control element inside the ARIA element.
1020         if (Element* nativeElement = nativeActionElement(node))
1021             return nativeElement;
1022         return downcast<Element>(node);
1023     default:
1024         break;
1025     }
1026     
1027     Element* elt = anchorElement();
1028     if (!elt)
1029         elt = mouseButtonListener();
1030     return elt;
1031 }
1032
1033 Element* AccessibilityNodeObject::mouseButtonListener(MouseButtonListenerResultFilter filter) const
1034 {
1035     Node* node = this->node();
1036     if (!node)
1037         return nullptr;
1038
1039     // check if our parent is a mouse button listener
1040     // FIXME: Do the continuation search like anchorElement does
1041     for (auto& element : elementLineage(is<Element>(*node) ? downcast<Element>(node) : node->parentElement())) {
1042         // 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.
1043         // It can cause false positives, where every piece of text is labeled as accepting press actions.
1044         if (element.hasTagName(bodyTag) && isStaticText() && filter == ExcludeBodyElement)
1045             break;
1046         
1047         if (element.hasEventListeners(eventNames().clickEvent) || element.hasEventListeners(eventNames().mousedownEvent) || element.hasEventListeners(eventNames().mouseupEvent))
1048             return &element;
1049     }
1050
1051     return nullptr;
1052 }
1053
1054 bool AccessibilityNodeObject::isDescendantOfBarrenParent() const
1055 {
1056     for (AccessibilityObject* object = parentObject(); object; object = object->parentObject()) {
1057         if (!object->canHaveChildren())
1058             return true;
1059     }
1060
1061     return false;
1062 }
1063
1064 void AccessibilityNodeObject::alterSliderValue(bool increase)
1065 {
1066     if (roleValue() != SliderRole)
1067         return;
1068
1069     if (!getAttribute(stepAttr).isEmpty())
1070         changeValueByStep(increase);
1071     else
1072         changeValueByPercent(increase ? 5 : -5);
1073 }
1074     
1075 void AccessibilityNodeObject::increment()
1076 {
1077     UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture, document());
1078     alterSliderValue(true);
1079 }
1080
1081 void AccessibilityNodeObject::decrement()
1082 {
1083     UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture, document());
1084     alterSliderValue(false);
1085 }
1086
1087 void AccessibilityNodeObject::changeValueByStep(bool increase)
1088 {
1089     float step = stepValueForRange();
1090     float value = valueForRange();
1091
1092     value += increase ? step : -step;
1093
1094     setValue(String::number(value));
1095
1096     axObjectCache()->postNotification(node(), AXObjectCache::AXValueChanged);
1097 }
1098
1099 void AccessibilityNodeObject::changeValueByPercent(float percentChange)
1100 {
1101     float range = maxValueForRange() - minValueForRange();
1102     float step = range * (percentChange / 100);
1103     float value = valueForRange();
1104
1105     // Make sure the specified percent will cause a change of one integer step or larger.
1106     if (fabs(step) < 1)
1107         step = fabs(percentChange) * (1 / percentChange);
1108
1109     value += step;
1110     setValue(String::number(value));
1111
1112     axObjectCache()->postNotification(node(), AXObjectCache::AXValueChanged);
1113 }
1114
1115 bool AccessibilityNodeObject::isGenericFocusableElement() const
1116 {
1117     if (!canSetFocusAttribute())
1118         return false;
1119
1120     // If it's a control, it's not generic.
1121     if (isControl())
1122         return false;
1123     
1124     AccessibilityRole role = roleValue();
1125     if (role == VideoRole || role == AudioRole)
1126         return false;
1127
1128     // If it has an aria role, it's not generic.
1129     if (m_ariaRole != UnknownRole)
1130         return false;
1131
1132     // If the content editable attribute is set on this element, that's the reason
1133     // it's focusable, and existing logic should handle this case already - so it's not a
1134     // generic focusable element.
1135
1136     if (hasContentEditableAttributeSet())
1137         return false;
1138
1139     // The web area and body element are both focusable, but existing logic handles these
1140     // cases already, so we don't need to include them here.
1141     if (role == WebAreaRole)
1142         return false;
1143     if (node() && node()->hasTagName(bodyTag))
1144         return false;
1145
1146     // An SVG root is focusable by default, but it's probably not interactive, so don't
1147     // include it. It can still be made accessible by giving it an ARIA role.
1148     if (role == SVGRootRole)
1149         return false;
1150
1151     return true;
1152 }
1153
1154 HTMLLabelElement* AccessibilityNodeObject::labelForElement(Element* element) const
1155 {
1156     if (!is<HTMLElement>(*element) || !downcast<HTMLElement>(*element).isLabelable())
1157         return nullptr;
1158
1159     const AtomicString& id = element->getIdAttribute();
1160     if (!id.isEmpty()) {
1161         if (HTMLLabelElement* label = element->treeScope().labelElementForId(id))
1162             return label;
1163     }
1164
1165     return ancestorsOfType<HTMLLabelElement>(*element).first();
1166 }
1167
1168 String AccessibilityNodeObject::ariaAccessibilityDescription() const
1169 {
1170     String ariaLabeledBy = ariaLabeledByAttribute();
1171     if (!ariaLabeledBy.isEmpty())
1172         return ariaLabeledBy;
1173
1174     const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
1175     if (!ariaLabel.isEmpty())
1176         return ariaLabel;
1177
1178     return String();
1179 }
1180
1181 static Element* siblingWithAriaRole(String role, Node* node)
1182 {
1183     ContainerNode* parent = node->parentNode();
1184     if (!parent)
1185         return nullptr;
1186
1187     for (auto& sibling : childrenOfType<Element>(*parent)) {
1188         const AtomicString& siblingAriaRole = sibling.fastGetAttribute(roleAttr);
1189         if (equalIgnoringCase(siblingAriaRole, role))
1190             return &sibling;
1191     }
1192
1193     return nullptr;
1194 }
1195
1196 Element* AccessibilityNodeObject::menuElementForMenuButton() const
1197 {
1198     if (ariaRoleAttribute() != MenuButtonRole)
1199         return nullptr;
1200
1201     return siblingWithAriaRole("menu", node());
1202 }
1203
1204 AccessibilityObject* AccessibilityNodeObject::menuForMenuButton() const
1205 {
1206     if (AXObjectCache* cache = axObjectCache())
1207         return cache->getOrCreate(menuElementForMenuButton());
1208     return nullptr;
1209 }
1210
1211 Element* AccessibilityNodeObject::menuItemElementForMenu() const
1212 {
1213     if (ariaRoleAttribute() != MenuRole)
1214         return nullptr;
1215     
1216     return siblingWithAriaRole("menuitem", node());    
1217 }
1218
1219 AccessibilityObject* AccessibilityNodeObject::menuButtonForMenu() const
1220 {
1221     AXObjectCache* cache = axObjectCache();
1222     if (!cache)
1223         return nullptr;
1224
1225     Element* menuItem = menuItemElementForMenu();
1226
1227     if (menuItem) {
1228         // ARIA just has generic menu items. AppKit needs to know if this is a top level items like MenuBarButton or MenuBarItem
1229         AccessibilityObject* menuItemAX = cache->getOrCreate(menuItem);
1230         if (menuItemAX && menuItemAX->isMenuButton())
1231             return menuItemAX;
1232     }
1233     return nullptr;
1234 }
1235
1236 bool AccessibilityNodeObject::usesAltTagForTextComputation() const
1237 {
1238     return isImage() || isInputImage() || isNativeImage() || isCanvas() || (node() && node()->hasTagName(imgTag));
1239 }
1240     
1241 void AccessibilityNodeObject::titleElementText(Vector<AccessibilityText>& textOrder) const
1242 {
1243     Node* node = this->node();
1244     if (!node)
1245         return;
1246     
1247     bool isInputTag = is<HTMLInputElement>(*node);
1248     if (isInputTag || AccessibilityObject::isARIAInput(ariaRoleAttribute()) || isControl()) {
1249         if (HTMLLabelElement* label = labelForElement(downcast<Element>(node))) {
1250             AccessibilityObject* labelObject = axObjectCache()->getOrCreate(label);
1251             String innerText = label->innerText();
1252             // Only use the <label> text if there's no ARIA override.
1253             if (!innerText.isEmpty() && !ariaAccessibilityDescription())
1254                 textOrder.append(AccessibilityText(innerText, LabelByElementText, labelObject));
1255             return;
1256         }
1257     }
1258     
1259     AccessibilityObject* titleUIElement = this->titleUIElement();
1260     if (titleUIElement)
1261         textOrder.append(AccessibilityText(String(), LabelByElementText, titleUIElement));
1262 }
1263
1264 void AccessibilityNodeObject::alternativeText(Vector<AccessibilityText>& textOrder) const
1265 {
1266     if (isWebArea()) {
1267         String webAreaText = alternativeTextForWebArea();
1268         if (!webAreaText.isEmpty())
1269             textOrder.append(AccessibilityText(webAreaText, AlternativeText));
1270         return;
1271     }
1272     
1273     ariaLabeledByText(textOrder);
1274     
1275     const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
1276     if (!ariaLabel.isEmpty())
1277         textOrder.append(AccessibilityText(ariaLabel, AlternativeText));
1278     
1279     if (usesAltTagForTextComputation()) {
1280         if (is<RenderImage>(renderer())) {
1281             String renderAltText = downcast<RenderImage>(*renderer()).altText();
1282
1283             // RenderImage will return title as a fallback from altText, but we don't want title here because we consider that in helpText.
1284             if (!renderAltText.isEmpty() && renderAltText != getAttribute(titleAttr)) {
1285                 textOrder.append(AccessibilityText(renderAltText, AlternativeText));
1286                 return;
1287             }
1288         }
1289         // Images should use alt as long as the attribute is present, even if empty.
1290         // Otherwise, it should fallback to other methods, like the title attribute.
1291         const AtomicString& alt = getAttribute(altAttr);
1292         if (!alt.isEmpty())
1293             textOrder.append(AccessibilityText(alt, AlternativeText));
1294     }
1295     
1296     Node* node = this->node();
1297     if (!node)
1298         return;
1299     
1300     // The fieldset element derives its alternative text from the first associated legend element if one is available.
1301     if (is<HTMLFieldSetElement>(*node)) {
1302         AccessibilityObject* object = axObjectCache()->getOrCreate(downcast<HTMLFieldSetElement>(*node).legend());
1303         if (object && !object->isHidden())
1304             textOrder.append(AccessibilityText(accessibleNameForNode(object->node()), AlternativeText));
1305     }
1306     
1307     // SVG elements all can have a <svg:title> element inside which should act as the descriptive text.
1308     if (node->isSVGElement())
1309         textOrder.append(AccessibilityText(downcast<SVGElement>(*node).title(), AlternativeText));
1310     
1311 #if ENABLE(MATHML)
1312     if (node->isMathMLElement())
1313         textOrder.append(AccessibilityText(getAttribute(MathMLNames::alttextAttr), AlternativeText));
1314 #endif
1315 }
1316
1317 void AccessibilityNodeObject::visibleText(Vector<AccessibilityText>& textOrder) const
1318 {
1319     Node* node = this->node();
1320     if (!node)
1321         return;
1322     
1323     bool isInputTag = is<HTMLInputElement>(*node);
1324     if (isInputTag) {
1325         HTMLInputElement& input = downcast<HTMLInputElement>(*node);
1326         if (input.isTextButton()) {
1327             textOrder.append(AccessibilityText(input.valueWithDefault(), VisibleText));
1328             return;
1329         }
1330     }
1331     
1332     // If this node isn't rendered, there's no inner text we can extract from a select element.
1333     if (!isAccessibilityRenderObject() && node->hasTagName(selectTag))
1334         return;
1335     
1336     bool useTextUnderElement = false;
1337     
1338     switch (roleValue()) {
1339     case PopUpButtonRole:
1340         // Native popup buttons should not use their button children's text as a title. That value is retrieved through stringValue().
1341         if (node->hasTagName(selectTag))
1342             break;
1343         FALLTHROUGH;
1344     case ButtonRole:
1345     case ToggleButtonRole:
1346     case CheckBoxRole:
1347     case ListBoxOptionRole:
1348     // MacOS does not expect native <li> elements to expose label information, it only expects leaf node elements to do that.
1349 #if !PLATFORM(COCOA)
1350     case ListItemRole:
1351 #endif
1352     case MenuButtonRole:
1353     case MenuItemRole:
1354     case MenuItemCheckboxRole:
1355     case MenuItemRadioRole:
1356     case RadioButtonRole:
1357     case TabRole:
1358     case ProgressIndicatorRole:
1359         useTextUnderElement = true;
1360         break;
1361     default:
1362         break;
1363     }
1364     
1365     // If it's focusable but it's not content editable or a known control type, then it will appear to
1366     // the user as a single atomic object, so we should use its text as the default title.
1367     if (isHeading() || isLink())
1368         useTextUnderElement = true;
1369     
1370     if (useTextUnderElement) {
1371         AccessibilityTextUnderElementMode mode;
1372         
1373         // Headings often include links as direct children. Those links need to be included in text under element.
1374         if (isHeading())
1375             mode.includeFocusableContent = true;
1376
1377         String text = textUnderElement(mode);
1378         if (!text.isEmpty())
1379             textOrder.append(AccessibilityText(text, ChildrenText));
1380     }
1381 }
1382
1383 void AccessibilityNodeObject::helpText(Vector<AccessibilityText>& textOrder) const
1384 {
1385     const AtomicString& ariaHelp = getAttribute(aria_helpAttr);
1386     if (!ariaHelp.isEmpty())
1387         textOrder.append(AccessibilityText(ariaHelp, HelpText));
1388     
1389     String describedBy = ariaDescribedByAttribute();
1390     if (!describedBy.isEmpty())
1391         textOrder.append(AccessibilityText(describedBy, SummaryText));
1392
1393     // Summary attribute used as help text on tables.
1394     const AtomicString& summary = getAttribute(summaryAttr);
1395     if (!summary.isEmpty())
1396         textOrder.append(AccessibilityText(summary, SummaryText));
1397
1398     // The title attribute should be used as help text unless it is already being used as descriptive text.
1399     const AtomicString& title = getAttribute(titleAttr);
1400     if (!title.isEmpty())
1401         textOrder.append(AccessibilityText(title, TitleTagText));
1402 }
1403
1404 void AccessibilityNodeObject::accessibilityText(Vector<AccessibilityText>& textOrder)
1405 {
1406     titleElementText(textOrder);
1407     alternativeText(textOrder);
1408     visibleText(textOrder);
1409     helpText(textOrder);
1410     
1411     String placeholder = placeholderValue();
1412     if (!placeholder.isEmpty())
1413         textOrder.append(AccessibilityText(placeholder, PlaceholderText));
1414 }
1415     
1416 void AccessibilityNodeObject::ariaLabeledByText(Vector<AccessibilityText>& textOrder) const
1417 {
1418     String ariaLabeledBy = ariaLabeledByAttribute();
1419     if (!ariaLabeledBy.isEmpty()) {
1420         Vector<Element*> elements;
1421         ariaLabeledByElements(elements);
1422         
1423         Vector<RefPtr<AccessibilityObject>> axElements;
1424         for (const auto& element : elements) {
1425             RefPtr<AccessibilityObject> axElement = axObjectCache()->getOrCreate(element);
1426             axElements.append(axElement);
1427         }
1428         
1429         textOrder.append(AccessibilityText(ariaLabeledBy, AlternativeText, WTF::move(axElements)));
1430     }
1431 }
1432     
1433 String AccessibilityNodeObject::alternativeTextForWebArea() const
1434 {
1435     // The WebArea description should follow this order:
1436     //     aria-label on the <html>
1437     //     title on the <html>
1438     //     <title> inside the <head> (of it was set through JS)
1439     //     name on the <html>
1440     // For iframes:
1441     //     aria-label on the <iframe>
1442     //     title on the <iframe>
1443     //     name on the <iframe>
1444     
1445     Document* document = this->document();
1446     if (!document)
1447         return String();
1448     
1449     // Check if the HTML element has an aria-label for the webpage.
1450     if (Element* documentElement = document->documentElement()) {
1451         const AtomicString& ariaLabel = documentElement->fastGetAttribute(aria_labelAttr);
1452         if (!ariaLabel.isEmpty())
1453             return ariaLabel;
1454     }
1455     
1456     if (auto* owner = document->ownerElement()) {
1457         if (owner->hasTagName(frameTag) || owner->hasTagName(iframeTag)) {
1458             const AtomicString& title = owner->fastGetAttribute(titleAttr);
1459             if (!title.isEmpty())
1460                 return title;
1461         }
1462         return owner->getNameAttribute();
1463     }
1464     
1465     String documentTitle = document->title();
1466     if (!documentTitle.isEmpty())
1467         return documentTitle;
1468     
1469     if (auto* body = document->body())
1470         return body->getNameAttribute();
1471     
1472     return String();
1473 }
1474     
1475 String AccessibilityNodeObject::accessibilityDescription() const
1476 {
1477     // Static text should not have a description, it should only have a stringValue.
1478     if (roleValue() == StaticTextRole)
1479         return String();
1480
1481     String ariaDescription = ariaAccessibilityDescription();
1482     if (!ariaDescription.isEmpty())
1483         return ariaDescription;
1484
1485     if (usesAltTagForTextComputation()) {
1486         // Images should use alt as long as the attribute is present, even if empty.                    
1487         // Otherwise, it should fallback to other methods, like the title attribute.                    
1488         const AtomicString& alt = getAttribute(altAttr);
1489         if (!alt.isNull())
1490             return alt;
1491     }
1492
1493     // SVG elements all can have a <svg:title> element inside which should act as the descriptive text.
1494     if (m_node && m_node->isSVGElement())
1495         return downcast<SVGElement>(*m_node).title();
1496     
1497 #if ENABLE(MATHML)
1498     if (is<MathMLElement>(m_node))
1499         return getAttribute(MathMLNames::alttextAttr);
1500 #endif
1501
1502     // An element's descriptive text is comprised of title() (what's visible on the screen) and accessibilityDescription() (other descriptive text).
1503     // Both are used to generate what a screen reader speaks.                                                           
1504     // If this point is reached (i.e. there's no accessibilityDescription) and there's no title(), we should fallback to using the title attribute.
1505     // 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).
1506     if (title().isEmpty())
1507         return getAttribute(titleAttr);
1508
1509     return String();
1510 }
1511
1512 String AccessibilityNodeObject::helpText() const
1513 {
1514     Node* node = this->node();
1515     if (!node)
1516         return String();
1517     
1518     const AtomicString& ariaHelp = getAttribute(aria_helpAttr);
1519     if (!ariaHelp.isEmpty())
1520         return ariaHelp;
1521     
1522     String describedBy = ariaDescribedByAttribute();
1523     if (!describedBy.isEmpty())
1524         return describedBy;
1525     
1526     String description = accessibilityDescription();
1527     for (Node* ancestor = node; ancestor; ancestor = ancestor->parentNode()) {
1528         if (is<HTMLElement>(*ancestor)) {
1529             HTMLElement& element = downcast<HTMLElement>(*ancestor);
1530             const AtomicString& summary = element.getAttribute(summaryAttr);
1531             if (!summary.isEmpty())
1532                 return summary;
1533             
1534             // The title attribute should be used as help text unless it is already being used as descriptive text.
1535             const AtomicString& title = element.getAttribute(titleAttr);
1536             if (!title.isEmpty() && description != title)
1537                 return title;
1538         }
1539         
1540         // Only take help text from an ancestor element if its a group or an unknown role. If help was 
1541         // added to those kinds of elements, it is likely it was meant for a child element.
1542         AccessibilityObject* axObj = axObjectCache()->getOrCreate(ancestor);
1543         if (axObj) {
1544             AccessibilityRole role = axObj->roleValue();
1545             if (role != GroupRole && role != UnknownRole)
1546                 break;
1547         }
1548     }
1549     
1550     return String();
1551 }
1552     
1553 unsigned AccessibilityNodeObject::hierarchicalLevel() const
1554 {
1555     Node* node = this->node();
1556     if (!is<Element>(node))
1557         return 0;
1558     Element& element = downcast<Element>(*node);
1559     const AtomicString& ariaLevel = element.fastGetAttribute(aria_levelAttr);
1560     if (!ariaLevel.isEmpty())
1561         return ariaLevel.toInt();
1562     
1563     // Only tree item will calculate its level through the DOM currently.
1564     if (roleValue() != TreeItemRole)
1565         return 0;
1566     
1567     // Hierarchy leveling starts at 1, to match the aria-level spec.
1568     // We measure tree hierarchy by the number of groups that the item is within.
1569     unsigned level = 1;
1570     for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) {
1571         AccessibilityRole parentRole = parent->roleValue();
1572         if (parentRole == GroupRole)
1573             level++;
1574         else if (parentRole == TreeRole)
1575             break;
1576     }
1577     
1578     return level;
1579 }
1580
1581 // When building the textUnderElement for an object, determine whether or not
1582 // we should include the inner text of this given descendant object or skip it.
1583 static bool shouldUseAccessiblityObjectInnerText(AccessibilityObject* obj, AccessibilityTextUnderElementMode mode)
1584 {
1585     // Do not use any heuristic if we are explicitly asking to include all the children.
1586     if (mode.childrenInclusion == AccessibilityTextUnderElementMode::TextUnderElementModeIncludeAllChildren)
1587         return true;
1588
1589     // Consider this hypothetical example:
1590     // <div tabindex=0>
1591     //   <h2>
1592     //     Table of contents
1593     //   </h2>
1594     //   <a href="#start">Jump to start of book</a>
1595     //   <ul>
1596     //     <li><a href="#1">Chapter 1</a></li>
1597     //     <li><a href="#1">Chapter 2</a></li>
1598     //   </ul>
1599     // </div>
1600     //
1601     // The goal is to return a reasonable title for the outer container div, because
1602     // it's focusable - but without making its title be the full inner text, which is
1603     // quite long. As a heuristic, skip links, controls, and elements that are usually
1604     // containers with lots of children.
1605
1606     // ARIA states that certain elements are not allowed to expose their children content for name calculation.
1607     if (mode.childrenInclusion == AccessibilityTextUnderElementMode::TextUnderElementModeIncludeNameFromContentsChildren
1608         && !obj->accessibleNameDerivesFromContent())
1609         return false;
1610     
1611     if (equalIgnoringCase(obj->getAttribute(aria_hiddenAttr), "true"))
1612         return false;
1613     
1614     // If something doesn't expose any children, then we can always take the inner text content.
1615     // This is what we want when someone puts an <a> inside a <button> for example.
1616     if (obj->isDescendantOfBarrenParent())
1617         return true;
1618     
1619     // Skip focusable children, so we don't include the text of links and controls.
1620     if (obj->canSetFocusAttribute() && !mode.includeFocusableContent)
1621         return false;
1622
1623     // Skip big container elements like lists, tables, etc.
1624     if (is<AccessibilityList>(*obj))
1625         return false;
1626
1627     if (is<AccessibilityTable>(*obj) && downcast<AccessibilityTable>(*obj).isExposableThroughAccessibility())
1628         return false;
1629
1630     if (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 (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 (is<AccessibilityNodeObject>(*child)) {
1677             Vector<AccessibilityText> textOrder;
1678             downcast<AccessibilityNodeObject>(*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(downcast<Element>(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 downcast<Element>(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 (!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 (!is<Element>(node))
1846         return String();
1847     
1848     Element& element = downcast<Element>(*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 (!is<Element>(node))
1943         return false;
1944
1945     Element& element = downcast<Element>(*node);
1946
1947     if (element.isDisabledFormControl())
1948         return false;
1949
1950     return element.supportsFocus();
1951 }
1952
1953 AccessibilityRole AccessibilityNodeObject::determineAriaRoleAttribute() const
1954 {
1955     const AtomicString& ariaRole = getAttribute(roleAttr);
1956     if (ariaRole.isNull() || ariaRole.isEmpty())
1957         return UnknownRole;
1958     
1959     AccessibilityRole role = ariaRoleToWebCoreRole(ariaRole);
1960
1961     // ARIA states if an item can get focus, it should not be presentational.
1962     if (role == PresentationalRole && canSetFocusAttribute())
1963         return UnknownRole;
1964
1965     if (role == ButtonRole)
1966         role = buttonRoleType();
1967
1968     if (role == TextAreaRole && !ariaIsMultiline())
1969         role = TextFieldRole;
1970
1971     role = remapAriaRoleDueToParent(role);
1972     
1973     // Presentational roles are invalidated by the presence of ARIA attributes.
1974     if (role == PresentationalRole && supportsARIAAttributes())
1975         role = UnknownRole;
1976     
1977     if (role)
1978         return role;
1979
1980     return UnknownRole;
1981 }
1982
1983 AccessibilityRole AccessibilityNodeObject::ariaRoleAttribute() const
1984 {
1985     return m_ariaRole;
1986 }
1987
1988 AccessibilityRole AccessibilityNodeObject::remapAriaRoleDueToParent(AccessibilityRole role) const
1989 {
1990     // Some objects change their role based on their parent.
1991     // However, asking for the unignoredParent calls accessibilityIsIgnored(), which can trigger a loop. 
1992     // While inside the call stack of creating an element, we need to avoid accessibilityIsIgnored().
1993     // https://bugs.webkit.org/show_bug.cgi?id=65174
1994
1995     if (role != ListBoxOptionRole && role != MenuItemRole)
1996         return role;
1997     
1998     for (AccessibilityObject* parent = parentObject(); parent && !parent->accessibilityIsIgnored(); parent = parent->parentObject()) {
1999         AccessibilityRole parentAriaRole = parent->ariaRoleAttribute();
2000
2001         // Selects and listboxes both have options as child roles, but they map to different roles within WebCore.
2002         if (role == ListBoxOptionRole && parentAriaRole == MenuRole)
2003             return MenuItemRole;
2004         // An aria "menuitem" may map to MenuButton or MenuItem depending on its parent.
2005         if (role == MenuItemRole && parentAriaRole == GroupRole)
2006             return MenuButtonRole;
2007         
2008         // If the parent had a different role, then we don't need to continue searching up the chain.
2009         if (parentAriaRole)
2010             break;
2011     }
2012     
2013     return role;
2014 }   
2015
2016 bool AccessibilityNodeObject::canSetSelectedAttribute() const
2017 {
2018     // Elements that can be selected
2019     switch (roleValue()) {
2020     case CellRole:
2021     case RadioButtonRole:
2022     case RowHeaderRole:
2023     case RowRole:
2024     case TabListRole:
2025     case TabRole:
2026     case TreeGridRole:
2027     case TreeItemRole:
2028     case TreeRole:
2029         return isEnabled();
2030     default:
2031         return false;
2032     }
2033 }
2034
2035 } // namespace WebCore