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