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