Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / accessibility / AXRenderObject.cpp
1 /*
2 * Copyright (C) 2008 Apple 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/AXRenderObject.h"
31
32 #include "bindings/v8/ExceptionStatePlaceholder.h"
33 #include "core/accessibility/AXImageMapLink.h"
34 #include "core/accessibility/AXInlineTextBox.h"
35 #include "core/accessibility/AXObjectCache.h"
36 #include "core/accessibility/AXSVGRoot.h"
37 #include "core/accessibility/AXSpinButton.h"
38 #include "core/accessibility/AXTable.h"
39 #include "core/dom/ElementTraversal.h"
40 #include "core/dom/shadow/ShadowRoot.h"
41 #include "core/editing/FrameSelection.h"
42 #include "core/editing/RenderedPosition.h"
43 #include "core/editing/TextIterator.h"
44 #include "core/editing/VisibleUnits.h"
45 #include "core/editing/htmlediting.h"
46 #include "core/frame/Frame.h"
47 #include "core/html/HTMLImageElement.h"
48 #include "core/html/HTMLLabelElement.h"
49 #include "core/html/HTMLOptionElement.h"
50 #include "core/html/HTMLSelectElement.h"
51 #include "core/html/HTMLTextAreaElement.h"
52 #include "core/html/shadow/ShadowElementNames.h"
53 #include "core/loader/ProgressTracker.h"
54 #include "core/page/Page.h"
55 #include "core/rendering/HitTestResult.h"
56 #include "core/rendering/RenderFieldset.h"
57 #include "core/rendering/RenderFileUploadControl.h"
58 #include "core/rendering/RenderHTMLCanvas.h"
59 #include "core/rendering/RenderImage.h"
60 #include "core/rendering/RenderInline.h"
61 #include "core/rendering/RenderLayer.h"
62 #include "core/rendering/RenderListMarker.h"
63 #include "core/rendering/RenderMenuList.h"
64 #include "core/rendering/RenderTextControlSingleLine.h"
65 #include "core/rendering/RenderTextFragment.h"
66 #include "core/rendering/RenderView.h"
67 #include "core/rendering/RenderWidget.h"
68 #include "core/svg/SVGDocument.h"
69 #include "core/svg/SVGSVGElement.h"
70 #include "core/svg/graphics/SVGImage.h"
71 #include "platform/text/PlatformLocale.h"
72 #include "wtf/StdLibExtras.h"
73
74 using blink::WebLocalizedString;
75 using namespace std;
76
77 namespace WebCore {
78
79 using namespace HTMLNames;
80
81 static inline RenderObject* firstChildInContinuation(RenderObject* renderer)
82 {
83     RenderObject* r = toRenderInline(renderer)->continuation();
84
85     while (r) {
86         if (r->isRenderBlock())
87             return r;
88         if (RenderObject* child = r->firstChild())
89             return child;
90         r = toRenderInline(r)->continuation();
91     }
92
93     return 0;
94 }
95
96 static inline bool isInlineWithContinuation(RenderObject* object)
97 {
98     if (!object->isBoxModelObject())
99         return false;
100
101     RenderBoxModelObject* renderer = toRenderBoxModelObject(object);
102     if (!renderer->isRenderInline())
103         return false;
104
105     return toRenderInline(renderer)->continuation();
106 }
107
108 static inline RenderObject* firstChildConsideringContinuation(RenderObject* renderer)
109 {
110     RenderObject* firstChild = renderer->firstChild();
111
112     if (!firstChild && isInlineWithContinuation(renderer))
113         firstChild = firstChildInContinuation(renderer);
114
115     return firstChild;
116 }
117
118 static inline RenderInline* startOfContinuations(RenderObject* r)
119 {
120     if (r->isInlineElementContinuation()) {
121         return toRenderInline(r->node()->renderer());
122     }
123
124     // Blocks with a previous continuation always have a next continuation
125     if (r->isRenderBlock() && toRenderBlock(r)->inlineElementContinuation())
126         return toRenderInline(toRenderBlock(r)->inlineElementContinuation()->node()->renderer());
127
128     return 0;
129 }
130
131 static inline RenderObject* endOfContinuations(RenderObject* renderer)
132 {
133     RenderObject* prev = renderer;
134     RenderObject* cur = renderer;
135
136     if (!cur->isRenderInline() && !cur->isRenderBlock())
137         return renderer;
138
139     while (cur) {
140         prev = cur;
141         if (cur->isRenderInline()) {
142             cur = toRenderInline(cur)->inlineElementContinuation();
143             ASSERT(cur || !toRenderInline(prev)->continuation());
144         } else {
145             cur = toRenderBlock(cur)->inlineElementContinuation();
146         }
147     }
148
149     return prev;
150 }
151
152 static inline bool lastChildHasContinuation(RenderObject* renderer)
153 {
154     return renderer->lastChild() && isInlineWithContinuation(renderer->lastChild());
155 }
156
157 static RenderBoxModelObject* nextContinuation(RenderObject* renderer)
158 {
159     ASSERT(renderer);
160     if (renderer->isRenderInline() && !renderer->isReplaced())
161         return toRenderInline(renderer)->continuation();
162     if (renderer->isRenderBlock())
163         return toRenderBlock(renderer)->inlineElementContinuation();
164     return 0;
165 }
166
167 AXRenderObject::AXRenderObject(RenderObject* renderer)
168     : AXNodeObject(renderer->node())
169     , m_renderer(renderer)
170     , m_cachedElementRectDirty(true)
171 {
172 #ifndef NDEBUG
173     m_renderer->setHasAXObject(true);
174 #endif
175 }
176
177 PassRefPtr<AXRenderObject> AXRenderObject::create(RenderObject* renderer)
178 {
179     return adoptRef(new AXRenderObject(renderer));
180 }
181
182 AXRenderObject::~AXRenderObject()
183 {
184     ASSERT(isDetached());
185 }
186
187 LayoutRect AXRenderObject::elementRect() const
188 {
189     if (!m_explicitElementRect.isEmpty())
190         return m_explicitElementRect;
191     if (!m_renderer)
192         return LayoutRect();
193     if (!m_renderer->isBox())
194         return computeElementRect();
195
196     for (const AXObject* obj = this; obj; obj = obj->parentObject()) {
197         if (obj->isAXRenderObject())
198             toAXRenderObject(obj)->checkCachedElementRect();
199     }
200     for (const AXObject* obj = this; obj; obj = obj->parentObject()) {
201         if (obj->isAXRenderObject())
202             toAXRenderObject(obj)->updateCachedElementRect();
203     }
204
205     return m_cachedElementRect;
206 }
207
208 void AXRenderObject::setRenderer(RenderObject* renderer)
209 {
210     m_renderer = renderer;
211     setNode(renderer->node());
212 }
213
214 RenderBoxModelObject* AXRenderObject::renderBoxModelObject() const
215 {
216     if (!m_renderer || !m_renderer->isBoxModelObject())
217         return 0;
218     return toRenderBoxModelObject(m_renderer);
219 }
220
221 RenderView* AXRenderObject::topRenderer() const
222 {
223     Document* topDoc = topDocument();
224     if (!topDoc)
225         return 0;
226
227     return topDoc->renderView();
228 }
229
230 Document* AXRenderObject::topDocument() const
231 {
232     if (!document())
233         return 0;
234     return document()->topDocument();
235 }
236
237 bool AXRenderObject::shouldNotifyActiveDescendant() const
238 {
239     // We want to notify that the combo box has changed its active descendant,
240     // but we do not want to change the focus, because focus should remain with the combo box.
241     if (isComboBox())
242         return true;
243
244     return shouldFocusActiveDescendant();
245 }
246
247 ScrollableArea* AXRenderObject::getScrollableAreaIfScrollable() const
248 {
249     // If the parent is a scroll view, then this object isn't really scrollable, the parent ScrollView should handle the scrolling.
250     if (parentObject() && parentObject()->isAXScrollView())
251         return 0;
252
253     if (!m_renderer || !m_renderer->isBox())
254         return 0;
255
256     RenderBox* box = toRenderBox(m_renderer);
257     if (!box->canBeScrolledAndHasScrollableArea())
258         return 0;
259
260     return box->scrollableArea();
261 }
262
263 AccessibilityRole AXRenderObject::determineAccessibilityRole()
264 {
265     if (!m_renderer)
266         return UnknownRole;
267
268     m_ariaRole = determineAriaRoleAttribute();
269
270     Node* node = m_renderer->node();
271     AccessibilityRole ariaRole = ariaRoleAttribute();
272     if (ariaRole != UnknownRole)
273         return ariaRole;
274
275     RenderBoxModelObject* cssBox = renderBoxModelObject();
276
277     if (node && node->isLink()) {
278         if (cssBox && cssBox->isImage())
279             return ImageMapRole;
280         return LinkRole;
281     }
282     if (cssBox && cssBox->isListItem())
283         return ListItemRole;
284     if (m_renderer->isListMarker())
285         return ListMarkerRole;
286     if (node && node->hasTagName(buttonTag))
287         return buttonRoleType();
288     if (node && node->hasTagName(legendTag))
289         return LegendRole;
290     if (m_renderer->isText())
291         return StaticTextRole;
292     if (cssBox && cssBox->isImage()) {
293         if (node && node->hasTagName(inputTag))
294             return ariaHasPopup() ? PopUpButtonRole : ButtonRole;
295         if (isSVGImage())
296             return SVGRootRole;
297         return ImageRole;
298     }
299
300     // Note: if JavaScript is disabled, the renderer won't be a RenderHTMLCanvas.
301     if (node && node->hasTagName(canvasTag) && m_renderer->isCanvas())
302         return CanvasRole;
303
304     if (cssBox && cssBox->isRenderView())
305         return WebAreaRole;
306
307     if (cssBox && cssBox->isTextField())
308         return TextFieldRole;
309
310     if (cssBox && cssBox->isTextArea())
311         return TextAreaRole;
312
313     if (node && node->hasTagName(inputTag)) {
314         HTMLInputElement* input = toHTMLInputElement(node);
315         if (input->isCheckbox())
316             return CheckBoxRole;
317         if (input->isRadioButton())
318             return RadioButtonRole;
319         if (input->isTextButton())
320             return buttonRoleType();
321
322         const AtomicString& type = input->getAttribute(typeAttr);
323         if (equalIgnoringCase(type, "color"))
324             return ColorWellRole;
325     }
326
327     if (isFileUploadButton())
328         return ButtonRole;
329
330     if (cssBox && cssBox->isMenuList())
331         return PopUpButtonRole;
332
333     if (headingLevel())
334         return HeadingRole;
335
336     if (m_renderer->isSVGImage())
337         return ImageRole;
338     if (m_renderer->isSVGRoot())
339         return SVGRootRole;
340
341     if (node && node->hasTagName(ddTag))
342         return DescriptionListDetailRole;
343
344     if (node && node->hasTagName(dtTag))
345         return DescriptionListTermRole;
346
347     if (node && (node->hasTagName(rpTag) || node->hasTagName(rtTag)))
348         return AnnotationRole;
349
350     // Table sections should be ignored.
351     if (m_renderer->isTableSection())
352         return IgnoredRole;
353
354     if (m_renderer->isHR())
355         return HorizontalRuleRole;
356
357     if (node && node->hasTagName(pTag))
358         return ParagraphRole;
359
360     if (node && node->hasTagName(labelTag))
361         return LabelRole;
362
363     if (node && node->hasTagName(divTag))
364         return DivRole;
365
366     if (node && node->hasTagName(formTag))
367         return FormRole;
368
369     if (node && node->hasTagName(articleTag))
370         return ArticleRole;
371
372     if (node && node->hasTagName(mainTag))
373         return MainRole;
374
375     if (node && node->hasTagName(navTag))
376         return NavigationRole;
377
378     if (node && node->hasTagName(asideTag))
379         return ComplementaryRole;
380
381     if (node && node->hasTagName(sectionTag))
382         return RegionRole;
383
384     if (node && node->hasTagName(addressTag))
385         return ContentInfoRole;
386
387     if (node && node->hasTagName(dialogTag))
388         return DialogRole;
389
390     // The HTML element should not be exposed as an element. That's what the RenderView element does.
391     if (node && node->hasTagName(htmlTag))
392         return IgnoredRole;
393
394     // There should only be one banner/contentInfo per page. If header/footer are being used within an article or section
395     // then it should not be exposed as whole page's banner/contentInfo
396     if (node && node->hasTagName(headerTag) && !isDescendantOfElementType(articleTag) && !isDescendantOfElementType(sectionTag))
397         return BannerRole;
398     if (node && node->hasTagName(footerTag) && !isDescendantOfElementType(articleTag) && !isDescendantOfElementType(sectionTag))
399         return FooterRole;
400
401     if (node && node->hasTagName(aTag) && isClickable())
402         return LinkRole;
403
404     if (m_renderer->isRenderBlockFlow())
405         return GroupRole;
406
407     // If the element does not have role, but it has ARIA attributes, accessibility should fallback to exposing it as a group.
408     if (supportsARIAAttributes())
409         return GroupRole;
410
411     return UnknownRole;
412 }
413
414 void AXRenderObject::init()
415 {
416     AXNodeObject::init();
417 }
418
419 void AXRenderObject::detach()
420 {
421     AXNodeObject::detach();
422
423     detachRemoteSVGRoot();
424
425 #ifndef NDEBUG
426     if (m_renderer)
427         m_renderer->setHasAXObject(false);
428 #endif
429     m_renderer = 0;
430 }
431
432 //
433 // Check object role or purpose.
434 //
435
436 bool AXRenderObject::isAttachment() const
437 {
438     RenderBoxModelObject* renderer = renderBoxModelObject();
439     if (!renderer)
440         return false;
441     // Widgets are the replaced elements that we represent to AX as attachments
442     bool isWidget = renderer->isWidget();
443     ASSERT(!isWidget || (renderer->isReplaced() && !isImage()));
444     return isWidget;
445 }
446
447 bool AXRenderObject::isFileUploadButton() const
448 {
449     if (m_renderer && m_renderer->node() && m_renderer->node()->hasTagName(inputTag)) {
450         HTMLInputElement* input = toHTMLInputElement(m_renderer->node());
451         return input->isFileUpload();
452     }
453
454     return false;
455 }
456
457 static bool isLinkable(const AXObject& object)
458 {
459     if (!object.renderer())
460         return false;
461
462     // See https://wiki.mozilla.org/Accessibility/AT-Windows-API for the elements
463     // Mozilla considers linkable.
464     return object.isLink() || object.isImage() || object.renderer()->isText();
465 }
466
467 bool AXRenderObject::isLinked() const
468 {
469     if (!isLinkable(*this))
470         return false;
471
472     Element* anchor = anchorElement();
473     if (!anchor || !anchor->hasTagName(aTag))
474         return false;
475
476     return !toHTMLAnchorElement(anchor)->href().isEmpty();
477 }
478
479 bool AXRenderObject::isLoaded() const
480 {
481     return !m_renderer->document().parser();
482 }
483
484 bool AXRenderObject::isOffScreen() const
485 {
486     ASSERT(m_renderer);
487     IntRect contentRect = pixelSnappedIntRect(m_renderer->absoluteClippedOverflowRect());
488     FrameView* view = m_renderer->frame()->view();
489     IntRect viewRect = view->visibleContentRect();
490     viewRect.intersect(contentRect);
491     return viewRect.isEmpty();
492 }
493
494 bool AXRenderObject::isReadOnly() const
495 {
496     ASSERT(m_renderer);
497
498     if (isWebArea()) {
499         Document& document = m_renderer->document();
500         HTMLElement* body = document.body();
501         if (body && body->rendererIsEditable())
502             return false;
503
504         return !document.rendererIsEditable();
505     }
506
507     return AXNodeObject::isReadOnly();
508 }
509
510 bool AXRenderObject::isVisited() const
511 {
512     // FIXME: Is it a privacy violation to expose visited information to accessibility APIs?
513     return m_renderer->style()->isLink() && m_renderer->style()->insideLink() == InsideVisitedLink;
514 }
515
516 //
517 // Check object state.
518 //
519
520 bool AXRenderObject::isFocused() const
521 {
522     if (!m_renderer)
523         return false;
524
525     Document& document = m_renderer->document();
526     Element* focusedElement = document.focusedElement();
527     if (!focusedElement)
528         return false;
529
530     // A web area is represented by the Document node in the DOM tree, which isn't focusable.
531     // Check instead if the frame's selection controller is focused
532     if (focusedElement == m_renderer->node()
533         || (roleValue() == WebAreaRole && document.frame()->selection().isFocusedAndActive()))
534         return true;
535
536     return false;
537 }
538
539 bool AXRenderObject::isSelected() const
540 {
541     if (!m_renderer)
542         return false;
543
544     Node* node = m_renderer->node();
545     if (!node)
546         return false;
547
548     const AtomicString& ariaSelected = getAttribute(aria_selectedAttr);
549     if (equalIgnoringCase(ariaSelected, "true"))
550         return true;
551
552     if (isTabItem() && isTabItemSelected())
553         return true;
554
555     return false;
556 }
557
558 //
559 // Whether objects are ignored, i.e. not included in the tree.
560 //
561
562 AXObjectInclusion AXRenderObject::defaultObjectInclusion() const
563 {
564     // The following cases can apply to any element that's a subclass of AXRenderObject.
565
566     if (!m_renderer)
567         return IgnoreObject;
568
569     if (m_renderer->style()->visibility() != VISIBLE) {
570         // aria-hidden is meant to override visibility as the determinant in AX hierarchy inclusion.
571         if (equalIgnoringCase(getAttribute(aria_hiddenAttr), "false"))
572             return DefaultBehavior;
573
574         return IgnoreObject;
575     }
576
577     return AXObject::defaultObjectInclusion();
578 }
579
580 bool AXRenderObject::computeAccessibilityIsIgnored() const
581 {
582 #ifndef NDEBUG
583     ASSERT(m_initialized);
584 #endif
585
586     // Check first if any of the common reasons cause this element to be ignored.
587     // Then process other use cases that need to be applied to all the various roles
588     // that AXRenderObjects take on.
589     AXObjectInclusion decision = defaultObjectInclusion();
590     if (decision == IncludeObject)
591         return false;
592     if (decision == IgnoreObject)
593         return true;
594
595     // If this element is within a parent that cannot have children, it should not be exposed.
596     if (isDescendantOfBarrenParent())
597         return true;
598
599     if (roleValue() == IgnoredRole)
600         return true;
601
602     if (roleValue() == PresentationalRole || inheritsPresentationalRole())
603         return true;
604
605     // An ARIA tree can only have tree items and static text as children.
606     if (!isAllowedChildOfTree())
607         return true;
608
609     // TODO: we should refactor this - but right now this is necessary to make
610     // sure scroll areas stay in the tree.
611     if (isAttachment())
612         return false;
613
614     // ignore popup menu items because AppKit does
615     for (RenderObject* parent = m_renderer->parent(); parent; parent = parent->parent()) {
616         if (parent->isBoxModelObject() && toRenderBoxModelObject(parent)->isMenuList())
617             return true;
618     }
619
620     // find out if this element is inside of a label element.
621     // if so, it may be ignored because it's the label for a checkbox or radio button
622     AXObject* controlObject = correspondingControlForLabelElement();
623     if (controlObject && !controlObject->exposesTitleUIElement() && controlObject->isCheckboxOrRadio())
624         return true;
625
626     // NOTE: BRs always have text boxes now, so the text box check here can be removed
627     if (m_renderer->isText()) {
628         // static text beneath MenuItems and MenuButtons are just reported along with the menu item, so it's ignored on an individual level
629         AXObject* parent = parentObjectUnignored();
630         if (parent && (parent->ariaRoleAttribute() == MenuItemRole || parent->ariaRoleAttribute() == MenuButtonRole))
631             return true;
632         RenderText* renderText = toRenderText(m_renderer);
633         if (m_renderer->isBR() || !renderText->firstTextBox())
634             return true;
635
636         // Don't ignore static text in editable text controls.
637         for (AXObject* parent = parentObject(); parent; parent = parent->parentObject()) {
638             if (parent->roleValue() == TextFieldRole || parent->roleValue() == TextAreaRole)
639                 return false;
640         }
641
642         // text elements that are just empty whitespace should not be returned
643         // FIXME(dmazzoni): we probably shouldn't ignore this if the style is 'pre', or similar...
644         return renderText->text().impl()->containsOnlyWhitespace();
645     }
646
647     if (isHeading())
648         return false;
649
650     if (isLandmarkRelated())
651         return false;
652
653     if (isLink())
654         return false;
655
656     // all controls are accessible
657     if (isControl())
658         return false;
659
660     if (ariaRoleAttribute() != UnknownRole)
661         return false;
662
663     // don't ignore labels, because they serve as TitleUIElements
664     Node* node = m_renderer->node();
665     if (node && node->hasTagName(labelTag))
666         return false;
667
668     // Anything that is content editable should not be ignored.
669     // However, one cannot just call node->rendererIsEditable() since that will ask if its parents
670     // are also editable. Only the top level content editable region should be exposed.
671     if (hasContentEditableAttributeSet())
672         return false;
673
674     // List items play an important role in defining the structure of lists. They should not be ignored.
675     if (roleValue() == ListItemRole)
676         return false;
677
678     if (roleValue() == DialogRole)
679         return false;
680
681     // if this element has aria attributes on it, it should not be ignored.
682     if (supportsARIAAttributes())
683         return false;
684
685     // <span> tags are inline tags and not meant to convey information if they have no other aria
686     // information on them. If we don't ignore them, they may emit signals expected to come from
687     // their parent. In addition, because included spans are GroupRole objects, and GroupRole
688     // objects are often containers with meaningful information, the inclusion of a span can have
689     // the side effect of causing the immediate parent accessible to be ignored. This is especially
690     // problematic for platforms which have distinct roles for textual block elements.
691     if (node && node->hasTagName(spanTag))
692         return true;
693
694     if (m_renderer->isRenderBlockFlow() && m_renderer->childrenInline() && !canSetFocusAttribute())
695         return !toRenderBlock(m_renderer)->firstLineBox() && !mouseButtonListener();
696
697     // ignore images seemingly used as spacers
698     if (isImage()) {
699
700         // If the image can take focus, it should not be ignored, lest the user not be able to interact with something important.
701         if (canSetFocusAttribute())
702             return false;
703
704         if (node && node->isElementNode()) {
705             Element* elt = toElement(node);
706             const AtomicString& alt = elt->getAttribute(altAttr);
707             // don't ignore an image that has an alt tag
708             if (!alt.string().containsOnlyWhitespace())
709                 return false;
710             // informal standard is to ignore images with zero-length alt strings
711             if (!alt.isNull())
712                 return true;
713         }
714
715         if (isNativeImage() && m_renderer->isImage()) {
716             // check for one-dimensional image
717             RenderImage* image = toRenderImage(m_renderer);
718             if (image->height() <= 1 || image->width() <= 1)
719                 return true;
720
721             // check whether rendered image was stretched from one-dimensional file image
722             if (image->cachedImage()) {
723                 LayoutSize imageSize = image->cachedImage()->imageSizeForRenderer(m_renderer, image->view()->zoomFactor());
724                 return imageSize.height() <= 1 || imageSize.width() <= 1;
725             }
726         }
727         return false;
728     }
729
730     if (isCanvas()) {
731         if (canvasHasFallbackContent())
732             return false;
733         RenderHTMLCanvas* canvas = toRenderHTMLCanvas(m_renderer);
734         if (canvas->height() <= 1 || canvas->width() <= 1)
735             return true;
736         // Otherwise fall through; use presence of help text, title, or description to decide.
737     }
738
739     if (isWebArea() || m_renderer->isListMarker())
740         return false;
741
742     // Using the help text, title or accessibility description (so we
743     // check if there's some kind of accessible name for the element)
744     // to decide an element's visibility is not as definitive as
745     // previous checks, so this should remain as one of the last.
746     //
747     // These checks are simplified in the interest of execution speed;
748     // for example, any element having an alt attribute will make it
749     // not ignored, rather than just images.
750     if (!getAttribute(aria_helpAttr).isEmpty() || !getAttribute(aria_describedbyAttr).isEmpty() || !getAttribute(altAttr).isEmpty() || !getAttribute(titleAttr).isEmpty())
751         return false;
752
753     // Don't ignore generic focusable elements like <div tabindex=0>
754     // unless they're completely empty, with no children.
755     if (isGenericFocusableElement() && node->firstChild())
756         return false;
757
758     if (!ariaAccessibilityDescription().isEmpty())
759         return false;
760
761     // By default, objects should be ignored so that the AX hierarchy is not
762     // filled with unnecessary items.
763     return true;
764 }
765
766 //
767 // Properties of static elements.
768 //
769
770 const AtomicString& AXRenderObject::accessKey() const
771 {
772     Node* node = m_renderer->node();
773     if (!node)
774         return nullAtom;
775     if (!node->isElementNode())
776         return nullAtom;
777     return toElement(node)->getAttribute(accesskeyAttr);
778 }
779
780 AccessibilityOrientation AXRenderObject::orientation() const
781 {
782     const AtomicString& ariaOrientation = getAttribute(aria_orientationAttr);
783     if (equalIgnoringCase(ariaOrientation, "horizontal"))
784         return AccessibilityOrientationHorizontal;
785     if (equalIgnoringCase(ariaOrientation, "vertical"))
786         return AccessibilityOrientationVertical;
787
788     return AXObject::orientation();
789 }
790
791 String AXRenderObject::text() const
792 {
793     if (isPasswordField())
794         return String();
795
796     return AXNodeObject::text();
797 }
798
799 int AXRenderObject::textLength() const
800 {
801     ASSERT(isTextControl());
802
803     if (isPasswordField())
804         return -1; // need to return something distinct from 0
805
806     return text().length();
807 }
808
809 KURL AXRenderObject::url() const
810 {
811     if (isAnchor() && m_renderer->node()->hasTagName(aTag)) {
812         if (HTMLAnchorElement* anchor = toHTMLAnchorElement(anchorElement()))
813             return anchor->href();
814     }
815
816     if (isWebArea())
817         return m_renderer->document().url();
818
819     if (isImage() && m_renderer->node() && m_renderer->node()->hasTagName(imgTag))
820         return toHTMLImageElement(m_renderer->node())->src();
821
822     if (isInputImage())
823         return toHTMLInputElement(m_renderer->node())->src();
824
825     return KURL();
826 }
827
828 //
829 // Properties of interactive elements.
830 //
831
832 static String queryString(WebLocalizedString::Name name)
833 {
834     return Locale::defaultLocale().queryString(name);
835 }
836
837 String AXRenderObject::actionVerb() const
838 {
839     switch (roleValue()) {
840     case ButtonRole:
841     case ToggleButtonRole:
842         return queryString(WebLocalizedString::AXButtonActionVerb);
843     case TextFieldRole:
844     case TextAreaRole:
845         return queryString(WebLocalizedString::AXTextFieldActionVerb);
846     case RadioButtonRole:
847         return queryString(WebLocalizedString::AXRadioButtonActionVerb);
848     case CheckBoxRole:
849         return queryString(isChecked() ? WebLocalizedString::AXCheckedCheckBoxActionVerb : WebLocalizedString::AXUncheckedCheckBoxActionVerb);
850     case LinkRole:
851         return queryString(WebLocalizedString::AXLinkActionVerb);
852     default:
853         return emptyString();
854     }
855 }
856
857 void AXRenderObject::selectedChildren(AccessibilityChildrenVector& result)
858 {
859     ASSERT(result.isEmpty());
860
861     // only listboxes should be asked for their selected children.
862     AccessibilityRole role = roleValue();
863     if (role == ListBoxRole) // native list boxes would be AXListBoxes, so only check for aria list boxes
864         ariaListboxSelectedChildren(result);
865     else if (role == TreeRole || role == TreeGridRole || role == TableRole)
866         ariaSelectedRows(result);
867 }
868
869 String AXRenderObject::stringValue() const
870 {
871     if (!m_renderer)
872         return String();
873
874     if (isPasswordField())
875         return String();
876
877     RenderBoxModelObject* cssBox = renderBoxModelObject();
878
879     if (ariaRoleAttribute() == StaticTextRole) {
880         String staticText = text();
881         if (!staticText.length())
882             staticText = textUnderElement();
883         return staticText;
884     }
885
886     if (m_renderer->isText())
887         return textUnderElement();
888
889     if (cssBox && cssBox->isMenuList()) {
890         // RenderMenuList will go straight to the text() of its selected item.
891         // This has to be overridden in the case where the selected item has an ARIA label.
892         HTMLSelectElement* selectElement = toHTMLSelectElement(m_renderer->node());
893         int selectedIndex = selectElement->selectedIndex();
894         const Vector<HTMLElement*> listItems = selectElement->listItems();
895         if (selectedIndex >= 0 && static_cast<size_t>(selectedIndex) < listItems.size()) {
896             const AtomicString& overriddenDescription = listItems[selectedIndex]->fastGetAttribute(aria_labelAttr);
897             if (!overriddenDescription.isNull())
898                 return overriddenDescription;
899         }
900         return toRenderMenuList(m_renderer)->text();
901     }
902
903     if (m_renderer->isListMarker())
904         return toRenderListMarker(m_renderer)->text();
905
906     if (isWebArea()) {
907         // FIXME: Why would a renderer exist when the Document isn't attached to a frame?
908         if (m_renderer->frame())
909             return String();
910
911         ASSERT_NOT_REACHED();
912     }
913
914     if (isTextControl())
915         return text();
916
917     if (m_renderer->isFileUploadControl())
918         return toRenderFileUploadControl(m_renderer)->fileTextValue();
919
920     // FIXME: We might need to implement a value here for more types
921     // FIXME: It would be better not to advertise a value at all for the types for which we don't implement one;
922     // this would require subclassing or making accessibilityAttributeNames do something other than return a
923     // single static array.
924     return String();
925 }
926
927 //
928 // ARIA attributes.
929 //
930
931 AXObject* AXRenderObject::activeDescendant() const
932 {
933     if (!m_renderer)
934         return 0;
935
936     if (m_renderer->node() && !m_renderer->node()->isElementNode())
937         return 0;
938     Element* element = toElement(m_renderer->node());
939
940     const AtomicString& activeDescendantAttrStr = element->getAttribute(aria_activedescendantAttr);
941     if (activeDescendantAttrStr.isNull() || activeDescendantAttrStr.isEmpty())
942         return 0;
943
944     Element* target = element->treeScope().getElementById(activeDescendantAttrStr);
945     if (!target)
946         return 0;
947
948     AXObject* obj = axObjectCache()->getOrCreate(target);
949
950     // An activedescendant is only useful if it has a renderer, because that's what's needed to post the notification.
951     if (obj && obj->isAXRenderObject())
952         return obj;
953
954     return 0;
955 }
956
957 void AXRenderObject::ariaFlowToElements(AccessibilityChildrenVector& flowTo) const
958 {
959     Vector<Element*> elements;
960     elementsFromAttribute(elements, aria_flowtoAttr);
961
962     AXObjectCache* cache = axObjectCache();
963     unsigned count = elements.size();
964     for (unsigned k = 0; k < count; ++k) {
965         Element* element = elements[k];
966         AXObject* flowToElement = cache->getOrCreate(element);
967         if (flowToElement)
968             flowTo.append(flowToElement);
969     }
970 }
971
972 bool AXRenderObject::ariaHasPopup() const
973 {
974     return elementAttributeValue(aria_haspopupAttr);
975 }
976
977 bool AXRenderObject::ariaRoleHasPresentationalChildren() const
978 {
979     switch (m_ariaRole) {
980     case ButtonRole:
981     case SliderRole:
982     case ImageRole:
983     case ProgressIndicatorRole:
984     case SpinButtonRole:
985     // case SeparatorRole:
986         return true;
987     default:
988         return false;
989     }
990 }
991
992 bool AXRenderObject::isPresentationalChildOfAriaRole() const
993 {
994     // Walk the parent chain looking for a parent that has presentational children
995     AXObject* parent;
996     for (parent = parentObject(); parent && !parent->ariaRoleHasPresentationalChildren(); parent = parent->parentObject())
997     { }
998
999     return parent;
1000 }
1001
1002 bool AXRenderObject::shouldFocusActiveDescendant() const
1003 {
1004     switch (ariaRoleAttribute()) {
1005     case GroupRole:
1006     case ListBoxRole:
1007     case MenuRole:
1008     case MenuBarRole:
1009     case RadioGroupRole:
1010     case RowRole:
1011     case PopUpButtonRole:
1012     case ProgressIndicatorRole:
1013     case ToolbarRole:
1014     case OutlineRole:
1015     case TreeRole:
1016     case GridRole:
1017     /* FIXME: replace these with actual roles when they are added to AccessibilityRole
1018     composite
1019     alert
1020     alertdialog
1021     status
1022     timer
1023     */
1024         return true;
1025     default:
1026         return false;
1027     }
1028 }
1029
1030 bool AXRenderObject::supportsARIADragging() const
1031 {
1032     const AtomicString& grabbed = getAttribute(aria_grabbedAttr);
1033     return equalIgnoringCase(grabbed, "true") || equalIgnoringCase(grabbed, "false");
1034 }
1035
1036 bool AXRenderObject::supportsARIADropping() const
1037 {
1038     const AtomicString& dropEffect = getAttribute(aria_dropeffectAttr);
1039     return !dropEffect.isEmpty();
1040 }
1041
1042 bool AXRenderObject::supportsARIAFlowTo() const
1043 {
1044     return !getAttribute(aria_flowtoAttr).isEmpty();
1045 }
1046
1047 bool AXRenderObject::supportsARIAOwns() const
1048 {
1049     if (!m_renderer)
1050         return false;
1051     const AtomicString& ariaOwns = getAttribute(aria_ownsAttr);
1052
1053     return !ariaOwns.isEmpty();
1054 }
1055
1056 //
1057 // ARIA live-region features.
1058 //
1059
1060 const AtomicString& AXRenderObject::ariaLiveRegionStatus() const
1061 {
1062     DEFINE_STATIC_LOCAL(const AtomicString, liveRegionStatusAssertive, ("assertive", AtomicString::ConstructFromLiteral));
1063     DEFINE_STATIC_LOCAL(const AtomicString, liveRegionStatusPolite, ("polite", AtomicString::ConstructFromLiteral));
1064     DEFINE_STATIC_LOCAL(const AtomicString, liveRegionStatusOff, ("off", AtomicString::ConstructFromLiteral));
1065
1066     const AtomicString& liveRegionStatus = getAttribute(aria_liveAttr);
1067     // These roles have implicit live region status.
1068     if (liveRegionStatus.isEmpty()) {
1069         switch (roleValue()) {
1070         case AlertDialogRole:
1071         case AlertRole:
1072             return liveRegionStatusAssertive;
1073         case LogRole:
1074         case StatusRole:
1075             return liveRegionStatusPolite;
1076         case TimerRole:
1077         case MarqueeRole:
1078             return liveRegionStatusOff;
1079         default:
1080             break;
1081         }
1082     }
1083
1084     return liveRegionStatus;
1085 }
1086
1087 const AtomicString& AXRenderObject::ariaLiveRegionRelevant() const
1088 {
1089     DEFINE_STATIC_LOCAL(const AtomicString, defaultLiveRegionRelevant, ("additions text", AtomicString::ConstructFromLiteral));
1090     const AtomicString& relevant = getAttribute(aria_relevantAttr);
1091
1092     // Default aria-relevant = "additions text".
1093     if (relevant.isEmpty())
1094         return defaultLiveRegionRelevant;
1095
1096     return relevant;
1097 }
1098
1099 bool AXRenderObject::ariaLiveRegionAtomic() const
1100 {
1101     return elementAttributeValue(aria_atomicAttr);
1102 }
1103
1104 bool AXRenderObject::ariaLiveRegionBusy() const
1105 {
1106     return elementAttributeValue(aria_busyAttr);
1107 }
1108
1109 //
1110 // Accessibility Text.
1111 //
1112
1113 String AXRenderObject::textUnderElement() const
1114 {
1115     if (!m_renderer)
1116         return String();
1117
1118     if (m_renderer->isFileUploadControl())
1119         return toRenderFileUploadControl(m_renderer)->buttonValue();
1120
1121     if (m_renderer->isText())
1122         return toRenderText(m_renderer)->plainText();
1123
1124     return AXNodeObject::textUnderElement();
1125 }
1126
1127 //
1128 // Accessibility Text - (To be deprecated).
1129 //
1130
1131 String AXRenderObject::helpText() const
1132 {
1133     if (!m_renderer)
1134         return String();
1135
1136     const AtomicString& ariaHelp = getAttribute(aria_helpAttr);
1137     if (!ariaHelp.isEmpty())
1138         return ariaHelp;
1139
1140     String describedBy = ariaDescribedByAttribute();
1141     if (!describedBy.isEmpty())
1142         return describedBy;
1143
1144     String description = accessibilityDescription();
1145     for (RenderObject* curr = m_renderer; curr; curr = curr->parent()) {
1146         if (curr->node() && curr->node()->isHTMLElement()) {
1147             const AtomicString& summary = toElement(curr->node())->getAttribute(summaryAttr);
1148             if (!summary.isEmpty())
1149                 return summary;
1150
1151             // The title attribute should be used as help text unless it is already being used as descriptive text.
1152             const AtomicString& title = toElement(curr->node())->getAttribute(titleAttr);
1153             if (!title.isEmpty() && description != title)
1154                 return title;
1155         }
1156
1157         // Only take help text from an ancestor element if its a group or an unknown role. If help was
1158         // added to those kinds of elements, it is likely it was meant for a child element.
1159         AXObject* axObj = axObjectCache()->getOrCreate(curr);
1160         if (axObj) {
1161             AccessibilityRole role = axObj->roleValue();
1162             if (role != GroupRole && role != UnknownRole)
1163                 break;
1164         }
1165     }
1166
1167     return String();
1168 }
1169
1170 //
1171 // Position and size.
1172 //
1173
1174 void AXRenderObject::checkCachedElementRect() const
1175 {
1176     if (m_cachedElementRectDirty)
1177         return;
1178
1179     if (!m_renderer)
1180         return;
1181
1182     if (!m_renderer->isBox())
1183         return;
1184
1185     bool dirty = false;
1186     RenderBox* box = toRenderBox(m_renderer);
1187     if (box->frameRect() != m_cachedFrameRect)
1188         dirty = true;
1189
1190     if (box->canBeScrolledAndHasScrollableArea()) {
1191         ScrollableArea* scrollableArea = box->scrollableArea();
1192         if (scrollableArea && scrollableArea->scrollPosition() != m_cachedScrollPosition)
1193             dirty = true;
1194     }
1195
1196     if (dirty)
1197         markCachedElementRectDirty();
1198 }
1199
1200 void AXRenderObject::updateCachedElementRect() const
1201 {
1202     if (!m_cachedElementRectDirty)
1203         return;
1204
1205     if (!m_renderer)
1206         return;
1207
1208     if (!m_renderer->isBox())
1209         return;
1210
1211     RenderBox* box = toRenderBox(m_renderer);
1212     m_cachedFrameRect = box->frameRect();
1213
1214     if (box->canBeScrolledAndHasScrollableArea()) {
1215         ScrollableArea* scrollableArea = box->scrollableArea();
1216         if (scrollableArea)
1217             m_cachedScrollPosition = scrollableArea->scrollPosition();
1218     }
1219
1220     m_cachedElementRect = computeElementRect();
1221     m_cachedElementRectDirty = false;
1222 }
1223
1224 void AXRenderObject::markCachedElementRectDirty() const
1225 {
1226     if (m_cachedElementRectDirty)
1227         return;
1228
1229     // Marks children recursively, if this element changed.
1230     m_cachedElementRectDirty = true;
1231     for (AXObject* child = firstChild(); child; child = child->nextSibling())
1232         child->markCachedElementRectDirty();
1233 }
1234
1235 IntPoint AXRenderObject::clickPoint()
1236 {
1237     // Headings are usually much wider than their textual content. If the mid point is used, often it can be wrong.
1238     if (isHeading() && children().size() == 1)
1239         return children()[0]->clickPoint();
1240
1241     // use the default position unless this is an editable web area, in which case we use the selection bounds.
1242     if (!isWebArea() || isReadOnly())
1243         return AXObject::clickPoint();
1244
1245     LayoutRect bounds = elementRect();
1246     return IntPoint(bounds.x() + (bounds.width() / 2), bounds.y() - (bounds.height() / 2));
1247 }
1248
1249 //
1250 // Hit testing.
1251 //
1252
1253 AXObject* AXRenderObject::accessibilityHitTest(const IntPoint& point) const
1254 {
1255     if (!m_renderer || !m_renderer->hasLayer())
1256         return 0;
1257
1258     RenderLayer* layer = toRenderBox(m_renderer)->layer();
1259
1260     HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
1261     HitTestResult hitTestResult = HitTestResult(point);
1262     layer->hitTest(request, hitTestResult);
1263     if (!hitTestResult.innerNode())
1264         return 0;
1265     Node* node = hitTestResult.innerNode()->deprecatedShadowAncestorNode();
1266
1267     if (node->hasTagName(areaTag))
1268         return accessibilityImageMapHitTest(toHTMLAreaElement(node), point);
1269
1270     if (node->hasTagName(optionTag))
1271         node = toHTMLOptionElement(node)->ownerSelectElement();
1272
1273     RenderObject* obj = node->renderer();
1274     if (!obj)
1275         return 0;
1276
1277     AXObject* result = obj->document().axObjectCache()->getOrCreate(obj);
1278     result->updateChildrenIfNecessary();
1279
1280     // Allow the element to perform any hit-testing it might need to do to reach non-render children.
1281     result = result->elementAccessibilityHitTest(point);
1282
1283     if (result && result->accessibilityIsIgnored()) {
1284         // If this element is the label of a control, a hit test should return the control.
1285         if (result->isAXRenderObject()) {
1286             AXObject* controlObject = toAXRenderObject(result)->correspondingControlForLabelElement();
1287             if (controlObject && !controlObject->exposesTitleUIElement())
1288                 return controlObject;
1289         }
1290
1291         result = result->parentObjectUnignored();
1292     }
1293
1294     return result;
1295 }
1296
1297 AXObject* AXRenderObject::elementAccessibilityHitTest(const IntPoint& point) const
1298 {
1299     if (isSVGImage())
1300         return remoteSVGElementHitTest(point);
1301
1302     return AXObject::elementAccessibilityHitTest(point);
1303 }
1304
1305 //
1306 // High-level accessibility tree access.
1307 //
1308
1309 AXObject* AXRenderObject::parentObject() const
1310 {
1311     if (!m_renderer)
1312         return 0;
1313
1314     if (ariaRoleAttribute() == MenuBarRole)
1315         return axObjectCache()->getOrCreate(m_renderer->parent());
1316
1317     // menuButton and its corresponding menu are DOM siblings, but Accessibility needs them to be parent/child
1318     if (ariaRoleAttribute() == MenuRole) {
1319         AXObject* parent = menuButtonForMenu();
1320         if (parent)
1321             return parent;
1322     }
1323
1324     RenderObject* parentObj = renderParentObject();
1325     if (parentObj)
1326         return axObjectCache()->getOrCreate(parentObj);
1327
1328     // WebArea's parent should be the scroll view containing it.
1329     if (isWebArea())
1330         return axObjectCache()->getOrCreate(m_renderer->frame()->view());
1331
1332     return 0;
1333 }
1334
1335 AXObject* AXRenderObject::parentObjectIfExists() const
1336 {
1337     // WebArea's parent should be the scroll view containing it.
1338     if (isWebArea())
1339         return axObjectCache()->get(m_renderer->frame()->view());
1340
1341     return axObjectCache()->get(renderParentObject());
1342 }
1343
1344 //
1345 // Low-level accessibility tree exploration, only for use within the accessibility module.
1346 //
1347
1348 AXObject* AXRenderObject::firstChild() const
1349 {
1350     if (!m_renderer)
1351         return 0;
1352
1353     RenderObject* firstChild = firstChildConsideringContinuation(m_renderer);
1354
1355     if (!firstChild)
1356         return 0;
1357
1358     return axObjectCache()->getOrCreate(firstChild);
1359 }
1360
1361 AXObject* AXRenderObject::nextSibling() const
1362 {
1363     if (!m_renderer)
1364         return 0;
1365
1366     RenderObject* nextSibling = 0;
1367
1368     RenderInline* inlineContinuation;
1369     if (m_renderer->isRenderBlock() && (inlineContinuation = toRenderBlock(m_renderer)->inlineElementContinuation())) {
1370         // Case 1: node is a block and has an inline continuation. Next sibling is the inline continuation's first child.
1371         nextSibling = firstChildConsideringContinuation(inlineContinuation);
1372     } else if (m_renderer->isAnonymousBlock() && lastChildHasContinuation(m_renderer)) {
1373         // Case 2: Anonymous block parent of the start of a continuation - skip all the way to
1374         // after the parent of the end, since everything in between will be linked up via the continuation.
1375         RenderObject* lastParent = endOfContinuations(m_renderer->lastChild())->parent();
1376         while (lastChildHasContinuation(lastParent))
1377             lastParent = endOfContinuations(lastParent->lastChild())->parent();
1378         nextSibling = lastParent->nextSibling();
1379     } else if (RenderObject* ns = m_renderer->nextSibling()) {
1380         // Case 3: node has an actual next sibling
1381         nextSibling = ns;
1382     } else if (isInlineWithContinuation(m_renderer)) {
1383         // Case 4: node is an inline with a continuation. Next sibling is the next sibling of the end
1384         // of the continuation chain.
1385         nextSibling = endOfContinuations(m_renderer)->nextSibling();
1386     } else if (isInlineWithContinuation(m_renderer->parent())) {
1387         // Case 5: node has no next sibling, and its parent is an inline with a continuation.
1388         RenderObject* continuation = toRenderInline(m_renderer->parent())->continuation();
1389
1390         if (continuation->isRenderBlock()) {
1391             // Case 5a: continuation is a block - in this case the block itself is the next sibling.
1392             nextSibling = continuation;
1393         } else {
1394             // Case 5b: continuation is an inline - in this case the inline's first child is the next sibling.
1395             nextSibling = firstChildConsideringContinuation(continuation);
1396         }
1397     }
1398
1399     if (!nextSibling)
1400         return 0;
1401
1402     return axObjectCache()->getOrCreate(nextSibling);
1403 }
1404
1405 void AXRenderObject::addChildren()
1406 {
1407     // If the need to add more children in addition to existing children arises,
1408     // childrenChanged should have been called, leaving the object with no children.
1409     ASSERT(!m_haveChildren);
1410
1411     m_haveChildren = true;
1412
1413     if (!canHaveChildren())
1414         return;
1415
1416     for (RefPtr<AXObject> obj = firstChild(); obj; obj = obj->nextSibling())
1417         addChild(obj.get());
1418
1419     addHiddenChildren();
1420     addAttachmentChildren();
1421     addImageMapChildren();
1422     addTextFieldChildren();
1423     addCanvasChildren();
1424     addRemoteSVGChildren();
1425     addInlineTextBoxChildren();
1426 }
1427
1428 bool AXRenderObject::canHaveChildren() const
1429 {
1430     if (!m_renderer)
1431         return false;
1432
1433     return AXNodeObject::canHaveChildren();
1434 }
1435
1436 void AXRenderObject::updateChildrenIfNecessary()
1437 {
1438     if (needsToUpdateChildren())
1439         clearChildren();
1440
1441     AXObject::updateChildrenIfNecessary();
1442 }
1443
1444 void AXRenderObject::clearChildren()
1445 {
1446     AXObject::clearChildren();
1447     m_childrenDirty = false;
1448 }
1449
1450 AXObject* AXRenderObject::observableObject() const
1451 {
1452     // Find the object going up the parent chain that is used in accessibility to monitor certain notifications.
1453     for (RenderObject* renderer = m_renderer; renderer && renderer->node(); renderer = renderer->parent()) {
1454         if (renderObjectIsObservable(renderer))
1455             return axObjectCache()->getOrCreate(renderer);
1456     }
1457
1458     return 0;
1459 }
1460
1461 //
1462 // Properties of the object's owning document or page.
1463 //
1464
1465 double AXRenderObject::estimatedLoadingProgress() const
1466 {
1467     if (!m_renderer)
1468         return 0;
1469
1470     if (isLoaded())
1471         return 1.0;
1472
1473     if (Page* page = m_renderer->document().page())
1474         return page->progress().estimatedProgress();
1475     return 0;
1476 }
1477
1478 //
1479 // DOM and Render tree access.
1480 //
1481
1482 Node* AXRenderObject::node() const
1483 {
1484     return m_renderer ? m_renderer->node() : 0;
1485 }
1486
1487 Document* AXRenderObject::document() const
1488 {
1489     if (!m_renderer)
1490         return 0;
1491     return &m_renderer->document();
1492 }
1493
1494 FrameView* AXRenderObject::documentFrameView() const
1495 {
1496     if (!m_renderer)
1497         return 0;
1498
1499     // this is the RenderObject's Document's Frame's FrameView
1500     return m_renderer->document().view();
1501 }
1502
1503 Element* AXRenderObject::anchorElement() const
1504 {
1505     if (!m_renderer)
1506         return 0;
1507
1508     AXObjectCache* cache = axObjectCache();
1509     RenderObject* currRenderer;
1510
1511     // Search up the render tree for a RenderObject with a DOM node. Defer to an earlier continuation, though.
1512     for (currRenderer = m_renderer; currRenderer && !currRenderer->node(); currRenderer = currRenderer->parent()) {
1513         if (currRenderer->isAnonymousBlock()) {
1514             RenderObject* continuation = toRenderBlock(currRenderer)->continuation();
1515             if (continuation)
1516                 return cache->getOrCreate(continuation)->anchorElement();
1517         }
1518     }
1519
1520     // bail if none found
1521     if (!currRenderer)
1522         return 0;
1523
1524     // search up the DOM tree for an anchor element
1525     // NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElement
1526     Node* node = currRenderer->node();
1527     for ( ; node; node = node->parentNode()) {
1528         if (node->hasTagName(aTag) || (node->renderer() && cache->getOrCreate(node->renderer())->isAnchor()))
1529             return toElement(node);
1530     }
1531
1532     return 0;
1533 }
1534
1535 Widget* AXRenderObject::widgetForAttachmentView() const
1536 {
1537     if (!isAttachment())
1538         return 0;
1539     return toRenderWidget(m_renderer)->widget();
1540 }
1541
1542 //
1543 // Selected text.
1544 //
1545
1546 AXObject::PlainTextRange AXRenderObject::selectedTextRange() const
1547 {
1548     ASSERT(isTextControl());
1549
1550     if (isPasswordField())
1551         return PlainTextRange();
1552
1553     AccessibilityRole ariaRole = ariaRoleAttribute();
1554     if (isNativeTextControl() && ariaRole == UnknownRole && m_renderer->isTextControl()) {
1555         HTMLTextFormControlElement* textControl = toRenderTextControl(m_renderer)->textFormControlElement();
1556         return PlainTextRange(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart());
1557     }
1558
1559     if (ariaRole == UnknownRole)
1560         return PlainTextRange();
1561
1562     return ariaSelectedTextRange();
1563 }
1564
1565 VisibleSelection AXRenderObject::selection() const
1566 {
1567     return m_renderer->frame()->selection().selection();
1568 }
1569
1570 //
1571 // Modify or take an action on an object.
1572 //
1573
1574 void AXRenderObject::setSelectedTextRange(const PlainTextRange& range)
1575 {
1576     if (isNativeTextControl() && m_renderer->isTextControl()) {
1577         HTMLTextFormControlElement* textControl = toRenderTextControl(m_renderer)->textFormControlElement();
1578         textControl->setSelectionRange(range.start, range.start + range.length);
1579         return;
1580     }
1581
1582     Document& document = m_renderer->document();
1583     Frame* frame = document.frame();
1584     if (!frame)
1585         return;
1586     Node* node = m_renderer->node();
1587     frame->selection().setSelection(VisibleSelection(Position(node, range.start, Position::PositionIsOffsetInAnchor),
1588         Position(node, range.start + range.length, Position::PositionIsOffsetInAnchor), DOWNSTREAM));
1589 }
1590
1591 void AXRenderObject::setValue(const String& string)
1592 {
1593     if (!node() || !node()->isElementNode())
1594         return;
1595     if (!m_renderer || !m_renderer->isBoxModelObject())
1596         return;
1597
1598     RenderBoxModelObject* renderer = toRenderBoxModelObject(m_renderer);
1599     if (renderer->isTextField() && node()->hasTagName(inputTag)) {
1600         toHTMLInputElement(node())->setValue(string);
1601     } else if (renderer->isTextArea() && node()->hasTagName(textareaTag)) {
1602         toHTMLTextAreaElement(node())->setValue(string);
1603     }
1604 }
1605
1606 // FIXME: This function should use an IntSize to avoid the conversion below.
1607 void AXRenderObject::scrollTo(const IntPoint& point) const
1608 {
1609     if (!m_renderer || !m_renderer->isBox())
1610         return;
1611
1612     RenderBox* box = toRenderBox(m_renderer);
1613     if (!box->canBeScrolledAndHasScrollableArea())
1614         return;
1615
1616     box->scrollToOffset(IntSize(point.x(), point.y()));
1617 }
1618
1619 //
1620 // Notifications that this object may have changed.
1621 //
1622
1623 void AXRenderObject::handleActiveDescendantChanged()
1624 {
1625     Element* element = toElement(renderer()->node());
1626     if (!element)
1627         return;
1628     Document& doc = renderer()->document();
1629     if (!doc.frame()->selection().isFocusedAndActive() || doc.focusedElement() != element)
1630         return;
1631     AXRenderObject* activedescendant = toAXRenderObject(activeDescendant());
1632
1633     if (activedescendant && shouldNotifyActiveDescendant())
1634         doc.axObjectCache()->postNotification(m_renderer, AXObjectCache::AXActiveDescendantChanged, true);
1635 }
1636
1637 void AXRenderObject::handleAriaExpandedChanged()
1638 {
1639     // Find if a parent of this object should handle aria-expanded changes.
1640     AXObject* containerParent = this->parentObject();
1641     while (containerParent) {
1642         bool foundParent = false;
1643
1644         switch (containerParent->roleValue()) {
1645         case TreeRole:
1646         case TreeGridRole:
1647         case GridRole:
1648         case TableRole:
1649         case BrowserRole:
1650             foundParent = true;
1651             break;
1652         default:
1653             break;
1654         }
1655
1656         if (foundParent)
1657             break;
1658
1659         containerParent = containerParent->parentObject();
1660     }
1661
1662     // Post that the row count changed.
1663     if (containerParent)
1664         axObjectCache()->postNotification(containerParent, document(), AXObjectCache::AXRowCountChanged, true);
1665
1666     // Post that the specific row either collapsed or expanded.
1667     if (roleValue() == RowRole || roleValue() == TreeItemRole)
1668         axObjectCache()->postNotification(this, document(), isExpanded() ? AXObjectCache::AXRowExpanded : AXObjectCache::AXRowCollapsed, true);
1669 }
1670
1671 void AXRenderObject::textChanged()
1672 {
1673     if (!m_renderer)
1674         return;
1675
1676     if (AXObjectCache::inlineTextBoxAccessibility() && roleValue() == StaticTextRole)
1677         childrenChanged();
1678
1679     // Do this last - AXNodeObject::textChanged posts live region announcements,
1680     // and we should update the inline text boxes first.
1681     AXNodeObject::textChanged();
1682 }
1683
1684 //
1685 // Text metrics. Most of these should be deprecated, needs major cleanup.
1686 //
1687
1688 // NOTE: Consider providing this utility method as AX API
1689 int AXRenderObject::index(const VisiblePosition& position) const
1690 {
1691     if (position.isNull() || !isTextControl())
1692         return -1;
1693
1694     if (renderObjectContainsPosition(m_renderer, position.deepEquivalent()))
1695         return indexForVisiblePosition(position);
1696
1697     return -1;
1698 }
1699
1700 VisiblePosition AXRenderObject::visiblePositionForIndex(int index) const
1701 {
1702     if (!m_renderer)
1703         return VisiblePosition();
1704
1705     if (isNativeTextControl() && m_renderer->isTextControl())
1706         return toRenderTextControl(m_renderer)->textFormControlElement()->visiblePositionForIndex(index);
1707
1708     if (!allowsTextRanges() && !m_renderer->isText())
1709         return VisiblePosition();
1710
1711     Node* node = m_renderer->node();
1712     if (!node)
1713         return VisiblePosition();
1714
1715     if (index <= 0)
1716         return VisiblePosition(firstPositionInOrBeforeNode(node), DOWNSTREAM);
1717
1718     RefPtr<Range> range = Range::create(m_renderer->document());
1719     range->selectNodeContents(node, IGNORE_EXCEPTION);
1720     CharacterIterator it(range.get());
1721     it.advance(index - 1);
1722     return VisiblePosition(Position(it.range()->endContainer(), it.range()->endOffset(), Position::PositionIsOffsetInAnch\
1723 or), UPSTREAM);
1724 }
1725
1726 int AXRenderObject::indexForVisiblePosition(const VisiblePosition& pos) const
1727 {
1728     if (isNativeTextControl() && m_renderer->isTextControl()) {
1729         HTMLTextFormControlElement* textControl = toRenderTextControl(m_renderer)->textFormControlElement();
1730         return textControl->indexForVisiblePosition(pos);
1731     }
1732
1733     if (!isTextControl())
1734         return 0;
1735
1736     Node* node = m_renderer->node();
1737     if (!node)
1738         return 0;
1739
1740     Position indexPosition = pos.deepEquivalent();
1741     if (indexPosition.isNull() || highestEditableRoot(indexPosition, HasEditableAXRole) != node)
1742         return 0;
1743
1744     RefPtr<Range> range = Range::create(m_renderer->document());
1745     range->setStart(node, 0, IGNORE_EXCEPTION);
1746     range->setEnd(indexPosition, IGNORE_EXCEPTION);
1747
1748     return TextIterator::rangeLength(range.get());
1749 }
1750
1751 void AXRenderObject::addInlineTextBoxChildren()
1752 {
1753     if (!axObjectCache()->inlineTextBoxAccessibility())
1754         return;
1755
1756     if (!renderer() || !renderer()->isText())
1757         return;
1758
1759     RenderText* renderText = toRenderText(renderer());
1760     if (renderText->needsLayout())
1761         renderText->document().updateLayoutIgnorePendingStylesheets();
1762
1763     for (RefPtr<AbstractInlineTextBox> box = renderText->firstAbstractInlineTextBox(); box.get(); box = box->nextInlineTextBox()) {
1764         AXObject* axObject = axObjectCache()->getOrCreate(box.get());
1765         if (!axObject->accessibilityIsIgnored())
1766             m_children.append(axObject);
1767     }
1768 }
1769
1770 void AXRenderObject::lineBreaks(Vector<int>& lineBreaks) const
1771 {
1772     if (!isTextControl())
1773         return;
1774
1775     VisiblePosition visiblePos = visiblePositionForIndex(0);
1776     VisiblePosition savedVisiblePos = visiblePos;
1777     visiblePos = nextLinePosition(visiblePos, 0);
1778     while (!visiblePos.isNull() && visiblePos != savedVisiblePos) {
1779         lineBreaks.append(indexForVisiblePosition(visiblePos));
1780         savedVisiblePos = visiblePos;
1781         visiblePos = nextLinePosition(visiblePos, 0);
1782     }
1783 }
1784
1785 //
1786 // Private.
1787 //
1788
1789 bool AXRenderObject::isAllowedChildOfTree() const
1790 {
1791     // Determine if this is in a tree. If so, we apply special behavior to make it work like an AXOutline.
1792     AXObject* axObj = parentObject();
1793     bool isInTree = false;
1794     while (axObj) {
1795         if (axObj->isTree()) {
1796             isInTree = true;
1797             break;
1798         }
1799         axObj = axObj->parentObject();
1800     }
1801
1802     // If the object is in a tree, only tree items should be exposed (and the children of tree items).
1803     if (isInTree) {
1804         AccessibilityRole role = roleValue();
1805         if (role != TreeItemRole && role != StaticTextRole)
1806             return false;
1807     }
1808     return true;
1809 }
1810
1811 void AXRenderObject::ariaListboxSelectedChildren(AccessibilityChildrenVector& result)
1812 {
1813     bool isMulti = isMultiSelectable();
1814
1815     AccessibilityChildrenVector childObjects = children();
1816     unsigned childrenSize = childObjects.size();
1817     for (unsigned k = 0; k < childrenSize; ++k) {
1818         // Every child should have aria-role option, and if so, check for selected attribute/state.
1819         AXObject* child = childObjects[k].get();
1820         if (child->isSelected() && child->ariaRoleAttribute() == ListBoxOptionRole) {
1821             result.append(child);
1822             if (!isMulti)
1823                 return;
1824         }
1825     }
1826 }
1827
1828 AXObject::PlainTextRange AXRenderObject::ariaSelectedTextRange() const
1829 {
1830     Node* node = m_renderer->node();
1831     if (!node)
1832         return PlainTextRange();
1833
1834     VisibleSelection visibleSelection = selection();
1835     RefPtr<Range> currentSelectionRange = visibleSelection.toNormalizedRange();
1836     if (!currentSelectionRange || !currentSelectionRange->intersectsNode(node, IGNORE_EXCEPTION))
1837         return PlainTextRange();
1838
1839     int start = indexForVisiblePosition(visibleSelection.start());
1840     int end = indexForVisiblePosition(visibleSelection.end());
1841
1842     return PlainTextRange(start, end - start);
1843 }
1844
1845 bool AXRenderObject::nodeIsTextControl(const Node* node) const
1846 {
1847     if (!node)
1848         return false;
1849
1850     const AXObject* axObjectForNode = axObjectCache()->getOrCreate(const_cast<Node*>(node));
1851     if (!axObjectForNode)
1852         return false;
1853
1854     return axObjectForNode->isTextControl();
1855 }
1856
1857 bool AXRenderObject::isTabItemSelected() const
1858 {
1859     if (!isTabItem() || !m_renderer)
1860         return false;
1861
1862     Node* node = m_renderer->node();
1863     if (!node || !node->isElementNode())
1864         return false;
1865
1866     // The ARIA spec says a tab item can also be selected if it is aria-labeled by a tabpanel
1867     // that has keyboard focus inside of it, or if a tabpanel in its aria-controls list has KB
1868     // focus inside of it.
1869     AXObject* focusedElement = focusedUIElement();
1870     if (!focusedElement)
1871         return false;
1872
1873     Vector<Element*> elements;
1874     elementsFromAttribute(elements, aria_controlsAttr);
1875
1876     unsigned count = elements.size();
1877     for (unsigned k = 0; k < count; ++k) {
1878         Element* element = elements[k];
1879         AXObject* tabPanel = axObjectCache()->getOrCreate(element);
1880
1881         // A tab item should only control tab panels.
1882         if (!tabPanel || tabPanel->roleValue() != TabPanelRole)
1883             continue;
1884
1885         AXObject* checkFocusElement = focusedElement;
1886         // Check if the focused element is a descendant of the element controlled by the tab item.
1887         while (checkFocusElement) {
1888             if (tabPanel == checkFocusElement)
1889                 return true;
1890             checkFocusElement = checkFocusElement->parentObject();
1891         }
1892     }
1893
1894     return false;
1895 }
1896
1897 AXObject* AXRenderObject::internalLinkElement() const
1898 {
1899     Element* element = anchorElement();
1900     if (!element)
1901         return 0;
1902
1903     // Right now, we do not support ARIA links as internal link elements
1904     if (!element->hasTagName(aTag))
1905         return 0;
1906     HTMLAnchorElement* anchor = toHTMLAnchorElement(element);
1907
1908     KURL linkURL = anchor->href();
1909     String fragmentIdentifier = linkURL.fragmentIdentifier();
1910     if (fragmentIdentifier.isEmpty())
1911         return 0;
1912
1913     // check if URL is the same as current URL
1914     KURL documentURL = m_renderer->document().url();
1915     if (!equalIgnoringFragmentIdentifier(documentURL, linkURL))
1916         return 0;
1917
1918     Node* linkedNode = m_renderer->document().findAnchor(fragmentIdentifier);
1919     if (!linkedNode)
1920         return 0;
1921
1922     // The element we find may not be accessible, so find the first accessible object.
1923     return firstAccessibleObjectFromNode(linkedNode);
1924 }
1925
1926 AXObject* AXRenderObject::accessibilityImageMapHitTest(HTMLAreaElement* area, const IntPoint& point) const
1927 {
1928     if (!area)
1929         return 0;
1930
1931     AXObject* parent = axObjectCache()->getOrCreate(area->imageElement());
1932     if (!parent)
1933         return 0;
1934
1935     AXObject::AccessibilityChildrenVector children = parent->children();
1936     unsigned count = children.size();
1937     for (unsigned k = 0; k < count; ++k) {
1938         if (children[k]->elementRect().contains(point))
1939             return children[k].get();
1940     }
1941
1942     return 0;
1943 }
1944
1945 bool AXRenderObject::renderObjectIsObservable(RenderObject* renderer) const
1946 {
1947     // AX clients will listen for AXValueChange on a text control.
1948     if (renderer->isTextControl())
1949         return true;
1950
1951     // AX clients will listen for AXSelectedChildrenChanged on listboxes.
1952     Node* node = renderer->node();
1953     if (nodeHasRole(node, "listbox") || (renderer->isBoxModelObject() && toRenderBoxModelObject(renderer)->isListBox()))
1954         return true;
1955
1956     // Textboxes should send out notifications.
1957     if (nodeHasRole(node, "textbox"))
1958         return true;
1959
1960     return false;
1961 }
1962
1963 RenderObject* AXRenderObject::renderParentObject() const
1964 {
1965     if (!m_renderer)
1966         return 0;
1967
1968     RenderObject* parent = m_renderer->parent();
1969
1970     RenderObject* startOfConts = 0;
1971     RenderObject* firstChild = 0;
1972     if (m_renderer->isRenderBlock() && (startOfConts = startOfContinuations(m_renderer))) {
1973         // Case 1: node is a block and is an inline's continuation. Parent
1974         // is the start of the continuation chain.
1975         parent = startOfConts;
1976     } else if (parent && parent->isRenderInline() && (startOfConts = startOfContinuations(parent))) {
1977         // Case 2: node's parent is an inline which is some node's continuation; parent is
1978         // the earliest node in the continuation chain.
1979         parent = startOfConts;
1980     } else if (parent && (firstChild = parent->firstChild()) && firstChild->node()) {
1981         // Case 3: The first sibling is the beginning of a continuation chain. Find the origin of that continuation.
1982         // Get the node's renderer and follow that continuation chain until the first child is found.
1983         RenderObject* nodeRenderFirstChild = firstChild->node()->renderer();
1984         while (nodeRenderFirstChild != firstChild) {
1985             for (RenderObject* contsTest = nodeRenderFirstChild; contsTest; contsTest = nextContinuation(contsTest)) {
1986                 if (contsTest == firstChild) {
1987                     parent = nodeRenderFirstChild->parent();
1988                     break;
1989                 }
1990             }
1991             if (firstChild == parent->firstChild())
1992                 break;
1993             firstChild = parent->firstChild();
1994             if (!firstChild->node())
1995                 break;
1996             nodeRenderFirstChild = firstChild->node()->renderer();
1997         }
1998     }
1999
2000     return parent;
2001 }
2002
2003 bool AXRenderObject::isDescendantOfElementType(const QualifiedName& tagName) const
2004 {
2005     for (RenderObject* parent = m_renderer->parent(); parent; parent = parent->parent()) {
2006         if (parent->node() && parent->node()->hasTagName(tagName))
2007             return true;
2008     }
2009     return false;
2010 }
2011
2012 bool AXRenderObject::isSVGImage() const
2013 {
2014     return remoteSVGRootElement();
2015 }
2016
2017 void AXRenderObject::detachRemoteSVGRoot()
2018 {
2019     if (AXSVGRoot* root = remoteSVGRootElement())
2020         root->setParent(0);
2021 }
2022
2023 AXSVGRoot* AXRenderObject::remoteSVGRootElement() const
2024 {
2025     if (!m_renderer || !m_renderer->isRenderImage())
2026         return 0;
2027
2028     ImageResource* cachedImage = toRenderImage(m_renderer)->cachedImage();
2029     if (!cachedImage)
2030         return 0;
2031
2032     Image* image = cachedImage->image();
2033     if (!image || !image->isSVGImage())
2034         return 0;
2035
2036     FrameView* frameView = toSVGImage(image)->frameView();
2037     if (!frameView)
2038         return 0;
2039     Document* doc = frameView->frame().document();
2040     if (!doc || !doc->isSVGDocument())
2041         return 0;
2042
2043     SVGSVGElement* rootElement = toSVGDocument(doc)->rootElement();
2044     if (!rootElement)
2045         return 0;
2046     RenderObject* rendererRoot = rootElement->renderer();
2047     if (!rendererRoot)
2048         return 0;
2049
2050     AXObject* rootSVGObject = doc->axObjectCache()->getOrCreate(rendererRoot);
2051
2052     // In order to connect the AX hierarchy from the SVG root element from the loaded resource
2053     // the parent must be set, because there's no other way to get back to who created the image.
2054     ASSERT(rootSVGObject && rootSVGObject->isAXSVGRoot());
2055     if (!rootSVGObject->isAXSVGRoot())
2056         return 0;
2057
2058     return toAXSVGRoot(rootSVGObject);
2059 }
2060
2061 AXObject* AXRenderObject::remoteSVGElementHitTest(const IntPoint& point) const
2062 {
2063     AXObject* remote = remoteSVGRootElement();
2064     if (!remote)
2065         return 0;
2066
2067     IntSize offset = point - roundedIntPoint(elementRect().location());
2068     return remote->accessibilityHitTest(IntPoint(offset));
2069 }
2070
2071 // The boundingBox for elements within the remote SVG element needs to be offset by its position
2072 // within the parent page, otherwise they are in relative coordinates only.
2073 void AXRenderObject::offsetBoundingBoxForRemoteSVGElement(LayoutRect& rect) const
2074 {
2075     for (AXObject* parent = parentObject(); parent; parent = parent->parentObject()) {
2076         if (parent->isAXSVGRoot()) {
2077             rect.moveBy(parent->parentObject()->elementRect().location());
2078             break;
2079         }
2080     }
2081 }
2082
2083 // Hidden children are those that are not rendered or visible, but are specifically marked as aria-hidden=false,
2084 // meaning that they should be exposed to the AX hierarchy.
2085 void AXRenderObject::addHiddenChildren()
2086 {
2087     Node* node = this->node();
2088     if (!node)
2089         return;
2090
2091     // First do a quick run through to determine if we have any hidden nodes (most often we will not).
2092     // If we do have hidden nodes, we need to determine where to insert them so they match DOM order as close as possible.
2093     bool shouldInsertHiddenNodes = false;
2094     for (Node* child = node->firstChild(); child; child = child->nextSibling()) {
2095         if (!child->renderer() && isNodeAriaVisible(child)) {
2096             shouldInsertHiddenNodes = true;
2097             break;
2098         }
2099     }
2100
2101     if (!shouldInsertHiddenNodes)
2102         return;
2103
2104     // Iterate through all of the children, including those that may have already been added, and
2105     // try to insert hidden nodes in the correct place in the DOM order.
2106     unsigned insertionIndex = 0;
2107     for (Node* child = node->firstChild(); child; child = child->nextSibling()) {
2108         if (child->renderer()) {
2109             // Find out where the last render sibling is located within m_children.
2110             AXObject* childObject = axObjectCache()->get(child->renderer());
2111             if (childObject && childObject->accessibilityIsIgnored()) {
2112                 AccessibilityChildrenVector children = childObject->children();
2113                 if (children.size())
2114                     childObject = children.last().get();
2115                 else
2116                     childObject = 0;
2117             }
2118
2119             if (childObject)
2120                 insertionIndex = m_children.find(childObject) + 1;
2121             continue;
2122         }
2123
2124         if (!isNodeAriaVisible(child))
2125             continue;
2126
2127         unsigned previousSize = m_children.size();
2128         if (insertionIndex > previousSize)
2129             insertionIndex = previousSize;
2130
2131         insertChild(axObjectCache()->getOrCreate(child), insertionIndex);
2132         insertionIndex += (m_children.size() - previousSize);
2133     }
2134 }
2135
2136 void AXRenderObject::addTextFieldChildren()
2137 {
2138     Node* node = this->node();
2139     if (!node || !node->hasTagName(inputTag))
2140         return;
2141
2142     HTMLInputElement* input = toHTMLInputElement(node);
2143     Element* spinButtonElement = input->userAgentShadowRoot()->getElementById(ShadowElementNames::spinButton());
2144     if (!spinButtonElement || !spinButtonElement->isSpinButtonElement())
2145         return;
2146
2147     AXSpinButton* axSpinButton = toAXSpinButton(axObjectCache()->getOrCreate(SpinButtonRole));
2148     axSpinButton->setSpinButtonElement(toSpinButtonElement(spinButtonElement));
2149     axSpinButton->setParent(this);
2150     m_children.append(axSpinButton);
2151 }
2152
2153 void AXRenderObject::addImageMapChildren()
2154 {
2155     RenderBoxModelObject* cssBox = renderBoxModelObject();
2156     if (!cssBox || !cssBox->isRenderImage())
2157         return;
2158
2159     HTMLMapElement* map = toRenderImage(cssBox)->imageMap();
2160     if (!map)
2161         return;
2162
2163     for (Element* current = ElementTraversal::firstWithin(*map); current; current = ElementTraversal::next(*current, map)) {
2164         // add an <area> element for this child if it has a link
2165         if (current->hasTagName(areaTag) && current->isLink()) {
2166             AXImageMapLink* areaObject = toAXImageMapLink(axObjectCache()->getOrCreate(ImageMapLinkRole));
2167             areaObject->setHTMLAreaElement(toHTMLAreaElement(current));
2168             areaObject->setHTMLMapElement(map);
2169             areaObject->setParent(this);
2170             if (!areaObject->accessibilityIsIgnored())
2171                 m_children.append(areaObject);
2172             else
2173                 axObjectCache()->remove(areaObject->axObjectID());
2174         }
2175     }
2176 }
2177
2178 void AXRenderObject::addCanvasChildren()
2179 {
2180     if (!node() || !node()->hasTagName(canvasTag))
2181         return;
2182
2183     // If it's a canvas, it won't have rendered children, but it might have accessible fallback content.
2184     // Clear m_haveChildren because AXNodeObject::addChildren will expect it to be false.
2185     ASSERT(!m_children.size());
2186     m_haveChildren = false;
2187     AXNodeObject::addChildren();
2188 }
2189
2190 void AXRenderObject::addAttachmentChildren()
2191 {
2192     if (!isAttachment())
2193         return;
2194
2195     // FrameView's need to be inserted into the AX hierarchy when encountered.
2196     Widget* widget = widgetForAttachmentView();
2197     if (!widget || !widget->isFrameView())
2198         return;
2199
2200     AXObject* axWidget = axObjectCache()->getOrCreate(widget);
2201     if (!axWidget->accessibilityIsIgnored())
2202         m_children.append(axWidget);
2203 }
2204
2205 void AXRenderObject::addRemoteSVGChildren()
2206 {
2207     AXSVGRoot* root = remoteSVGRootElement();
2208     if (!root)
2209         return;
2210
2211     root->setParent(this);
2212
2213     if (root->accessibilityIsIgnored()) {
2214         AccessibilityChildrenVector children = root->children();
2215         unsigned length = children.size();
2216         for (unsigned i = 0; i < length; ++i)
2217             m_children.append(children[i]);
2218     } else {
2219         m_children.append(root);
2220     }
2221 }
2222
2223 void AXRenderObject::ariaSelectedRows(AccessibilityChildrenVector& result)
2224 {
2225     // Get all the rows.
2226     AccessibilityChildrenVector allRows;
2227     if (isTree())
2228         ariaTreeRows(allRows);
2229     else if (isAXTable() && toAXTable(this)->supportsSelectedRows())
2230         allRows = toAXTable(this)->rows();
2231
2232     // Determine which rows are selected.
2233     bool isMulti = isMultiSelectable();
2234
2235     // Prefer active descendant over aria-selected.
2236     AXObject* activeDesc = activeDescendant();
2237     if (activeDesc && (activeDesc->isTreeItem() || activeDesc->isTableRow())) {
2238         result.append(activeDesc);
2239         if (!isMulti)
2240             return;
2241     }
2242
2243     unsigned count = allRows.size();
2244     for (unsigned k = 0; k < count; ++k) {
2245         if (allRows[k]->isSelected()) {
2246             result.append(allRows[k]);
2247             if (!isMulti)
2248                 break;
2249         }
2250     }
2251 }
2252
2253 bool AXRenderObject::elementAttributeValue(const QualifiedName& attributeName) const
2254 {
2255     if (!m_renderer)
2256         return false;
2257
2258     return equalIgnoringCase(getAttribute(attributeName), "true");
2259 }
2260
2261 bool AXRenderObject::inheritsPresentationalRole() const
2262 {
2263     // ARIA states if an item can get focus, it should not be presentational.
2264     if (canSetFocusAttribute())
2265         return false;
2266
2267     // ARIA spec says that when a parent object is presentational, and it has required child elements,
2268     // those child elements are also presentational. For example, <li> becomes presentational from <ul>.
2269     // http://www.w3.org/WAI/PF/aria/complete#presentation
2270     if (roleValue() != ListItemRole && roleValue() != ListMarkerRole)
2271         return false;
2272
2273     AXObject* parent = parentObject();
2274     if (!parent->isAXRenderObject())
2275         return false;
2276
2277     Node* elementNode = toAXRenderObject(parent)->node();
2278     if (!elementNode || !elementNode->isElementNode())
2279         return false;
2280
2281     QualifiedName tagName = toElement(elementNode)->tagQName();
2282     if (tagName == ulTag || tagName == olTag || tagName == dlTag)
2283         return parent->roleValue() == PresentationalRole;
2284
2285     return false;
2286 }
2287
2288 LayoutRect AXRenderObject::computeElementRect() const
2289 {
2290     RenderObject* obj = m_renderer;
2291
2292     if (!obj)
2293         return LayoutRect();
2294
2295     if (obj->node()) // If we are a continuation, we want to make sure to use the primary renderer.
2296         obj = obj->node()->renderer();
2297
2298     // absoluteFocusRingQuads will query the hierarchy below this element, which for large webpages can be very slow.
2299     // For a web area, which will have the most elements of any element, absoluteQuads should be used.
2300     // We should also use absoluteQuads for SVG elements, otherwise transforms won't be applied.
2301     Vector<FloatQuad> quads;
2302
2303     if (obj->isText())
2304         toRenderText(obj)->absoluteQuads(quads, 0, RenderText::ClipToEllipsis);
2305     else if (isWebArea() || obj->isSVGRoot())
2306         obj->absoluteQuads(quads);
2307     else
2308         obj->absoluteFocusRingQuads(quads);
2309
2310     LayoutRect result = boundingBoxForQuads(obj, quads);
2311
2312     Document* document = this->document();
2313     if (document && document->isSVGDocument())
2314         offsetBoundingBoxForRemoteSVGElement(result);
2315
2316     // The size of the web area should be the content size, not the clipped size.
2317     if (isWebArea() && obj->frame()->view())
2318         result.setSize(obj->frame()->view()->contentsSize());
2319
2320     // Checkboxes and radio buttons include their label as part of their rect.
2321     if (isCheckboxOrRadio()) {
2322         HTMLLabelElement* label = labelForElement(toElement(m_renderer->node()));
2323         if (label && label->renderer()) {
2324             LayoutRect labelRect = axObjectCache()->getOrCreate(label)->elementRect();
2325             result.unite(labelRect);
2326         }
2327     }
2328
2329     return result;
2330 }
2331
2332 } // namespace WebCore