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