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