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