Move "hover" state logic from Node to Element.
[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()->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     return node->active();
638 }
639
640 bool AccessibilityNodeObject::isChecked() const
641 {
642     Node* node = this->node();
643     if (!node)
644         return false;
645
646     // First test for native checkedness semantics
647     HTMLInputElement* inputElement = node->toInputElement();
648     if (inputElement)
649         return inputElement->shouldAppearChecked();
650
651     // Else, if this is an ARIA checkbox or radio, respect the aria-checked attribute
652     bool validRole = false;
653     switch (ariaRoleAttribute()) {
654     case RadioButtonRole:
655     case CheckBoxRole:
656     case MenuItemRole:
657         validRole = true;
658         break;
659     default:
660         break;
661     }
662     
663     if (validRole && equalIgnoringCase(getAttribute(aria_checkedAttr), "true"))
664         return true;
665
666     return false;
667 }
668
669 bool AccessibilityNodeObject::isHovered() const
670 {
671     Node* node = this->node();
672     if (!node)
673         return false;
674
675     return node->isElementNode() && toElement(node)->hovered();
676 }
677
678 bool AccessibilityNodeObject::isMultiSelectable() const
679 {
680     const AtomicString& ariaMultiSelectable = getAttribute(aria_multiselectableAttr);
681     if (equalIgnoringCase(ariaMultiSelectable, "true"))
682         return true;
683     if (equalIgnoringCase(ariaMultiSelectable, "false"))
684         return false;
685     
686     return node() && node()->hasTagName(selectTag) && toHTMLSelectElement(node())->multiple();
687 }
688
689 bool AccessibilityNodeObject::isReadOnly() const
690 {
691     Node* node = this->node();
692     if (!node)
693         return true;
694
695     if (node->hasTagName(textareaTag))
696         return static_cast<HTMLTextAreaElement*>(node)->isReadOnly();
697
698     if (node->hasTagName(inputTag)) {
699         HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
700         if (input->isTextField())
701             return input->isReadOnly();
702     }
703
704     return !node->rendererIsEditable();
705 }
706
707 bool AccessibilityNodeObject::isRequired() const
708 {
709     if (equalIgnoringCase(getAttribute(aria_requiredAttr), "true"))
710         return true;
711
712     Node* n = this->node();
713     if (n && (n->isElementNode() && toElement(n)->isFormControlElement()))
714         return static_cast<HTMLFormControlElement*>(n)->isRequired();
715
716     return false;
717 }
718
719 int AccessibilityNodeObject::headingLevel() const
720 {
721     // headings can be in block flow and non-block flow
722     Node* node = this->node();
723     if (!node)
724         return false;
725
726     if (isHeading()) {
727         int ariaLevel = getAttribute(aria_levelAttr).toInt();
728         if (ariaLevel > 0)
729             return ariaLevel;
730     }
731
732     if (node->hasTagName(h1Tag))
733         return 1;
734
735     if (node->hasTagName(h2Tag))
736         return 2;
737
738     if (node->hasTagName(h3Tag))
739         return 3;
740
741     if (node->hasTagName(h4Tag))
742         return 4;
743
744     if (node->hasTagName(h5Tag))
745         return 5;
746
747     if (node->hasTagName(h6Tag))
748         return 6;
749
750     return 0;
751 }
752
753 String AccessibilityNodeObject::valueDescription() const
754 {
755     if (!isRangeControl())
756         return String();
757
758     return getAttribute(aria_valuetextAttr).string();
759 }
760
761 float AccessibilityNodeObject::valueForRange() const
762 {
763     if (node() && node()->hasTagName(inputTag)) {
764         HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
765         if (input->isRangeControl())
766             return input->valueAsNumber();
767     }
768
769     if (!isRangeControl())
770         return 0.0f;
771
772     return getAttribute(aria_valuenowAttr).toFloat();
773 }
774
775 float AccessibilityNodeObject::maxValueForRange() const
776 {
777     if (node() && node()->hasTagName(inputTag)) {
778         HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
779         if (input->isRangeControl())
780             return input->maximum();
781     }
782
783     if (!isRangeControl())
784         return 0.0f;
785
786     return getAttribute(aria_valuemaxAttr).toFloat();
787 }
788
789 float AccessibilityNodeObject::minValueForRange() const
790 {
791     if (node() && node()->hasTagName(inputTag)) {
792         HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
793         if (input->isRangeControl())
794             return input->minimum();
795     }
796
797     if (!isRangeControl())
798         return 0.0f;
799
800     return getAttribute(aria_valueminAttr).toFloat();
801 }
802
803 float AccessibilityNodeObject::stepValueForRange() const
804 {
805     return getAttribute(stepAttr).toFloat();
806 }
807
808 bool AccessibilityNodeObject::isHeading() const
809 {
810     return roleValue() == HeadingRole;
811 }
812
813 bool AccessibilityNodeObject::isLink() const
814 {
815     return roleValue() == WebCoreLinkRole;
816 }
817
818 bool AccessibilityNodeObject::isControl() const
819 {
820     Node* node = this->node();
821     if (!node)
822         return false;
823
824     return ((node->isElementNode() && toElement(node)->isFormControlElement())
825         || AccessibilityObject::isARIAControl(ariaRoleAttribute()));
826 }
827
828 bool AccessibilityNodeObject::isFieldset() const
829 {
830     Node* node = this->node();
831     if (!node)
832         return false;
833
834     return node->hasTagName(fieldsetTag);
835 }
836
837 bool AccessibilityNodeObject::isGroup() const
838 {
839     return roleValue() == GroupRole;
840 }
841
842 AccessibilityObject* AccessibilityNodeObject::selectedRadioButton()
843 {
844     if (!isRadioGroup())
845         return 0;
846
847     AccessibilityObject::AccessibilityChildrenVector children = this->children();
848
849     // Find the child radio button that is selected (ie. the intValue == 1).
850     size_t size = children.size();
851     for (size_t i = 0; i < size; ++i) {
852         AccessibilityObject* object = children[i].get();
853         if (object->roleValue() == RadioButtonRole && object->checkboxOrRadioValue() == ButtonStateOn)
854             return object;
855     }
856     return 0;
857 }
858
859 AccessibilityObject* AccessibilityNodeObject::selectedTabItem()
860 {
861     if (!isTabList())
862         return 0;
863
864     // Find the child tab item that is selected (ie. the intValue == 1).
865     AccessibilityObject::AccessibilityChildrenVector tabs;
866     tabChildren(tabs);
867
868     AccessibilityObject::AccessibilityChildrenVector children = this->children();
869     size_t size = tabs.size();
870     for (size_t i = 0; i < size; ++i) {
871         AccessibilityObject* object = children[i].get();
872         if (object->isTabItem() && object->isChecked())
873             return object;
874     }
875     return 0;
876 }
877
878 AccessibilityButtonState AccessibilityNodeObject::checkboxOrRadioValue() const
879 {
880     if (isNativeCheckboxOrRadio())
881         return isChecked() ? ButtonStateOn : ButtonStateOff;
882
883     return AccessibilityObject::checkboxOrRadioValue();
884 }
885
886 Element* AccessibilityNodeObject::anchorElement() const
887 {
888     Node* node = this->node();
889     if (!node)
890         return 0;
891
892     AXObjectCache* cache = axObjectCache();
893
894     // search up the DOM tree for an anchor element
895     // NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElement
896     for ( ; node; node = node->parentNode()) {
897         if (node->hasTagName(aTag) || (node->renderer() && cache->getOrCreate(node->renderer())->isAnchor()))
898             return toElement(node);
899     }
900
901     return 0;
902 }
903
904 Element* AccessibilityNodeObject::actionElement() const
905 {
906     Node* node = this->node();
907     if (!node)
908         return 0;
909
910     if (node->hasTagName(inputTag)) {
911         HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
912         if (!input->isDisabledFormControl() && (isCheckboxOrRadio() || input->isTextButton()))
913             return input;
914     } else if (node->hasTagName(buttonTag))
915         return toElement(node);
916
917     if (isFileUploadButton())
918         return toElement(node);
919             
920     if (AccessibilityObject::isARIAInput(ariaRoleAttribute()))
921         return toElement(node);
922
923     if (isImageButton())
924         return toElement(node);
925     
926     if (node->hasTagName(selectTag))
927         return toElement(node);
928
929     switch (roleValue()) {
930     case ButtonRole:
931     case PopUpButtonRole:
932     case ToggleButtonRole:
933     case TabRole:
934     case MenuItemRole:
935     case ListItemRole:
936         return toElement(node);
937     default:
938         break;
939     }
940     
941     Element* elt = anchorElement();
942     if (!elt)
943         elt = mouseButtonListener();
944     return elt;
945 }
946
947 Element* AccessibilityNodeObject::mouseButtonListener() const
948 {
949     Node* node = this->node();
950     if (!node)
951         return 0;
952
953     // check if our parent is a mouse button listener
954     while (node && !node->isElementNode())
955         node = node->parentNode();
956
957     if (!node)
958         return 0;
959
960     // FIXME: Do the continuation search like anchorElement does
961     for (Element* element = toElement(node); element; element = element->parentElement()) {
962         // If we've reached the body and this is not a control element, do not expose press action for this element.
963         // It can cause false positives, where every piece of text is labeled as accepting press actions. 
964         if (element->hasTagName(bodyTag) && isStaticText())
965             break;
966         
967         if (element->hasEventListeners(eventNames().clickEvent) || element->hasEventListeners(eventNames().mousedownEvent) || element->hasEventListeners(eventNames().mouseupEvent))
968             return element;
969     }
970
971     return 0;
972 }
973
974 bool AccessibilityNodeObject::isDescendantOfBarrenParent() const
975 {
976     for (AccessibilityObject* object = parentObject(); object; object = object->parentObject()) {
977         if (!object->canHaveChildren())
978             return true;
979     }
980
981     return false;
982 }
983
984 void AccessibilityNodeObject::alterSliderValue(bool increase)
985 {
986     if (roleValue() != SliderRole)
987         return;
988
989     if (!getAttribute(stepAttr).isEmpty())
990         changeValueByStep(increase);
991     else
992         changeValueByPercent(increase ? 5 : -5);
993 }
994     
995 void AccessibilityNodeObject::increment()
996 {
997     UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture);
998     alterSliderValue(true);
999 }
1000
1001 void AccessibilityNodeObject::decrement()
1002 {
1003     UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture);
1004     alterSliderValue(false);
1005 }
1006
1007 void AccessibilityNodeObject::changeValueByStep(bool increase)
1008 {
1009     float step = stepValueForRange();
1010     float value = valueForRange();
1011
1012     value += increase ? step : -step;
1013
1014     setValue(String::number(value));
1015
1016     axObjectCache()->postNotification(node(), AXObjectCache::AXValueChanged, true);
1017 }
1018
1019 void AccessibilityNodeObject::changeValueByPercent(float percentChange)
1020 {
1021     float range = maxValueForRange() - minValueForRange();
1022     float value = valueForRange();
1023
1024     value += range * (percentChange / 100);
1025     setValue(String::number(value));
1026
1027     axObjectCache()->postNotification(node(), AXObjectCache::AXValueChanged, true);
1028 }
1029
1030 bool AccessibilityNodeObject::isGenericFocusableElement() const
1031 {
1032     if (!canSetFocusAttribute())
1033         return false;
1034
1035      // If it's a control, it's not generic.
1036      if (isControl())
1037         return false;
1038
1039     // If it has an aria role, it's not generic.
1040     if (m_ariaRole != UnknownRole)
1041         return false;
1042
1043     // If the content editable attribute is set on this element, that's the reason
1044     // it's focusable, and existing logic should handle this case already - so it's not a
1045     // generic focusable element.
1046
1047     if (hasContentEditableAttributeSet())
1048         return false;
1049
1050     // The web area and body element are both focusable, but existing logic handles these
1051     // cases already, so we don't need to include them here.
1052     if (roleValue() == WebAreaRole)
1053         return false;
1054     if (node() && node()->hasTagName(bodyTag))
1055         return false;
1056
1057     // An SVG root is focusable by default, but it's probably not interactive, so don't
1058     // include it. It can still be made accessible by giving it an ARIA role.
1059     if (roleValue() == SVGRootRole)
1060         return false;
1061
1062     return true;
1063 }
1064
1065 HTMLLabelElement* AccessibilityNodeObject::labelForElement(Element* element) const
1066 {
1067     if (!element->isHTMLElement() || !toHTMLElement(element)->isLabelable())
1068         return 0;
1069
1070     const AtomicString& id = element->getIdAttribute();
1071     if (!id.isEmpty()) {
1072         if (HTMLLabelElement* label = element->treeScope()->labelElementForId(id))
1073             return label;
1074     }
1075
1076     for (Element* parent = element->parentElement(); parent; parent = parent->parentElement()) {
1077         if (parent->hasTagName(labelTag))
1078             return static_cast<HTMLLabelElement*>(parent);
1079     }
1080
1081     return 0;
1082 }
1083
1084 String AccessibilityNodeObject::ariaAccessibilityDescription() const
1085 {
1086     String ariaLabeledBy = ariaLabeledByAttribute();
1087     if (!ariaLabeledBy.isEmpty())
1088         return ariaLabeledBy;
1089
1090     const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
1091     if (!ariaLabel.isEmpty())
1092         return ariaLabel;
1093
1094     return String();
1095 }
1096
1097 static Element* siblingWithAriaRole(String role, Node* node)
1098 {
1099     Node* parent = node->parentNode();
1100     if (!parent)
1101         return 0;
1102     
1103     for (Node* sibling = parent->firstChild(); sibling; sibling = sibling->nextSibling()) {
1104         if (sibling->isElementNode()) {
1105             const AtomicString& siblingAriaRole = toElement(sibling)->getAttribute(roleAttr);
1106             if (equalIgnoringCase(siblingAriaRole, role))
1107                 return toElement(sibling);
1108         }
1109     }
1110     
1111     return 0;
1112 }
1113
1114 Element* AccessibilityNodeObject::menuElementForMenuButton() const
1115 {
1116     if (ariaRoleAttribute() != MenuButtonRole)
1117         return 0;
1118
1119     return siblingWithAriaRole("menu", node());
1120 }
1121
1122 AccessibilityObject* AccessibilityNodeObject::menuForMenuButton() const
1123 {
1124     return axObjectCache()->getOrCreate(menuElementForMenuButton());
1125 }
1126
1127 Element* AccessibilityNodeObject::menuItemElementForMenu() const
1128 {
1129     if (ariaRoleAttribute() != MenuRole)
1130         return 0;
1131     
1132     return siblingWithAriaRole("menuitem", node());    
1133 }
1134
1135 AccessibilityObject* AccessibilityNodeObject::menuButtonForMenu() const
1136 {
1137     Element* menuItem = menuItemElementForMenu();
1138
1139     if (menuItem) {
1140         // ARIA just has generic menu items. AppKit needs to know if this is a top level items like MenuBarButton or MenuBarItem
1141         AccessibilityObject* menuItemAX = axObjectCache()->getOrCreate(menuItem);
1142         if (menuItemAX && menuItemAX->isMenuButton())
1143             return menuItemAX;
1144     }
1145     return 0;
1146 }
1147
1148 void AccessibilityNodeObject::titleElementText(Vector<AccessibilityText>& textOrder)
1149 {
1150     Node* node = this->node();
1151     if (!node)
1152         return;
1153     
1154     bool isInputTag = node->hasTagName(inputTag);
1155     if (isInputTag || AccessibilityObject::isARIAInput(ariaRoleAttribute()) || isControl()) {
1156         HTMLLabelElement* label = labelForElement(toElement(node));
1157         if (label) {
1158             AccessibilityObject* labelObject = axObjectCache()->getOrCreate(label);
1159             textOrder.append(AccessibilityText(label->innerText(), LabelByElementText, labelObject));
1160             return;
1161         }
1162     }
1163     
1164     AccessibilityObject* titleUIElement = this->titleUIElement();
1165     if (titleUIElement)
1166         textOrder.append(AccessibilityText(String(), LabelByElementText, titleUIElement));
1167 }
1168
1169 void AccessibilityNodeObject::alternativeText(Vector<AccessibilityText>& textOrder) const
1170 {
1171     if (isWebArea()) {
1172         String webAreaText = alternativeTextForWebArea();
1173         if (!webAreaText.isEmpty())
1174             textOrder.append(AccessibilityText(webAreaText, AlternativeText));
1175         return;
1176     }
1177     
1178     ariaLabeledByText(textOrder);
1179     
1180     const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
1181     if (!ariaLabel.isEmpty())
1182         textOrder.append(AccessibilityText(ariaLabel, AlternativeText));
1183     
1184     if (isImage() || isInputImage() || isNativeImage() || isCanvas()) {
1185         // Images should use alt as long as the attribute is present, even if empty.
1186         // Otherwise, it should fallback to other methods, like the title attribute.
1187         const AtomicString& alt = getAttribute(altAttr);
1188         if (!alt.isNull())
1189             textOrder.append(AccessibilityText(alt, AlternativeText));
1190     }
1191     
1192     Node* node = this->node();
1193     if (!node)
1194         return;
1195     
1196 #if ENABLE(SVG)
1197     // SVG elements all can have a <svg:title> element inside which should act as the descriptive text.
1198     if (node->isSVGElement() && toSVGElement(node)->isSVGStyledElement())
1199         textOrder.append(AccessibilityText(toSVGStyledElement(node)->title(), AlternativeText));
1200 #endif
1201     
1202 #if ENABLE(MATHML)
1203     if (node->isElementNode() && toElement(node)->isMathMLElement())
1204         textOrder.append(AccessibilityText(getAttribute(MathMLNames::alttextAttr), AlternativeText));
1205 #endif
1206 }
1207
1208 void AccessibilityNodeObject::visibleText(Vector<AccessibilityText>& textOrder) const
1209 {
1210     Node* node = this->node();
1211     if (!node)
1212         return;
1213     
1214     bool isInputTag = node->hasTagName(inputTag);
1215     if (isInputTag) {
1216         HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
1217         if (input->isTextButton()) {
1218             textOrder.append(AccessibilityText(input->valueWithDefault(), VisibleText));
1219             return;
1220         }
1221     }
1222     
1223     // If this node isn't rendered, there's no inner text we can extract from a select element.
1224     if (!isAccessibilityRenderObject() && node->hasTagName(selectTag))
1225         return;
1226     
1227     bool useTextUnderElement = false;
1228     
1229     switch (roleValue()) {
1230     case PopUpButtonRole:
1231         // Native popup buttons should not use their button children's text as a title. That value is retrieved through stringValue().
1232         if (node->hasTagName(selectTag))
1233             break;
1234     case ButtonRole:
1235     case ToggleButtonRole:
1236     case CheckBoxRole:
1237     case ListBoxOptionRole:
1238     case MenuButtonRole:
1239     case MenuItemRole:
1240     case RadioButtonRole:
1241     case TabRole:
1242     case ProgressIndicatorRole:
1243         useTextUnderElement = true;
1244         break;
1245     default:
1246         break;
1247     }
1248     
1249     // If it's focusable but it's not content editable or a known control type, then it will appear to
1250     // the user as a single atomic object, so we should use its text as the default title.
1251     if (isHeading() || isLink() || isGenericFocusableElement())
1252         useTextUnderElement = true;
1253     
1254     if (useTextUnderElement) {
1255         String text = textUnderElement();
1256         if (!text.isEmpty())
1257             textOrder.append(AccessibilityText(text, ChildrenText));
1258     }
1259 }
1260
1261 void AccessibilityNodeObject::helpText(Vector<AccessibilityText>& textOrder) const
1262 {
1263     const AtomicString& ariaHelp = getAttribute(aria_helpAttr);
1264     if (!ariaHelp.isEmpty())
1265         textOrder.append(AccessibilityText(ariaHelp, HelpText));
1266     
1267     String describedBy = ariaDescribedByAttribute();
1268     if (!describedBy.isEmpty())
1269         textOrder.append(AccessibilityText(describedBy, SummaryText));
1270     
1271     // Add help type text that is derived from ancestors.
1272     for (Node* curr = node(); curr; curr = curr->parentNode()) {
1273         const AtomicString& summary = getAttribute(summaryAttr);
1274         if (!summary.isEmpty())
1275             textOrder.append(AccessibilityText(summary, SummaryText));
1276         
1277         // The title attribute should be used as help text unless it is already being used as descriptive text.
1278         const AtomicString& title = getAttribute(titleAttr);
1279         if (!title.isEmpty())
1280             textOrder.append(AccessibilityText(title, TitleTagText));
1281         
1282         // Only take help text from an ancestor element if its a group or an unknown role. If help was
1283         // added to those kinds of elements, it is likely it was meant for a child element.
1284         AccessibilityObject* axObj = axObjectCache()->getOrCreate(curr);
1285         if (!axObj)
1286             return;
1287         
1288         AccessibilityRole role = axObj->roleValue();
1289         if (role != GroupRole && role != UnknownRole)
1290             break;
1291     }
1292 }
1293
1294 void AccessibilityNodeObject::accessibilityText(Vector<AccessibilityText>& textOrder)
1295 {
1296     titleElementText(textOrder);
1297     alternativeText(textOrder);
1298     visibleText(textOrder);
1299     helpText(textOrder);
1300     
1301     String placeholder = placeholderValue();
1302     if (!placeholder.isEmpty())
1303         textOrder.append(AccessibilityText(placeholder, PlaceholderText));
1304 }
1305     
1306 void AccessibilityNodeObject::ariaLabeledByText(Vector<AccessibilityText>& textOrder) const
1307 {
1308     String ariaLabeledBy = ariaLabeledByAttribute();
1309     if (!ariaLabeledBy.isEmpty()) {
1310         Vector<Element*> elements;
1311         ariaLabeledByElements(elements);
1312         
1313         Vector<RefPtr<AccessibilityObject> > axElements;
1314         unsigned length = elements.size();
1315         for (unsigned k = 0; k < length; k++) {
1316             RefPtr<AccessibilityObject> axElement = axObjectCache()->getOrCreate(elements[k]);
1317             axElements.append(axElement);
1318         }
1319         
1320         textOrder.append(AccessibilityText(ariaLabeledBy, AlternativeText, axElements));
1321     }
1322 }
1323     
1324 String AccessibilityNodeObject::alternativeTextForWebArea() const
1325 {
1326     // The WebArea description should follow this order:
1327     //     aria-label on the <html>
1328     //     title on the <html>
1329     //     <title> inside the <head> (of it was set through JS)
1330     //     name on the <html>
1331     // For iframes:
1332     //     aria-label on the <iframe>
1333     //     title on the <iframe>
1334     //     name on the <iframe>
1335     
1336     Document* document = this->document();
1337     if (!document)
1338         return String();
1339     
1340     // Check if the HTML element has an aria-label for the webpage.
1341     if (Element* documentElement = document->documentElement()) {
1342         const AtomicString& ariaLabel = documentElement->getAttribute(aria_labelAttr);
1343         if (!ariaLabel.isEmpty())
1344             return ariaLabel;
1345     }
1346     
1347     Node* owner = document->ownerElement();
1348     if (owner) {
1349         if (owner->hasTagName(frameTag) || owner->hasTagName(iframeTag)) {
1350             const AtomicString& title = static_cast<HTMLFrameElementBase*>(owner)->getAttribute(titleAttr);
1351             if (!title.isEmpty())
1352                 return title;
1353             return static_cast<HTMLFrameElementBase*>(owner)->getNameAttribute();
1354         }
1355         if (owner->isHTMLElement())
1356             return toHTMLElement(owner)->getNameAttribute();
1357     }
1358     
1359     String documentTitle = document->title();
1360     if (!documentTitle.isEmpty())
1361         return documentTitle;
1362     
1363     owner = document->body();
1364     if (owner && owner->isHTMLElement())
1365         return toHTMLElement(owner)->getNameAttribute();
1366     
1367     return String();
1368 }
1369     
1370 String AccessibilityNodeObject::accessibilityDescription() const
1371 {
1372     // Static text should not have a description, it should only have a stringValue.
1373     if (roleValue() == StaticTextRole)
1374         return String();
1375
1376     String ariaDescription = ariaAccessibilityDescription();
1377     if (!ariaDescription.isEmpty())
1378         return ariaDescription;
1379
1380     if (isImage() || isInputImage() || isNativeImage() || isCanvas()) {
1381         // Images should use alt as long as the attribute is present, even if empty.                    
1382         // Otherwise, it should fallback to other methods, like the title attribute.                    
1383         const AtomicString& alt = getAttribute(altAttr);
1384         if (!alt.isNull())
1385             return alt;
1386     }
1387
1388 #if ENABLE(SVG)
1389     // SVG elements all can have a <svg:title> element inside which should act as the descriptive text.
1390     if (m_node && m_node->isSVGElement() && toSVGElement(m_node)->isSVGStyledElement())
1391         return toSVGStyledElement(m_node)->title();
1392 #endif
1393     
1394 #if ENABLE(MATHML)
1395     if (m_node && m_node->isElementNode() && toElement(m_node)->isMathMLElement())
1396         return getAttribute(MathMLNames::alttextAttr);
1397 #endif
1398
1399     // An element's descriptive text is comprised of title() (what's visible on the screen) and accessibilityDescription() (other descriptive text).
1400     // Both are used to generate what a screen reader speaks.                                                           
1401     // If this point is reached (i.e. there's no accessibilityDescription) and there's no title(), we should fallback to using the title attribute.
1402     // 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).
1403     if (title().isEmpty())
1404         return getAttribute(titleAttr);
1405
1406     return String();
1407 }
1408
1409 String AccessibilityNodeObject::helpText() const
1410 {
1411     Node* node = this->node();
1412     if (!node)
1413         return String();
1414     
1415     const AtomicString& ariaHelp = getAttribute(aria_helpAttr);
1416     if (!ariaHelp.isEmpty())
1417         return ariaHelp;
1418     
1419     String describedBy = ariaDescribedByAttribute();
1420     if (!describedBy.isEmpty())
1421         return describedBy;
1422     
1423     String description = accessibilityDescription();
1424     for (Node* curr = node; curr; curr = curr->parentNode()) {
1425         if (curr->isHTMLElement()) {
1426             const AtomicString& summary = toElement(curr)->getAttribute(summaryAttr);
1427             if (!summary.isEmpty())
1428                 return summary;
1429             
1430             // The title attribute should be used as help text unless it is already being used as descriptive text.
1431             const AtomicString& title = toElement(curr)->getAttribute(titleAttr);
1432             if (!title.isEmpty() && description != title)
1433                 return title;
1434         }
1435         
1436         // Only take help text from an ancestor element if its a group or an unknown role. If help was 
1437         // added to those kinds of elements, it is likely it was meant for a child element.
1438         AccessibilityObject* axObj = axObjectCache()->getOrCreate(curr);
1439         if (axObj) {
1440             AccessibilityRole role = axObj->roleValue();
1441             if (role != GroupRole && role != UnknownRole)
1442                 break;
1443         }
1444     }
1445     
1446     return String();
1447 }
1448     
1449 unsigned AccessibilityNodeObject::hierarchicalLevel() const
1450 {
1451     Node* node = this->node();
1452     if (!node || !node->isElementNode())
1453         return 0;
1454     Element* element = toElement(node);
1455     String ariaLevel = element->getAttribute(aria_levelAttr);
1456     if (!ariaLevel.isEmpty())
1457         return ariaLevel.toInt();
1458     
1459     // Only tree item will calculate its level through the DOM currently.
1460     if (roleValue() != TreeItemRole)
1461         return 0;
1462     
1463     // Hierarchy leveling starts at 1, to match the aria-level spec.
1464     // We measure tree hierarchy by the number of groups that the item is within.
1465     unsigned level = 1;
1466     for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) {
1467         AccessibilityRole parentRole = parent->roleValue();
1468         if (parentRole == GroupRole)
1469             level++;
1470         else if (parentRole == TreeRole)
1471             break;
1472     }
1473     
1474     return level;
1475 }
1476
1477 // When building the textUnderElement for an object, determine whether or not
1478 // we should include the inner text of this given descendant object or skip it.
1479 static bool shouldUseAccessiblityObjectInnerText(AccessibilityObject* obj)
1480 {
1481     // Consider this hypothetical example:
1482     // <div tabindex=0>
1483     //   <h2>
1484     //     Table of contents
1485     //   </h2>
1486     //   <a href="#start">Jump to start of book</a>
1487     //   <ul>
1488     //     <li><a href="#1">Chapter 1</a></li>
1489     //     <li><a href="#1">Chapter 2</a></li>
1490     //   </ul>
1491     // </div>
1492     //
1493     // The goal is to return a reasonable title for the outer container div, because
1494     // it's focusable - but without making its title be the full inner text, which is
1495     // quite long. As a heuristic, skip links, controls, and elements that are usually
1496     // containers with lots of children.
1497
1498     // If something doesn't expose any children, then we can always take the inner text content.
1499     // This is what we want when someone puts an <a> inside a <button> for example.
1500     if (obj->isDescendantOfBarrenParent())
1501         return true;
1502     
1503     // Skip focusable children, so we don't include the text of links and controls.
1504     if (obj->canSetFocusAttribute())
1505         return false;
1506
1507     // Skip big container elements like lists, tables, etc.
1508     if (obj->isList() || obj->isAccessibilityTable() || obj->isTree() || obj->isCanvas())
1509         return false;
1510
1511     return true;
1512 }
1513
1514 String AccessibilityNodeObject::textUnderElement() const
1515 {
1516     Node* node = this->node();
1517     if (node && node->isTextNode())
1518         return toText(node)->wholeText();
1519
1520     String result;
1521     for (AccessibilityObject* child = firstChild(); child; child = child->nextSibling()) {
1522         if (!shouldUseAccessiblityObjectInnerText(child))
1523             continue;
1524
1525         if (child->isAccessibilityNodeObject()) {
1526             Vector<AccessibilityText> textOrder;
1527             toAccessibilityNodeObject(child)->alternativeText(textOrder);
1528             if (textOrder.size() > 0) {
1529                 result.append(textOrder[0].text);
1530                 continue;
1531             }
1532         }
1533
1534         result.append(child->textUnderElement());
1535     }
1536
1537     return result;
1538 }
1539
1540 String AccessibilityNodeObject::title() const
1541 {
1542     Node* node = this->node();
1543     if (!node)
1544         return String();
1545
1546     bool isInputTag = node->hasTagName(inputTag);
1547     if (isInputTag) {
1548         HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
1549         if (input->isTextButton())
1550             return input->valueWithDefault();
1551     }
1552
1553     if (isInputTag || AccessibilityObject::isARIAInput(ariaRoleAttribute()) || isControl()) {
1554         HTMLLabelElement* label = labelForElement(toElement(node));
1555         if (label && !exposesTitleUIElement())
1556             return label->innerText();
1557     }
1558
1559     // If this node isn't rendered, there's no inner text we can extract from a select element.
1560     if (!isAccessibilityRenderObject() && node->hasTagName(selectTag))
1561         return String();
1562
1563     switch (roleValue()) {
1564     case PopUpButtonRole:
1565         // Native popup buttons should not use their button children's text as a title. That value is retrieved through stringValue().
1566         if (node->hasTagName(selectTag))
1567             return String();
1568     case ButtonRole:
1569     case ToggleButtonRole:
1570     case CheckBoxRole:
1571     case ListBoxOptionRole:
1572     case MenuButtonRole:
1573     case MenuItemRole:
1574     case RadioButtonRole:
1575     case TabRole:
1576         return textUnderElement();
1577     // SVGRoots should not use the text under itself as a title. That could include the text of objects like <text>.
1578     case SVGRootRole:
1579         return String();
1580     default:
1581         break;
1582     }
1583
1584     if (isHeading() || isLink())
1585         return textUnderElement();
1586
1587     // If it's focusable but it's not content editable or a known control type, then it will appear to                  
1588     // the user as a single atomic object, so we should use its text as the default title.                              
1589     if (isGenericFocusableElement())
1590         return textUnderElement();
1591
1592     return String();
1593 }
1594
1595 String AccessibilityNodeObject::text() const
1596 {
1597     // If this is a user defined static text, use the accessible name computation.                                      
1598     if (ariaRoleAttribute() == StaticTextRole)
1599         return ariaAccessibilityDescription();
1600
1601     if (!isTextControl())
1602         return String();
1603
1604     Node* node = this->node();
1605     if (!node)
1606         return String();
1607
1608     if (isNativeTextControl()) {
1609         if (node->hasTagName(textareaTag))
1610             return static_cast<HTMLTextAreaElement*>(node)->value();
1611         if (node->hasTagName(inputTag))
1612             return node->toInputElement()->value();
1613     }
1614
1615     if (!node->isElementNode())
1616         return String();
1617
1618     return toElement(node)->innerText();
1619 }
1620
1621 String AccessibilityNodeObject::stringValue() const
1622 {
1623     Node* node = this->node();
1624     if (!node)
1625         return String();
1626
1627     if (ariaRoleAttribute() == StaticTextRole) {
1628         String staticText = text();
1629         if (!staticText.length())
1630             staticText = textUnderElement();
1631         return staticText;
1632     }
1633
1634     if (node->isTextNode())
1635         return textUnderElement();
1636
1637     if (node->hasTagName(selectTag)) {
1638         HTMLSelectElement* selectElement = toHTMLSelectElement(node);
1639         int selectedIndex = selectElement->selectedIndex();
1640         const Vector<HTMLElement*> listItems = selectElement->listItems();
1641         if (selectedIndex >= 0 && static_cast<size_t>(selectedIndex) < listItems.size()) {
1642             const AtomicString& overriddenDescription = listItems[selectedIndex]->fastGetAttribute(aria_labelAttr);
1643             if (!overriddenDescription.isNull())
1644                 return overriddenDescription;
1645         }
1646         if (!selectElement->multiple())
1647             return selectElement->value();
1648         return String();
1649     }
1650
1651     if (isTextControl())
1652         return text();
1653
1654     // FIXME: We might need to implement a value here for more types
1655     // FIXME: It would be better not to advertise a value at all for the types for which we don't implement one;
1656     // this would require subclassing or making accessibilityAttributeNames do something other than return a
1657     // single static array.
1658     return String();
1659 }
1660
1661 void AccessibilityNodeObject::colorValue(int& r, int& g, int& b) const
1662 {
1663     r = 0;
1664     g = 0;
1665     b = 0;
1666
1667     if (!isColorWell())
1668         return;
1669
1670     if (!node() || !node()->hasTagName(inputTag))
1671         return;
1672
1673     HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
1674     const AtomicString& type = input->getAttribute(typeAttr);
1675     if (!equalIgnoringCase(type, "color"))
1676         return;
1677
1678     // HTMLInputElement::value always returns a string parseable by Color().
1679     Color color(input->value());
1680     r = color.red();
1681     g = color.green();
1682     b = color.blue();
1683 }
1684
1685 // This function implements the ARIA accessible name as described by the Mozilla                                        
1686 // ARIA Implementer's Guide.                                                                                            
1687 static String accessibleNameForNode(Node* node)
1688 {
1689     if (node->isTextNode())
1690         return toText(node)->data();
1691
1692     if (node->hasTagName(inputTag))
1693         return static_cast<HTMLInputElement*>(node)->value();
1694
1695     if (node->isHTMLElement()) {
1696         const AtomicString& alt = toHTMLElement(node)->getAttribute(altAttr);
1697         if (!alt.isEmpty())
1698             return alt;
1699     }
1700
1701     return String();
1702 }
1703
1704 String AccessibilityNodeObject::accessibilityDescriptionForElements(Vector<Element*> &elements) const
1705 {
1706     StringBuilder builder;
1707     unsigned size = elements.size();
1708     for (unsigned i = 0; i < size; ++i) {
1709         Element* idElement = elements[i];
1710
1711         builder.append(accessibleNameForNode(idElement));
1712         for (Node* n = idElement->firstChild(); n; n = NodeTraversal::next(n, idElement))
1713             builder.append(accessibleNameForNode(n));
1714
1715         if (i != size - 1)
1716             builder.append(' ');
1717     }
1718     return builder.toString();
1719 }
1720
1721 String AccessibilityNodeObject::ariaDescribedByAttribute() const
1722 {
1723     Vector<Element*> elements;
1724     elementsFromAttribute(elements, aria_describedbyAttr);
1725     
1726     return accessibilityDescriptionForElements(elements);
1727 }
1728
1729 void AccessibilityNodeObject::elementsFromAttribute(Vector<Element*>& elements, const QualifiedName& attribute) const
1730 {
1731     Node* node = this->node();
1732     if (!node || !node->isElementNode())
1733         return;
1734
1735     TreeScope* scope = node->treeScope();
1736     if (!scope)
1737         return;
1738
1739     String idList = getAttribute(attribute).string();
1740     if (idList.isEmpty())
1741         return;
1742
1743     idList.replace('\n', ' ');
1744     Vector<String> idVector;
1745     idList.split(' ', idVector);
1746
1747     unsigned size = idVector.size();
1748     for (unsigned i = 0; i < size; ++i) {
1749         AtomicString idName(idVector[i]);
1750         Element* idElement = scope->getElementById(idName);
1751         if (idElement)
1752             elements.append(idElement);
1753     }
1754 }
1755
1756
1757 void AccessibilityNodeObject::ariaLabeledByElements(Vector<Element*>& elements) const
1758 {
1759     elementsFromAttribute(elements, aria_labeledbyAttr);
1760     if (!elements.size())
1761         elementsFromAttribute(elements, aria_labelledbyAttr);
1762 }
1763
1764
1765 String AccessibilityNodeObject::ariaLabeledByAttribute() const
1766 {
1767     Vector<Element*> elements;
1768     ariaLabeledByElements(elements);
1769
1770     return accessibilityDescriptionForElements(elements);
1771 }
1772
1773 bool AccessibilityNodeObject::canSetFocusAttribute() const
1774 {
1775     Node* node = this->node();
1776     if (!node)
1777         return false;
1778
1779     if (isWebArea())
1780         return true;
1781     
1782     // NOTE: It would be more accurate to ask the document whether setFocusedNode() would
1783     // do anything. For example, setFocusedNode() will do nothing if the current focused
1784     // node will not relinquish the focus.
1785     if (!node)
1786         return false;
1787
1788     if (isDisabledFormControl(node))
1789         return false;
1790
1791     return node->supportsFocus();
1792 }
1793
1794 AccessibilityRole AccessibilityNodeObject::determineAriaRoleAttribute() const
1795 {
1796     const AtomicString& ariaRole = getAttribute(roleAttr);
1797     if (ariaRole.isNull() || ariaRole.isEmpty())
1798         return UnknownRole;
1799     
1800     AccessibilityRole role = ariaRoleToWebCoreRole(ariaRole);
1801
1802     // ARIA states if an item can get focus, it should not be presentational.
1803     if (role == PresentationalRole && canSetFocusAttribute())
1804         return UnknownRole;
1805
1806     if (role == ButtonRole)
1807         role = buttonRoleType();
1808
1809     if (role == TextAreaRole && !ariaIsMultiline())
1810         role = TextFieldRole;
1811
1812     role = remapAriaRoleDueToParent(role);
1813     
1814     if (role)
1815         return role;
1816
1817     return UnknownRole;
1818 }
1819
1820 AccessibilityRole AccessibilityNodeObject::ariaRoleAttribute() const
1821 {
1822     return m_ariaRole;
1823 }
1824
1825 AccessibilityRole AccessibilityNodeObject::remapAriaRoleDueToParent(AccessibilityRole role) const
1826 {
1827     // Some objects change their role based on their parent.
1828     // However, asking for the unignoredParent calls accessibilityIsIgnored(), which can trigger a loop. 
1829     // While inside the call stack of creating an element, we need to avoid accessibilityIsIgnored().
1830     // https://bugs.webkit.org/show_bug.cgi?id=65174
1831
1832     if (role != ListBoxOptionRole && role != MenuItemRole)
1833         return role;
1834     
1835     for (AccessibilityObject* parent = parentObject(); parent && !parent->accessibilityIsIgnored(); parent = parent->parentObject()) {
1836         AccessibilityRole parentAriaRole = parent->ariaRoleAttribute();
1837
1838         // Selects and listboxes both have options as child roles, but they map to different roles within WebCore.
1839         if (role == ListBoxOptionRole && parentAriaRole == MenuRole)
1840             return MenuItemRole;
1841         // An aria "menuitem" may map to MenuButton or MenuItem depending on its parent.
1842         if (role == MenuItemRole && parentAriaRole == GroupRole)
1843             return MenuButtonRole;
1844         
1845         // If the parent had a different role, then we don't need to continue searching up the chain.
1846         if (parentAriaRole)
1847             break;
1848     }
1849     
1850     return role;
1851 }   
1852
1853 // If you call node->rendererIsEditable() since that will return true if an ancestor is editable.
1854 // This only returns true if this is the element that actually has the contentEditable attribute set.
1855 bool AccessibilityNodeObject::hasContentEditableAttributeSet() const
1856 {
1857     if (!hasAttribute(contenteditableAttr))
1858         return false;
1859     const AtomicString& contentEditableValue = getAttribute(contenteditableAttr);
1860     // Both "true" (case-insensitive) and the empty string count as true.
1861     return contentEditableValue.isEmpty() || equalIgnoringCase(contentEditableValue, "true");
1862 }
1863
1864 } // namespace WebCore