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