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