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