WK2: Support Accessibility
[WebKit-https.git] / WebCore / accessibility / AccessibilityRenderObject.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 "AccessibilityRenderObject.h"
31
32 #include "AXObjectCache.h"
33 #include "AccessibilityImageMapLink.h"
34 #include "AccessibilityListBox.h"
35 #include "CharacterNames.h"
36 #include "EventNames.h"
37 #include "FloatRect.h"
38 #include "Frame.h"
39 #include "FrameLoader.h"
40 #include "HTMLAreaElement.h"
41 #include "HTMLFormElement.h"
42 #include "HTMLFrameElementBase.h"
43 #include "HTMLImageElement.h"
44 #include "HTMLInputElement.h"
45 #include "HTMLLabelElement.h"
46 #include "HTMLMapElement.h"
47 #include "HTMLOptGroupElement.h"
48 #include "HTMLOptionElement.h"
49 #include "HTMLOptionsCollection.h"
50 #include "HTMLSelectElement.h"
51 #include "HTMLTextAreaElement.h"
52 #include "HitTestRequest.h"
53 #include "HitTestResult.h"
54 #include "LocalizedStrings.h"
55 #include "NodeList.h"
56 #include "ProgressTracker.h"
57 #include "RenderButton.h"
58 #include "RenderFieldset.h"
59 #include "RenderFileUploadControl.h"
60 #include "RenderHTMLCanvas.h"
61 #include "RenderImage.h"
62 #include "RenderInline.h"
63 #include "RenderLayer.h"
64 #include "RenderListBox.h"
65 #include "RenderListMarker.h"
66 #include "RenderMenuList.h"
67 #include "RenderText.h"
68 #include "RenderTextControl.h"
69 #include "RenderTextFragment.h"
70 #include "RenderTheme.h"
71 #include "RenderView.h"
72 #include "RenderWidget.h"
73 #include "SelectElement.h"
74 #include "SelectionController.h"
75 #include "Text.h"
76 #include "TextIterator.h"
77 #include "htmlediting.h"
78 #include "visible_units.h"
79 #include <wtf/StdLibExtras.h>
80
81 using namespace std;
82
83 namespace WebCore {
84
85 using namespace HTMLNames;
86
87 AccessibilityRenderObject::AccessibilityRenderObject(RenderObject* renderer)
88     : AccessibilityObject()
89     , m_renderer(renderer)
90     , m_ariaRole(UnknownRole)
91     , m_childrenDirty(false)
92     , m_roleForMSAA(UnknownRole)
93 {
94     m_role = determineAccessibilityRole();
95     
96 #ifndef NDEBUG
97     m_renderer->setHasAXObject(true);
98 #endif
99 }
100
101 AccessibilityRenderObject::~AccessibilityRenderObject()
102 {
103     ASSERT(isDetached());
104 }
105
106 PassRefPtr<AccessibilityRenderObject> AccessibilityRenderObject::create(RenderObject* renderer)
107 {
108     return adoptRef(new AccessibilityRenderObject(renderer));
109 }
110
111 void AccessibilityRenderObject::detach()
112 {
113     clearChildren();
114     AccessibilityObject::detach();
115     
116 #ifndef NDEBUG
117     if (m_renderer)
118         m_renderer->setHasAXObject(false);
119 #endif
120     m_renderer = 0;    
121 }
122
123 RenderBoxModelObject* AccessibilityRenderObject::renderBoxModelObject() const
124 {
125     if (!m_renderer || !m_renderer->isBoxModelObject())
126         return 0;
127     return toRenderBoxModelObject(m_renderer);
128 }
129
130 static inline bool isInlineWithContinuation(RenderObject* object)
131 {
132     if (!object->isBoxModelObject())
133         return false;
134
135     RenderBoxModelObject* renderer = toRenderBoxModelObject(object);
136     if (!renderer->isRenderInline())
137         return false;
138
139     return toRenderInline(renderer)->continuation();
140 }
141
142 static inline RenderObject* firstChildInContinuation(RenderObject* renderer)
143 {
144     RenderObject* r = toRenderInline(renderer)->continuation();
145
146     while (r) {
147         if (r->isRenderBlock())
148             return r;
149         if (RenderObject* child = r->firstChild())
150             return child;
151         r = toRenderInline(r)->continuation(); 
152     }
153
154     return 0;
155 }
156
157 static inline RenderObject* firstChildConsideringContinuation(RenderObject* renderer)
158 {
159     RenderObject* firstChild = renderer->firstChild();
160
161     if (!firstChild && isInlineWithContinuation(renderer))
162         firstChild = firstChildInContinuation(renderer);
163
164     return firstChild;
165 }
166
167
168 static inline RenderObject* lastChildConsideringContinuation(RenderObject* renderer)
169 {
170     RenderObject* lastChild = renderer->lastChild();
171     RenderObject* prev;
172     RenderObject* cur = renderer;
173
174     if (!cur->isRenderInline() && !cur->isRenderBlock())
175         return renderer;
176
177     while (cur) {
178         prev = cur;
179
180         if (RenderObject* lc = cur->lastChild())
181             lastChild = lc;
182
183         if (cur->isRenderInline()) {
184             cur = toRenderInline(cur)->inlineElementContinuation();
185             ASSERT(cur || !toRenderInline(prev)->continuation());
186         } else
187             cur = toRenderBlock(cur)->inlineElementContinuation();
188     }
189
190     return lastChild;
191 }
192
193 AccessibilityObject* AccessibilityRenderObject::firstChild() const
194 {
195     if (!m_renderer)
196         return 0;
197     
198     RenderObject* firstChild = firstChildConsideringContinuation(m_renderer);
199
200     if (!firstChild)
201         return 0;
202     
203     return axObjectCache()->getOrCreate(firstChild);
204 }
205
206 AccessibilityObject* AccessibilityRenderObject::lastChild() const
207 {
208     if (!m_renderer)
209         return 0;
210
211     RenderObject* lastChild = lastChildConsideringContinuation(m_renderer);
212
213     if (!lastChild)
214         return 0;
215     
216     return axObjectCache()->getOrCreate(lastChild);
217 }
218
219 static inline RenderInline* startOfContinuations(RenderObject* r)
220 {
221     if (r->isInlineElementContinuation())
222         return toRenderInline(r->node()->renderer());
223
224     // Blocks with a previous continuation always have a next continuation
225     if (r->isRenderBlock() && toRenderBlock(r)->inlineElementContinuation())
226         return toRenderInline(toRenderBlock(r)->inlineElementContinuation()->node()->renderer());
227
228     return 0;
229 }
230
231 static inline RenderObject* endOfContinuations(RenderObject* renderer)
232 {
233     RenderObject* prev = renderer;
234     RenderObject* cur = renderer;
235
236     if (!cur->isRenderInline() && !cur->isRenderBlock())
237         return renderer;
238
239     while (cur) {
240         prev = cur;
241         if (cur->isRenderInline()) {
242             cur = toRenderInline(cur)->inlineElementContinuation();
243             ASSERT(cur || !toRenderInline(prev)->continuation());
244         } else 
245             cur = toRenderBlock(cur)->inlineElementContinuation();
246     }
247
248     return prev;
249 }
250
251
252 static inline RenderObject* childBeforeConsideringContinuations(RenderInline* r, RenderObject* child)
253 {
254     RenderBoxModelObject* curContainer = r;
255     RenderObject* cur = 0;
256     RenderObject* prev = 0;
257
258     while (curContainer) {
259         if (curContainer->isRenderInline()) {
260             cur = curContainer->firstChild();
261             while (cur) {
262                 if (cur == child)
263                     return prev;
264                 prev = cur;
265                 cur = cur->nextSibling();
266             }
267
268             curContainer = toRenderInline(curContainer)->continuation();
269         } else if (curContainer->isRenderBlock()) {
270             if (curContainer == child)
271                 return prev;
272
273             prev = curContainer;
274             curContainer = toRenderBlock(curContainer)->inlineElementContinuation();
275         }
276     }
277
278     ASSERT_NOT_REACHED();
279
280     return 0;
281 }
282
283 static inline bool firstChildIsInlineContinuation(RenderObject* renderer)
284 {
285     return renderer->firstChild() && renderer->firstChild()->isInlineElementContinuation();
286 }
287
288 AccessibilityObject* AccessibilityRenderObject::previousSibling() const
289 {
290     if (!m_renderer)
291         return 0;
292
293     RenderObject* previousSibling = 0;
294
295     // Case 1: The node is a block and is an inline's continuation. In that case, the inline's
296     // last child is our previous sibling (or further back in the continuation chain)
297     RenderInline* startOfConts;
298     if (m_renderer->isRenderBlock() && (startOfConts = startOfContinuations(m_renderer)))
299         previousSibling = childBeforeConsideringContinuations(startOfConts, m_renderer);
300
301     // Case 2: Anonymous block parent of the end of a continuation - skip all the way to before
302     // the parent of the start, since everything in between will be linked up via the continuation.
303     else if (m_renderer->isAnonymousBlock() && firstChildIsInlineContinuation(m_renderer))
304         previousSibling = startOfContinuations(m_renderer->firstChild())->parent()->previousSibling();
305
306     // Case 3: The node has an actual previous sibling
307     else if (RenderObject* ps = m_renderer->previousSibling())
308         previousSibling = ps;
309
310     // Case 4: This node has no previous siblings, but its parent is an inline,
311     // and is another node's inline continutation. Follow the continuation chain.
312     else if (m_renderer->parent()->isRenderInline() && (startOfConts = startOfContinuations(m_renderer->parent())))
313         previousSibling = childBeforeConsideringContinuations(startOfConts, m_renderer->parent()->firstChild());
314
315     if (!previousSibling)
316         return 0;
317     
318     return axObjectCache()->getOrCreate(previousSibling);
319 }
320
321 static inline bool lastChildHasContinuation(RenderObject* renderer)
322 {
323     return renderer->lastChild() && isInlineWithContinuation(renderer->lastChild());
324 }
325
326 AccessibilityObject* AccessibilityRenderObject::nextSibling() const
327 {
328     if (!m_renderer)
329         return 0;
330
331     RenderObject* nextSibling = 0;
332
333     // Case 1: node is a block and has an inline continuation. Next sibling is the inline continuation's
334     // first child.
335     RenderInline* inlineContinuation;
336     if (m_renderer->isRenderBlock() && (inlineContinuation = toRenderBlock(m_renderer)->inlineElementContinuation()))
337         nextSibling = firstChildConsideringContinuation(inlineContinuation);
338
339     // Case 2: Anonymous block parent of the start of a continuation - skip all the way to
340     // after the parent of the end, since everything in between will be linked up via the continuation.
341     else if (m_renderer->isAnonymousBlock() && lastChildHasContinuation(m_renderer))
342         nextSibling = endOfContinuations(m_renderer->lastChild())->parent()->nextSibling();
343
344     // Case 3: node has an actual next sibling
345     else if (RenderObject* ns = m_renderer->nextSibling())
346         nextSibling = ns;
347
348     // Case 4: node is an inline with a continuation. Next sibling is the next sibling of the end 
349     // of the continuation chain.
350     else if (isInlineWithContinuation(m_renderer))
351         nextSibling = endOfContinuations(m_renderer)->nextSibling();
352
353     // Case 5: node has no next sibling, and its parent is an inline with a continuation.
354     else if (isInlineWithContinuation(m_renderer->parent())) {
355         RenderObject* continuation = toRenderInline(m_renderer->parent())->continuation();
356         
357         // Case 5a: continuation is a block - in this case the block itself is the next sibling.
358         if (continuation->isRenderBlock())
359             nextSibling = continuation;
360         // Case 5b: continuation is an inline - in this case the inline's first child is the next sibling
361         else
362             nextSibling = firstChildConsideringContinuation(continuation);
363     }
364
365     if (!nextSibling)
366         return 0;
367     
368     return axObjectCache()->getOrCreate(nextSibling);
369 }
370
371 static RenderBoxModelObject* nextContinuation(RenderObject* renderer)
372 {
373     ASSERT(renderer);
374     if (renderer->isRenderInline() && !renderer->isReplaced())
375         return toRenderInline(renderer)->continuation();
376     if (renderer->isRenderBlock())
377         return toRenderBlock(renderer)->inlineElementContinuation();
378     return 0;
379 }
380     
381 RenderObject* AccessibilityRenderObject::renderParentObject() const
382 {
383     if (!m_renderer)
384         return 0;
385
386     RenderObject* parent = m_renderer->parent();
387
388     // Case 1: node is a block and is an inline's continuation. Parent
389     // is the start of the continuation chain.
390     RenderObject* startOfConts = 0;
391     RenderObject* firstChild = 0;
392     if (m_renderer->isRenderBlock() && (startOfConts = startOfContinuations(m_renderer)))
393         parent = startOfConts;
394
395     // Case 2: node's parent is an inline which is some node's continuation; parent is 
396     // the earliest node in the continuation chain.
397     else if (parent && parent->isRenderInline() && (startOfConts = startOfContinuations(parent)))
398         parent = startOfConts;
399     
400     // Case 3: The first sibling is the beginning of a continuation chain. Find the origin of that continuation.
401     else if (parent && (firstChild = parent->firstChild()) && firstChild->node()) {
402         // Get the node's renderer and follow that continuation chain until the first child is found
403         RenderObject* nodeRenderFirstChild = firstChild->node()->renderer();
404         if (nodeRenderFirstChild != firstChild) {
405             for (RenderObject* contsTest = nodeRenderFirstChild; contsTest; contsTest = nextContinuation(contsTest)) {
406                 if (contsTest == firstChild) {
407                     parent = nodeRenderFirstChild->parent();
408                     break;
409                 }
410             }
411         }
412     }
413         
414     return parent;
415 }
416     
417 AccessibilityObject* AccessibilityRenderObject::parentObjectIfExists() const
418 {
419     return axObjectCache()->get(renderParentObject());
420 }
421     
422 AccessibilityObject* AccessibilityRenderObject::parentObject() const
423 {
424     if (!m_renderer)
425         return 0;
426     
427     if (ariaRoleAttribute() == MenuBarRole)
428         return axObjectCache()->getOrCreate(m_renderer->parent());
429
430     // menuButton and its corresponding menu are DOM siblings, but Accessibility needs them to be parent/child
431     if (ariaRoleAttribute() == MenuRole) {
432         AccessibilityObject* parent = menuButtonForMenu();
433         if (parent)
434             return parent;
435     }
436     
437     RenderObject* parentObj = renderParentObject();
438     if (parentObj)
439         return axObjectCache()->getOrCreate(parentObj);
440     
441     // WebArea's parent should be the scroll view containing it.
442     if (isWebArea())
443         return axObjectCache()->getOrCreate(m_renderer->frame()->view());
444     
445     return 0;
446 }
447
448 bool AccessibilityRenderObject::isWebArea() const
449 {
450     return roleValue() == WebAreaRole;
451 }
452
453 bool AccessibilityRenderObject::isImageButton() const
454 {
455     return isNativeImage() && roleValue() == ButtonRole;
456 }
457
458 bool AccessibilityRenderObject::isAnchor() const
459 {
460     return !isNativeImage() && isLink();
461 }
462
463 bool AccessibilityRenderObject::isNativeTextControl() const
464 {
465     return m_renderer->isTextControl();
466 }
467     
468 bool AccessibilityRenderObject::isNativeImage() const
469 {
470     return m_renderer->isBoxModelObject() && toRenderBoxModelObject(m_renderer)->isImage();
471 }    
472     
473 bool AccessibilityRenderObject::isImage() const
474 {
475     return roleValue() == ImageRole;
476 }
477
478 bool AccessibilityRenderObject::isAttachment() const
479 {
480     RenderBoxModelObject* renderer = renderBoxModelObject();
481     if (!renderer)
482         return false;
483     // Widgets are the replaced elements that we represent to AX as attachments
484     bool isWidget = renderer->isWidget();
485     ASSERT(!isWidget || (renderer->isReplaced() && !isImage()));
486     return isWidget && ariaRoleAttribute() == UnknownRole;
487 }
488
489 bool AccessibilityRenderObject::isPasswordField() const
490 {
491     ASSERT(m_renderer);
492     if (!m_renderer->node() || !m_renderer->node()->isHTMLElement())
493         return false;
494     if (ariaRoleAttribute() != UnknownRole)
495         return false;
496
497     InputElement* inputElement = toInputElement(static_cast<Element*>(m_renderer->node()));
498     if (!inputElement)
499         return false;
500
501     return inputElement->isPasswordField();
502 }
503     
504 bool AccessibilityRenderObject::isFileUploadButton() const
505 {
506     if (m_renderer && m_renderer->node() && m_renderer->node()->hasTagName(inputTag)) {
507         HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->node());
508         return input->isFileUpload();
509     }
510     
511     return false;
512 }
513     
514 bool AccessibilityRenderObject::isInputImage() const
515 {
516     Node* elementNode = node();
517     if (roleValue() == ButtonRole && elementNode && elementNode->hasTagName(inputTag)) {
518         HTMLInputElement* input = static_cast<HTMLInputElement*>(elementNode);
519         return input->isImageButton();
520     }
521     
522     return false;
523 }
524
525 bool AccessibilityRenderObject::isProgressIndicator() const
526 {
527     return roleValue() == ProgressIndicatorRole;
528 }
529
530 bool AccessibilityRenderObject::isSlider() const
531 {
532     return roleValue() == SliderRole;
533 }
534
535 bool AccessibilityRenderObject::isMenuRelated() const
536 {
537     AccessibilityRole role = roleValue();
538     return role == MenuRole 
539         || role == MenuBarRole
540         || role == MenuButtonRole
541         || role == MenuItemRole;
542 }    
543
544 bool AccessibilityRenderObject::isMenu() const
545 {
546     return roleValue() == MenuRole;
547 }
548
549 bool AccessibilityRenderObject::isMenuBar() const
550 {
551     return roleValue() == MenuBarRole;
552 }
553
554 bool AccessibilityRenderObject::isMenuButton() const
555 {
556     return roleValue() == MenuButtonRole;
557 }
558
559 bool AccessibilityRenderObject::isMenuItem() const
560 {
561     return roleValue() == MenuItemRole;
562 }
563      
564 bool AccessibilityRenderObject::isPressed() const
565 {
566     ASSERT(m_renderer);
567     if (roleValue() != ButtonRole)
568         return false;
569
570     Node* node = m_renderer->node();
571     if (!node)
572         return false;
573
574     // If this is an ARIA button, check the aria-pressed attribute rather than node()->active()
575     if (ariaRoleAttribute() == ButtonRole) {
576         if (equalIgnoringCase(getAttribute(aria_pressedAttr), "true"))
577             return true;
578         return false;
579     }
580
581     return node->active();
582 }
583
584 bool AccessibilityRenderObject::isIndeterminate() const
585 {
586     ASSERT(m_renderer);
587     if (!m_renderer->node() || !m_renderer->node()->isElementNode())
588         return false;
589
590     InputElement* inputElement = toInputElement(static_cast<Element*>(m_renderer->node()));
591     if (!inputElement)
592         return false;
593
594     return inputElement->isIndeterminate();
595 }
596
597 bool AccessibilityRenderObject::isNativeCheckboxOrRadio() const
598 {
599     Node* elementNode = node();
600     if (elementNode && elementNode->isElementNode()) {
601         InputElement* input = toInputElement(static_cast<Element*>(elementNode));
602         if (input)
603             return input->isCheckbox() || input->isRadioButton();
604     }
605     
606     return false;
607 }
608     
609 bool AccessibilityRenderObject::isChecked() const
610 {
611     ASSERT(m_renderer);
612     if (!m_renderer->node() || !m_renderer->node()->isElementNode())
613         return false;
614
615     // First test for native checkedness semantics
616     InputElement* inputElement = toInputElement(static_cast<Element*>(m_renderer->node()));
617     if (inputElement)
618         return inputElement->isChecked();
619
620     // Else, if this is an ARIA checkbox or radio, respect the aria-checked attribute
621     AccessibilityRole ariaRole = ariaRoleAttribute();
622     if (ariaRole == RadioButtonRole || ariaRole == CheckBoxRole) {
623         if (equalIgnoringCase(getAttribute(aria_checkedAttr), "true"))
624             return true;
625         return false;
626     }
627
628     // Otherwise it's not checked
629     return false;
630 }
631
632 bool AccessibilityRenderObject::isHovered() const
633 {
634     ASSERT(m_renderer);
635     return m_renderer->node() && m_renderer->node()->hovered();
636 }
637
638 bool AccessibilityRenderObject::isMultiSelectable() const
639 {
640     ASSERT(m_renderer);
641     
642     const AtomicString& ariaMultiSelectable = getAttribute(aria_multiselectableAttr);
643     if (equalIgnoringCase(ariaMultiSelectable, "true"))
644         return true;
645     if (equalIgnoringCase(ariaMultiSelectable, "false"))
646         return false;
647     
648     if (!m_renderer->isBoxModelObject() || !toRenderBoxModelObject(m_renderer)->isListBox())
649         return false;
650     return m_renderer->node() && static_cast<HTMLSelectElement*>(m_renderer->node())->multiple();
651 }
652     
653 bool AccessibilityRenderObject::isReadOnly() const
654 {
655     ASSERT(m_renderer);
656     
657     if (isWebArea()) {
658         Document* document = m_renderer->document();
659         if (!document)
660             return true;
661         
662         HTMLElement* body = document->body();
663         if (body && body->isContentEditable())
664             return false;
665         
666         Frame* frame = document->frame();
667         if (!frame)
668             return true;
669         
670         return !frame->isContentEditable();
671     }
672
673     if (m_renderer->isBoxModelObject()) {
674         RenderBoxModelObject* box = toRenderBoxModelObject(m_renderer);
675         if (box->isTextField())
676             return static_cast<HTMLInputElement*>(box->node())->readOnly();
677         if (box->isTextArea())
678             return static_cast<HTMLTextAreaElement*>(box->node())->readOnly();
679     }
680
681     return !m_renderer->node() || !m_renderer->node()->isContentEditable();
682 }
683
684 bool AccessibilityRenderObject::isOffScreen() const
685 {
686     ASSERT(m_renderer);
687     IntRect contentRect = m_renderer->absoluteClippedOverflowRect();
688     FrameView* view = m_renderer->frame()->view();
689     FloatRect viewRect = view->visibleContentRect();
690     viewRect.intersect(contentRect);
691     return viewRect.isEmpty();
692 }
693
694 int AccessibilityRenderObject::headingLevel() const
695 {
696     // headings can be in block flow and non-block flow
697     Node* element = node();
698     if (!element)
699         return 0;
700
701     if (ariaRoleAttribute() == HeadingRole)
702         return getAttribute(aria_levelAttr).toInt();
703
704     if (element->hasTagName(h1Tag))
705         return 1;
706     
707     if (element->hasTagName(h2Tag))
708         return 2;
709     
710     if (element->hasTagName(h3Tag))
711         return 3;
712     
713     if (element->hasTagName(h4Tag))
714         return 4;
715     
716     if (element->hasTagName(h5Tag))
717         return 5;
718     
719     if (element->hasTagName(h6Tag))
720         return 6;
721     
722     return 0;
723 }
724
725 bool AccessibilityRenderObject::isHeading() const
726 {
727     return roleValue() == HeadingRole;
728 }
729     
730 bool AccessibilityRenderObject::isLink() const
731 {
732     return roleValue() == WebCoreLinkRole;
733 }    
734     
735 bool AccessibilityRenderObject::isControl() const
736 {
737     if (!m_renderer)
738         return false;
739     
740     Node* node = m_renderer->node();
741     return node && ((node->isElementNode() && static_cast<Element*>(node)->isFormControlElement())
742                     || AccessibilityObject::isARIAControl(ariaRoleAttribute()));
743 }
744
745 bool AccessibilityRenderObject::isFieldset() const
746 {
747     RenderBoxModelObject* renderer = renderBoxModelObject();
748     if (!renderer)
749         return false;
750     return renderer->isFieldset();
751 }
752   
753 bool AccessibilityRenderObject::isGroup() const
754 {
755     return roleValue() == GroupRole;
756 }
757     
758 AccessibilityObject* AccessibilityRenderObject::selectedRadioButton()
759 {
760     if (!isRadioGroup())
761         return 0;
762     
763     // Find the child radio button that is selected (ie. the intValue == 1).
764     int count = m_children.size();
765     for (int i = 0; i < count; ++i) {
766         AccessibilityObject* object = m_children[i].get();
767         if (object->roleValue() == RadioButtonRole && object->checkboxOrRadioValue() == ButtonStateOn)
768             return object;
769     }
770     return 0;
771 }
772
773 AccessibilityObject* AccessibilityRenderObject::selectedTabItem()
774 {
775     if (!isTabList())
776         return 0;
777     
778     // Find the child tab item that is selected (ie. the intValue == 1).
779     AccessibilityObject::AccessibilityChildrenVector tabs;
780     tabChildren(tabs);
781     
782     int count = tabs.size();
783     for (int i = 0; i < count; ++i) {
784         AccessibilityObject* object = m_children[i].get();
785         if (object->isTabItem() && object->isChecked())
786             return object;
787     }
788     return 0;
789 }
790
791 Element* AccessibilityRenderObject::anchorElement() const
792 {
793     if (!m_renderer)
794         return 0;
795     
796     AXObjectCache* cache = axObjectCache();
797     RenderObject* currRenderer;
798     
799     // Search up the render tree for a RenderObject with a DOM node.  Defer to an earlier continuation, though.
800     for (currRenderer = m_renderer; currRenderer && !currRenderer->node(); currRenderer = currRenderer->parent()) {
801         if (currRenderer->isAnonymousBlock()) {
802             RenderObject* continuation = toRenderBlock(currRenderer)->continuation();
803             if (continuation)
804                 return cache->getOrCreate(continuation)->anchorElement();
805         }
806     }
807     
808     // bail if none found
809     if (!currRenderer)
810         return 0;
811     
812     // search up the DOM tree for an anchor element
813     // NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElement
814     Node* node = currRenderer->node();
815     for ( ; node; node = node->parentNode()) {
816         if (node->hasTagName(aTag) || (node->renderer() && cache->getOrCreate(node->renderer())->isAnchor()))
817             return static_cast<Element*>(node);
818     }
819     
820     return 0;
821 }
822
823 Element* AccessibilityRenderObject::actionElement() const
824 {
825     if (!m_renderer)
826         return 0;
827     
828     Node* node = m_renderer->node();
829     if (node) {
830         if (node->hasTagName(inputTag)) {
831             HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
832             if (!input->disabled() && (isCheckboxOrRadio() || input->isTextButton()))
833                 return input;
834         } else if (node->hasTagName(buttonTag))
835             return static_cast<Element*>(node);
836     }
837
838     if (isFileUploadButton())
839         return static_cast<Element*>(m_renderer->node());
840             
841     if (AccessibilityObject::isARIAInput(ariaRoleAttribute()))
842         return static_cast<Element*>(m_renderer->node());
843
844     if (isImageButton())
845         return static_cast<Element*>(m_renderer->node());
846     
847     if (m_renderer->isBoxModelObject() && toRenderBoxModelObject(m_renderer)->isMenuList())
848         return static_cast<Element*>(m_renderer->node());
849
850     AccessibilityRole role = roleValue();
851     if (role == ButtonRole || role == PopUpButtonRole)
852         return static_cast<Element*>(m_renderer->node()); 
853     
854     Element* elt = anchorElement();
855     if (!elt)
856         elt = mouseButtonListener();
857     return elt;
858 }
859
860 Element* AccessibilityRenderObject::mouseButtonListener() const
861 {
862     Node* node = m_renderer->node();
863     if (!node)
864         return 0;
865     
866     // check if our parent is a mouse button listener
867     while (node && !node->isElementNode())
868         node = node->parentNode();
869
870     if (!node)
871         return 0;
872
873     // FIXME: Do the continuation search like anchorElement does
874     for (Element* element = static_cast<Element*>(node); element; element = element->parentElement()) {
875         if (element->getAttributeEventListener(eventNames().clickEvent) || element->getAttributeEventListener(eventNames().mousedownEvent) || element->getAttributeEventListener(eventNames().mouseupEvent))
876             return element;
877     }
878
879     return 0;
880 }
881
882 void AccessibilityRenderObject::increment()
883 {
884     if (roleValue() != SliderRole)
885         return;
886     
887     changeValueByPercent(5);
888 }
889
890 void AccessibilityRenderObject::decrement()
891 {
892     if (roleValue() != SliderRole)
893         return;
894     
895     changeValueByPercent(-5);
896 }
897
898 static Element* siblingWithAriaRole(String role, Node* node)
899 {
900     Node* sibling = node->parentNode()->firstChild();
901     while (sibling) {
902         if (sibling->isElementNode()) {
903             const AtomicString& siblingAriaRole = static_cast<Element*>(sibling)->getAttribute(roleAttr);
904             if (equalIgnoringCase(siblingAriaRole, role))
905                 return static_cast<Element*>(sibling);
906         }
907         sibling = sibling->nextSibling();
908     }
909     
910     return 0;
911 }
912
913 Element* AccessibilityRenderObject::menuElementForMenuButton() const
914 {
915     if (ariaRoleAttribute() != MenuButtonRole)
916         return 0;
917
918     return siblingWithAriaRole("menu", renderer()->node());
919 }
920
921 AccessibilityObject* AccessibilityRenderObject::menuForMenuButton() const
922 {
923     Element* menu = menuElementForMenuButton();
924     if (menu && menu->renderer())
925         return axObjectCache()->getOrCreate(menu->renderer());
926     return 0;
927 }
928
929 Element* AccessibilityRenderObject::menuItemElementForMenu() const
930 {
931     if (ariaRoleAttribute() != MenuRole)
932         return 0;
933     
934     return siblingWithAriaRole("menuitem", renderer()->node());    
935 }
936
937 AccessibilityObject* AccessibilityRenderObject::menuButtonForMenu() const
938 {
939     Element* menuItem = menuItemElementForMenu();
940
941     if (menuItem && menuItem->renderer()) {
942         // ARIA just has generic menu items.  AppKit needs to know if this is a top level items like MenuBarButton or MenuBarItem
943         AccessibilityObject* menuItemAX = axObjectCache()->getOrCreate(menuItem->renderer());
944         if (menuItemAX->isMenuButton())
945             return menuItemAX;
946     }
947     return 0;
948 }
949
950 String AccessibilityRenderObject::helpText() const
951 {
952     if (!m_renderer)
953         return String();
954     
955     const AtomicString& ariaHelp = getAttribute(aria_helpAttr);
956     if (!ariaHelp.isEmpty())
957         return ariaHelp;
958     
959     for (RenderObject* curr = m_renderer; curr; curr = curr->parent()) {
960         if (curr->node() && curr->node()->isHTMLElement()) {
961             const AtomicString& summary = static_cast<Element*>(curr->node())->getAttribute(summaryAttr);
962             if (!summary.isEmpty())
963                 return summary;
964             const AtomicString& title = static_cast<Element*>(curr->node())->getAttribute(titleAttr);
965             if (!title.isEmpty())
966                 return title;
967         }
968         
969         // Only take help text from an ancestor element if its a group or an unknown role. If help was 
970         // added to those kinds of elements, it is likely it was meant for a child element.
971         AccessibilityObject* axObj = axObjectCache()->getOrCreate(curr);
972         if (axObj) {
973             AccessibilityRole role = axObj->roleValue();
974             if (role != GroupRole && role != UnknownRole)
975                 break;
976         }
977     }
978     
979     return String();
980 }
981     
982 unsigned AccessibilityRenderObject::hierarchicalLevel() const
983 {
984     if (!m_renderer)
985         return 0;
986
987     Node* node = m_renderer->node();
988     if (!node || !node->isElementNode())
989         return 0;
990     Element* element = static_cast<Element*>(node);
991     String ariaLevel = element->getAttribute(aria_levelAttr);
992     if (!ariaLevel.isEmpty())
993         return ariaLevel.toInt();
994     
995     // Only tree item will calculate its level through the DOM currently.
996     if (roleValue() != TreeItemRole)
997         return 0;
998     
999     // Hierarchy leveling starts at 0.
1000     // We measure tree hierarchy by the number of groups that the item is within.
1001     unsigned level = 0;
1002     AccessibilityObject* parent = parentObject();
1003     while (parent) {
1004         AccessibilityRole parentRole = parent->roleValue();
1005         if (parentRole == GroupRole)
1006             level++;
1007         else if (parentRole == TreeRole)
1008             break;
1009         
1010         parent = parent->parentObject();
1011     }
1012     
1013     return level;
1014 }
1015
1016 String AccessibilityRenderObject::textUnderElement() const
1017 {
1018     if (!m_renderer)
1019         return String();
1020     
1021     if (isFileUploadButton())
1022         return toRenderFileUploadControl(m_renderer)->buttonValue();
1023     
1024     Node* node = m_renderer->node();
1025     if (node) {
1026         if (Frame* frame = node->document()->frame()) {
1027             // catch stale WebCoreAXObject (see <rdar://problem/3960196>)
1028             if (frame->document() != node->document())
1029                 return String();
1030             return plainText(rangeOfContents(node).get(), TextIteratorIgnoresStyleVisibility);
1031         }
1032     }
1033     
1034     // Sometimes text fragments don't have Node's associated with them (like when
1035     // CSS content is used to insert text).
1036     if (m_renderer->isText()) {
1037         RenderText* renderTextObject = toRenderText(m_renderer);
1038         if (renderTextObject->isTextFragment())
1039             return String(static_cast<RenderTextFragment*>(m_renderer)->contentString());
1040     }
1041     
1042     // return the null string for anonymous text because it is non-trivial to get
1043     // the actual text and, so far, that is not needed
1044     return String();
1045 }
1046
1047 Node* AccessibilityRenderObject::node() const
1048
1049     return m_renderer ? m_renderer->node() : 0; 
1050 }    
1051     
1052 AccessibilityButtonState AccessibilityRenderObject::checkboxOrRadioValue() const
1053 {
1054     if (isNativeCheckboxOrRadio())
1055         return isChecked() ? ButtonStateOn : ButtonStateOff;
1056     
1057     return AccessibilityObject::checkboxOrRadioValue();
1058 }
1059
1060 String AccessibilityRenderObject::valueDescription() const
1061 {
1062     // Only sliders and progress bars support value descriptions currently.
1063     if (!isProgressIndicator() && !isSlider())
1064         return String();
1065     
1066     return getAttribute(aria_valuetextAttr).string();
1067 }
1068     
1069 float AccessibilityRenderObject::valueForRange() const
1070 {
1071     if (!isProgressIndicator() && !isSlider() && !isScrollbar())
1072         return 0.0f;
1073
1074     return getAttribute(aria_valuenowAttr).toFloat();
1075 }
1076
1077 float AccessibilityRenderObject::maxValueForRange() const
1078 {
1079     if (!isProgressIndicator() && !isSlider())
1080         return 0.0f;
1081
1082     return getAttribute(aria_valuemaxAttr).toFloat();
1083 }
1084
1085 float AccessibilityRenderObject::minValueForRange() const
1086 {
1087     if (!isProgressIndicator() && !isSlider())
1088         return 0.0f;
1089
1090     return getAttribute(aria_valueminAttr).toFloat();
1091 }
1092
1093 String AccessibilityRenderObject::stringValue() const
1094 {
1095     if (!m_renderer || isPasswordField())
1096         return String();
1097
1098     RenderBoxModelObject* cssBox = renderBoxModelObject();
1099
1100     if (ariaRoleAttribute() == StaticTextRole) {
1101         String staticText = text();
1102         if (!staticText.length())
1103             staticText = textUnderElement();
1104         return staticText;
1105     }
1106         
1107     if (m_renderer->isText())
1108         return textUnderElement();
1109     
1110     if (cssBox && cssBox->isMenuList()) {
1111         // RenderMenuList will go straight to the text() of its selected item.
1112         // This has to be overriden in the case where the selected item has an aria label
1113         SelectElement* selectNode = toSelectElement(static_cast<Element*>(m_renderer->node()));
1114         int selectedIndex = selectNode->selectedIndex();
1115         const Vector<Element*> listItems = selectNode->listItems();
1116         
1117         Element* selectedOption = 0;
1118         if (selectedIndex >= 0 && selectedIndex < (int)listItems.size()) 
1119             selectedOption = listItems[selectedIndex];
1120         if (selectedOption) {
1121             String overridenDescription = selectedOption->getAttribute(aria_labelAttr);
1122             if (!overridenDescription.isNull())
1123                 return overridenDescription;
1124         }
1125         
1126         return toRenderMenuList(m_renderer)->text();
1127     }
1128     
1129     if (m_renderer->isListMarker())
1130         return toRenderListMarker(m_renderer)->text();
1131     
1132     if (cssBox && cssBox->isRenderButton())
1133         return toRenderButton(m_renderer)->text();
1134
1135     if (isWebArea()) {
1136         if (m_renderer->frame())
1137             return String();
1138         
1139         // FIXME: should use startOfDocument and endOfDocument (or rangeForDocument?) here
1140         VisiblePosition startVisiblePosition = m_renderer->positionForCoordinates(0, 0);
1141         VisiblePosition endVisiblePosition = m_renderer->positionForCoordinates(INT_MAX, INT_MAX);
1142         if (startVisiblePosition.isNull() || endVisiblePosition.isNull())
1143             return String();
1144         
1145         return plainText(makeRange(startVisiblePosition, endVisiblePosition).get(), TextIteratorIgnoresStyleVisibility);
1146     }
1147     
1148     if (isTextControl())
1149         return text();
1150     
1151     if (isFileUploadButton())
1152         return toRenderFileUploadControl(m_renderer)->fileTextValue();
1153     
1154     // FIXME: We might need to implement a value here for more types
1155     // FIXME: It would be better not to advertise a value at all for the types for which we don't implement one;
1156     // this would require subclassing or making accessibilityAttributeNames do something other than return a
1157     // single static array.
1158     return String();
1159 }
1160
1161 // This function implements the ARIA accessible name as described by the Mozilla
1162 // ARIA Implementer's Guide.
1163 static String accessibleNameForNode(Node* node)
1164 {
1165     if (node->isTextNode())
1166         return static_cast<Text*>(node)->data();
1167
1168     if (node->hasTagName(inputTag))
1169         return static_cast<HTMLInputElement*>(node)->value();
1170
1171     if (node->isHTMLElement()) {
1172         const AtomicString& alt = static_cast<HTMLElement*>(node)->getAttribute(altAttr);
1173         if (!alt.isEmpty())
1174             return alt;
1175     }
1176
1177     return String();
1178 }
1179
1180 String AccessibilityRenderObject::accessibilityDescriptionForElements(Vector<Element*> &elements) const
1181 {
1182     Vector<UChar> ariaLabel;
1183     unsigned size = elements.size();
1184     for (unsigned i = 0; i < size; ++i) {
1185         Element* idElement = elements[i];
1186         
1187         String nameFragment = accessibleNameForNode(idElement);
1188         ariaLabel.append(nameFragment.characters(), nameFragment.length());
1189         for (Node* n = idElement->firstChild(); n; n = n->traverseNextNode(idElement)) {
1190             nameFragment = accessibleNameForNode(n);
1191             ariaLabel.append(nameFragment.characters(), nameFragment.length());
1192         }
1193             
1194         if (i != size - 1)
1195             ariaLabel.append(' ');
1196     }
1197     return String::adopt(ariaLabel);
1198 }
1199
1200     
1201 void AccessibilityRenderObject::elementsFromAttribute(Vector<Element*>& elements, const QualifiedName& attribute) const
1202 {
1203     Node* node = m_renderer->node();
1204     if (!node || !node->isElementNode())
1205         return;
1206
1207     Document* document = m_renderer->document();
1208     if (!document)
1209         return;
1210     
1211     String idList = getAttribute(attribute).string();
1212     if (idList.isEmpty())
1213         return;
1214     
1215     idList.replace('\n', ' ');
1216     Vector<String> idVector;
1217     idList.split(' ', idVector);
1218     
1219     unsigned size = idVector.size();
1220     for (unsigned i = 0; i < size; ++i) {
1221         String idName = idVector[i];
1222         Element* idElement = document->getElementById(idName);
1223         if (idElement)
1224             elements.append(idElement);
1225     }
1226 }
1227     
1228 void AccessibilityRenderObject::ariaLabeledByElements(Vector<Element*>& elements) const
1229 {
1230     elementsFromAttribute(elements, aria_labeledbyAttr);
1231     if (!elements.size())
1232         elementsFromAttribute(elements, aria_labelledbyAttr);
1233 }
1234    
1235 String AccessibilityRenderObject::ariaLabeledByAttribute() const
1236 {
1237     Vector<Element*> elements;
1238     ariaLabeledByElements(elements);
1239     
1240     return accessibilityDescriptionForElements(elements);
1241 }
1242
1243 static HTMLLabelElement* labelForElement(Element* element)
1244 {
1245     RefPtr<NodeList> list = element->document()->getElementsByTagName("label");
1246     unsigned len = list->length();
1247     for (unsigned i = 0; i < len; i++) {
1248         if (list->item(i)->hasTagName(labelTag)) {
1249             HTMLLabelElement* label = static_cast<HTMLLabelElement*>(list->item(i));
1250             if (label->control() == element)
1251                 return label;
1252         }
1253     }
1254     
1255     return 0;
1256 }
1257     
1258 HTMLLabelElement* AccessibilityRenderObject::labelElementContainer() const
1259 {
1260     if (!m_renderer)
1261         return 0;
1262
1263     // the control element should not be considered part of the label
1264     if (isControl())
1265         return 0;
1266     
1267     // find if this has a parent that is a label
1268     for (Node* parentNode = m_renderer->node(); parentNode; parentNode = parentNode->parentNode()) {
1269         if (parentNode->hasTagName(labelTag))
1270             return static_cast<HTMLLabelElement*>(parentNode);
1271     }
1272     
1273     return 0;
1274 }
1275
1276 String AccessibilityRenderObject::title() const
1277 {
1278     AccessibilityRole ariaRole = ariaRoleAttribute();
1279     
1280     if (!m_renderer)
1281         return String();
1282
1283     Node* node = m_renderer->node();
1284     if (!node)
1285         return String();
1286     
1287     String ariaLabel = ariaLabeledByAttribute();
1288     if (!ariaLabel.isEmpty())
1289         return ariaLabel;
1290     
1291     const AtomicString& title = getAttribute(titleAttr);
1292     if (!title.isEmpty())
1293         return title;
1294     
1295     bool isInputTag = node->hasTagName(inputTag);
1296     if (isInputTag) {
1297         HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
1298         if (input->isTextButton())
1299             return input->value();
1300     }
1301     
1302     if (isInputTag || AccessibilityObject::isARIAInput(ariaRole) || isControl()) {
1303         HTMLLabelElement* label = labelForElement(static_cast<Element*>(node));
1304         if (label && !titleUIElement())
1305             return label->innerText();
1306     }
1307     
1308     if (roleValue() == ButtonRole
1309         || ariaRole == ListBoxOptionRole
1310         || ariaRole == MenuItemRole
1311         || ariaRole == MenuButtonRole
1312         || ariaRole == RadioButtonRole
1313         || ariaRole == CheckBoxRole
1314         || ariaRole == TabRole
1315         || ariaRole == PopUpButtonRole
1316         || isHeading()
1317         || isLink())
1318         return textUnderElement();
1319     
1320     return String();
1321 }
1322
1323 String AccessibilityRenderObject::ariaDescribedByAttribute() const
1324 {
1325     Vector<Element*> elements;
1326     elementsFromAttribute(elements, aria_describedbyAttr);
1327     
1328     return accessibilityDescriptionForElements(elements);
1329 }
1330     
1331 String AccessibilityRenderObject::ariaAccessibilityDescription() const
1332 {
1333     const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
1334     if (!ariaLabel.isEmpty())
1335         return ariaLabel;
1336     
1337     String ariaDescription = ariaDescribedByAttribute();
1338     if (!ariaDescription.isEmpty())
1339         return ariaDescription;
1340     
1341     return String();
1342 }
1343
1344 String AccessibilityRenderObject::accessibilityDescription() const
1345 {
1346     if (!m_renderer)
1347         return String();
1348
1349     // Static text should not have a description, it should only have a stringValue.
1350     if (roleValue() == StaticTextRole)
1351         return String();
1352     
1353     String ariaDescription = ariaAccessibilityDescription();
1354     if (!ariaDescription.isEmpty())
1355         return ariaDescription;
1356     
1357     if (isImage() || isInputImage() || isNativeImage()) {
1358         Node* node = m_renderer->node();
1359         if (node && node->isHTMLElement()) {
1360             const AtomicString& alt = static_cast<HTMLElement*>(node)->getAttribute(altAttr);
1361             if (alt.isEmpty())
1362                 return String();
1363             return alt;
1364         }
1365     }
1366     
1367     if (isWebArea()) {
1368         Document* document = m_renderer->document();
1369         
1370         // Check if the HTML element has an aria-label for the webpage.
1371         Element* documentElement = document->documentElement();
1372         if (documentElement) {
1373             const AtomicString& ariaLabel = documentElement->getAttribute(aria_labelAttr);
1374             if (!ariaLabel.isEmpty())
1375                 return ariaLabel;
1376         }
1377         
1378         Node* owner = document->ownerElement();
1379         if (owner) {
1380             if (owner->hasTagName(frameTag) || owner->hasTagName(iframeTag)) {
1381                 const AtomicString& title = static_cast<HTMLFrameElementBase*>(owner)->getAttribute(titleAttr);
1382                 if (!title.isEmpty())
1383                     return title;
1384                 return static_cast<HTMLFrameElementBase*>(owner)->getAttribute(nameAttr);
1385             }
1386             if (owner->isHTMLElement())
1387                 return static_cast<HTMLElement*>(owner)->getAttribute(nameAttr);
1388         }
1389         owner = document->body();
1390         if (owner && owner->isHTMLElement())
1391             return static_cast<HTMLElement*>(owner)->getAttribute(nameAttr);
1392     }
1393
1394     return String();
1395 }
1396
1397 IntRect AccessibilityRenderObject::boundingBoxRect() const
1398 {
1399     RenderObject* obj = m_renderer;
1400     
1401     if (!obj)
1402         return IntRect();
1403     
1404     if (obj->node()) // If we are a continuation, we want to make sure to use the primary renderer.
1405         obj = obj->node()->renderer();
1406     
1407     // absoluteFocusRingQuads will query the hierarchy below this element, which for large webpages can be very slow.
1408     // For a web area, which will have the most elements of any element, absoluteQuads should be used.
1409     Vector<FloatQuad> quads;
1410     if (obj->isText())
1411         toRenderText(obj)->absoluteQuads(quads, RenderText::ClipToEllipsis);
1412     else if (isWebArea())
1413         obj->absoluteQuads(quads);
1414     else
1415         obj->absoluteFocusRingQuads(quads);
1416     const size_t n = quads.size();
1417     if (!n)
1418         return IntRect();
1419
1420     IntRect result;
1421     for (size_t i = 0; i < n; ++i) {
1422         IntRect r = quads[i].enclosingBoundingBox();
1423         if (!r.isEmpty()) {
1424             if (obj->style()->hasAppearance())
1425                 obj->theme()->adjustRepaintRect(obj, r);
1426             result.unite(r);
1427         }
1428     }
1429
1430     // The size of the web area should be the content size, not the clipped size.
1431     if (isWebArea() && obj->frame()->view())
1432         result.setSize(obj->frame()->view()->contentsSize());
1433     
1434     return result;
1435 }
1436     
1437 IntRect AccessibilityRenderObject::checkboxOrRadioRect() const
1438 {
1439     if (!m_renderer)
1440         return IntRect();
1441     
1442     HTMLLabelElement* label = labelForElement(static_cast<Element*>(m_renderer->node()));
1443     if (!label || !label->renderer())
1444         return boundingBoxRect();
1445     
1446     IntRect labelRect = axObjectCache()->getOrCreate(label->renderer())->elementRect();
1447     labelRect.unite(boundingBoxRect());
1448     return labelRect;
1449 }
1450
1451 IntRect AccessibilityRenderObject::elementRect() const
1452 {
1453     // a checkbox or radio button should encompass its label
1454     if (isCheckboxOrRadio())
1455         return checkboxOrRadioRect();
1456     
1457     return boundingBoxRect();
1458 }
1459
1460 IntSize AccessibilityRenderObject::size() const
1461 {
1462     IntRect rect = elementRect();
1463     return rect.size();
1464 }
1465
1466 IntPoint AccessibilityRenderObject::clickPoint() const
1467 {
1468     // use the default position unless this is an editable web area, in which case we use the selection bounds.
1469     if (!isWebArea() || isReadOnly())
1470         return AccessibilityObject::clickPoint();
1471     
1472     VisibleSelection visSelection = selection();
1473     VisiblePositionRange range = VisiblePositionRange(visSelection.visibleStart(), visSelection.visibleEnd());
1474     IntRect bounds = boundsForVisiblePositionRange(range);
1475 #if PLATFORM(MAC)
1476     bounds.setLocation(m_renderer->document()->view()->screenToContents(bounds.location()));
1477 #endif        
1478     return IntPoint(bounds.x() + (bounds.width() / 2), bounds.y() - (bounds.height() / 2));
1479 }
1480     
1481 AccessibilityObject* AccessibilityRenderObject::internalLinkElement() const
1482 {
1483     Element* element = anchorElement();
1484     if (!element)
1485         return 0;
1486     
1487     // Right now, we do not support ARIA links as internal link elements
1488     if (!element->hasTagName(aTag))
1489         return 0;
1490     HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(element);
1491     
1492     KURL linkURL = anchor->href();
1493     String fragmentIdentifier = linkURL.fragmentIdentifier();
1494     if (fragmentIdentifier.isEmpty())
1495         return 0;
1496     
1497     // check if URL is the same as current URL
1498     KURL documentURL = m_renderer->document()->url();
1499     if (!equalIgnoringFragmentIdentifier(documentURL, linkURL))
1500         return 0;
1501     
1502     Node* linkedNode = m_renderer->document()->findAnchor(fragmentIdentifier);
1503     if (!linkedNode)
1504         return 0;
1505     
1506     // The element we find may not be accessible, so find the first accessible object.
1507     return firstAccessibleObjectFromNode(linkedNode);
1508 }
1509
1510 ESpeak AccessibilityRenderObject::speakProperty() const
1511 {
1512     if (!m_renderer)
1513         return AccessibilityObject::speakProperty();
1514     
1515     return m_renderer->style()->speak();
1516 }
1517     
1518 void AccessibilityRenderObject::addRadioButtonGroupMembers(AccessibilityChildrenVector& linkedUIElements) const
1519 {
1520     if (!m_renderer || roleValue() != RadioButtonRole)
1521         return;
1522     
1523     Node* node = m_renderer->node();
1524     if (!node || !node->hasTagName(inputTag))
1525         return;
1526     
1527     HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
1528     // if there's a form, then this is easy
1529     if (input->form()) {
1530         Vector<RefPtr<Node> > formElements;
1531         input->form()->getNamedElements(input->name(), formElements);
1532         
1533         unsigned len = formElements.size();
1534         for (unsigned i = 0; i < len; ++i) {
1535             Node* associateElement = formElements[i].get();
1536             if (AccessibilityObject* object = axObjectCache()->getOrCreate(associateElement->renderer()))
1537                 linkedUIElements.append(object);        
1538         } 
1539     } else {
1540         RefPtr<NodeList> list = node->document()->getElementsByTagName("input");
1541         unsigned len = list->length();
1542         for (unsigned i = 0; i < len; ++i) {
1543             if (list->item(i)->hasTagName(inputTag)) {
1544                 HTMLInputElement* associateElement = static_cast<HTMLInputElement*>(list->item(i));
1545                 if (associateElement->isRadioButton() && associateElement->name() == input->name()) {
1546                     if (AccessibilityObject* object = axObjectCache()->getOrCreate(associateElement->renderer()))
1547                         linkedUIElements.append(object);
1548                 }
1549             }
1550         }
1551     }
1552 }
1553     
1554 // linked ui elements could be all the related radio buttons in a group
1555 // or an internal anchor connection
1556 void AccessibilityRenderObject::linkedUIElements(AccessibilityChildrenVector& linkedUIElements) const
1557 {
1558     ariaFlowToElements(linkedUIElements);
1559
1560     if (isAnchor()) {
1561         AccessibilityObject* linkedAXElement = internalLinkElement();
1562         if (linkedAXElement)
1563             linkedUIElements.append(linkedAXElement);
1564     }
1565
1566     if (roleValue() == RadioButtonRole)
1567         addRadioButtonGroupMembers(linkedUIElements);
1568 }
1569
1570 bool AccessibilityRenderObject::hasTextAlternative() const
1571 {
1572     // ARIA: section 2A, bullet #3 says if aria-labeledby or aria-label appears, it should
1573     // override the "label" element association.
1574     if (!ariaLabeledByAttribute().isEmpty() || !getAttribute(aria_labelAttr).isEmpty())
1575         return true;
1576         
1577     return false;   
1578 }
1579     
1580 bool AccessibilityRenderObject::ariaHasPopup() const
1581 {
1582     return elementAttributeValue(aria_haspopupAttr);
1583 }
1584     
1585 bool AccessibilityRenderObject::supportsARIAFlowTo() const
1586 {
1587     return !getAttribute(aria_flowtoAttr).isEmpty();
1588 }
1589     
1590 void AccessibilityRenderObject::ariaFlowToElements(AccessibilityChildrenVector& flowTo) const
1591 {
1592     Vector<Element*> elements;
1593     elementsFromAttribute(elements, aria_flowtoAttr);
1594     
1595     AXObjectCache* cache = axObjectCache();
1596     unsigned count = elements.size();
1597     for (unsigned k = 0; k < count; ++k) {
1598         Element* element = elements[k];
1599         AccessibilityObject* flowToElement = cache->getOrCreate(element->renderer());
1600         if (flowToElement)
1601             flowTo.append(flowToElement);
1602     }
1603         
1604 }
1605     
1606 bool AccessibilityRenderObject::supportsARIADropping() const 
1607 {
1608     const AtomicString& dropEffect = getAttribute(aria_dropeffectAttr);
1609     return !dropEffect.isEmpty();
1610 }
1611
1612 bool AccessibilityRenderObject::supportsARIADragging() const
1613 {
1614     const AtomicString& grabbed = getAttribute(aria_grabbedAttr);
1615     return equalIgnoringCase(grabbed, "true") || equalIgnoringCase(grabbed, "false");   
1616 }
1617
1618 bool AccessibilityRenderObject::isARIAGrabbed()
1619 {
1620     return elementAttributeValue(aria_grabbedAttr);
1621 }
1622
1623 void AccessibilityRenderObject::setARIAGrabbed(bool grabbed)
1624 {
1625     setElementAttributeValue(aria_grabbedAttr, grabbed);
1626 }
1627
1628 void AccessibilityRenderObject::determineARIADropEffects(Vector<String>& effects)
1629 {
1630     const AtomicString& dropEffects = getAttribute(aria_dropeffectAttr);
1631     if (dropEffects.isEmpty()) {
1632         effects.clear();
1633         return;
1634     }
1635     
1636     String dropEffectsString = dropEffects.string();
1637     dropEffectsString.replace('\n', ' ');
1638     dropEffectsString.split(' ', effects);
1639 }
1640     
1641 bool AccessibilityRenderObject::exposesTitleUIElement() const
1642 {
1643     if (!isControl())
1644         return false;
1645
1646     // checkbox or radio buttons don't expose the title ui element unless it has a title already
1647     if (isCheckboxOrRadio() && getAttribute(titleAttr).isEmpty())
1648         return false;
1649     
1650     if (hasTextAlternative())
1651         return false;
1652     
1653     return true;
1654 }
1655     
1656 AccessibilityObject* AccessibilityRenderObject::titleUIElement() const
1657 {
1658     if (!m_renderer)
1659         return 0;
1660     
1661     // if isFieldset is true, the renderer is guaranteed to be a RenderFieldset
1662     if (isFieldset())
1663         return axObjectCache()->getOrCreate(toRenderFieldset(m_renderer)->findLegend());
1664     
1665     if (!exposesTitleUIElement())
1666         return 0;
1667     
1668     Node* element = m_renderer->node();
1669     HTMLLabelElement* label = labelForElement(static_cast<Element*>(element));
1670     if (label && label->renderer())
1671         return axObjectCache()->getOrCreate(label->renderer());
1672
1673     return 0;   
1674 }
1675     
1676 bool AccessibilityRenderObject::ariaIsHidden() const
1677 {
1678     if (equalIgnoringCase(getAttribute(aria_hiddenAttr), "true"))
1679         return true;
1680     
1681     // aria-hidden hides this object and any children
1682     AccessibilityObject* object = parentObject();
1683     while (object) {
1684         if (object->isAccessibilityRenderObject() && equalIgnoringCase(static_cast<AccessibilityRenderObject*>(object)->getAttribute(aria_hiddenAttr), "true"))
1685             return true;
1686         object = object->parentObject();
1687     }
1688
1689     return false;
1690 }
1691
1692 bool AccessibilityRenderObject::isDescendantOfBarrenParent() const
1693 {
1694     for (AccessibilityObject* object = parentObject(); object; object = object->parentObject()) {
1695         if (!object->canHaveChildren())
1696             return true;
1697     }
1698     
1699     return false;
1700 }
1701     
1702 bool AccessibilityRenderObject::isAllowedChildOfTree() const
1703 {
1704     // Determine if this is in a tree. If so, we apply special behavior to make it work like an AXOutline.
1705     AccessibilityObject* axObj = parentObject();
1706     bool isInTree = false;
1707     while (axObj) {
1708         if (axObj->isTree()) {
1709             isInTree = true;
1710             break;
1711         }
1712         axObj = axObj->parentObject();
1713     }
1714     
1715     // If the object is in a tree, only tree items should be exposed (and the children of tree items).
1716     if (isInTree) {
1717         AccessibilityRole role = roleValue();
1718         if (role != TreeItemRole && role != StaticTextRole)
1719             return false;
1720     }
1721     return true;
1722 }
1723     
1724 AccessibilityObjectInclusion AccessibilityRenderObject::accessibilityIsIgnoredBase() const
1725 {
1726     // The following cases can apply to any element that's a subclass of AccessibilityRenderObject.
1727     
1728     // Ignore invisible elements.
1729     if (!m_renderer || m_renderer->style()->visibility() != VISIBLE)
1730         return IgnoreObject;
1731
1732     // Anything marked as aria-hidden or a child of something aria-hidden must be hidden.
1733     if (ariaIsHidden())
1734         return IgnoreObject;
1735     
1736     // Anything that is a presentational role must be hidden.
1737     if (isPresentationalChildOfAriaRole())
1738         return IgnoreObject;
1739
1740     // Allow the platform to make a decision.
1741     AccessibilityObjectInclusion decision = accessibilityPlatformIncludesObject();
1742     if (decision == IncludeObject)
1743         return IncludeObject;
1744     if (decision == IgnoreObject)
1745         return IgnoreObject;
1746         
1747     return DefaultBehavior;
1748 }  
1749  
1750 bool AccessibilityRenderObject::accessibilityIsIgnored() const
1751 {
1752     // Check first if any of the common reasons cause this element to be ignored.
1753     // Then process other use cases that need to be applied to all the various roles
1754     // that AccessibilityRenderObjects take on.
1755     AccessibilityObjectInclusion decision = accessibilityIsIgnoredBase();
1756     if (decision == IncludeObject)
1757         return false;
1758     if (decision == IgnoreObject)
1759         return true;
1760     
1761     // If this element is within a parent that cannot have children, it should not be exposed.
1762     if (isDescendantOfBarrenParent())
1763         return true;    
1764     
1765     if (roleValue() == IgnoredRole)
1766         return true;
1767     
1768     if (roleValue() == PresentationalRole || inheritsPresentationalRole())
1769         return true;
1770     
1771     // An ARIA tree can only have tree items and static text as children.
1772     if (!isAllowedChildOfTree())
1773         return true;
1774
1775     // ignore popup menu items because AppKit does
1776     for (RenderObject* parent = m_renderer->parent(); parent; parent = parent->parent()) {
1777         if (parent->isBoxModelObject() && toRenderBoxModelObject(parent)->isMenuList())
1778             return true;
1779     }
1780
1781     // find out if this element is inside of a label element.
1782     // if so, it may be ignored because it's the label for a checkbox or radio button
1783     AccessibilityObject* controlObject = correspondingControlForLabelElement();
1784     if (controlObject && !controlObject->exposesTitleUIElement() && controlObject->isCheckboxOrRadio())
1785         return true;
1786         
1787     // NOTE: BRs always have text boxes now, so the text box check here can be removed
1788     if (m_renderer->isText()) {
1789         // static text beneath MenuItems and MenuButtons are just reported along with the menu item, so it's ignored on an individual level
1790         if (parentObjectUnignored()->ariaRoleAttribute() == MenuItemRole
1791             || parentObjectUnignored()->ariaRoleAttribute() == MenuButtonRole)
1792             return true;
1793         RenderText* renderText = toRenderText(m_renderer);
1794         if (m_renderer->isBR() || !renderText->firstTextBox())
1795             return true;
1796
1797         // static text beneath TextControls is reported along with the text control text so it's ignored.
1798         for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) { 
1799             if (parent->roleValue() == TextFieldRole)
1800                 return true;
1801         }
1802
1803         // text elements that are just empty whitespace should not be returned
1804         return renderText->text()->containsOnlyWhitespace();
1805     }
1806     
1807     if (isHeading())
1808         return false;
1809     
1810     if (isLink())
1811         return false;
1812     
1813     // all controls are accessible
1814     if (isControl())
1815         return false;
1816     
1817     if (ariaRoleAttribute() != UnknownRole)
1818         return false;
1819
1820     if (!helpText().isEmpty())
1821         return false;
1822     
1823     // don't ignore labels, because they serve as TitleUIElements
1824     Node* node = m_renderer->node();
1825     if (node && node->hasTagName(labelTag))
1826         return false;
1827     
1828     // Anything that is content editable should not be ignored.
1829     // However, one cannot just call node->isContentEditable() since that will ask if its parents
1830     // are also editable. Only the top level content editable region should be exposed.
1831     if (node && node->isElementNode()) {
1832         Element* element = static_cast<Element*>(node);
1833         const AtomicString& contentEditable = element->getAttribute(contenteditableAttr);
1834         if (equalIgnoringCase(contentEditable, "true"))
1835             return false;
1836     }
1837     
1838     // if this element has aria attributes on it, it should not be ignored.
1839     if (supportsARIAAttributes())
1840         return false;
1841     
1842     if (m_renderer->isBlockFlow() && m_renderer->childrenInline())
1843         return !toRenderBlock(m_renderer)->firstLineBox() && !mouseButtonListener();
1844     
1845     // ignore images seemingly used as spacers
1846     if (isImage()) {
1847         if (node && node->isElementNode()) {
1848             Element* elt = static_cast<Element*>(node);
1849             const AtomicString& alt = elt->getAttribute(altAttr);
1850             // don't ignore an image that has an alt tag
1851             if (!alt.isEmpty())
1852                 return false;
1853             // informal standard is to ignore images with zero-length alt strings
1854             if (!alt.isNull())
1855                 return true;
1856         }
1857         
1858         if (node && node->hasTagName(canvasTag)) {
1859             RenderHTMLCanvas* canvas = toRenderHTMLCanvas(m_renderer);
1860             if (canvas->height() <= 1 || canvas->width() <= 1)
1861                 return true;
1862             return false;
1863         }
1864         
1865         if (isNativeImage()) {
1866             // check for one-dimensional image
1867             RenderImage* image = toRenderImage(m_renderer);
1868             if (image->height() <= 1 || image->width() <= 1)
1869                 return true;
1870             
1871             // check whether rendered image was stretched from one-dimensional file image
1872             if (image->cachedImage()) {
1873                 IntSize imageSize = image->cachedImage()->imageSize(image->view()->zoomFactor());
1874                 return imageSize.height() <= 1 || imageSize.width() <= 1;
1875             }
1876         }
1877         return false;
1878     }
1879     
1880     // make a platform-specific decision
1881     if (isAttachment())
1882         return accessibilityIgnoreAttachment();
1883     
1884     return !m_renderer->isListMarker() && !isWebArea();
1885 }
1886
1887 bool AccessibilityRenderObject::isLoaded() const
1888 {
1889     return !m_renderer->document()->parser();
1890 }
1891
1892 double AccessibilityRenderObject::estimatedLoadingProgress() const
1893 {
1894     if (!m_renderer)
1895         return 0;
1896     
1897     if (isLoaded())
1898         return 1.0;
1899     
1900     Page* page = m_renderer->document()->page();
1901     if (!page)
1902         return 0;
1903     
1904     return page->progress()->estimatedProgress();
1905 }
1906     
1907 int AccessibilityRenderObject::layoutCount() const
1908 {
1909     if (!m_renderer->isRenderView())
1910         return 0;
1911     return toRenderView(m_renderer)->frameView()->layoutCount();
1912 }
1913
1914 String AccessibilityRenderObject::text() const
1915 {
1916     // If this is a user defined static text, use the accessible name computation.
1917     if (ariaRoleAttribute() == StaticTextRole)
1918         return ariaAccessibilityDescription();
1919     
1920     if (!isTextControl() || isPasswordField())
1921         return String();
1922     
1923     if (isNativeTextControl())
1924         return toRenderTextControl(m_renderer)->text();
1925     
1926     Node* node = m_renderer->node();
1927     if (!node)
1928         return String();
1929     if (!node->isElementNode())
1930         return String();
1931     
1932     return static_cast<Element*>(node)->innerText();
1933 }
1934     
1935 int AccessibilityRenderObject::textLength() const
1936 {
1937     ASSERT(isTextControl());
1938     
1939     if (isPasswordField())
1940         return -1; // need to return something distinct from 0
1941     
1942     return text().length();
1943 }
1944
1945 PlainTextRange AccessibilityRenderObject::ariaSelectedTextRange() const
1946 {
1947     Node* node = m_renderer->node();
1948     if (!node)
1949         return PlainTextRange();
1950     
1951     ExceptionCode ec = 0;
1952     VisibleSelection visibleSelection = selection();
1953     RefPtr<Range> currentSelectionRange = visibleSelection.toNormalizedRange();
1954     if (!currentSelectionRange || !currentSelectionRange->intersectsNode(node, ec))
1955         return PlainTextRange();
1956     
1957     int start = indexForVisiblePosition(visibleSelection.start());
1958     int end = indexForVisiblePosition(visibleSelection.end());
1959     
1960     return PlainTextRange(start, end - start);
1961 }
1962
1963 String AccessibilityRenderObject::selectedText() const
1964 {
1965     ASSERT(isTextControl());
1966     
1967     if (isPasswordField())
1968         return String(); // need to return something distinct from empty string
1969     
1970     if (isNativeTextControl()) {
1971         RenderTextControl* textControl = toRenderTextControl(m_renderer);
1972         return textControl->text().substring(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart());
1973     }
1974     
1975     if (ariaRoleAttribute() == UnknownRole)
1976         return String();
1977     
1978     return doAXStringForRange(ariaSelectedTextRange());
1979 }
1980
1981 const AtomicString& AccessibilityRenderObject::accessKey() const
1982 {
1983     Node* node = m_renderer->node();
1984     if (!node)
1985         return nullAtom;
1986     if (!node->isElementNode())
1987         return nullAtom;
1988     return static_cast<Element*>(node)->getAttribute(accesskeyAttr);
1989 }
1990
1991 VisibleSelection AccessibilityRenderObject::selection() const
1992 {
1993     return m_renderer->frame()->selection()->selection();
1994 }
1995
1996 PlainTextRange AccessibilityRenderObject::selectedTextRange() const
1997 {
1998     ASSERT(isTextControl());
1999     
2000     if (isPasswordField())
2001         return PlainTextRange();
2002     
2003     AccessibilityRole ariaRole = ariaRoleAttribute();
2004     if (isNativeTextControl() && ariaRole == UnknownRole) {
2005         RenderTextControl* textControl = toRenderTextControl(m_renderer);
2006         return PlainTextRange(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart());
2007     }
2008     
2009     if (ariaRole == UnknownRole)
2010         return PlainTextRange();
2011     
2012     return ariaSelectedTextRange();
2013 }
2014
2015 void AccessibilityRenderObject::setSelectedTextRange(const PlainTextRange& range)
2016 {
2017     if (isNativeTextControl()) {
2018         setSelectionRange(m_renderer->node(), range.start, range.start + range.length);
2019         return;
2020     }
2021
2022     Document* document = m_renderer->document();
2023     if (!document)
2024         return;
2025     Frame* frame = document->frame();
2026     if (!frame)
2027         return;
2028     Node* node = m_renderer->node();
2029     frame->selection()->setSelection(VisibleSelection(Position(node, range.start),
2030         Position(node, range.start + range.length), DOWNSTREAM));
2031 }
2032
2033 KURL AccessibilityRenderObject::url() const
2034 {
2035     if (isAnchor() && m_renderer->node()->hasTagName(aTag)) {
2036         if (HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(anchorElement()))
2037             return anchor->href();
2038     }
2039     
2040     if (isWebArea())
2041         return m_renderer->document()->url();
2042     
2043     if (isImage() && m_renderer->node() && m_renderer->node()->hasTagName(imgTag))
2044         return static_cast<HTMLImageElement*>(m_renderer->node())->src();
2045     
2046     if (isInputImage())
2047         return static_cast<HTMLInputElement*>(m_renderer->node())->src();
2048     
2049     return KURL();
2050 }
2051
2052 bool AccessibilityRenderObject::isVisited() const
2053 {
2054     // FIXME: Is it a privacy violation to expose visited information to accessibility APIs?
2055     return m_renderer->style()->isLink() && m_renderer->style()->insideLink() == InsideVisitedLink;
2056 }
2057     
2058 bool AccessibilityRenderObject::isExpanded() const
2059 {
2060     if (equalIgnoringCase(getAttribute(aria_expandedAttr), "true"))
2061         return true;
2062     
2063     return false;  
2064 }
2065
2066 void AccessibilityRenderObject::setElementAttributeValue(const QualifiedName& attributeName, bool value)
2067 {
2068     if (!m_renderer)
2069         return;
2070     
2071     Node* node = m_renderer->node();
2072     if (!node || !node->isElementNode())
2073         return;
2074     
2075     Element* element = static_cast<Element*>(node);
2076     element->setAttribute(attributeName, (value) ? "true" : "false");        
2077 }
2078     
2079 bool AccessibilityRenderObject::elementAttributeValue(const QualifiedName& attributeName) const
2080 {
2081     if (!m_renderer)
2082         return false;
2083     
2084     return equalIgnoringCase(getAttribute(attributeName), "true");
2085 }
2086     
2087 void AccessibilityRenderObject::setIsExpanded(bool isExpanded)
2088 {
2089     // Combo boxes, tree items and rows can be expanded (in different ways on different platforms).
2090     // That action translates into setting the aria-expanded attribute to true.
2091     AccessibilityRole role = roleValue();
2092     switch (role) {
2093     case ComboBoxRole:
2094     case TreeItemRole:
2095     case RowRole:
2096         setElementAttributeValue(aria_expandedAttr, isExpanded);
2097         break;
2098     default:
2099         break;
2100     }
2101 }
2102     
2103 bool AccessibilityRenderObject::isRequired() const
2104 {
2105     if (equalIgnoringCase(getAttribute(aria_requiredAttr), "true"))
2106         return true;
2107     
2108     Node* n = node();
2109     if (n && (n->isElementNode() && static_cast<Element*>(n)->isFormControlElement()))
2110         return static_cast<HTMLFormControlElement*>(n)->required();
2111     
2112     return false;
2113 }
2114
2115 bool AccessibilityRenderObject::isSelected() const
2116 {
2117     if (!m_renderer)
2118         return false;
2119     
2120     Node* node = m_renderer->node();
2121     if (!node)
2122         return false;
2123     
2124     const AtomicString& ariaSelected = getAttribute(aria_selectedAttr);
2125     if (equalIgnoringCase(ariaSelected, "true"))
2126         return true;    
2127     
2128     if (isTabItem() && isTabItemSelected())
2129         return true;
2130
2131     return false;
2132 }
2133
2134 bool AccessibilityRenderObject::isTabItemSelected() const
2135 {
2136     if (!isTabItem() || !m_renderer)
2137         return false;
2138     
2139     Node* node = m_renderer->node();
2140     if (!node || !node->isElementNode())
2141         return false;
2142     
2143     // The ARIA spec says a tab item can also be selected if it is aria-labeled by a tabpanel
2144     // that has keyboard focus inside of it, or if a tabpanel in its aria-controls list has KB
2145     // focus inside of it.
2146     AccessibilityObject* focusedElement = focusedUIElement();
2147     if (!focusedElement)
2148         return false;
2149     
2150     Vector<Element*> elements;
2151     elementsFromAttribute(elements, aria_controlsAttr);
2152     
2153     unsigned count = elements.size();
2154     for (unsigned k = 0; k < count; ++k) {
2155         Element* element = elements[k];
2156         AccessibilityObject* tabPanel = axObjectCache()->getOrCreate(element->renderer());
2157
2158         // A tab item should only control tab panels.
2159         if (!tabPanel || tabPanel->roleValue() != TabPanelRole)
2160             continue;
2161         
2162         AccessibilityObject* checkFocusElement = focusedElement;
2163         // Check if the focused element is a descendant of the element controlled by the tab item.
2164         while (checkFocusElement) {
2165             if (tabPanel == checkFocusElement)
2166                 return true;
2167             checkFocusElement = checkFocusElement->parentObject();
2168         }
2169     }
2170     
2171     return false;
2172 }
2173     
2174 bool AccessibilityRenderObject::isFocused() const
2175 {
2176     if (!m_renderer)
2177         return false;
2178     
2179     Document* document = m_renderer->document();
2180     if (!document)
2181         return false;
2182     
2183     Node* focusedNode = document->focusedNode();
2184     if (!focusedNode)
2185         return false;
2186     
2187     // A web area is represented by the Document node in the DOM tree, which isn't focusable.
2188     // Check instead if the frame's selection controller is focused
2189     if (focusedNode == m_renderer->node()
2190         || (roleValue() == WebAreaRole && document->frame()->selection()->isFocusedAndActive()))
2191         return true;
2192     
2193     return false;
2194 }
2195
2196 void AccessibilityRenderObject::setFocused(bool on)
2197 {
2198     if (!canSetFocusAttribute())
2199         return;
2200     
2201     if (!on)
2202         m_renderer->document()->setFocusedNode(0);
2203     else {
2204         if (m_renderer->node()->isElementNode())
2205             static_cast<Element*>(m_renderer->node())->focus();
2206         else
2207             m_renderer->document()->setFocusedNode(m_renderer->node());
2208     }
2209 }
2210
2211 void AccessibilityRenderObject::changeValueByPercent(float percentChange)
2212 {
2213     float range = maxValueForRange() - minValueForRange();
2214     float value = valueForRange();
2215     
2216     value += range * (percentChange / 100);
2217     setValue(String::number(value));
2218     
2219     axObjectCache()->postNotification(m_renderer, AXObjectCache::AXValueChanged, true);
2220 }
2221     
2222 void AccessibilityRenderObject::setSelected(bool enabled)
2223 {
2224     setElementAttributeValue(aria_selectedAttr, enabled);
2225 }
2226
2227 void AccessibilityRenderObject::setSelectedRows(AccessibilityChildrenVector& selectedRows)
2228 {
2229     // Setting selected only makes sense in trees and tables (and tree-tables).
2230     AccessibilityRole role = roleValue();
2231     if (role != TreeRole && role != TreeGridRole && role != TableRole)
2232         return;
2233     
2234     bool isMulti = isMultiSelectable();
2235     unsigned count = selectedRows.size();
2236     if (count > 1 && !isMulti)
2237         count = 1;
2238     
2239     for (unsigned k = 0; k < count; ++k)
2240         selectedRows[k]->setSelected(true);
2241 }
2242     
2243 void AccessibilityRenderObject::setValue(const String& string)
2244 {
2245     if (!m_renderer || !m_renderer->node() || !m_renderer->node()->isElementNode())
2246         return;
2247     Element* element = static_cast<Element*>(m_renderer->node());
2248
2249     if (roleValue() == SliderRole)
2250         element->setAttribute(aria_valuenowAttr, string);
2251
2252     if (!m_renderer->isBoxModelObject())
2253         return;
2254     RenderBoxModelObject* renderer = toRenderBoxModelObject(m_renderer);
2255
2256     // FIXME: Do we want to do anything here for ARIA textboxes?
2257     if (renderer->isTextField()) {
2258         // FIXME: This is not safe!  Other elements could have a TextField renderer.
2259         static_cast<HTMLInputElement*>(element)->setValue(string);
2260     } else if (renderer->isTextArea()) {
2261         // FIXME: This is not safe!  Other elements could have a TextArea renderer.
2262         static_cast<HTMLTextAreaElement*>(element)->setValue(string);
2263     }
2264 }
2265
2266 void AccessibilityRenderObject::ariaOwnsElements(AccessibilityChildrenVector& axObjects) const
2267 {
2268     Vector<Element*> elements;
2269     elementsFromAttribute(elements, aria_ownsAttr);
2270     
2271     unsigned count = elements.size();
2272     for (unsigned k = 0; k < count; ++k) {
2273         RenderObject* render = elements[k]->renderer();
2274         AccessibilityObject* obj = axObjectCache()->getOrCreate(render);
2275         if (obj)
2276             axObjects.append(obj);
2277     }
2278 }
2279
2280 bool AccessibilityRenderObject::supportsARIAOwns() const
2281 {
2282     if (!m_renderer)
2283         return false;
2284     const AtomicString& ariaOwns = getAttribute(aria_ownsAttr);
2285
2286     return !ariaOwns.isEmpty();
2287 }
2288     
2289 bool AccessibilityRenderObject::isEnabled() const
2290 {
2291     ASSERT(m_renderer);
2292     
2293     if (equalIgnoringCase(getAttribute(aria_disabledAttr), "true"))
2294         return false;
2295     
2296     Node* node = m_renderer->node();
2297     if (!node || !node->isElementNode())
2298         return true;
2299
2300     return static_cast<Element*>(node)->isEnabledFormControl();
2301 }
2302
2303 RenderView* AccessibilityRenderObject::topRenderer() const
2304 {
2305     return m_renderer->document()->topDocument()->renderView();
2306 }
2307
2308 Document* AccessibilityRenderObject::document() const
2309 {
2310     if (!m_renderer)
2311         return 0;
2312     return m_renderer->document();
2313 }
2314
2315 FrameView* AccessibilityRenderObject::topDocumentFrameView() const
2316 {
2317     return topRenderer()->view()->frameView();
2318 }
2319
2320 Widget* AccessibilityRenderObject::widget() const
2321 {
2322     if (!m_renderer->isBoxModelObject() || !toRenderBoxModelObject(m_renderer)->isWidget())
2323         return 0;
2324     return toRenderWidget(m_renderer)->widget();
2325 }
2326
2327 AccessibilityObject* AccessibilityRenderObject::accessibilityParentForImageMap(HTMLMapElement* map) const
2328 {
2329     // find an image that is using this map
2330     if (!map)
2331         return 0;
2332
2333     HTMLImageElement* imageElement = map->imageElement();
2334     if (!imageElement)
2335         return 0;
2336     
2337     return axObjectCache()->getOrCreate(imageElement->renderer());
2338 }
2339     
2340 void AccessibilityRenderObject::getDocumentLinks(AccessibilityChildrenVector& result)
2341 {
2342     Document* document = m_renderer->document();
2343     RefPtr<HTMLCollection> coll = document->links();
2344     Node* curr = coll->firstItem();
2345     while (curr) {
2346         RenderObject* obj = curr->renderer();
2347         if (obj) {
2348             RefPtr<AccessibilityObject> axobj = document->axObjectCache()->getOrCreate(obj);
2349             ASSERT(axobj);
2350             if (!axobj->accessibilityIsIgnored() && axobj->isLink())
2351                 result.append(axobj);
2352         } else {
2353             Node* parent = curr->parentNode();
2354             if (parent && curr->hasTagName(areaTag) && parent->hasTagName(mapTag)) {
2355                 AccessibilityImageMapLink* areaObject = static_cast<AccessibilityImageMapLink*>(axObjectCache()->getOrCreate(ImageMapLinkRole));
2356                 areaObject->setHTMLAreaElement(static_cast<HTMLAreaElement*>(curr));
2357                 areaObject->setHTMLMapElement(static_cast<HTMLMapElement*>(parent));
2358                 areaObject->setParent(accessibilityParentForImageMap(static_cast<HTMLMapElement*>(parent)));
2359
2360                 result.append(areaObject);
2361             }
2362         }
2363         curr = coll->nextItem();
2364     }
2365 }
2366
2367 FrameView* AccessibilityRenderObject::documentFrameView() const 
2368
2369     if (!m_renderer || !m_renderer->document()) 
2370         return 0; 
2371
2372     // this is the RenderObject's Document's Frame's FrameView 
2373     return m_renderer->document()->view();
2374 }
2375
2376 Widget* AccessibilityRenderObject::widgetForAttachmentView() const
2377 {
2378     if (!isAttachment())
2379         return 0;
2380     return toRenderWidget(m_renderer)->widget();
2381 }
2382
2383 FrameView* AccessibilityRenderObject::frameViewIfRenderView() const
2384 {
2385     if (!m_renderer->isRenderView())
2386         return 0;
2387     // this is the RenderObject's Document's renderer's FrameView
2388     return m_renderer->view()->frameView();
2389 }
2390
2391 // This function is like a cross-platform version of - (WebCoreTextMarkerRange*)textMarkerRange. It returns
2392 // a Range that we can convert to a WebCoreTextMarkerRange in the Obj-C file
2393 VisiblePositionRange AccessibilityRenderObject::visiblePositionRange() const
2394 {
2395     if (!m_renderer)
2396         return VisiblePositionRange();
2397     
2398     // construct VisiblePositions for start and end
2399     Node* node = m_renderer->node();
2400     if (!node)
2401         return VisiblePositionRange();
2402
2403     VisiblePosition startPos = firstDeepEditingPositionForNode(node);
2404     VisiblePosition endPos = lastDeepEditingPositionForNode(node);
2405
2406     // the VisiblePositions are equal for nodes like buttons, so adjust for that
2407     // FIXME: Really?  [button, 0] and [button, 1] are distinct (before and after the button)
2408     // I expect this code is only hit for things like empty divs?  In which case I don't think
2409     // the behavior is correct here -- eseidel
2410     if (startPos == endPos) {
2411         endPos = endPos.next();
2412         if (endPos.isNull())
2413             endPos = startPos;
2414     }
2415
2416     return VisiblePositionRange(startPos, endPos);
2417 }
2418
2419 VisiblePositionRange AccessibilityRenderObject::visiblePositionRangeForLine(unsigned lineCount) const
2420 {
2421     if (!lineCount || !m_renderer)
2422         return VisiblePositionRange();
2423     
2424     // iterate over the lines
2425     // FIXME: this is wrong when lineNumber is lineCount+1,  because nextLinePosition takes you to the
2426     // last offset of the last line
2427     VisiblePosition visiblePos = m_renderer->document()->renderer()->positionForCoordinates(0, 0);
2428     VisiblePosition savedVisiblePos;
2429     while (--lineCount) {
2430         savedVisiblePos = visiblePos;
2431         visiblePos = nextLinePosition(visiblePos, 0);
2432         if (visiblePos.isNull() || visiblePos == savedVisiblePos)
2433             return VisiblePositionRange();
2434     }
2435     
2436     // make a caret selection for the marker position, then extend it to the line
2437     // NOTE: ignores results of sel.modify because it returns false when
2438     // starting at an empty line.  The resulting selection in that case
2439     // will be a caret at visiblePos.
2440     SelectionController selection;
2441     selection.setSelection(VisibleSelection(visiblePos));
2442     selection.modify(SelectionController::AlterationExtend, DirectionRight, LineBoundary);
2443     
2444     return VisiblePositionRange(selection.selection().visibleStart(), selection.selection().visibleEnd());
2445 }
2446     
2447 VisiblePosition AccessibilityRenderObject::visiblePositionForIndex(int index) const
2448 {
2449     if (!m_renderer)
2450         return VisiblePosition();
2451     
2452     if (isNativeTextControl())
2453         return toRenderTextControl(m_renderer)->visiblePositionForIndex(index);
2454
2455     if (!allowsTextRanges() && !m_renderer->isText())
2456         return VisiblePosition();
2457     
2458     Node* node = m_renderer->node();
2459     if (!node)
2460         return VisiblePosition();
2461     
2462     if (index <= 0)
2463         return VisiblePosition(node, 0, DOWNSTREAM);
2464     
2465     ExceptionCode ec = 0;
2466     RefPtr<Range> range = Range::create(m_renderer->document());
2467     range->selectNodeContents(node, ec);
2468     CharacterIterator it(range.get());
2469     it.advance(index - 1);
2470     return VisiblePosition(it.range()->endContainer(ec), it.range()->endOffset(ec), UPSTREAM);
2471 }
2472     
2473 int AccessibilityRenderObject::indexForVisiblePosition(const VisiblePosition& pos) const
2474 {
2475     if (isNativeTextControl())
2476         return toRenderTextControl(m_renderer)->indexForVisiblePosition(pos);
2477     
2478     if (!isTextControl())
2479         return 0;
2480     
2481     Node* node = m_renderer->node();
2482     if (!node)
2483         return 0;
2484     
2485     Position indexPosition = pos.deepEquivalent();
2486     if (!indexPosition.node() || indexPosition.node()->rootEditableElement() != node)
2487         return 0;
2488     
2489     ExceptionCode ec = 0;
2490     RefPtr<Range> range = Range::create(m_renderer->document());
2491     range->setStart(node, 0, ec);
2492     range->setEnd(indexPosition.node(), indexPosition.deprecatedEditingOffset(), ec);
2493     return TextIterator::rangeLength(range.get());
2494 }
2495
2496 IntRect AccessibilityRenderObject::boundsForVisiblePositionRange(const VisiblePositionRange& visiblePositionRange) const
2497 {
2498     if (visiblePositionRange.isNull())
2499         return IntRect();
2500     
2501     // Create a mutable VisiblePositionRange.
2502     VisiblePositionRange range(visiblePositionRange);
2503     IntRect rect1 = range.start.absoluteCaretBounds();
2504     IntRect rect2 = range.end.absoluteCaretBounds();
2505     
2506     // readjust for position at the edge of a line.  This is to exclude line rect that doesn't need to be accounted in the range bounds
2507     if (rect2.y() != rect1.y()) {
2508         VisiblePosition endOfFirstLine = endOfLine(range.start);
2509         if (range.start == endOfFirstLine) {
2510             range.start.setAffinity(DOWNSTREAM);
2511             rect1 = range.start.absoluteCaretBounds();
2512         }
2513         if (range.end == endOfFirstLine) {
2514             range.end.setAffinity(UPSTREAM);
2515             rect2 = range.end.absoluteCaretBounds();
2516         }
2517     }
2518     
2519     IntRect ourrect = rect1;
2520     ourrect.unite(rect2);
2521     
2522     // if the rectangle spans lines and contains multiple text chars, use the range's bounding box intead
2523     if (rect1.bottom() != rect2.bottom()) {
2524         RefPtr<Range> dataRange = makeRange(range.start, range.end);
2525         IntRect boundingBox = dataRange->boundingBox();
2526         String rangeString = plainText(dataRange.get());
2527         if (rangeString.length() > 1 && !boundingBox.isEmpty())
2528             ourrect = boundingBox;
2529     }
2530     
2531 #if PLATFORM(MAC)
2532     return m_renderer->document()->view()->contentsToScreen(ourrect);
2533 #else
2534     return ourrect;
2535 #endif
2536 }
2537     
2538 void AccessibilityRenderObject::setSelectedVisiblePositionRange(const VisiblePositionRange& range) const
2539 {
2540     if (range.start.isNull() || range.end.isNull())
2541         return;
2542     
2543     // make selection and tell the document to use it. if it's zero length, then move to that position
2544     if (range.start == range.end)
2545         m_renderer->frame()->selection()->moveTo(range.start, true);
2546     else {
2547         VisibleSelection newSelection = VisibleSelection(range.start, range.end);
2548         m_renderer->frame()->selection()->setSelection(newSelection);
2549     }    
2550 }
2551
2552 VisiblePosition AccessibilityRenderObject::visiblePositionForPoint(const IntPoint& point) const
2553 {
2554     if (!m_renderer)
2555         return VisiblePosition();
2556     
2557     // convert absolute point to view coordinates
2558     FrameView* frameView = m_renderer->document()->topDocument()->renderer()->view()->frameView();
2559     RenderView* renderView = topRenderer();
2560     Node* innerNode = 0;
2561     
2562     // locate the node containing the point
2563     IntPoint pointResult;
2564     while (1) {
2565         IntPoint ourpoint;
2566 #if PLATFORM(MAC)
2567         ourpoint = frameView->screenToContents(point);
2568 #else
2569         ourpoint = point;
2570 #endif
2571         HitTestRequest request(HitTestRequest::ReadOnly |
2572                                HitTestRequest::Active);
2573         HitTestResult result(ourpoint);
2574         renderView->layer()->hitTest(request, result);
2575         innerNode = result.innerNode();
2576         if (!innerNode)
2577             return VisiblePosition();
2578         
2579         RenderObject* renderer = innerNode->renderer();
2580         if (!renderer)
2581             return VisiblePosition();
2582         
2583         pointResult = result.localPoint();
2584
2585         // done if hit something other than a widget
2586         if (!renderer->isWidget())
2587             break;
2588
2589         // descend into widget (FRAME, IFRAME, OBJECT...)
2590         Widget* widget = toRenderWidget(renderer)->widget();
2591         if (!widget || !widget->isFrameView())
2592             break;
2593         Frame* frame = static_cast<FrameView*>(widget)->frame();
2594         if (!frame)
2595             break;
2596         renderView = frame->document()->renderView();
2597         frameView = static_cast<FrameView*>(widget);
2598     }
2599     
2600     return innerNode->renderer()->positionForPoint(pointResult);
2601 }
2602
2603 // NOTE: Consider providing this utility method as AX API
2604 VisiblePosition AccessibilityRenderObject::visiblePositionForIndex(unsigned indexValue, bool lastIndexOK) const
2605 {
2606     if (!isTextControl())
2607         return VisiblePosition();
2608     
2609     // lastIndexOK specifies whether the position after the last character is acceptable
2610     if (indexValue >= text().length()) {
2611         if (!lastIndexOK || indexValue > text().length())
2612             return VisiblePosition();
2613     }
2614     VisiblePosition position = visiblePositionForIndex(indexValue);
2615     position.setAffinity(DOWNSTREAM);
2616     return position;
2617 }
2618
2619 // NOTE: Consider providing this utility method as AX API
2620 int AccessibilityRenderObject::index(const VisiblePosition& position) const
2621 {
2622     if (!isTextControl())
2623         return -1;
2624     
2625     Node* node = position.deepEquivalent().node();
2626     if (!node)
2627         return -1;
2628     
2629     for (RenderObject* renderer = node->renderer(); renderer && renderer->node(); renderer = renderer->parent()) {
2630         if (renderer == m_renderer)
2631             return indexForVisiblePosition(position);
2632     }
2633     
2634     return -1;
2635 }
2636
2637 // Given a line number, the range of characters of the text associated with this accessibility
2638 // object that contains the line number.
2639 PlainTextRange AccessibilityRenderObject::doAXRangeForLine(unsigned lineNumber) const
2640 {
2641     if (!isTextControl())
2642         return PlainTextRange();
2643     
2644     // iterate to the specified line
2645     VisiblePosition visiblePos = visiblePositionForIndex(0);
2646     VisiblePosition savedVisiblePos;
2647     for (unsigned lineCount = lineNumber; lineCount; lineCount -= 1) {
2648         savedVisiblePos = visiblePos;
2649         visiblePos = nextLinePosition(visiblePos, 0);
2650         if (visiblePos.isNull() || visiblePos == savedVisiblePos)
2651             return PlainTextRange();
2652     }
2653
2654     // Get the end of the line based on the starting position.
2655     VisiblePosition endPosition = endOfLine(visiblePos);
2656
2657     int index1 = indexForVisiblePosition(visiblePos);
2658     int index2 = indexForVisiblePosition(endPosition);
2659     
2660     // add one to the end index for a line break not caused by soft line wrap (to match AppKit)
2661     if (endPosition.affinity() == DOWNSTREAM && endPosition.next().isNotNull())
2662         index2 += 1;
2663     
2664     // return nil rather than an zero-length range (to match AppKit)
2665     if (index1 == index2)
2666         return PlainTextRange();
2667     
2668     return PlainTextRange(index1, index2 - index1);
2669 }
2670
2671 // The composed character range in the text associated with this accessibility object that
2672 // is specified by the given index value. This parameterized attribute returns the complete
2673 // range of characters (including surrogate pairs of multi-byte glyphs) at the given index.
2674 PlainTextRange AccessibilityRenderObject::doAXRangeForIndex(unsigned index) const
2675 {
2676     if (!isTextControl())
2677         return PlainTextRange();
2678     
2679     String elementText = text();
2680     if (!elementText.length() || index > elementText.length() - 1)
2681         return PlainTextRange();
2682     
2683     return PlainTextRange(index, 1);
2684 }
2685
2686 // A substring of the text associated with this accessibility object that is
2687 // specified by the given character range.
2688 String AccessibilityRenderObject::doAXStringForRange(const PlainTextRange& range) const
2689 {
2690     if (isPasswordField())
2691         return String();
2692     
2693     if (!range.length)
2694         return String();
2695     
2696     if (!isTextControl())
2697         return String();
2698     
2699     String elementText = text();
2700     if (range.start + range.length > elementText.length())
2701         return String();
2702     
2703     return elementText.substring(range.start, range.length);
2704 }
2705
2706 // The bounding rectangle of the text associated with this accessibility object that is
2707 // specified by the given range. This is the bounding rectangle a sighted user would see
2708 // on the display screen, in pixels.
2709 IntRect AccessibilityRenderObject::doAXBoundsForRange(const PlainTextRange& range) const
2710 {
2711     if (allowsTextRanges())
2712         return boundsForVisiblePositionRange(visiblePositionRangeForRange(range));
2713     return IntRect();
2714 }
2715
2716 AccessibilityObject* AccessibilityRenderObject::accessibilityImageMapHitTest(HTMLAreaElement* area, const IntPoint& point) const
2717 {
2718     if (!area)
2719         return 0;
2720     
2721     HTMLMapElement* map = static_cast<HTMLMapElement*>(area->parentNode());
2722     AccessibilityObject* parent = accessibilityParentForImageMap(map);
2723     if (!parent)
2724         return 0;
2725     
2726     AccessibilityObject::AccessibilityChildrenVector children = parent->children();
2727     
2728     unsigned count = children.size();
2729     for (unsigned k = 0; k < count; ++k) {
2730         if (children[k]->elementRect().contains(point))
2731             return children[k].get();
2732     }
2733     
2734     return 0;
2735 }
2736     
2737 AccessibilityObject* AccessibilityRenderObject::accessibilityHitTest(const IntPoint& point) const
2738 {
2739     if (!m_renderer || !m_renderer->hasLayer())
2740         return 0;
2741     
2742     RenderLayer* layer = toRenderBox(m_renderer)->layer();
2743      
2744     HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
2745     HitTestResult hitTestResult = HitTestResult(point);
2746     layer->hitTest(request, hitTestResult);
2747     if (!hitTestResult.innerNode())
2748         return 0;
2749     Node* node = hitTestResult.innerNode()->shadowAncestorNode();
2750
2751     if (node->hasTagName(areaTag)) 
2752         return accessibilityImageMapHitTest(static_cast<HTMLAreaElement*>(node), point);
2753     
2754     if (node->hasTagName(optionTag))
2755         node = static_cast<HTMLOptionElement*>(node)->ownerSelectElement();
2756     
2757     RenderObject* obj = node->renderer();
2758     if (!obj)
2759         return 0;
2760     
2761     AccessibilityObject* result = obj->document()->axObjectCache()->getOrCreate(obj);
2762     result->updateChildrenIfNecessary();
2763
2764     // Allow the element to perform any hit-testing it might need to do to reach non-render children.
2765     result = result->elementAccessibilityHitTest(point);
2766     
2767     if (result->accessibilityIsIgnored()) {
2768         // If this element is the label of a control, a hit test should return the control.
2769         AccessibilityObject* controlObject = result->correspondingControlForLabelElement();
2770         if (controlObject && !controlObject->exposesTitleUIElement())
2771             return controlObject;
2772
2773         result = result->parentObjectUnignored();
2774     }
2775
2776     return result;
2777 }
2778
2779 bool AccessibilityRenderObject::shouldFocusActiveDescendant() const
2780 {
2781     switch (ariaRoleAttribute()) {
2782     case GroupRole:
2783     case ComboBoxRole:
2784     case ListBoxRole:
2785     case MenuRole:
2786     case MenuBarRole:
2787     case RadioGroupRole:
2788     case RowRole:
2789     case PopUpButtonRole:
2790     case ProgressIndicatorRole:
2791     case ToolbarRole:
2792     case OutlineRole:
2793     case TreeRole:
2794     case GridRole:
2795     /* FIXME: replace these with actual roles when they are added to AccessibilityRole
2796     composite
2797     alert
2798     alertdialog
2799     status
2800     timer
2801     */
2802         return true;
2803     default:
2804         return false;
2805     }
2806 }
2807
2808 AccessibilityObject* AccessibilityRenderObject::activeDescendant() const
2809 {
2810     if (!m_renderer)
2811         return 0;
2812     
2813     if (m_renderer->node() && !m_renderer->node()->isElementNode())
2814         return 0;
2815     Element* element = static_cast<Element*>(m_renderer->node());
2816         
2817     const AtomicString& activeDescendantAttrStr = element->getAttribute(aria_activedescendantAttr);
2818     if (activeDescendantAttrStr.isNull() || activeDescendantAttrStr.isEmpty())
2819         return 0;
2820     
2821     Element* target = document()->getElementById(activeDescendantAttrStr);
2822     if (!target)
2823         return 0;
2824     
2825     AccessibilityObject* obj = axObjectCache()->getOrCreate(target->renderer());
2826     if (obj && obj->isAccessibilityRenderObject())
2827     // an activedescendant is only useful if it has a renderer, because that's what's needed to post the notification
2828         return obj;
2829     return 0;
2830 }
2831
2832 void AccessibilityRenderObject::handleAriaExpandedChanged()
2833 {
2834     // Find if a parent of this object should handle aria-expanded changes.
2835     AccessibilityObject* containerParent = this->parentObject();
2836     while (containerParent) {
2837         bool foundParent = false;
2838         
2839         switch (containerParent->roleValue()) {
2840         case TreeRole:
2841         case TreeGridRole:
2842         case GridRole:
2843         case TableRole:
2844         case BrowserRole:
2845             foundParent = true;
2846             break;
2847         default:
2848             break;
2849         }
2850         
2851         if (foundParent)
2852             break;
2853         
2854         containerParent = containerParent->parentObject();
2855     }
2856     
2857     // Post that the row count changed.
2858     if (containerParent)
2859         axObjectCache()->postNotification(containerParent, document(), AXObjectCache::AXRowCountChanged, true);
2860
2861     // Post that the specific row either collapsed or expanded.
2862     if (roleValue() == RowRole || roleValue() == TreeItemRole)
2863         axObjectCache()->postNotification(this, document(), isExpanded() ? AXObjectCache::AXRowExpanded : AXObjectCache::AXRowCollapsed, true);
2864 }
2865
2866 void AccessibilityRenderObject::handleActiveDescendantChanged()
2867 {
2868     Element* element = static_cast<Element*>(renderer()->node());
2869     if (!element)
2870         return;
2871     Document* doc = renderer()->document();
2872     if (!doc->frame()->selection()->isFocusedAndActive() || doc->focusedNode() != element)
2873         return; 
2874     AccessibilityRenderObject* activedescendant = static_cast<AccessibilityRenderObject*>(activeDescendant());
2875     
2876     if (activedescendant && shouldFocusActiveDescendant())
2877         doc->axObjectCache()->postNotification(m_renderer, AXObjectCache::AXActiveDescendantChanged, true);
2878 }
2879
2880 AccessibilityObject* AccessibilityRenderObject::correspondingControlForLabelElement() const
2881 {
2882     HTMLLabelElement* labelElement = labelElementContainer();
2883     if (!labelElement)
2884         return 0;
2885     
2886     HTMLElement* correspondingControl = labelElement->control();
2887     if (!correspondingControl)
2888         return 0;
2889     
2890     return axObjectCache()->getOrCreate(correspondingControl->renderer());     
2891 }
2892
2893 AccessibilityObject* AccessibilityRenderObject::correspondingLabelForControlElement() const
2894 {
2895     if (!m_renderer)
2896         return 0;
2897
2898     Node* node = m_renderer->node();
2899     if (node && node->isHTMLElement()) {
2900         HTMLLabelElement* label = labelForElement(static_cast<Element*>(node));
2901         if (label)
2902             return axObjectCache()->getOrCreate(label->renderer());
2903     }
2904
2905     return 0;
2906 }
2907
2908 bool AccessibilityRenderObject::renderObjectIsObservable(RenderObject* renderer) const
2909 {
2910     // AX clients will listen for AXValueChange on a text control.
2911     if (renderer->isTextControl())
2912         return true;
2913     
2914     // AX clients will listen for AXSelectedChildrenChanged on listboxes.
2915     Node* node = renderer->node();
2916     if (nodeHasRole(node, "listbox") || (renderer->isBoxModelObject() && toRenderBoxModelObject(renderer)->isListBox()))
2917         return true;
2918
2919     // Textboxes should send out notifications.
2920     if (nodeHasRole(node, "textbox"))
2921         return true;
2922     
2923     return false;
2924 }
2925     
2926 AccessibilityObject* AccessibilityRenderObject::observableObject() const
2927 {
2928     // Find the object going up the parent chain that is used in accessibility to monitor certain notifications.
2929     for (RenderObject* renderer = m_renderer; renderer && renderer->node(); renderer = renderer->parent()) {
2930         if (renderObjectIsObservable(renderer))
2931             return axObjectCache()->getOrCreate(renderer);
2932     }
2933     
2934     return 0;
2935 }
2936
2937 AccessibilityRole AccessibilityRenderObject::determineAriaRoleAttribute() const
2938 {
2939     const AtomicString& ariaRole = getAttribute(roleAttr);
2940     if (ariaRole.isNull() || ariaRole.isEmpty())
2941         return UnknownRole;
2942     
2943     AccessibilityRole role = ariaRoleToWebCoreRole(ariaRole);
2944
2945     if (role == ButtonRole && ariaHasPopup())
2946         role = PopUpButtonRole;
2947
2948     if (role == TextAreaRole && ariaIsMultiline())
2949         role = TextFieldRole;
2950     
2951     if (role)
2952         return role;
2953     // selects and listboxes both have options as child roles, but they map to different roles within WebCore
2954     if (equalIgnoringCase(ariaRole, "option")) {
2955         if (parentObjectUnignored()->ariaRoleAttribute() == MenuRole)
2956             return MenuItemRole;
2957         if (parentObjectUnignored()->ariaRoleAttribute() == ListBoxRole)
2958             return ListBoxOptionRole;
2959     }
2960     // an aria "menuitem" may map to MenuButton or MenuItem depending on its parent
2961     if (equalIgnoringCase(ariaRole, "menuitem")) {
2962         if (parentObjectUnignored()->ariaRoleAttribute() == GroupRole)
2963             return MenuButtonRole;
2964         if (parentObjectUnignored()->ariaRoleAttribute() == MenuRole)
2965             return MenuItemRole;
2966     }
2967     
2968     return UnknownRole;
2969 }
2970
2971 AccessibilityRole AccessibilityRenderObject::ariaRoleAttribute() const
2972 {
2973     return m_ariaRole;
2974 }
2975     
2976 void AccessibilityRenderObject::updateAccessibilityRole()
2977 {
2978     bool ignoredStatus = accessibilityIsIgnored();
2979     m_role = determineAccessibilityRole();
2980     
2981     // The AX hierarchy only needs to be updated if the ignored status of an element has changed.
2982     if (ignoredStatus != accessibilityIsIgnored())
2983         childrenChanged();
2984 }
2985     
2986 AccessibilityRole AccessibilityRenderObject::determineAccessibilityRole()
2987 {
2988     if (!m_renderer)
2989         return UnknownRole;
2990
2991     m_ariaRole = determineAriaRoleAttribute();
2992     
2993     Node* node = m_renderer->node();
2994     AccessibilityRole ariaRole = ariaRoleAttribute();
2995     if (ariaRole != UnknownRole)
2996         return ariaRole;
2997
2998     RenderBoxModelObject* cssBox = renderBoxModelObject();
2999
3000     if (node && node->isLink()) {
3001         if (cssBox && cssBox->isImage())
3002             return ImageMapRole;
3003         return WebCoreLinkRole;
3004     }
3005     if (cssBox && cssBox->isListItem())
3006         return ListItemRole;
3007     if (m_renderer->isListMarker())
3008         return ListMarkerRole;
3009     if (node && node->hasTagName(buttonTag))
3010         return ButtonRole;
3011     if (m_renderer->isText())
3012         return StaticTextRole;
3013     if (cssBox && cssBox->isImage()) {
3014         if (node && node->hasTagName(inputTag))
3015             return ButtonRole;
3016         return ImageRole;
3017     }
3018     if (node && node->hasTagName(canvasTag))
3019         return ImageRole;
3020
3021     if (cssBox && cssBox->isRenderView())
3022         return WebAreaRole;
3023     
3024     if (cssBox && cssBox->isTextField())
3025         return TextFieldRole;
3026     
3027     if (cssBox && cssBox->isTextArea())
3028         return TextAreaRole;
3029
3030     if (node && node->hasTagName(inputTag)) {
3031         HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
3032         if (input->isCheckbox())
3033             return CheckBoxRole;
3034         if (input->isRadioButton())
3035             return RadioButtonRole;
3036         if (input->isTextButton())
3037             return ButtonRole;
3038     }
3039
3040     if (node && node->hasTagName(buttonTag))
3041         return ButtonRole;
3042
3043     if (isFileUploadButton())
3044         return ButtonRole;
3045     
3046     if (cssBox && cssBox->isMenuList())
3047         return PopUpButtonRole;
3048     
3049     if (headingLevel())
3050         return HeadingRole;
3051     
3052     if (node && node->hasTagName(ddTag))
3053         return DefinitionListDefinitionRole;
3054     
3055     if (node && node->hasTagName(dtTag))
3056         return DefinitionListTermRole;
3057
3058     if (node && (node->hasTagName(rpTag) || node->hasTagName(rtTag)))
3059         return AnnotationRole;
3060
3061 #if PLATFORM(GTK)
3062     // Gtk ATs expect all tables, data and layout, to be exposed as tables.
3063     if (node && (node->hasTagName(tdTag) || node->hasTagName(thTag)))
3064         return CellRole;
3065
3066     if (node && node->hasTagName(trTag))
3067         return RowRole;
3068
3069     if (node && node->hasTagName(tableTag))
3070         return TableRole;
3071 #endif
3072
3073     // Table sections should be ignored.
3074     if (m_renderer->isTableSection())
3075         return IgnoredRole;
3076     
3077 #if PLATFORM(GTK)
3078     if (m_renderer->isHR())
3079         return SplitterRole;
3080 #endif
3081
3082     if (m_renderer->isBlockFlow() || (node && node->hasTagName(labelTag)))
3083         return GroupRole;
3084     
3085     // If the element does not have role, but it has ARIA attributes, accessibility should fallback to exposing it as a group.
3086     if (supportsARIAAttributes())
3087         return GroupRole;
3088     
3089     return UnknownRole;
3090 }
3091
3092 AccessibilityOrientation AccessibilityRenderObject::orientation() const
3093 {
3094     const AtomicString& ariaOrientation = getAttribute(aria_orientationAttr);
3095     if (equalIgnoringCase(ariaOrientation, "horizontal"))
3096         return AccessibilityOrientationHorizontal;
3097     if (equalIgnoringCase(ariaOrientation, "vertical"))
3098         return AccessibilityOrientationVertical;
3099     
3100     return AccessibilityObject::orientation();
3101 }
3102     
3103 bool AccessibilityRenderObject::inheritsPresentationalRole() const
3104 {
3105     // ARIA spec says that when a parent object is presentational, and it has required child elements,
3106     // those child elements are also presentational. For example, <li> becomes presentational from <ul>.
3107     // http://www.w3.org/WAI/PF/aria/complete#presentation
3108     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, listItemParents, ());
3109
3110     HashSet<QualifiedName>* possibleParentTagNames = 0;
3111     switch (roleValue()) {
3112     case ListItemRole:
3113     case ListMarkerRole:
3114         if (listItemParents.isEmpty()) {
3115             listItemParents.add(ulTag);
3116             listItemParents.add(olTag);
3117             listItemParents.add(dlTag);
3118         }
3119         possibleParentTagNames = &listItemParents;
3120         break;
3121     default:
3122         break;
3123     }
3124     
3125     // Not all elements need to check for this, only ones that are required children.
3126     if (!possibleParentTagNames)
3127         return false;
3128     
3129     for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) { 
3130         if (!parent->isAccessibilityRenderObject())
3131             continue;
3132         
3133         Node* elementNode = static_cast<AccessibilityRenderObject*>(parent)->node();
3134         if (!elementNode || !elementNode->isElementNode())
3135             continue;
3136         
3137         // If native tag of the parent element matches an acceptable name, then return
3138         // based on its presentational status.
3139         if (possibleParentTagNames->contains(static_cast<Element*>(elementNode)->tagQName()))
3140             return parent->roleValue() == PresentationalRole;
3141     }
3142     
3143     return false;
3144 }
3145     
3146 bool AccessibilityRenderObject::isPresentationalChildOfAriaRole() const
3147 {
3148     // Walk the parent chain looking for a parent that has presentational children
3149     AccessibilityObject* parent;
3150     for (parent = parentObject(); parent && !parent->ariaRoleHasPresentationalChildren(); parent = parent->parentObject())
3151     { }
3152     
3153     return parent;
3154 }
3155     
3156 bool AccessibilityRenderObject::ariaRoleHasPresentationalChildren() const
3157 {
3158     switch (m_ariaRole) {
3159     case ButtonRole:
3160     case SliderRole:
3161     case ImageRole:
3162     case ProgressIndicatorRole:
3163     // case SeparatorRole:
3164         return true;
3165     default:
3166         return false;
3167     }
3168 }
3169
3170 bool AccessibilityRenderObject::canSetFocusAttribute() const
3171 {
3172     ASSERT(m_renderer);
3173     Node* node = m_renderer->node();
3174
3175     // NOTE: It would be more accurate to ask the document whether setFocusedNode() would
3176     // do anything.  For example, setFocusedNode() will do nothing if the current focused
3177     // node will not relinquish the focus.
3178     if (!node || !node->isElementNode())
3179         return false;
3180
3181     if (!static_cast<Element*>(node)->isEnabledFormControl())
3182         return false;
3183
3184     switch (roleValue()) {
3185     case WebCoreLinkRole:
3186     case ImageMapLinkRole:
3187     case TextFieldRole:
3188     case TextAreaRole:
3189     case ButtonRole:
3190     case PopUpButtonRole:
3191     case CheckBoxRole:
3192     case RadioButtonRole:
3193     case SliderRole:
3194         return true;
3195     default:
3196         return node->supportsFocus();
3197     }
3198 }
3199     
3200 bool AccessibilityRenderObject::canSetExpandedAttribute() const
3201 {
3202     // An object can be expanded if it aria-expanded is true or false.
3203     const AtomicString& ariaExpanded = getAttribute(aria_expandedAttr);
3204     return equalIgnoringCase(ariaExpanded, "true") || equalIgnoringCase(ariaExpanded, "false");
3205 }
3206
3207 bool AccessibilityRenderObject::canSetValueAttribute() const
3208 {
3209     if (equalIgnoringCase(getAttribute(aria_readonlyAttr), "true"))
3210         return false;
3211
3212     // Any node could be contenteditable, so isReadOnly should be relied upon
3213     // for this information for all elements.
3214     return isProgressIndicator() || isSlider() || !isReadOnly();
3215 }
3216
3217 bool AccessibilityRenderObject::canSetTextRangeAttributes() const
3218 {
3219     return isTextControl();
3220 }
3221
3222 void AccessibilityRenderObject::contentChanged()
3223 {
3224     // If this element supports ARIA live regions, then notify the AT of changes.
3225     AXObjectCache* cache = axObjectCache();
3226     for (RenderObject* renderParent = m_renderer; renderParent; renderParent = renderParent->parent()) {
3227         AccessibilityObject* parent = cache->get(renderParent);
3228         if (!parent)
3229             continue;
3230         
3231         // If we find a parent that has ARIA live region on, send the notification and stop processing.
3232         // The spec does not talk about nested live regions.
3233         if (parent->supportsARIALiveRegion()) {
3234             axObjectCache()->postNotification(renderParent, AXObjectCache::AXLiveRegionChanged, true);
3235             break;
3236         }
3237     }
3238 }
3239     
3240 void AccessibilityRenderObject::childrenChanged()
3241 {
3242     // This method is meant as a quick way of marking a portion of the accessibility tree dirty.
3243     if (!m_renderer)
3244         return;
3245     
3246     bool sentChildrenChanged = false;
3247     
3248     // Go up the accessibility parent chain, but only if the element already exists. This method is
3249     // called during render layouts, minimal work should be done. 
3250     // If AX elements are created now, they could interrogate the render tree while it's in a funky state.
3251     // At the same time, process ARIA live region changes.
3252     for (AccessibilityObject* parent = this; parent; parent = parent->parentObjectIfExists()) {
3253         if (!parent->isAccessibilityRenderObject())
3254             continue;
3255         
3256         AccessibilityRenderObject* axParent = static_cast<AccessibilityRenderObject*>(parent);
3257         
3258         // Send the children changed notification on the first accessibility render object ancestor.
3259         if (!sentChildrenChanged) {
3260             axObjectCache()->postNotification(axParent->renderer(), AXObjectCache::AXChildrenChanged, true);
3261             sentChildrenChanged = true;
3262         }
3263         
3264         // Only do work if the children haven't been marked dirty. This has the effect of blocking
3265         // future live region change notifications until the AX tree has been accessed again. This
3266         // is a good performance win for all parties.
3267         if (!axParent->needsToUpdateChildren()) {
3268             axParent->setNeedsToUpdateChildren();
3269             
3270             // If this element supports ARIA live regions, then notify the AT of changes.
3271             if (axParent->supportsARIALiveRegion())
3272                 axObjectCache()->postNotification(axParent->renderer(), AXObjectCache::AXLiveRegionChanged, true);
3273         }
3274     }
3275 }
3276     
3277 bool AccessibilityRenderObject::canHaveChildren() const
3278 {
3279     if (!m_renderer)
3280         return false;
3281     
3282     // Elements that should not have children
3283     switch (roleValue()) {
3284     case ImageRole:
3285     case ButtonRole:
3286     case PopUpButtonRole:
3287     case CheckBoxRole:
3288     case RadioButtonRole:
3289     case TabRole:
3290     case StaticTextRole:
3291     case ListBoxOptionRole:
3292     case ScrollBarRole:
3293         return false;
3294     default:
3295         return true;
3296     }
3297 }
3298
3299 void AccessibilityRenderObject::clearChildren()
3300 {
3301     AccessibilityObject::clearChildren();
3302     m_childrenDirty = false;
3303 }
3304     
3305 void AccessibilityRenderObject::updateChildrenIfNecessary()
3306 {
3307     if (needsToUpdateChildren())
3308         clearChildren();        
3309     
3310     AccessibilityObject::updateChildrenIfNecessary();
3311 }
3312     
3313 const AccessibilityObject::AccessibilityChildrenVector& AccessibilityRenderObject::children()
3314 {
3315     updateChildrenIfNecessary();
3316     
3317     return m_children;
3318 }
3319
3320 void AccessibilityRenderObject::addChildren()
3321 {
3322     // If the need to add more children in addition to existing children arises, 
3323     // childrenChanged should have been called, leaving the object with no children.
3324     ASSERT(!m_haveChildren); 
3325     
3326     // nothing to add if there is no RenderObject
3327     if (!m_renderer)
3328         return;
3329     
3330     m_haveChildren = true;
3331     
3332     if (!canHaveChildren())
3333         return;
3334     
3335     // add all unignored acc children
3336     for (RefPtr<AccessibilityObject> obj = firstChild(); obj; obj = obj->nextSibling()) {
3337         if (obj->accessibilityIsIgnored()) {
3338             obj->updateChildrenIfNecessary();
3339             AccessibilityChildrenVector children = obj->children();
3340             unsigned length = children.size();
3341             for (unsigned i = 0; i < length; ++i)
3342                 m_children.append(children[i]);
3343         } else {
3344             ASSERT(obj->parentObject() == this);
3345             m_children.append(obj);
3346         }
3347     }
3348     
3349     // FrameView's need to be inserted into the AX hierarchy when encountered.
3350     if (isAttachment()) {
3351         Widget* widget = widgetForAttachmentView();
3352         if (widget && widget->isFrameView())
3353             m_children.append(axObjectCache()->getOrCreate(widget));
3354     }
3355     
3356     // for a RenderImage, add the <area> elements as individual accessibility objects
3357     RenderBoxModelObject* cssBox = renderBoxModelObject();
3358     if (cssBox && cssBox->isRenderImage()) {
3359         HTMLMapElement* map = toRenderImage(cssBox)->imageMap();
3360         if (map) {
3361             for (Node* current = map->firstChild(); current; current = current->traverseNextNode(map)) {
3362
3363                 // add an <area> element for this child if it has a link
3364                 if (current->hasTagName(areaTag) && current->isLink()) {
3365                     AccessibilityImageMapLink* areaObject = static_cast<AccessibilityImageMapLink*>(axObjectCache()->getOrCreate(ImageMapLinkRole));
3366                     areaObject->setHTMLAreaElement(static_cast<HTMLAreaElement*>(current));
3367                     areaObject->setHTMLMapElement(map);
3368                     areaObject->setParent(this);
3369
3370                     m_children.append(areaObject);
3371                 }
3372             }
3373         }
3374     }
3375 }
3376         
3377 const AtomicString& AccessibilityRenderObject::ariaLiveRegionStatus() const
3378 {
3379     DEFINE_STATIC_LOCAL(const AtomicString, liveRegionStatusAssertive, ("assertive"));
3380     DEFINE_STATIC_LOCAL(const AtomicString, liveRegionStatusPolite, ("polite"));
3381     DEFINE_STATIC_LOCAL(const AtomicString, liveRegionStatusOff, ("off"));
3382     
3383     const AtomicString& liveRegionStatus = getAttribute(aria_liveAttr);
3384     // These roles have implicit live region status.
3385     if (liveRegionStatus.isEmpty()) {
3386         switch (roleValue()) {
3387         case ApplicationAlertD