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