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