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