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