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