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