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 "AccessibilitySVGRoot.h"
36#include "AccessibilitySpinButton.h"
37#include "AccessibilityTable.h"
38#include "CachedImage.h"
39#include "Chrome.h"
40#include "EventNames.h"
41#include "FloatRect.h"
42#include "Frame.h"
43#include "FrameLoader.h"
44#include "FrameSelection.h"
45#include "HTMLAreaElement.h"
46#include "HTMLFormElement.h"
47#include "HTMLFrameElementBase.h"
48#include "HTMLImageElement.h"
49#include "HTMLInputElement.h"
50#include "HTMLLabelElement.h"
51#include "HTMLMapElement.h"
52#include "HTMLNames.h"
53#include "HTMLOptGroupElement.h"
54#include "HTMLOptionElement.h"
55#include "HTMLOptionsCollection.h"
56#include "HTMLSelectElement.h"
57#include "HTMLTextAreaElement.h"
58#include "HitTestRequest.h"
59#include "HitTestResult.h"
60#include "Image.h"
61#include "LocalizedStrings.h"
62#include "MathMLNames.h"
63#include "NodeList.h"
64#include "NodeTraversal.h"
65#include "Page.h"
66#include "ProgressTracker.h"
67#include "RenderButton.h"
68#include "RenderFieldset.h"
69#include "RenderFileUploadControl.h"
70#include "RenderHTMLCanvas.h"
71#include "RenderImage.h"
72#include "RenderInline.h"
73#include "RenderLayer.h"
74#include "RenderListBox.h"
75#include "RenderListMarker.h"
76#include "RenderMathMLBlock.h"
77#include "RenderMathMLFraction.h"
78#include "RenderMathMLOperator.h"
79#include "RenderMenuList.h"
80#include "RenderSVGShape.h"
81#include "RenderText.h"
82#include "RenderTextControl.h"
83#include "RenderTextControlSingleLine.h"
84#include "RenderTextFragment.h"
85#include "RenderTheme.h"
86#include "RenderView.h"
87#include "RenderWidget.h"
88#include "RenderedPosition.h"
89#include "SVGDocument.h"
90#include "SVGImage.h"
91#include "SVGImageChromeClient.h"
92#include "SVGNames.h"
93#include "SVGSVGElement.h"
94#include "Text.h"
95#include "TextControlInnerElements.h"
96#include "VisibleUnits.h"
97#include "htmlediting.h"
98#include <wtf/StdLibExtras.h>
99#include <wtf/text/StringBuilder.h>
100#include <wtf/unicode/CharacterNames.h>
101
102using namespace std;
103
104namespace WebCore {
105
106using namespace HTMLNames;
107
108AccessibilityRenderObject::AccessibilityRenderObject(RenderObject* renderer)
109    : AccessibilityNodeObject(renderer->node())
110    , m_renderer(renderer)
111{
112#ifndef NDEBUG
113    m_renderer->setHasAXObject(true);
114#endif
115}
116
117AccessibilityRenderObject::~AccessibilityRenderObject()
118{
119    ASSERT(isDetached());
120}
121
122void AccessibilityRenderObject::init()
123{
124    AccessibilityNodeObject::init();
125}
126
127PassRefPtr<AccessibilityRenderObject> AccessibilityRenderObject::create(RenderObject* renderer)
128{
129    return adoptRef(new AccessibilityRenderObject(renderer));
130}
131
132void AccessibilityRenderObject::detach()
133{
134    AccessibilityNodeObject::detach();
135
136    detachRemoteSVGRoot();
137
138#ifndef NDEBUG
139    if (m_renderer)
140        m_renderer->setHasAXObject(false);
141#endif
142    m_renderer = 0;
143}
144
145RenderBoxModelObject* AccessibilityRenderObject::renderBoxModelObject() const
146{
147    if (!m_renderer || !m_renderer->isBoxModelObject())
148        return 0;
149    return toRenderBoxModelObject(m_renderer);
150}
151
152void AccessibilityRenderObject::setRenderer(RenderObject* renderer)
153{
154    m_renderer = renderer;
155    setNode(renderer->node());
156}
157
158static inline bool isInlineWithContinuation(RenderObject* object)
159{
160    if (!object->isBoxModelObject())
161        return false;
162
163    RenderBoxModelObject* renderer = toRenderBoxModelObject(object);
164    if (!renderer->isRenderInline())
165        return false;
166
167    return toRenderInline(renderer)->continuation();
168}
169
170static inline RenderObject* firstChildInContinuation(RenderObject* renderer)
171{
172    RenderObject* r = toRenderInline(renderer)->continuation();
173
174    while (r) {
175        if (r->isRenderBlock())
176            return r;
177        if (RenderObject* child = r->firstChild())
178            return child;
179        r = toRenderInline(r)->continuation();
180    }
181
182    return 0;
183}
184
185static inline RenderObject* firstChildConsideringContinuation(RenderObject* renderer)
186{
187    RenderObject* firstChild = renderer->firstChild();
188
189    if (!firstChild && isInlineWithContinuation(renderer))
190        firstChild = firstChildInContinuation(renderer);
191
192    return firstChild;
193}
194
195
196static inline RenderObject* lastChildConsideringContinuation(RenderObject* renderer)
197{
198    RenderObject* lastChild = renderer->lastChild();
199    RenderObject* prev;
200    RenderObject* cur = renderer;
201
202    if (!cur->isRenderInline() && !cur->isRenderBlock())
203        return renderer;
204
205    while (cur) {
206        prev = cur;
207
208        if (RenderObject* lc = cur->lastChild())
209            lastChild = lc;
210
211        if (cur->isRenderInline()) {
212            cur = toRenderInline(cur)->inlineElementContinuation();
213            ASSERT_UNUSED(prev, cur || !toRenderInline(prev)->continuation());
214        } else
215            cur = toRenderBlock(cur)->inlineElementContinuation();
216    }
217
218    return lastChild;
219}
220
221AccessibilityObject* AccessibilityRenderObject::firstChild() const
222{
223    if (!m_renderer)
224        return 0;
225
226    RenderObject* firstChild = firstChildConsideringContinuation(m_renderer);
227
228    // If an object can't have children, then it is using this method to help
229    // calculate some internal property (like its description).
230    // In this case, it should check the Node level for children in case they're
231    // not rendered (like a <meter> element).
232    if (!firstChild && !canHaveChildren())
233        return AccessibilityNodeObject::firstChild();
234
235    return axObjectCache()->getOrCreate(firstChild);
236}
237
238AccessibilityObject* AccessibilityRenderObject::lastChild() const
239{
240    if (!m_renderer)
241        return 0;
242
243    RenderObject* lastChild = lastChildConsideringContinuation(m_renderer);
244
245    if (!lastChild && !canHaveChildren())
246        return AccessibilityNodeObject::lastChild();
247
248    return axObjectCache()->getOrCreate(lastChild);
249}
250
251static inline RenderInline* startOfContinuations(RenderObject* r)
252{
253    if (r->isInlineElementContinuation()) {
254#if ENABLE(MATHML)
255        // MathML elements make anonymous RenderObjects, then set their node to the parent's node.
256        // This makes it so that the renderer() != renderer()->node()->renderer()
257        // (which is what isInlineElementContinuation() uses as a determinant).
258        if (r->node()->isElementNode() && toElement(r->node())->isMathMLElement())
259            return 0;
260#endif
261
262        return toRenderInline(r->node()->renderer());
263    }
264
265    // Blocks with a previous continuation always have a next continuation
266    if (r->isRenderBlock() && toRenderBlock(r)->inlineElementContinuation())
267        return toRenderInline(toRenderBlock(r)->inlineElementContinuation()->node()->renderer());
268
269    return 0;
270}
271
272static inline RenderObject* endOfContinuations(RenderObject* renderer)
273{
274    RenderObject* prev = renderer;
275    RenderObject* cur = renderer;
276
277    if (!cur->isRenderInline() && !cur->isRenderBlock())
278        return renderer;
279
280    while (cur) {
281        prev = cur;
282        if (cur->isRenderInline()) {
283            cur = toRenderInline(cur)->inlineElementContinuation();
284            ASSERT(cur || !toRenderInline(prev)->continuation());
285        } else
286            cur = toRenderBlock(cur)->inlineElementContinuation();
287    }
288
289    return prev;
290}
291
292
293static inline RenderObject* childBeforeConsideringContinuations(RenderInline* r, RenderObject* child)
294{
295    RenderBoxModelObject* curContainer = r;
296    RenderObject* cur = 0;
297    RenderObject* prev = 0;
298
299    while (curContainer) {
300        if (curContainer->isRenderInline()) {
301            cur = curContainer->firstChild();
302            while (cur) {
303                if (cur == child)
304                    return prev;
305                prev = cur;
306                cur = cur->nextSibling();
307            }
308
309            curContainer = toRenderInline(curContainer)->continuation();
310        } else if (curContainer->isRenderBlock()) {
311            if (curContainer == child)
312                return prev;
313
314            prev = curContainer;
315            curContainer = toRenderBlock(curContainer)->inlineElementContinuation();
316        }
317    }
318
319    ASSERT_NOT_REACHED();
320
321    return 0;
322}
323
324static inline bool firstChildIsInlineContinuation(RenderObject* renderer)
325{
326    return renderer->firstChild() && renderer->firstChild()->isInlineElementContinuation();
327}
328
329AccessibilityObject* AccessibilityRenderObject::previousSibling() const
330{
331    if (!m_renderer)
332        return 0;
333
334    RenderObject* previousSibling = 0;
335
336    // Case 1: The node is a block and is an inline's continuation. In that case, the inline's
337    // last child is our previous sibling (or further back in the continuation chain)
338    RenderInline* startOfConts;
339    if (m_renderer->isRenderBlock() && (startOfConts = startOfContinuations(m_renderer)))
340        previousSibling = childBeforeConsideringContinuations(startOfConts, m_renderer);
341
342    // Case 2: Anonymous block parent of the end of a continuation - skip all the way to before
343    // the parent of the start, since everything in between will be linked up via the continuation.
344    else if (m_renderer->isAnonymousBlock() && firstChildIsInlineContinuation(m_renderer)) {
345        RenderObject* firstParent = startOfContinuations(m_renderer->firstChild())->parent();
346        while (firstChildIsInlineContinuation(firstParent))
347            firstParent = startOfContinuations(firstParent->firstChild())->parent();
348        previousSibling = firstParent->previousSibling();
349    }
350
351    // Case 3: The node has an actual previous sibling
352    else if (RenderObject* ps = m_renderer->previousSibling())
353        previousSibling = ps;
354
355    // Case 4: This node has no previous siblings, but its parent is an inline,
356    // and is another node's inline continutation. Follow the continuation chain.
357    else if (m_renderer->parent()->isRenderInline() && (startOfConts = startOfContinuations(m_renderer->parent())))
358        previousSibling = childBeforeConsideringContinuations(startOfConts, m_renderer->parent()->firstChild());
359
360    if (!previousSibling)
361        return 0;
362
363    return axObjectCache()->getOrCreate(previousSibling);
364}
365
366static inline bool lastChildHasContinuation(RenderObject* renderer)
367{
368    return renderer->lastChild() && isInlineWithContinuation(renderer->lastChild());
369}
370
371AccessibilityObject* AccessibilityRenderObject::nextSibling() const
372{
373    if (!m_renderer)
374        return 0;
375
376    RenderObject* nextSibling = 0;
377
378    // Case 1: node is a block and has an inline continuation. Next sibling is the inline continuation's
379    // first child.
380    RenderInline* inlineContinuation;
381    if (m_renderer->isRenderBlock() && (inlineContinuation = toRenderBlock(m_renderer)->inlineElementContinuation()))
382        nextSibling = firstChildConsideringContinuation(inlineContinuation);
383
384    // Case 2: Anonymous block parent of the start of a continuation - skip all the way to
385    // after the parent of the end, since everything in between will be linked up via the continuation.
386    else if (m_renderer->isAnonymousBlock() && lastChildHasContinuation(m_renderer)) {
387        RenderObject* lastParent = endOfContinuations(m_renderer->lastChild())->parent();
388        while (lastChildHasContinuation(lastParent))
389            lastParent = endOfContinuations(lastParent->lastChild())->parent();
390        nextSibling = lastParent->nextSibling();
391    }
392
393    // Case 3: node has an actual next sibling
394    else if (RenderObject* ns = m_renderer->nextSibling())
395        nextSibling = ns;
396
397    // Case 4: node is an inline with a continuation. Next sibling is the next sibling of the end
398    // of the continuation chain.
399    else if (isInlineWithContinuation(m_renderer))
400        nextSibling = endOfContinuations(m_renderer)->nextSibling();
401
402    // Case 5: node has no next sibling, and its parent is an inline with a continuation.
403    else if (isInlineWithContinuation(m_renderer->parent())) {
404        RenderObject* continuation = toRenderInline(m_renderer->parent())->continuation();
405
406        // Case 5a: continuation is a block - in this case the block itself is the next sibling.
407        if (continuation->isRenderBlock())
408            nextSibling = continuation;
409        // Case 5b: continuation is an inline - in this case the inline's first child is the next sibling
410        else
411            nextSibling = firstChildConsideringContinuation(continuation);
412    }
413
414    if (!nextSibling)
415        return 0;
416
417    return axObjectCache()->getOrCreate(nextSibling);
418}
419
420static RenderBoxModelObject* nextContinuation(RenderObject* renderer)
421{
422    ASSERT(renderer);
423    if (renderer->isRenderInline() && !renderer->isReplaced())
424        return toRenderInline(renderer)->continuation();
425    if (renderer->isRenderBlock())
426        return toRenderBlock(renderer)->inlineElementContinuation();
427    return 0;
428}
429
430RenderObject* AccessibilityRenderObject::renderParentObject() const
431{
432    if (!m_renderer)
433        return 0;
434
435    RenderObject* parent = m_renderer->parent();
436
437    // Case 1: node is a block and is an inline's continuation. Parent
438    // is the start of the continuation chain.
439    RenderObject* startOfConts = 0;
440    RenderObject* firstChild = 0;
441    if (m_renderer->isRenderBlock() && (startOfConts = startOfContinuations(m_renderer)))
442        parent = startOfConts;
443
444    // Case 2: node's parent is an inline which is some node's continuation; parent is
445    // the earliest node in the continuation chain.
446    else if (parent && parent->isRenderInline() && (startOfConts = startOfContinuations(parent)))
447        parent = startOfConts;
448
449    // Case 3: The first sibling is the beginning of a continuation chain. Find the origin of that continuation.
450    else if (parent && (firstChild = parent->firstChild()) && firstChild->node()) {
451        // Get the node's renderer and follow that continuation chain until the first child is found
452        RenderObject* nodeRenderFirstChild = firstChild->node()->renderer();
453        while (nodeRenderFirstChild != firstChild) {
454            for (RenderObject* contsTest = nodeRenderFirstChild; contsTest; contsTest = nextContinuation(contsTest)) {
455                if (contsTest == firstChild) {
456                    parent = nodeRenderFirstChild->parent();
457                    break;
458                }
459            }
460            if (firstChild == parent->firstChild())
461                break;
462            firstChild = parent->firstChild();
463            if (!firstChild->node())
464                break;
465            nodeRenderFirstChild = firstChild->node()->renderer();
466        }
467    }
468
469    return parent;
470}
471
472AccessibilityObject* AccessibilityRenderObject::parentObjectIfExists() const
473{
474    // WebArea's parent should be the scroll view containing it.
475    if (isWebArea() || isSeamlessWebArea())
476        return axObjectCache()->get(m_renderer->frame()->view());
477
478    return axObjectCache()->get(renderParentObject());
479}
480
481AccessibilityObject* AccessibilityRenderObject::parentObject() const
482{
483    if (!m_renderer)
484        return 0;
485
486    if (ariaRoleAttribute() == MenuBarRole)
487        return axObjectCache()->getOrCreate(m_renderer->parent());
488
489    // menuButton and its corresponding menu are DOM siblings, but Accessibility needs them to be parent/child
490    if (ariaRoleAttribute() == MenuRole) {
491        AccessibilityObject* parent = menuButtonForMenu();
492        if (parent)
493            return parent;
494    }
495
496    RenderObject* parentObj = renderParentObject();
497    if (parentObj)
498        return axObjectCache()->getOrCreate(parentObj);
499
500    // WebArea's parent should be the scroll view containing it.
501    if (isWebArea() || isSeamlessWebArea())
502        return axObjectCache()->getOrCreate(m_renderer->frame()->view());
503
504    return 0;
505}
506
507bool AccessibilityRenderObject::isAttachment() const
508{
509    RenderBoxModelObject* renderer = renderBoxModelObject();
510    if (!renderer)
511        return false;
512    // Widgets are the replaced elements that we represent to AX as attachments
513    bool isWidget = renderer->isWidget();
514
515    return isWidget && ariaRoleAttribute() == UnknownRole;
516}
517
518bool AccessibilityRenderObject::isFileUploadButton() const
519{
520    if (m_renderer && m_renderer->node() && m_renderer->node()->hasTagName(inputTag)) {
521        HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->node());
522        return input->isFileUpload();
523    }
524
525    return false;
526}
527
528bool AccessibilityRenderObject::isReadOnly() const
529{
530    ASSERT(m_renderer);
531
532    if (isWebArea()) {
533        Document* document = m_renderer->document();
534        if (!document)
535            return true;
536
537        HTMLElement* body = document->body();
538        if (body && body->rendererIsEditable())
539            return false;
540
541        return !document->rendererIsEditable();
542    }
543
544    return AccessibilityNodeObject::isReadOnly();
545}
546
547bool AccessibilityRenderObject::isOffScreen() const
548{
549    ASSERT(m_renderer);
550    IntRect contentRect = pixelSnappedIntRect(m_renderer->absoluteClippedOverflowRect());
551    FrameView* view = m_renderer->frame()->view();
552    IntRect viewRect = view->visibleContentRect();
553    viewRect.intersect(contentRect);
554    return viewRect.isEmpty();
555}
556
557Element* AccessibilityRenderObject::anchorElement() const
558{
559    if (!m_renderer)
560        return 0;
561
562    AXObjectCache* cache = axObjectCache();
563    RenderObject* currRenderer;
564
565    // Search up the render tree for a RenderObject with a DOM node.  Defer to an earlier continuation, though.
566    for (currRenderer = m_renderer; currRenderer && !currRenderer->node(); currRenderer = currRenderer->parent()) {
567        if (currRenderer->isAnonymousBlock()) {
568            RenderObject* continuation = toRenderBlock(currRenderer)->continuation();
569            if (continuation)
570                return cache->getOrCreate(continuation)->anchorElement();
571        }
572    }
573
574    // bail if none found
575    if (!currRenderer)
576        return 0;
577
578    // search up the DOM tree for an anchor element
579    // NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElement
580    Node* node = currRenderer->node();
581    for ( ; node; node = node->parentNode()) {
582        if (node->hasTagName(aTag) || (node->renderer() && cache->getOrCreate(node->renderer())->isAnchor()))
583            return toElement(node);
584    }
585
586    return 0;
587}
588
589String AccessibilityRenderObject::helpText() const
590{
591    if (!m_renderer)
592        return String();
593
594    const AtomicString& ariaHelp = getAttribute(aria_helpAttr);
595    if (!ariaHelp.isEmpty())
596        return ariaHelp;
597
598    String describedBy = ariaDescribedByAttribute();
599    if (!describedBy.isEmpty())
600        return describedBy;
601
602    String description = accessibilityDescription();
603    for (RenderObject* curr = m_renderer; curr; curr = curr->parent()) {
604        if (curr->node() && curr->node()->isHTMLElement()) {
605            const AtomicString& summary = toElement(curr->node())->getAttribute(summaryAttr);
606            if (!summary.isEmpty())
607                return summary;
608
609            // The title attribute should be used as help text unless it is already being used as descriptive text.
610            const AtomicString& title = toElement(curr->node())->getAttribute(titleAttr);
611            if (!title.isEmpty() && description != title)
612                return title;
613        }
614
615        // Only take help text from an ancestor element if its a group or an unknown role. If help was
616        // added to those kinds of elements, it is likely it was meant for a child element.
617        AccessibilityObject* axObj = axObjectCache()->getOrCreate(curr);
618        if (axObj) {
619            AccessibilityRole role = axObj->roleValue();
620            if (role != GroupRole && role != UnknownRole)
621                break;
622        }
623    }
624
625    return String();
626}
627
628String AccessibilityRenderObject::textUnderElement() const
629{
630    if (!m_renderer)
631        return String();
632
633    if (m_renderer->isFileUploadControl())
634        return toRenderFileUploadControl(m_renderer)->buttonValue();
635
636#if ENABLE(MATHML)
637    // Math operators create RenderText nodes on the fly that are not tied into the DOM in a reasonable way,
638    // so rangeOfContents does not work for them (nor does regular text selection).
639    if (m_renderer->isText() && isMathElement()) {
640        for (RenderObject* parent = m_renderer->parent(); parent; parent = parent->parent()) {
641            if (parent->isRenderMathMLBlock() && toRenderMathMLBlock(parent)->isRenderMathMLOperator())
642                return toRenderText(m_renderer)->text();
643        }
644    }
645#endif
646
647#if PLATFORM(GTK)
648    // On GTK, always use a text iterator in order to get embedded object characters.
649    // TODO: Add support for embedded object characters to the other codepaths that try
650    // to build the accessible text recursively, so this special case isn't needed.
651    // https://bugs.webkit.org/show_bug.cgi?id=105214
652    if (Node* node = this->node()) {
653        if (Frame* frame = node->document()->frame()) {
654            // catch stale WebCoreAXObject (see <rdar://problem/3960196>)
655            if (frame->document() != node->document())
656                return String();
657
658            return plainText(rangeOfContents(node).get(), textIteratorBehaviorForTextRange());
659        }
660    }
661#endif
662
663    if (m_renderer->isText()) {
664        // If possible, use a text iterator to get the text, so that whitespace
665        // is handled consistently.
666        if (Node* node = this->node()) {
667            if (Frame* frame = node->document()->frame()) {
668                // catch stale WebCoreAXObject (see <rdar://problem/3960196>)
669                if (frame->document() != node->document())
670                    return String();
671
672                return plainText(rangeOfContents(node).get(), textIteratorBehaviorForTextRange());
673            }
674        }
675
676        // Sometimes text fragments don't have Nodes associated with them (like when
677        // CSS content is used to insert text or when a RenderCounter is used.)
678        RenderText* renderTextObject = toRenderText(m_renderer);
679        if (renderTextObject->isTextFragment())
680            return String(static_cast<RenderTextFragment*>(m_renderer)->contentString());
681        else
682            return String(renderTextObject->text());
683    }
684
685    return AccessibilityNodeObject::textUnderElement();
686}
687
688Node* AccessibilityRenderObject::node() const
689{
690    return m_renderer ? m_renderer->node() : 0;
691}
692
693String AccessibilityRenderObject::stringValue() const
694{
695    if (!m_renderer)
696        return String();
697
698    if (isPasswordField())
699        return passwordFieldValue();
700
701    RenderBoxModelObject* cssBox = renderBoxModelObject();
702
703    if (ariaRoleAttribute() == StaticTextRole) {
704        String staticText = text();
705        if (!staticText.length())
706            staticText = textUnderElement();
707        return staticText;
708    }
709
710    if (m_renderer->isText())
711        return textUnderElement();
712
713    if (cssBox && cssBox->isMenuList()) {
714        // RenderMenuList will go straight to the text() of its selected item.
715        // This has to be overridden in the case where the selected item has an ARIA label.
716        HTMLSelectElement* selectElement = toHTMLSelectElement(m_renderer->node());
717        int selectedIndex = selectElement->selectedIndex();
718        const Vector<HTMLElement*> listItems = selectElement->listItems();
719        if (selectedIndex >= 0 && static_cast<size_t>(selectedIndex) < listItems.size()) {
720            const AtomicString& overriddenDescription = listItems[selectedIndex]->fastGetAttribute(aria_labelAttr);
721            if (!overriddenDescription.isNull())
722                return overriddenDescription;
723        }
724        return toRenderMenuList(m_renderer)->text();
725    }
726
727    if (m_renderer->isListMarker())
728        return toRenderListMarker(m_renderer)->text();
729
730    if (isWebArea()) {
731        // FIXME: Why would a renderer exist when the Document isn't attached to a frame?
732        if (m_renderer->frame())
733            return String();
734
735        ASSERT_NOT_REACHED();
736    }
737
738    if (isTextControl())
739        return text();
740
741    if (m_renderer->isFileUploadControl())
742        return toRenderFileUploadControl(m_renderer)->fileTextValue();
743
744    // FIXME: We might need to implement a value here for more types
745    // FIXME: It would be better not to advertise a value at all for the types for which we don't implement one;
746    // this would require subclassing or making accessibilityAttributeNames do something other than return a
747    // single static array.
748    return String();
749}
750
751HTMLLabelElement* AccessibilityRenderObject::labelElementContainer() const
752{
753    if (!m_renderer)
754        return 0;
755
756    // the control element should not be considered part of the label
757    if (isControl())
758        return 0;
759
760    // find if this has a parent that is a label
761    for (Node* parentNode = m_renderer->node(); parentNode; parentNode = parentNode->parentNode()) {
762        if (parentNode->hasTagName(labelTag))
763            return static_cast<HTMLLabelElement*>(parentNode);
764    }
765
766    return 0;
767}
768
769// The boundingBox for elements within the remote SVG element needs to be offset by its position
770// within the parent page, otherwise they are in relative coordinates only.
771void AccessibilityRenderObject::offsetBoundingBoxForRemoteSVGElement(LayoutRect& rect) const
772{
773    for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) {
774        if (parent->isAccessibilitySVGRoot()) {
775            rect.moveBy(parent->parentObject()->boundingBoxRect().location());
776            break;
777        }
778    }
779}
780
781LayoutRect AccessibilityRenderObject::boundingBoxRect() const
782{
783    RenderObject* obj = m_renderer;
784
785    if (!obj)
786        return LayoutRect();
787
788    if (obj->node()) // If we are a continuation, we want to make sure to use the primary renderer.
789        obj = obj->node()->renderer();
790
791    // absoluteFocusRingQuads will query the hierarchy below this element, which for large webpages can be very slow.
792    // For a web area, which will have the most elements of any element, absoluteQuads should be used.
793    // We should also use absoluteQuads for SVG elements, otherwise transforms won't be applied.
794    Vector<FloatQuad> quads;
795    bool isSVGRoot = false;
796#if ENABLE(SVG)
797    if (obj->isSVGRoot())
798        isSVGRoot = true;
799#endif
800    if (obj->isText())
801        toRenderText(obj)->absoluteQuads(quads, 0, RenderText::ClipToEllipsis);
802    else if (isWebArea() || isSeamlessWebArea() || isSVGRoot)
803        obj->absoluteQuads(quads);
804    else
805        obj->absoluteFocusRingQuads(quads);
806
807    LayoutRect result = boundingBoxForQuads(obj, quads);
808
809#if ENABLE(SVG)
810    Document* document = this->document();
811    if (document && document->isSVGDocument())
812        offsetBoundingBoxForRemoteSVGElement(result);
813#endif
814
815    // The size of the web area should be the content size, not the clipped size.
816    if ((isWebArea() || isSeamlessWebArea()) && obj->frame()->view())
817        result.setSize(obj->frame()->view()->contentsSize());
818
819    return result;
820}
821
822LayoutRect AccessibilityRenderObject::checkboxOrRadioRect() const
823{
824    if (!m_renderer)
825        return LayoutRect();
826
827    HTMLLabelElement* label = labelForElement(toElement(m_renderer->node()));
828    if (!label || !label->renderer())
829        return boundingBoxRect();
830
831    LayoutRect labelRect = axObjectCache()->getOrCreate(label)->elementRect();
832    labelRect.unite(boundingBoxRect());
833    return labelRect;
834}
835
836LayoutRect AccessibilityRenderObject::elementRect() const
837{
838    // a checkbox or radio button should encompass its label
839    if (isCheckboxOrRadio())
840        return checkboxOrRadioRect();
841
842    return boundingBoxRect();
843}
844
845bool AccessibilityRenderObject::supportsPath() const
846{
847#if ENABLE(SVG)
848    if (m_renderer && m_renderer->isSVGShape())
849        return true;
850#endif
851
852    return false;
853}
854
855Path AccessibilityRenderObject::elementPath() const
856{
857#if ENABLE(SVG)
858    if (m_renderer && m_renderer->isSVGShape())
859        return toRenderSVGShape(m_renderer)->path();
860#endif
861
862    return Path();
863}
864
865IntPoint AccessibilityRenderObject::clickPoint()
866{
867    // Headings are usually much wider than their textual content. If the mid point is used, often it can be wrong.
868    if (isHeading() && children().size() == 1)
869        return children()[0]->clickPoint();
870
871    // use the default position unless this is an editable web area, in which case we use the selection bounds.
872    if (!isWebArea() || isReadOnly())
873        return AccessibilityObject::clickPoint();
874
875    VisibleSelection visSelection = selection();
876    VisiblePositionRange range = VisiblePositionRange(visSelection.visibleStart(), visSelection.visibleEnd());
877    IntRect bounds = boundsForVisiblePositionRange(range);
878#if PLATFORM(MAC)
879    bounds.setLocation(m_renderer->document()->view()->screenToContents(bounds.location()));
880#endif
881    return IntPoint(bounds.x() + (bounds.width() / 2), bounds.y() - (bounds.height() / 2));
882}
883
884AccessibilityObject* AccessibilityRenderObject::internalLinkElement() const
885{
886    Element* element = anchorElement();
887    if (!element)
888        return 0;
889
890    // Right now, we do not support ARIA links as internal link elements
891    if (!element->hasTagName(aTag))
892        return 0;
893    HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(element);
894
895    KURL linkURL = anchor->href();
896    String fragmentIdentifier = linkURL.fragmentIdentifier();
897    if (fragmentIdentifier.isEmpty())
898        return 0;
899
900    // check if URL is the same as current URL
901    KURL documentURL = m_renderer->document()->url();
902    if (!equalIgnoringFragmentIdentifier(documentURL, linkURL))
903        return 0;
904
905    Node* linkedNode = m_renderer->document()->findAnchor(fragmentIdentifier);
906    if (!linkedNode)
907        return 0;
908
909    // The element we find may not be accessible, so find the first accessible object.
910    return firstAccessibleObjectFromNode(linkedNode);
911}
912
913ESpeak AccessibilityRenderObject::speakProperty() const
914{
915    if (!m_renderer)
916        return AccessibilityObject::speakProperty();
917
918    return m_renderer->style()->speak();
919}
920
921void AccessibilityRenderObject::addRadioButtonGroupMembers(AccessibilityChildrenVector& linkedUIElements) const
922{
923    if (!m_renderer || roleValue() != RadioButtonRole)
924        return;
925
926    Node* node = m_renderer->node();
927    if (!node || !node->hasTagName(inputTag))
928        return;
929
930    HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
931    // if there's a form, then this is easy
932    if (input->form()) {
933        Vector<RefPtr<Node> > formElements;
934        input->form()->getNamedElements(input->name(), formElements);
935
936        unsigned len = formElements.size();
937        for (unsigned i = 0; i < len; ++i) {
938            Node* associateElement = formElements[i].get();
939            if (AccessibilityObject* object = axObjectCache()->getOrCreate(associateElement))
940                linkedUIElements.append(object);
941        }
942    } else {
943        RefPtr<NodeList> list = node->document()->getElementsByTagName("input");
944        unsigned len = list->length();
945        for (unsigned i = 0; i < len; ++i) {
946            if (list->item(i)->hasTagName(inputTag)) {
947                HTMLInputElement* associateElement = static_cast<HTMLInputElement*>(list->item(i));
948                if (associateElement->isRadioButton() && associateElement->name() == input->name()) {
949                    if (AccessibilityObject* object = axObjectCache()->getOrCreate(associateElement))
950                        linkedUIElements.append(object);
951                }
952            }
953        }
954    }
955}
956
957// linked ui elements could be all the related radio buttons in a group
958// or an internal anchor connection
959void AccessibilityRenderObject::linkedUIElements(AccessibilityChildrenVector& linkedUIElements) const
960{
961    ariaFlowToElements(linkedUIElements);
962
963    if (isAnchor()) {
964        AccessibilityObject* linkedAXElement = internalLinkElement();
965        if (linkedAXElement)
966            linkedUIElements.append(linkedAXElement);
967    }
968
969    if (roleValue() == RadioButtonRole)
970        addRadioButtonGroupMembers(linkedUIElements);
971}
972
973bool AccessibilityRenderObject::hasTextAlternative() const
974{
975    // ARIA: section 2A, bullet #3 says if aria-labeledby or aria-label appears, it should
976    // override the "label" element association.
977    if (!ariaLabeledByAttribute().isEmpty() || !getAttribute(aria_labelAttr).isEmpty())
978        return true;
979
980    return false;
981}
982
983bool AccessibilityRenderObject::ariaHasPopup() const
984{
985    return elementAttributeValue(aria_haspopupAttr);
986}
987
988bool AccessibilityRenderObject::supportsARIAFlowTo() const
989{
990    return !getAttribute(aria_flowtoAttr).isEmpty();
991}
992
993void AccessibilityRenderObject::ariaFlowToElements(AccessibilityChildrenVector& flowTo) const
994{
995    Vector<Element*> elements;
996    elementsFromAttribute(elements, aria_flowtoAttr);
997
998    AXObjectCache* cache = axObjectCache();
999    unsigned count = elements.size();
1000    for (unsigned k = 0; k < count; ++k) {
1001        Element* element = elements[k];
1002        AccessibilityObject* flowToElement = cache->getOrCreate(element);
1003        if (flowToElement)
1004            flowTo.append(flowToElement);
1005    }
1006
1007}
1008
1009bool AccessibilityRenderObject::supportsARIADropping() const
1010{
1011    const AtomicString& dropEffect = getAttribute(aria_dropeffectAttr);
1012    return !dropEffect.isEmpty();
1013}
1014
1015bool AccessibilityRenderObject::supportsARIADragging() const
1016{
1017    const AtomicString& grabbed = getAttribute(aria_grabbedAttr);
1018    return equalIgnoringCase(grabbed, "true") || equalIgnoringCase(grabbed, "false");
1019}
1020
1021bool AccessibilityRenderObject::isARIAGrabbed()
1022{
1023    return elementAttributeValue(aria_grabbedAttr);
1024}
1025
1026void AccessibilityRenderObject::determineARIADropEffects(Vector<String>& effects)
1027{
1028    const AtomicString& dropEffects = getAttribute(aria_dropeffectAttr);
1029    if (dropEffects.isEmpty()) {
1030        effects.clear();
1031        return;
1032    }
1033
1034    String dropEffectsString = dropEffects.string();
1035    dropEffectsString.replace('\n', ' ');
1036    dropEffectsString.split(' ', effects);
1037}
1038
1039bool AccessibilityRenderObject::exposesTitleUIElement() const
1040{
1041    if (!isControl())
1042        return false;
1043
1044    // If this control is ignored (because it's invisible),
1045    // then the label needs to be exposed so it can be visible to accessibility.
1046    if (accessibilityIsIgnored())
1047        return true;
1048
1049    // Checkboxes and radio buttons use the text of their title ui element as their own AXTitle.
1050    // This code controls whether the title ui element should appear in the AX tree (usually, no).
1051    // It should appear if the control already has a label (which will be used as the AXTitle instead).
1052    if (isCheckboxOrRadio())
1053        return hasTextAlternative();
1054
1055    // When controls have their own descriptions, the title element should be ignored.
1056    if (hasTextAlternative())
1057        return false;
1058
1059    return true;
1060}
1061
1062AccessibilityObject* AccessibilityRenderObject::titleUIElement() const
1063{
1064    if (!m_renderer)
1065        return 0;
1066
1067    // if isFieldset is true, the renderer is guaranteed to be a RenderFieldset
1068    if (isFieldset())
1069        return axObjectCache()->getOrCreate(toRenderFieldset(m_renderer)->findLegend(RenderFieldset::IncludeFloatingOrOutOfFlow));
1070
1071    Node* node = m_renderer->node();
1072    if (!node || !node->isElementNode())
1073        return 0;
1074    HTMLLabelElement* label = labelForElement(toElement(node));
1075    if (label && label->renderer())
1076        return axObjectCache()->getOrCreate(label);
1077
1078    return 0;
1079}
1080
1081bool AccessibilityRenderObject::isAllowedChildOfTree() const
1082{
1083    // Determine if this is in a tree. If so, we apply special behavior to make it work like an AXOutline.
1084    AccessibilityObject* axObj = parentObject();
1085    bool isInTree = false;
1086    while (axObj) {
1087        if (axObj->isTree()) {
1088            isInTree = true;
1089            break;
1090        }
1091        axObj = axObj->parentObject();
1092    }
1093
1094    // If the object is in a tree, only tree items should be exposed (and the children of tree items).
1095    if (isInTree) {
1096        AccessibilityRole role = roleValue();
1097        if (role != TreeItemRole && role != StaticTextRole)
1098            return false;
1099    }
1100    return true;
1101}
1102
1103AccessibilityObjectInclusion AccessibilityRenderObject::defaultObjectInclusion() const
1104{
1105    // The following cases can apply to any element that's a subclass of AccessibilityRenderObject.
1106
1107    if (!m_renderer)
1108        return IgnoreObject;
1109
1110    if (m_renderer->style()->visibility() != VISIBLE) {
1111        // aria-hidden is meant to override visibility as the determinant in AX hierarchy inclusion.
1112        if (equalIgnoringCase(getAttribute(aria_hiddenAttr), "false"))
1113            return DefaultBehavior;
1114
1115        return IgnoreObject;
1116    }
1117
1118    return AccessibilityObject::defaultObjectInclusion();
1119}
1120
1121bool AccessibilityRenderObject::computeAccessibilityIsIgnored() const
1122{
1123#ifndef NDEBUG
1124    ASSERT(m_initialized);
1125#endif
1126
1127    // Check first if any of the common reasons cause this element to be ignored.
1128    // Then process other use cases that need to be applied to all the various roles
1129    // that AccessibilityRenderObjects take on.
1130    AccessibilityObjectInclusion decision = defaultObjectInclusion();
1131    if (decision == IncludeObject)
1132        return false;
1133    if (decision == IgnoreObject)
1134        return true;
1135
1136    // If this element is within a parent that cannot have children, it should not be exposed.
1137    if (isDescendantOfBarrenParent())
1138        return true;
1139
1140    if (roleValue() == IgnoredRole)
1141        return true;
1142
1143    if (roleValue() == PresentationalRole || inheritsPresentationalRole())
1144        return true;
1145
1146    // An ARIA tree can only have tree items and static text as children.
1147    if (!isAllowedChildOfTree())
1148        return true;
1149
1150    // Allow the platform to decide if the attachment is ignored or not.
1151    if (isAttachment())
1152        return accessibilityIgnoreAttachment();
1153
1154    // ignore popup menu items because AppKit does
1155    for (RenderObject* parent = m_renderer->parent(); parent; parent = parent->parent()) {
1156        if (parent->isBoxModelObject() && toRenderBoxModelObject(parent)->isMenuList())
1157            return true;
1158    }
1159
1160    // find out if this element is inside of a label element.
1161    // if so, it may be ignored because it's the label for a checkbox or radio button
1162    AccessibilityObject* controlObject = correspondingControlForLabelElement();
1163    if (controlObject && !controlObject->exposesTitleUIElement() && controlObject->isCheckboxOrRadio())
1164        return true;
1165
1166    // NOTE: BRs always have text boxes now, so the text box check here can be removed
1167    if (m_renderer->isText()) {
1168        // static text beneath MenuItems and MenuButtons are just reported along with the menu item, so it's ignored on an individual level
1169        AccessibilityObject* parent = parentObjectUnignored();
1170        if (parent && (parent->ariaRoleAttribute() == MenuItemRole || parent->ariaRoleAttribute() == MenuButtonRole))
1171            return true;
1172        RenderText* renderText = toRenderText(m_renderer);
1173        if (m_renderer->isBR() || !renderText->firstTextBox())
1174            return true;
1175
1176        // static text beneath TextControls is reported along with the text control text so it's ignored.
1177        for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) {
1178            if (parent->roleValue() == TextFieldRole)
1179                return true;
1180        }
1181
1182        // text elements that are just empty whitespace should not be returned
1183        return renderText->text()->containsOnlyWhitespace();
1184    }
1185
1186    if (isHeading())
1187        return false;
1188
1189    if (isLink())
1190        return false;
1191
1192    // all controls are accessible
1193    if (isControl())
1194        return false;
1195
1196    if (ariaRoleAttribute() != UnknownRole)
1197        return false;
1198
1199    // don't ignore labels, because they serve as TitleUIElements
1200    Node* node = m_renderer->node();
1201    if (node && node->hasTagName(labelTag))
1202        return false;
1203
1204    // Anything that is content editable should not be ignored.
1205    // However, one cannot just call node->rendererIsEditable() since that will ask if its parents
1206    // are also editable. Only the top level content editable region should be exposed.
1207    if (hasContentEditableAttributeSet())
1208        return false;
1209
1210    switch (roleValue()) {
1211    case AudioRole:
1212    case ListItemRole:
1213    case VideoRole:
1214        return false;
1215    default:
1216        break;
1217    }
1218
1219    // if this element has aria attributes on it, it should not be ignored.
1220    if (supportsARIAAttributes())
1221        return false;
1222
1223#if ENABLE(MATHML)
1224    // First check if this is a special case within the math tree that needs to be ignored.
1225    if (isIgnoredElementWithinMathTree())
1226        return true;
1227    // Otherwise all other math elements are in the tree.
1228    if (isMathElement())
1229        return false;
1230#endif
1231
1232    // <span> tags are inline tags and not meant to convey information if they have no other aria
1233    // information on them. If we don't ignore them, they may emit signals expected to come from
1234    // their parent. In addition, because included spans are GroupRole objects, and GroupRole
1235    // objects are often containers with meaningful information, the inclusion of a span can have
1236    // the side effect of causing the immediate parent accessible to be ignored. This is especially
1237    // problematic for platforms which have distinct roles for textual block elements.
1238    if (node && node->hasTagName(spanTag))
1239        return true;
1240
1241    if (m_renderer->isBlockFlow() && m_renderer->childrenInline() && !canSetFocusAttribute())
1242        return !toRenderBlock(m_renderer)->firstLineBox() && !mouseButtonListener();
1243
1244    // ignore images seemingly used as spacers
1245    if (isImage()) {
1246
1247        // If the image can take focus, it should not be ignored, lest the user not be able to interact with something important.
1248        if (canSetFocusAttribute())
1249            return false;
1250
1251        if (node && node->isElementNode()) {
1252            Element* elt = toElement(node);
1253            const AtomicString& alt = elt->getAttribute(altAttr);
1254            // don't ignore an image that has an alt tag
1255            if (!alt.string().containsOnlyWhitespace())
1256                return false;
1257            // informal standard is to ignore images with zero-length alt strings
1258            if (!alt.isNull())
1259                return true;
1260            // If an image has a title attribute on it, accessibility should be lenient and allow it to appear in the hierarchy (according to WAI-ARIA).
1261            if (!getAttribute(titleAttr).isEmpty())
1262                return false;
1263        }
1264
1265        if (isNativeImage()) {
1266            // check for one-dimensional image
1267            RenderImage* image = toRenderImage(m_renderer);
1268            if (image->height() <= 1 || image->width() <= 1)
1269                return true;
1270
1271            // check whether rendered image was stretched from one-dimensional file image
1272            if (image->cachedImage()) {
1273                LayoutSize imageSize = image->cachedImage()->imageSizeForRenderer(m_renderer, image->view()->zoomFactor());
1274                return imageSize.height() <= 1 || imageSize.width() <= 1;
1275            }
1276        }
1277        return false;
1278    }
1279
1280    if (isCanvas()) {
1281        if (canvasHasFallbackContent())
1282            return false;
1283
1284        if (m_renderer->isBox()) {
1285            RenderBox* canvasBox = toRenderBox(m_renderer);
1286            if (canvasBox->height() <= 1 || canvasBox->width() <= 1)
1287                return true;
1288        }
1289        // Otherwise fall through; use presence of help text, title, or description to decide.
1290    }
1291
1292    if (isWebArea() || isSeamlessWebArea() || m_renderer->isListMarker())
1293        return false;
1294
1295    // Using the help text, title or accessibility description (so we
1296    // check if there's some kind of accessible name for the element)
1297    // to decide an element's visibility is not as definitive as
1298    // previous checks, so this should remain as one of the last.
1299    //
1300    // These checks are simplified in the interest of execution speed;
1301    // for example, any element having an alt attribute will make it
1302    // not ignored, rather than just images.
1303    if (!getAttribute(aria_helpAttr).isEmpty() || !getAttribute(aria_describedbyAttr).isEmpty() || !getAttribute(altAttr).isEmpty() || !getAttribute(titleAttr).isEmpty())
1304        return false;
1305
1306    // Don't ignore generic focusable elements like <div tabindex=0>
1307    // unless they're completely empty, with no children.
1308    if (isGenericFocusableElement() && node->firstChild())
1309        return false;
1310
1311    if (!ariaAccessibilityDescription().isEmpty())
1312        return false;
1313
1314#if ENABLE(MATHML)
1315    if (!getAttribute(MathMLNames::alttextAttr).isEmpty())
1316        return false;
1317#endif
1318
1319    // Other non-ignored host language elements
1320    if (node && node->hasTagName(dfnTag))
1321        return false;
1322
1323    // By default, objects should be ignored so that the AX hierarchy is not
1324    // filled with unnecessary items.
1325    return true;
1326}
1327
1328bool AccessibilityRenderObject::isLoaded() const
1329{
1330    return !m_renderer->document()->parser();
1331}
1332
1333double AccessibilityRenderObject::estimatedLoadingProgress() const
1334{
1335    if (!m_renderer)
1336        return 0;
1337
1338    if (isLoaded())
1339        return 1.0;
1340
1341    Page* page = m_renderer->document()->page();
1342    if (!page)
1343        return 0;
1344
1345    return page->progress()->estimatedProgress();
1346}
1347
1348int AccessibilityRenderObject::layoutCount() const
1349{
1350    if (!m_renderer->isRenderView())
1351        return 0;
1352    return toRenderView(m_renderer)->frameView()->layoutCount();
1353}
1354
1355String AccessibilityRenderObject::text() const
1356{
1357    if (isPasswordField())
1358        return passwordFieldValue();
1359
1360    return AccessibilityNodeObject::text();
1361}
1362
1363int AccessibilityRenderObject::textLength() const
1364{
1365    ASSERT(isTextControl());
1366
1367    if (isPasswordField())
1368#if PLATFORM(GTK)
1369        return passwordFieldValue().length();
1370#else
1371        return -1; // need to return something distinct from 0
1372#endif
1373
1374    return text().length();
1375}
1376
1377PlainTextRange AccessibilityRenderObject::ariaSelectedTextRange() const
1378{
1379    Node* node = m_renderer->node();
1380    if (!node)
1381        return PlainTextRange();
1382
1383    VisibleSelection visibleSelection = selection();
1384    RefPtr<Range> currentSelectionRange = visibleSelection.toNormalizedRange();
1385    if (!currentSelectionRange || !currentSelectionRange->intersectsNode(node, IGNORE_EXCEPTION))
1386        return PlainTextRange();
1387
1388    int start = indexForVisiblePosition(visibleSelection.start());
1389    int end = indexForVisiblePosition(visibleSelection.end());
1390
1391    return PlainTextRange(start, end - start);
1392}
1393
1394String AccessibilityRenderObject::selectedText() const
1395{
1396    ASSERT(isTextControl());
1397
1398    if (isPasswordField())
1399        return String(); // need to return something distinct from empty string
1400
1401    if (isNativeTextControl()) {
1402        HTMLTextFormControlElement* textControl = toRenderTextControl(m_renderer)->textFormControlElement();
1403        return textControl->selectedText();
1404    }
1405
1406    if (ariaRoleAttribute() == UnknownRole)
1407        return String();
1408
1409    return doAXStringForRange(ariaSelectedTextRange());
1410}
1411
1412const AtomicString& AccessibilityRenderObject::accessKey() const
1413{
1414    Node* node = m_renderer->node();
1415    if (!node)
1416        return nullAtom;
1417    if (!node->isElementNode())
1418        return nullAtom;
1419    return toElement(node)->getAttribute(accesskeyAttr);
1420}
1421
1422VisibleSelection AccessibilityRenderObject::selection() const
1423{
1424    return m_renderer->frame()->selection()->selection();
1425}
1426
1427PlainTextRange AccessibilityRenderObject::selectedTextRange() const
1428{
1429    ASSERT(isTextControl());
1430
1431    if (isPasswordField())
1432        return PlainTextRange();
1433
1434    AccessibilityRole ariaRole = ariaRoleAttribute();
1435    if (isNativeTextControl() && ariaRole == UnknownRole) {
1436        HTMLTextFormControlElement* textControl = toRenderTextControl(m_renderer)->textFormControlElement();
1437        return PlainTextRange(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart());
1438    }
1439
1440    if (ariaRole == UnknownRole)
1441        return PlainTextRange();
1442
1443    return ariaSelectedTextRange();
1444}
1445
1446void AccessibilityRenderObject::setSelectedTextRange(const PlainTextRange& range)
1447{
1448    if (isNativeTextControl()) {
1449        HTMLTextFormControlElement* textControl = toRenderTextControl(m_renderer)->textFormControlElement();
1450        textControl->setSelectionRange(range.start, range.start + range.length);
1451        return;
1452    }
1453
1454    Document* document = m_renderer->document();
1455    if (!document)
1456        return;
1457    Frame* frame = document->frame();
1458    if (!frame)
1459        return;
1460    Node* node = m_renderer->node();
1461    frame->selection()->setSelection(VisibleSelection(Position(node, range.start, Position::PositionIsOffsetInAnchor),
1462        Position(node, range.start + range.length, Position::PositionIsOffsetInAnchor), DOWNSTREAM));
1463}
1464
1465KURL AccessibilityRenderObject::url() const
1466{
1467    if (isAnchor() && m_renderer->node()->hasTagName(aTag)) {
1468        if (HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(anchorElement()))
1469            return anchor->href();
1470    }
1471
1472    if (isWebArea())
1473        return m_renderer->document()->url();
1474
1475    if (isImage() && m_renderer->node() && m_renderer->node()->hasTagName(imgTag))
1476        return static_cast<HTMLImageElement*>(m_renderer->node())->src();
1477
1478    if (isInputImage())
1479        return static_cast<HTMLInputElement*>(m_renderer->node())->src();
1480
1481    return KURL();
1482}
1483
1484bool AccessibilityRenderObject::isUnvisited() const
1485{
1486    // FIXME: Is it a privacy violation to expose unvisited information to accessibility APIs?
1487    return m_renderer->style()->isLink() && m_renderer->style()->insideLink() == InsideUnvisitedLink;
1488}
1489
1490bool AccessibilityRenderObject::isVisited() const
1491{
1492    // FIXME: Is it a privacy violation to expose visited information to accessibility APIs?
1493    return m_renderer->style()->isLink() && m_renderer->style()->insideLink() == InsideVisitedLink;
1494}
1495
1496void AccessibilityRenderObject::setElementAttributeValue(const QualifiedName& attributeName, bool value)
1497{
1498    if (!m_renderer)
1499        return;
1500
1501    Node* node = m_renderer->node();
1502    if (!node || !node->isElementNode())
1503        return;
1504
1505    Element* element = toElement(node);
1506    element->setAttribute(attributeName, (value) ? "true" : "false");
1507}
1508
1509bool AccessibilityRenderObject::elementAttributeValue(const QualifiedName& attributeName) const
1510{
1511    if (!m_renderer)
1512        return false;
1513
1514    return equalIgnoringCase(getAttribute(attributeName), "true");
1515}
1516
1517bool AccessibilityRenderObject::isSelected() const
1518{
1519    if (!m_renderer)
1520        return false;
1521
1522    Node* node = m_renderer->node();
1523    if (!node)
1524        return false;
1525
1526    const AtomicString& ariaSelected = getAttribute(aria_selectedAttr);
1527    if (equalIgnoringCase(ariaSelected, "true"))
1528        return true;
1529
1530    if (isTabItem() && isTabItemSelected())
1531        return true;
1532
1533    return false;
1534}
1535
1536bool AccessibilityRenderObject::isTabItemSelected() const
1537{
1538    if (!isTabItem() || !m_renderer)
1539        return false;
1540
1541    Node* node = m_renderer->node();
1542    if (!node || !node->isElementNode())
1543        return false;
1544
1545    // The ARIA spec says a tab item can also be selected if it is aria-labeled by a tabpanel
1546    // that has keyboard focus inside of it, or if a tabpanel in its aria-controls list has KB
1547    // focus inside of it.
1548    AccessibilityObject* focusedElement = focusedUIElement();
1549    if (!focusedElement)
1550        return false;
1551
1552    Vector<Element*> elements;
1553    elementsFromAttribute(elements, aria_controlsAttr);
1554
1555    unsigned count = elements.size();
1556    for (unsigned k = 0; k < count; ++k) {
1557        Element* element = elements[k];
1558        AccessibilityObject* tabPanel = axObjectCache()->getOrCreate(element);
1559
1560        // A tab item should only control tab panels.
1561        if (!tabPanel || tabPanel->roleValue() != TabPanelRole)
1562            continue;
1563
1564        AccessibilityObject* checkFocusElement = focusedElement;
1565        // Check if the focused element is a descendant of the element controlled by the tab item.
1566        while (checkFocusElement) {
1567            if (tabPanel == checkFocusElement)
1568                return true;
1569            checkFocusElement = checkFocusElement->parentObject();
1570        }
1571    }
1572
1573    return false;
1574}
1575
1576bool AccessibilityRenderObject::isFocused() const
1577{
1578    if (!m_renderer)
1579        return false;
1580
1581    Document* document = m_renderer->document();
1582    if (!document)
1583        return false;
1584
1585    Element* focusedElement = document->focusedElement();
1586    if (!focusedElement)
1587        return false;
1588
1589    // A web area is represented by the Document node in the DOM tree, which isn't focusable.
1590    // Check instead if the frame's selection controller is focused
1591    if (focusedElement == m_renderer->node()
1592        || (roleValue() == WebAreaRole && document->frame()->selection()->isFocusedAndActive()))
1593        return true;
1594
1595    return false;
1596}
1597
1598void AccessibilityRenderObject::setFocused(bool on)
1599{
1600    if (!canSetFocusAttribute())
1601        return;
1602
1603    Document* document = this->document();
1604    Node* node = this->node();
1605
1606    if (!on || !node || !node->isElementNode()) {
1607        document->setFocusedElement(0);
1608        return;
1609    }
1610
1611    // If this node is already the currently focused node, then calling focus() won't do anything.
1612    // That is a problem when focus is removed from the webpage to chrome, and then returns.
1613    // In these cases, we need to do what keyboard and mouse focus do, which is reset focus first.
1614    if (document->focusedElement() == node)
1615        document->setFocusedElement(0);
1616
1617    toElement(node)->focus();
1618}
1619
1620void AccessibilityRenderObject::setSelectedRows(AccessibilityChildrenVector& selectedRows)
1621{
1622    // Setting selected only makes sense in trees and tables (and tree-tables).
1623    AccessibilityRole role = roleValue();
1624    if (role != TreeRole && role != TreeGridRole && role != TableRole)
1625        return;
1626
1627    bool isMulti = isMultiSelectable();
1628    unsigned count = selectedRows.size();
1629    if (count > 1 && !isMulti)
1630        count = 1;
1631
1632    for (unsigned k = 0; k < count; ++k)
1633        selectedRows[k]->setSelected(true);
1634}
1635
1636void AccessibilityRenderObject::setValue(const String& string)
1637{
1638    if (!m_renderer || !m_renderer->node() || !m_renderer->node()->isElementNode())
1639        return;
1640    Element* element = toElement(m_renderer->node());
1641
1642    if (!m_renderer->isBoxModelObject())
1643        return;
1644    RenderBoxModelObject* renderer = toRenderBoxModelObject(m_renderer);
1645
1646    // FIXME: Do we want to do anything here for ARIA textboxes?
1647    if (renderer->isTextField()) {
1648        // FIXME: This is not safe!  Other elements could have a TextField renderer.
1649        static_cast<HTMLInputElement*>(element)->setValue(string);
1650    } else if (renderer->isTextArea()) {
1651        // FIXME: This is not safe!  Other elements could have a TextArea renderer.
1652        static_cast<HTMLTextAreaElement*>(element)->setValue(string);
1653    }
1654}
1655
1656void AccessibilityRenderObject::ariaOwnsElements(AccessibilityChildrenVector& axObjects) const
1657{
1658    Vector<Element*> elements;
1659    elementsFromAttribute(elements, aria_ownsAttr);
1660
1661    unsigned count = elements.size();
1662    for (unsigned k = 0; k < count; ++k) {
1663        RenderObject* render = elements[k]->renderer();
1664        AccessibilityObject* obj = axObjectCache()->getOrCreate(render);
1665        if (obj)
1666            axObjects.append(obj);
1667    }
1668}
1669
1670bool AccessibilityRenderObject::supportsARIAOwns() const
1671{
1672    if (!m_renderer)
1673        return false;
1674    const AtomicString& ariaOwns = getAttribute(aria_ownsAttr);
1675
1676    return !ariaOwns.isEmpty();
1677}
1678
1679RenderView* AccessibilityRenderObject::topRenderer() const
1680{
1681    Document* topDoc = topDocument();
1682    if (!topDoc)
1683        return 0;
1684
1685    return topDoc->renderView();
1686}
1687
1688Document* AccessibilityRenderObject::document() const
1689{
1690    if (!m_renderer)
1691        return 0;
1692    return m_renderer->document();
1693}
1694
1695FrameView* AccessibilityRenderObject::topDocumentFrameView() const
1696{
1697    RenderView* renderView = topRenderer();
1698    if (!renderView || !renderView->view())
1699        return 0;
1700    return renderView->view()->frameView();
1701}
1702
1703Widget* AccessibilityRenderObject::widget() const
1704{
1705    if (!m_renderer->isBoxModelObject() || !toRenderBoxModelObject(m_renderer)->isWidget())
1706        return 0;
1707    return toRenderWidget(m_renderer)->widget();
1708}
1709
1710AccessibilityObject* AccessibilityRenderObject::accessibilityParentForImageMap(HTMLMapElement* map) const
1711{
1712    // find an image that is using this map
1713    if (!map)
1714        return 0;
1715
1716    HTMLImageElement* imageElement = map->imageElement();
1717    if (!imageElement)
1718        return 0;
1719
1720    return axObjectCache()->getOrCreate(imageElement);
1721}
1722
1723void AccessibilityRenderObject::getDocumentLinks(AccessibilityChildrenVector& result)
1724{
1725    Document* document = m_renderer->document();
1726    RefPtr<HTMLCollection> links = document->links();
1727    for (unsigned i = 0; Node* curr = links->item(i); i++) {
1728        RenderObject* obj = curr->renderer();
1729        if (obj) {
1730            RefPtr<AccessibilityObject> axobj = document->axObjectCache()->getOrCreate(obj);
1731            ASSERT(axobj);
1732            if (!axobj->accessibilityIsIgnored() && axobj->isLink())
1733                result.append(axobj);
1734        } else {
1735            Node* parent = curr->parentNode();
1736            if (parent && curr->hasTagName(areaTag) && parent->hasTagName(mapTag)) {
1737                AccessibilityImageMapLink* areaObject = static_cast<AccessibilityImageMapLink*>(axObjectCache()->getOrCreate(ImageMapLinkRole));
1738                areaObject->setHTMLAreaElement(static_cast<HTMLAreaElement*>(curr));
1739                areaObject->setHTMLMapElement(static_cast<HTMLMapElement*>(parent));
1740                areaObject->setParent(accessibilityParentForImageMap(static_cast<HTMLMapElement*>(parent)));
1741
1742                result.append(areaObject);
1743            }
1744        }
1745    }
1746}
1747
1748FrameView* AccessibilityRenderObject::documentFrameView() const
1749{
1750    if (!m_renderer || !m_renderer->document())
1751        return 0;
1752
1753    // this is the RenderObject's Document's Frame's FrameView
1754    return m_renderer->document()->view();
1755}
1756
1757Widget* AccessibilityRenderObject::widgetForAttachmentView() const
1758{
1759    if (!isAttachment())
1760        return 0;
1761    return toRenderWidget(m_renderer)->widget();
1762}
1763
1764FrameView* AccessibilityRenderObject::frameViewIfRenderView() const
1765{
1766    if (!m_renderer->isRenderView())
1767        return 0;
1768    // this is the RenderObject's Document's renderer's FrameView
1769    return m_renderer->view()->frameView();
1770}
1771
1772// This function is like a cross-platform version of - (WebCoreTextMarkerRange*)textMarkerRange. It returns
1773// a Range that we can convert to a WebCoreTextMarkerRange in the Obj-C file
1774VisiblePositionRange AccessibilityRenderObject::visiblePositionRange() const
1775{
1776    if (!m_renderer)
1777        return VisiblePositionRange();
1778
1779    // construct VisiblePositions for start and end
1780    Node* node = m_renderer->node();
1781    if (!node)
1782        return VisiblePositionRange();
1783
1784    VisiblePosition startPos = firstPositionInOrBeforeNode(node);
1785    VisiblePosition endPos = lastPositionInOrAfterNode(node);
1786
1787    // the VisiblePositions are equal for nodes like buttons, so adjust for that
1788    // FIXME: Really?  [button, 0] and [button, 1] are distinct (before and after the button)
1789    // I expect this code is only hit for things like empty divs?  In which case I don't think
1790    // the behavior is correct here -- eseidel
1791    if (startPos == endPos) {
1792        endPos = endPos.next();
1793        if (endPos.isNull())
1794            endPos = startPos;
1795    }
1796
1797    return VisiblePositionRange(startPos, endPos);
1798}
1799
1800VisiblePositionRange AccessibilityRenderObject::visiblePositionRangeForLine(unsigned lineCount) const
1801{
1802    if (!lineCount || !m_renderer)
1803        return VisiblePositionRange();
1804
1805    // iterate over the lines
1806    // FIXME: this is wrong when lineNumber is lineCount+1,  because nextLinePosition takes you to the
1807    // last offset of the last line
1808    VisiblePosition visiblePos = m_renderer->document()->renderer()->positionForPoint(IntPoint());
1809    VisiblePosition savedVisiblePos;
1810    while (--lineCount) {
1811        savedVisiblePos = visiblePos;
1812        visiblePos = nextLinePosition(visiblePos, 0);
1813        if (visiblePos.isNull() || visiblePos == savedVisiblePos)
1814            return VisiblePositionRange();
1815    }
1816
1817    // make a caret selection for the marker position, then extend it to the line
1818    // NOTE: ignores results of sel.modify because it returns false when
1819    // starting at an empty line.  The resulting selection in that case
1820    // will be a caret at visiblePos.
1821    FrameSelection selection;
1822    selection.setSelection(VisibleSelection(visiblePos));
1823    selection.modify(FrameSelection::AlterationExtend, DirectionRight, LineBoundary);
1824
1825    return VisiblePositionRange(selection.selection().visibleStart(), selection.selection().visibleEnd());
1826}
1827
1828VisiblePosition AccessibilityRenderObject::visiblePositionForIndex(int index) const
1829{
1830    if (!m_renderer)
1831        return VisiblePosition();
1832
1833    if (isNativeTextControl())
1834        return toRenderTextControl(m_renderer)->visiblePositionForIndex(index);
1835
1836    if (!allowsTextRanges() && !m_renderer->isText())
1837        return VisiblePosition();
1838
1839    Node* node = m_renderer->node();
1840    if (!node)
1841        return VisiblePosition();
1842
1843    if (index <= 0)
1844        return VisiblePosition(firstPositionInOrBeforeNode(node), DOWNSTREAM);
1845
1846    RefPtr<Range> range = Range::create(m_renderer->document());
1847    range->selectNodeContents(node, IGNORE_EXCEPTION);
1848    CharacterIterator it(range.get());
1849    it.advance(index - 1);
1850    return VisiblePosition(Position(it.range()->endContainer(), it.range()->endOffset(), Position::PositionIsOffsetInAnchor), UPSTREAM);
1851}
1852
1853int AccessibilityRenderObject::indexForVisiblePosition(const VisiblePosition& pos) const
1854{
1855    if (isNativeTextControl()) {
1856        HTMLTextFormControlElement* textControl = toRenderTextControl(m_renderer)->textFormControlElement();
1857        return textControl->indexForVisiblePosition(pos);
1858    }
1859
1860    if (!isTextControl())
1861        return 0;
1862
1863    Node* node = m_renderer->node();
1864    if (!node)
1865        return 0;
1866
1867    Position indexPosition = pos.deepEquivalent();
1868    if (indexPosition.isNull() || highestEditableRoot(indexPosition, HasEditableAXRole) != node)
1869        return 0;
1870
1871    RefPtr<Range> range = Range::create(m_renderer->document());
1872    range->setStart(node, 0, IGNORE_EXCEPTION);
1873    range->setEnd(indexPosition, IGNORE_EXCEPTION);
1874
1875#if PLATFORM(GTK)
1876    // We need to consider replaced elements for GTK, as they will be
1877    // presented with the 'object replacement character' (0xFFFC).
1878    return TextIterator::rangeLength(range.get(), true);
1879#else
1880    return TextIterator::rangeLength(range.get());
1881#endif
1882}
1883
1884Element* AccessibilityRenderObject::rootEditableElementForPosition(const Position& position) const
1885{
1886    // Find the root editable or pseudo-editable (i.e. having an editable ARIA role) element.
1887    Element* result = 0;
1888
1889    Element* rootEditableElement = position.rootEditableElement();
1890
1891    for (Element* e = position.element(); e && e != rootEditableElement; e = e->parentElement()) {
1892        if (nodeIsTextControl(e))
1893            result = e;
1894        if (e->hasTagName(bodyTag))
1895            break;
1896    }
1897
1898    if (result)
1899        return result;
1900
1901    return rootEditableElement;
1902}
1903
1904bool AccessibilityRenderObject::nodeIsTextControl(const Node* node) const
1905{
1906    if (!node)
1907        return false;
1908
1909    const AccessibilityObject* axObjectForNode = axObjectCache()->getOrCreate(const_cast<Node*>(node));
1910    if (!axObjectForNode)
1911        return false;
1912
1913    return axObjectForNode->isTextControl();
1914}
1915
1916IntRect AccessibilityRenderObject::boundsForVisiblePositionRange(const VisiblePositionRange& visiblePositionRange) const
1917{
1918    if (visiblePositionRange.isNull())
1919        return IntRect();
1920
1921    // Create a mutable VisiblePositionRange.
1922    VisiblePositionRange range(visiblePositionRange);
1923    LayoutRect rect1 = range.start.absoluteCaretBounds();
1924    LayoutRect rect2 = range.end.absoluteCaretBounds();
1925
1926    // 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
1927    if (rect2.y() != rect1.y()) {
1928        VisiblePosition endOfFirstLine = endOfLine(range.start);
1929        if (range.start == endOfFirstLine) {
1930            range.start.setAffinity(DOWNSTREAM);
1931            rect1 = range.start.absoluteCaretBounds();
1932        }
1933        if (range.end == endOfFirstLine) {
1934            range.end.setAffinity(UPSTREAM);
1935            rect2 = range.end.absoluteCaretBounds();
1936        }
1937    }
1938
1939    LayoutRect ourrect = rect1;
1940    ourrect.unite(rect2);
1941
1942    // if the rectangle spans lines and contains multiple text chars, use the range's bounding box intead
1943    if (rect1.maxY() != rect2.maxY()) {
1944        RefPtr<Range> dataRange = makeRange(range.start, range.end);
1945        LayoutRect boundingBox = dataRange->boundingBox();
1946        String rangeString = plainText(dataRange.get());
1947        if (rangeString.length() > 1 && !boundingBox.isEmpty())
1948            ourrect = boundingBox;
1949    }
1950
1951#if PLATFORM(MAC)
1952    return m_renderer->document()->view()->contentsToScreen(pixelSnappedIntRect(ourrect));
1953#else
1954    return pixelSnappedIntRect(ourrect);
1955#endif
1956}
1957
1958void AccessibilityRenderObject::setSelectedVisiblePositionRange(const VisiblePositionRange& range) const
1959{
1960    if (range.start.isNull() || range.end.isNull())
1961        return;
1962
1963    // make selection and tell the document to use it. if it's zero length, then move to that position
1964    if (range.start == range.end)
1965        m_renderer->frame()->selection()->moveTo(range.start, UserTriggered);
1966    else {
1967        VisibleSelection newSelection = VisibleSelection(range.start, range.end);
1968        m_renderer->frame()->selection()->setSelection(newSelection);
1969    }
1970}
1971
1972VisiblePosition AccessibilityRenderObject::visiblePositionForPoint(const IntPoint& point) const
1973{
1974    if (!m_renderer)
1975        return VisiblePosition();
1976
1977    // convert absolute point to view coordinates
1978    RenderView* renderView = topRenderer();
1979    if (!renderView)
1980        return VisiblePosition();
1981
1982    FrameView* frameView = renderView->frameView();
1983    if (!frameView)
1984        return VisiblePosition();
1985
1986    Node* innerNode = 0;
1987
1988    // locate the node containing the point
1989    LayoutPoint pointResult;
1990    while (1) {
1991        LayoutPoint ourpoint;
1992#if PLATFORM(MAC)
1993        ourpoint = frameView->screenToContents(point);
1994#else
1995        ourpoint = point;
1996#endif
1997        HitTestRequest request(HitTestRequest::ReadOnly |
1998                               HitTestRequest::Active);
1999        HitTestResult result(ourpoint);
2000        renderView->hitTest(request, result);
2001        innerNode = result.innerNode();
2002        if (!innerNode)
2003            return VisiblePosition();
2004
2005        RenderObject* renderer = innerNode->renderer();
2006        if (!renderer)
2007            return VisiblePosition();
2008
2009        pointResult = result.localPoint();
2010
2011        // done if hit something other than a widget
2012        if (!renderer->isWidget())
2013            break;
2014
2015        // descend into widget (FRAME, IFRAME, OBJECT...)
2016        Widget* widget = toRenderWidget(renderer)->widget();
2017        if (!widget || !widget->isFrameView())
2018            break;
2019        Frame* frame = toFrameView(widget)->frame();
2020        if (!frame)
2021            break;
2022        renderView = frame->document()->renderView();
2023        frameView = toFrameView(widget);
2024    }
2025
2026    return innerNode->renderer()->positionForPoint(pointResult);
2027}
2028
2029// NOTE: Consider providing this utility method as AX API
2030VisiblePosition AccessibilityRenderObject::visiblePositionForIndex(unsigned indexValue, bool lastIndexOK) const
2031{
2032    if (!isTextControl())
2033        return VisiblePosition();
2034
2035    // lastIndexOK specifies whether the position after the last character is acceptable
2036    if (indexValue >= text().length()) {
2037        if (!lastIndexOK || indexValue > text().length())
2038            return VisiblePosition();
2039    }
2040    VisiblePosition position = visiblePositionForIndex(indexValue);
2041    position.setAffinity(DOWNSTREAM);
2042    return position;
2043}
2044
2045// NOTE: Consider providing this utility method as AX API
2046int AccessibilityRenderObject::index(const VisiblePosition& position) const
2047{
2048    if (position.isNull() || !isTextControl())
2049        return -1;
2050
2051    if (renderObjectContainsPosition(m_renderer, position.deepEquivalent()))
2052        return indexForVisiblePosition(position);
2053
2054    return -1;
2055}
2056
2057void AccessibilityRenderObject::lineBreaks(Vector<int>& lineBreaks) const
2058{
2059    if (!isTextControl())
2060        return;
2061
2062    VisiblePosition visiblePos = visiblePositionForIndex(0);
2063    VisiblePosition savedVisiblePos = visiblePos;
2064    visiblePos = nextLinePosition(visiblePos, 0);
2065    while (!visiblePos.isNull() && visiblePos != savedVisiblePos) {
2066        lineBreaks.append(indexForVisiblePosition(visiblePos));
2067        savedVisiblePos = visiblePos;
2068        visiblePos = nextLinePosition(visiblePos, 0);
2069    }
2070}
2071
2072// Given a line number, the range of characters of the text associated with this accessibility
2073// object that contains the line number.
2074PlainTextRange AccessibilityRenderObject::doAXRangeForLine(unsigned lineNumber) const
2075{
2076    if (!isTextControl())
2077        return PlainTextRange();
2078
2079    // iterate to the specified line
2080    VisiblePosition visiblePos = visiblePositionForIndex(0);
2081    VisiblePosition savedVisiblePos;
2082    for (unsigned lineCount = lineNumber; lineCount; lineCount -= 1) {
2083        savedVisiblePos = visiblePos;
2084        visiblePos = nextLinePosition(visiblePos, 0);
2085        if (visiblePos.isNull() || visiblePos == savedVisiblePos)
2086            return PlainTextRange();
2087    }
2088
2089    // Get the end of the line based on the starting position.
2090    VisiblePosition endPosition = endOfLine(visiblePos);
2091
2092    int index1 = indexForVisiblePosition(visiblePos);
2093    int index2 = indexForVisiblePosition(endPosition);
2094
2095    // add one to the end index for a line break not caused by soft line wrap (to match AppKit)
2096    if (endPosition.affinity() == DOWNSTREAM && endPosition.next().isNotNull())
2097        index2 += 1;
2098
2099    // return nil rather than an zero-length range (to match AppKit)
2100    if (index1 == index2)
2101        return PlainTextRange();
2102
2103    return PlainTextRange(index1, index2 - index1);
2104}
2105
2106// The composed character range in the text associated with this accessibility object that
2107// is specified by the given index value. This parameterized attribute returns the complete
2108// range of characters (including surrogate pairs of multi-byte glyphs) at the given index.
2109PlainTextRange AccessibilityRenderObject::doAXRangeForIndex(unsigned index) const
2110{
2111    if (!isTextControl())
2112        return PlainTextRange();
2113
2114    String elementText = text();
2115    if (!elementText.length() || index > elementText.length() - 1)
2116        return PlainTextRange();
2117
2118    return PlainTextRange(index, 1);
2119}
2120
2121// A substring of the text associated with this accessibility object that is
2122// specified by the given character range.
2123String AccessibilityRenderObject::doAXStringForRange(const PlainTextRange& range) const
2124{
2125    if (!range.length)
2126        return String();
2127
2128    if (!isTextControl())
2129        return String();
2130
2131    String elementText = isPasswordField() ? passwordFieldValue() : text();
2132    if (range.start + range.length > elementText.length())
2133        return String();
2134
2135    return elementText.substring(range.start, range.length);
2136}
2137
2138// The bounding rectangle of the text associated with this accessibility object that is
2139// specified by the given range. This is the bounding rectangle a sighted user would see
2140// on the display screen, in pixels.
2141IntRect AccessibilityRenderObject::doAXBoundsForRange(const PlainTextRange& range) const
2142{
2143    if (allowsTextRanges())
2144        return boundsForVisiblePositionRange(visiblePositionRangeForRange(range));
2145    return IntRect();
2146}
2147
2148AccessibilityObject* AccessibilityRenderObject::accessibilityImageMapHitTest(HTMLAreaElement* area, const IntPoint& point) const
2149{
2150    if (!area)
2151        return 0;
2152
2153    AccessibilityObject* parent = 0;
2154    for (Element* mapParent = area->parentElement(); mapParent; mapParent = mapParent->parentElement()) {
2155        if (mapParent->hasTagName(mapTag)) {
2156            parent = accessibilityParentForImageMap(static_cast<HTMLMapElement*>(mapParent));
2157            break;
2158        }
2159    }
2160    if (!parent)
2161        return 0;
2162
2163    AccessibilityObject::AccessibilityChildrenVector children = parent->children();
2164
2165    unsigned count = children.size();
2166    for (unsigned k = 0; k < count; ++k) {
2167        if (children[k]->elementRect().contains(point))
2168            return children[k].get();
2169    }
2170
2171    return 0;
2172}
2173
2174AccessibilityObject* AccessibilityRenderObject::remoteSVGElementHitTest(const IntPoint& point) const
2175{
2176    AccessibilityObject* remote = remoteSVGRootElement();
2177    if (!remote)
2178        return 0;
2179
2180    IntSize offset = point - roundedIntPoint(boundingBoxRect().location());
2181    return remote->accessibilityHitTest(IntPoint(offset));
2182}
2183
2184AccessibilityObject* AccessibilityRenderObject::elementAccessibilityHitTest(const IntPoint& point) const
2185{
2186    if (isSVGImage())
2187        return remoteSVGElementHitTest(point);
2188
2189    return AccessibilityObject::elementAccessibilityHitTest(point);
2190}
2191
2192AccessibilityObject* AccessibilityRenderObject::accessibilityHitTest(const IntPoint& point) const
2193{
2194    if (!m_renderer || !m_renderer->hasLayer())
2195        return 0;
2196
2197    RenderLayer* layer = toRenderBox(m_renderer)->layer();
2198
2199    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::AccessibilityHitTest);
2200    HitTestResult hitTestResult = HitTestResult(point);
2201    layer->hitTest(request, hitTestResult);
2202    if (!hitTestResult.innerNode())
2203        return 0;
2204    Node* node = hitTestResult.innerNode()->deprecatedShadowAncestorNode();
2205
2206    if (node->hasTagName(areaTag))
2207        return accessibilityImageMapHitTest(static_cast<HTMLAreaElement*>(node), point);
2208
2209    if (node->hasTagName(optionTag))
2210        node = static_cast<HTMLOptionElement*>(node)->ownerSelectElement();
2211
2212    RenderObject* obj = node->renderer();
2213    if (!obj)
2214        return 0;
2215
2216    AccessibilityObject* result = obj->document()->axObjectCache()->getOrCreate(obj);
2217    result->updateChildrenIfNecessary();
2218
2219    // Allow the element to perform any hit-testing it might need to do to reach non-render children.
2220    result = result->elementAccessibilityHitTest(point);
2221
2222    if (result && result->accessibilityIsIgnored()) {
2223        // If this element is the label of a control, a hit test should return the control.
2224        AccessibilityObject* controlObject = result->correspondingControlForLabelElement();
2225        if (controlObject && !controlObject->exposesTitleUIElement())
2226            return controlObject;
2227
2228        result = result->parentObjectUnignored();
2229    }
2230
2231    return result;
2232}
2233
2234bool AccessibilityRenderObject::shouldNotifyActiveDescendant() const
2235{
2236    // We want to notify that the combo box has changed its active descendant,
2237    // but we do not want to change the focus, because focus should remain with the combo box.
2238    if (isComboBox())
2239        return true;
2240
2241    return shouldFocusActiveDescendant();
2242}
2243
2244bool AccessibilityRenderObject::shouldFocusActiveDescendant() const
2245{
2246    switch (ariaRoleAttribute()) {
2247    case GroupRole:
2248    case ListBoxRole:
2249    case MenuRole:
2250    case MenuBarRole:
2251    case RadioGroupRole:
2252    case RowRole:
2253    case PopUpButtonRole:
2254    case ProgressIndicatorRole:
2255    case ToolbarRole:
2256    case OutlineRole:
2257    case TreeRole:
2258    case GridRole:
2259    /* FIXME: replace these with actual roles when they are added to AccessibilityRole
2260    composite
2261    alert
2262    alertdialog
2263    status
2264    timer
2265    */
2266        return true;
2267    default:
2268        return false;
2269    }
2270}
2271
2272AccessibilityObject* AccessibilityRenderObject::activeDescendant() const
2273{
2274    if (!m_renderer)
2275        return 0;
2276
2277    if (m_renderer->node() && !m_renderer->node()->isElementNode())
2278        return 0;
2279    Element* element = toElement(m_renderer->node());
2280
2281    const AtomicString& activeDescendantAttrStr = element->getAttribute(aria_activedescendantAttr);
2282    if (activeDescendantAttrStr.isNull() || activeDescendantAttrStr.isEmpty())
2283        return 0;
2284
2285    Element* target = element->treeScope()->getElementById(activeDescendantAttrStr);
2286    if (!target)
2287        return 0;
2288
2289    AccessibilityObject* obj = axObjectCache()->getOrCreate(target);
2290    if (obj && obj->isAccessibilityRenderObject())
2291    // an activedescendant is only useful if it has a renderer, because that's what's needed to post the notification
2292        return obj;
2293    return 0;
2294}
2295
2296void AccessibilityRenderObject::handleAriaExpandedChanged()
2297{
2298    // Find if a parent of this object should handle aria-expanded changes.
2299    AccessibilityObject* containerParent = this->parentObject();
2300    while (containerParent) {
2301        bool foundParent = false;
2302
2303        switch (containerParent->roleValue()) {
2304        case TreeRole:
2305        case TreeGridRole:
2306        case GridRole:
2307        case TableRole:
2308        case BrowserRole:
2309            foundParent = true;
2310            break;
2311        default:
2312            break;
2313        }
2314
2315        if (foundParent)
2316            break;
2317
2318        containerParent = containerParent->parentObject();
2319    }
2320
2321    // Post that the row count changed.
2322    if (containerParent)
2323        axObjectCache()->postNotification(containerParent, document(), AXObjectCache::AXRowCountChanged, true);
2324
2325    // Post that the specific row either collapsed or expanded.
2326    if (roleValue() == RowRole || roleValue() == TreeItemRole)
2327        axObjectCache()->postNotification(this, document(), isExpanded() ? AXObjectCache::AXRowExpanded : AXObjectCache::AXRowCollapsed, true);
2328}
2329
2330void AccessibilityRenderObject::handleActiveDescendantChanged()
2331{
2332    Element* element = toElement(renderer()->node());
2333    if (!element)
2334        return;
2335    Document* doc = renderer()->document();
2336    if (!doc->frame()->selection()->isFocusedAndActive() || doc->focusedElement() != element)
2337        return;
2338    AccessibilityRenderObject* activedescendant = static_cast<AccessibilityRenderObject*>(activeDescendant());
2339
2340    if (activedescendant && shouldNotifyActiveDescendant())
2341        doc->axObjectCache()->postNotification(m_renderer, AXObjectCache::AXActiveDescendantChanged, true);
2342}
2343
2344AccessibilityObject* AccessibilityRenderObject::correspondingControlForLabelElement() const
2345{
2346    HTMLLabelElement* labelElement = labelElementContainer();
2347    if (!labelElement)
2348        return 0;
2349
2350    HTMLElement* correspondingControl = labelElement->control();
2351    if (!correspondingControl)
2352        return 0;
2353
2354    // Make sure the corresponding control isn't a descendant of this label that's in the middle of being destroyed.
2355    if (correspondingControl->renderer() && !correspondingControl->renderer()->parent())
2356        return 0;
2357
2358    return axObjectCache()->getOrCreate(correspondingControl);
2359}
2360
2361AccessibilityObject* AccessibilityRenderObject::correspondingLabelForControlElement() const
2362{
2363    if (!m_renderer)
2364        return 0;
2365
2366    // ARIA: section 2A, bullet #3 says if aria-labeledby or aria-label appears, it should
2367    // override the "label" element association.
2368    if (hasTextAlternative())
2369        return 0;
2370
2371    Node* node = m_renderer->node();
2372    if (node && node->isHTMLElement()) {
2373        HTMLLabelElement* label = labelForElement(toElement(node));
2374        if (label)
2375            return axObjectCache()->getOrCreate(label);
2376    }
2377
2378    return 0;
2379}
2380
2381bool AccessibilityRenderObject::renderObjectIsObservable(RenderObject* renderer) const
2382{
2383    // AX clients will listen for AXValueChange on a text control.
2384    if (renderer->isTextControl())
2385        return true;
2386
2387    // AX clients will listen for AXSelectedChildrenChanged on listboxes.
2388    Node* node = renderer->node();
2389    if (nodeHasRole(node, "listbox") || (renderer->isBoxModelObject() && toRenderBoxModelObject(renderer)->isListBox()))
2390        return true;
2391
2392    // Textboxes should send out notifications.
2393    if (nodeHasRole(node, "textbox"))
2394        return true;
2395
2396    return false;
2397}
2398
2399AccessibilityObject* AccessibilityRenderObject::observableObject() const
2400{
2401    // Find the object going up the parent chain that is used in accessibility to monitor certain notifications.
2402    for (RenderObject* renderer = m_renderer; renderer && renderer->node(); renderer = renderer->parent()) {
2403        if (renderObjectIsObservable(renderer))
2404            return axObjectCache()->getOrCreate(renderer);
2405    }
2406
2407    return 0;
2408}
2409
2410bool AccessibilityRenderObject::isDescendantOfElementType(const QualifiedName& tagName) const
2411{
2412    for (RenderObject* parent = m_renderer->parent(); parent; parent = parent->parent()) {
2413        if (parent->node() && parent->node()->hasTagName(tagName))
2414            return true;
2415    }
2416    return false;
2417}
2418
2419AccessibilityRole AccessibilityRenderObject::determineAccessibilityRole()
2420{
2421    if (!m_renderer)
2422        return UnknownRole;
2423
2424    m_ariaRole = determineAriaRoleAttribute();
2425
2426    Node* node = m_renderer->node();
2427    AccessibilityRole ariaRole = ariaRoleAttribute();
2428    if (ariaRole != UnknownRole)
2429        return ariaRole;
2430
2431    RenderBoxModelObject* cssBox = renderBoxModelObject();
2432
2433    if (node && node->isLink()) {
2434        if (cssBox && cssBox->isImage())
2435            return ImageMapRole;
2436        return WebCoreLinkRole;
2437    }
2438    if ((cssBox && cssBox->isListItem()) || (node && node->hasTagName(liTag)))
2439        return ListItemRole;
2440    if (m_renderer->isListMarker())
2441        return ListMarkerRole;
2442    if (node && node->hasTagName(buttonTag))
2443        return buttonRoleType();
2444    if (node && node->hasTagName(legendTag))
2445        return LegendRole;
2446    if (m_renderer->isText())
2447        return StaticTextRole;
2448    if (cssBox && cssBox->isImage()) {
2449        if (node && node->hasTagName(inputTag))
2450            return ariaHasPopup() ? PopUpButtonRole : ButtonRole;
2451        if (isSVGImage())
2452            return SVGRootRole;
2453        return ImageRole;
2454    }
2455
2456    if (node && node->hasTagName(canvasTag))
2457        return CanvasRole;
2458
2459    if (cssBox && cssBox->isRenderView()) {
2460        // If the iframe is seamless, it should not be announced as a web area to AT clients.
2461        if (document() && document()->shouldDisplaySeamlesslyWithParent())
2462            return SeamlessWebAreaRole;
2463        return WebAreaRole;
2464    }
2465
2466    if (cssBox && cssBox->isTextField())
2467        return TextFieldRole;
2468
2469    if (cssBox && cssBox->isTextArea())
2470        return TextAreaRole;
2471
2472    if (node && node->hasTagName(inputTag)) {
2473        HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
2474        if (input->isCheckbox())
2475            return CheckBoxRole;
2476        if (input->isRadioButton())
2477            return RadioButtonRole;
2478        if (input->isTextButton())
2479            return buttonRoleType();
2480
2481#if ENABLE(INPUT_TYPE_COLOR)
2482        const AtomicString& type = input->getAttribute(typeAttr);
2483        if (equalIgnoringCase(type, "color"))
2484            return ColorWellRole;
2485#endif
2486    }
2487
2488    if (isFileUploadButton())
2489        return ButtonRole;
2490
2491    if (cssBox && cssBox->isMenuList())
2492        return PopUpButtonRole;
2493
2494    if (headingLevel())
2495        return HeadingRole;
2496
2497#if ENABLE(SVG)
2498    if (m_renderer->isSVGImage())
2499        return ImageRole;
2500    if (m_renderer->isSVGRoot())
2501        return SVGRootRole;
2502    if (node && node->hasTagName(SVGNames::gTag))
2503        return GroupRole;
2504#endif
2505
2506#if ENABLE(MATHML)
2507    if (node && node->hasTagName(MathMLNames::mathTag))
2508        return DocumentMathRole;
2509#endif
2510    // It's not clear which role a platform should choose for a math element.
2511    // Declaring a math element role should give flexibility to platforms to choose.
2512    if (isMathElement())
2513        return MathElementRole;
2514
2515    if (node && node->hasTagName(ddTag))
2516        return DescriptionListDetailRole;
2517
2518    if (node && node->hasTagName(dtTag))
2519        return DescriptionListTermRole;
2520
2521    if (node && node->hasTagName(dlTag))
2522        return DescriptionListRole;
2523
2524    if (node && (node->hasTagName(rpTag) || node->hasTagName(rtTag)))
2525        return AnnotationRole;
2526
2527#if PLATFORM(GTK)
2528    // Gtk ATs expect all tables, data and layout, to be exposed as tables.
2529    if (node && (node->hasTagName(tdTag) || node->hasTagName(thTag)))
2530        return CellRole;
2531
2532    if (node && node->hasTagName(trTag))
2533        return RowRole;
2534
2535    if (node && node->hasTagName(tableTag))
2536        return TableRole;
2537#endif
2538
2539    // Table sections should be ignored.
2540    if (m_renderer->isTableSection())
2541        return IgnoredRole;
2542
2543    if (m_renderer->isHR())
2544        return HorizontalRuleRole;
2545
2546    if (node && node->hasTagName(pTag))
2547        return ParagraphRole;
2548
2549    if (node && node->hasTagName(labelTag))
2550        return LabelRole;
2551
2552    if (node && node->hasTagName(dfnTag))
2553        return DefinitionRole;
2554
2555    if (node && node->hasTagName(divTag))
2556        return DivRole;
2557
2558    if (node && node->hasTagName(formTag))
2559        return FormRole;
2560
2561    if (node && node->hasTagName(articleTag))
2562        return DocumentArticleRole;
2563
2564    if (node && node->hasTagName(mainTag))
2565        return LandmarkMainRole;
2566
2567    if (node && node->hasTagName(navTag))
2568        return LandmarkNavigationRole;
2569
2570    if (node && node->hasTagName(asideTag))
2571        return LandmarkComplementaryRole;
2572
2573    if (node && node->hasTagName(sectionTag))
2574        return DocumentRegionRole;
2575
2576    if (node && node->hasTagName(addressTag))
2577        return LandmarkContentInfoRole;
2578
2579#if ENABLE(VIDEO)
2580    if (node && node->hasTagName(videoTag))
2581        return VideoRole;
2582    if (node && node->hasTagName(audioTag))
2583        return AudioRole;
2584#endif
2585
2586    // The HTML element should not be exposed as an element. That's what the RenderView element does.
2587    if (node && node->hasTagName(htmlTag))
2588        return IgnoredRole;
2589
2590    // There should only be one banner/contentInfo per page. If header/footer are being used within an article or section
2591    // then it should not be exposed as whole page's banner/contentInfo
2592    if (node && node->hasTagName(headerTag) && !isDescendantOfElementType(articleTag) && !isDescendantOfElementType(sectionTag))
2593        return LandmarkBannerRole;
2594    if (node && node->hasTagName(footerTag) && !isDescendantOfElementType(articleTag) && !isDescendantOfElementType(sectionTag))
2595        return FooterRole;
2596
2597    if (m_renderer->isBlockFlow())
2598        return GroupRole;
2599
2600    // If the element does not have role, but it has ARIA attributes, accessibility should fallback to exposing it as a group.
2601    if (supportsARIAAttributes())
2602        return GroupRole;
2603
2604    return UnknownRole;
2605}
2606
2607AccessibilityOrientation AccessibilityRenderObject::orientation() const
2608{
2609    const AtomicString& ariaOrientation = getAttribute(aria_orientationAttr);
2610    if (equalIgnoringCase(ariaOrientation, "horizontal"))
2611        return AccessibilityOrientationHorizontal;
2612    if (equalIgnoringCase(ariaOrientation, "vertical"))
2613        return AccessibilityOrientationVertical;
2614
2615    return AccessibilityObject::orientation();
2616}
2617
2618bool AccessibilityRenderObject::inheritsPresentationalRole() const
2619{
2620    // ARIA states if an item can get focus, it should not be presentational.
2621    if (canSetFocusAttribute())
2622        return false;
2623
2624    // ARIA spec says that when a parent object is presentational, and it has required child elements,
2625    // those child elements are also presentational. For example, <li> becomes presentational from <ul>.
2626    // http://www.w3.org/WAI/PF/aria/complete#presentation
2627    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, listItemParents, ());
2628
2629    HashSet<QualifiedName>* possibleParentTagNames = 0;
2630    switch (roleValue()) {
2631    case ListItemRole:
2632    case ListMarkerRole:
2633        if (listItemParents.isEmpty()) {
2634            listItemParents.add(ulTag);
2635            listItemParents.add(olTag);
2636            listItemParents.add(dlTag);
2637        }
2638        possibleParentTagNames = &listItemParents;
2639        break;
2640    default:
2641        break;
2642    }
2643
2644    // Not all elements need to check for this, only ones that are required children.
2645    if (!possibleParentTagNames)
2646        return false;
2647
2648    for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) {
2649        if (!parent->isAccessibilityRenderObject())
2650            continue;
2651
2652        Node* elementNode = static_cast<AccessibilityRenderObject*>(parent)->node();
2653        if (!elementNode || !elementNode->isElementNode())
2654            continue;
2655
2656        // If native tag of the parent element matches an acceptable name, then return
2657        // based on its presentational status.
2658        if (possibleParentTagNames->contains(toElement(elementNode)->tagQName()))
2659            return parent->roleValue() == PresentationalRole;
2660    }
2661
2662    return false;
2663}
2664
2665bool AccessibilityRenderObject::isPresentationalChildOfAriaRole() const
2666{
2667    // Walk the parent chain looking for a parent that has presentational children
2668    AccessibilityObject* parent;
2669    for (parent = parentObject(); parent && !parent->ariaRoleHasPresentationalChildren(); parent = parent->parentObject())
2670    { }
2671
2672    return parent;
2673}
2674
2675bool AccessibilityRenderObject::ariaRoleHasPresentationalChildren() const
2676{
2677    switch (m_ariaRole) {
2678    case ButtonRole:
2679    case SliderRole:
2680    case ImageRole:
2681    case ProgressIndicatorRole:
2682    case SpinButtonRole:
2683    // case SeparatorRole:
2684        return true;
2685    default:
2686        return false;
2687    }
2688}
2689
2690bool AccessibilityRenderObject::canSetExpandedAttribute() const
2691{
2692    // An object can be expanded if it aria-expanded is true or false.
2693    const AtomicString& ariaExpanded = getAttribute(aria_expandedAttr);
2694    return equalIgnoringCase(ariaExpanded, "true") || equalIgnoringCase(ariaExpanded, "false");
2695}
2696
2697bool AccessibilityRenderObject::canSetValueAttribute() const
2698{
2699
2700    // In the event of a (Boolean)@readonly and (True/False/Undefined)@aria-readonly
2701    // value mismatch, the host language native attribute value wins.
2702    if (isNativeTextControl())
2703        return !isReadOnly();
2704
2705    if (equalIgnoringCase(getAttribute(aria_readonlyAttr), "true"))
2706        return false;
2707
2708    if (equalIgnoringCase(getAttribute(aria_readonlyAttr), "false"))
2709        return true;
2710
2711    if (isProgressIndicator() || isSlider())
2712        return true;
2713
2714    if (isTextControl() && !isNativeTextControl())
2715        return true;
2716
2717    // Any node could be contenteditable, so isReadOnly should be relied upon
2718    // for this information for all elements.
2719    return !isReadOnly();
2720}
2721
2722bool AccessibilityRenderObject::canSetTextRangeAttributes() const
2723{
2724    return isTextControl();
2725}
2726
2727void AccessibilityRenderObject::textChanged()
2728{
2729    // If this element supports ARIA live regions, or is part of a region with an ARIA editable role,
2730    // then notify the AT of changes.
2731    AXObjectCache* cache = axObjectCache();
2732    for (RenderObject* renderParent = m_renderer; renderParent; renderParent = renderParent->parent()) {
2733        AccessibilityObject* parent = cache->get(renderParent);
2734        if (!parent)
2735            continue;
2736
2737        if (parent->supportsARIALiveRegion())
2738            cache->postNotification(renderParent, AXObjectCache::AXLiveRegionChanged, true);
2739
2740        if (parent->isARIATextControl() && !parent->isNativeTextControl() && !parent->node()->rendererIsEditable())
2741            cache->postNotification(renderParent, AXObjectCache::AXValueChanged, true);
2742    }
2743}
2744
2745void AccessibilityRenderObject::clearChildren()
2746{
2747    AccessibilityObject::clearChildren();
2748    m_childrenDirty = false;
2749}
2750
2751void AccessibilityRenderObject::addImageMapChildren()
2752{
2753    RenderBoxModelObject* cssBox = renderBoxModelObject();
2754    if (!cssBox || !cssBox->isRenderImage())
2755        return;
2756
2757    HTMLMapElement* map = toRenderImage(cssBox)->imageMap();
2758    if (!map)
2759        return;
2760
2761    for (Element* current = ElementTraversal::firstWithin(map); current; current = ElementTraversal::next(current, map)) {
2762        // add an <area> element for this child if it has a link
2763        if (current->hasTagName(areaTag) && current->isLink()) {
2764            AccessibilityImageMapLink* areaObject = static_cast<AccessibilityImageMapLink*>(axObjectCache()->getOrCreate(ImageMapLinkRole));
2765            areaObject->setHTMLAreaElement(static_cast<HTMLAreaElement*>(current));
2766            areaObject->setHTMLMapElement(map);
2767            areaObject->setParent(this);
2768            if (!areaObject->accessibilityIsIgnored())
2769                m_children.append(areaObject);
2770            else
2771                axObjectCache()->remove(areaObject->axObjectID());
2772        }
2773    }
2774}
2775
2776void AccessibilityRenderObject::updateChildrenIfNecessary()
2777{
2778    if (needsToUpdateChildren())
2779        clearChildren();
2780
2781    AccessibilityObject::updateChildrenIfNecessary();
2782}
2783
2784void AccessibilityRenderObject::addTextFieldChildren()
2785{
2786    Node* node = this->node();
2787    if (!node || !node->hasTagName(inputTag))
2788        return;
2789
2790    HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
2791    HTMLElement* spinButtonElement = input->innerSpinButtonElement();
2792    if (!spinButtonElement || !spinButtonElement->isSpinButtonElement())
2793        return;
2794
2795    AccessibilitySpinButton* axSpinButton = static_cast<AccessibilitySpinButton*>(axObjectCache()->getOrCreate(SpinButtonRole));
2796    axSpinButton->setSpinButtonElement(static_cast<SpinButtonElement*>(spinButtonElement));
2797    axSpinButton->setParent(this);
2798    m_children.append(axSpinButton);
2799}
2800
2801bool AccessibilityRenderObject::isSVGImage() const
2802{
2803    return remoteSVGRootElement();
2804}
2805
2806void AccessibilityRenderObject::detachRemoteSVGRoot()
2807{
2808    if (AccessibilitySVGRoot* root = remoteSVGRootElement())
2809        root->setParent(0);
2810}
2811
2812AccessibilitySVGRoot* AccessibilityRenderObject::remoteSVGRootElement() const
2813{
2814#if ENABLE(SVG)
2815    if (!m_renderer || !m_renderer->isRenderImage())
2816        return 0;
2817
2818    CachedImage* cachedImage = toRenderImage(m_renderer)->cachedImage();
2819    if (!cachedImage)
2820        return 0;
2821
2822    Image* image = cachedImage->image();
2823    if (!image || !image->isSVGImage())
2824        return 0;
2825
2826    SVGImage* svgImage = static_cast<SVGImage*>(image);
2827    FrameView* frameView = svgImage->frameView();
2828    if (!frameView)
2829        return 0;
2830    Frame* frame = frameView->frame();
2831    if (!frame)
2832        return 0;
2833
2834    Document* doc = frame->document();
2835    if (!doc || !doc->isSVGDocument())
2836        return 0;
2837
2838    SVGSVGElement* rootElement = toSVGDocument(doc)->rootElement();
2839    if (!rootElement)
2840        return 0;
2841    RenderObject* rendererRoot = rootElement->renderer();
2842    if (!rendererRoot)
2843        return 0;
2844
2845    AccessibilityObject* rootSVGObject = frame->document()->axObjectCache()->getOrCreate(rendererRoot);
2846
2847    // In order to connect the AX hierarchy from the SVG root element from the loaded resource
2848    // the parent must be set, because there's no other way to get back to who created the image.
2849    ASSERT(rootSVGObject && rootSVGObject->isAccessibilitySVGRoot());
2850    if (!rootSVGObject->isAccessibilitySVGRoot())
2851        return 0;
2852
2853    return toAccessibilitySVGRoot(rootSVGObject);
2854#else
2855    return 0;
2856#endif
2857}
2858
2859void AccessibilityRenderObject::addRemoteSVGChildren()
2860{
2861    AccessibilitySVGRoot* root = remoteSVGRootElement();
2862    if (!root)
2863        return;
2864
2865    root->setParent(this);
2866
2867    if (root->accessibilityIsIgnored()) {
2868        AccessibilityChildrenVector children = root->children();
2869        unsigned length = children.size();
2870        for (unsigned i = 0; i < length; ++i)
2871            m_children.append(children[i]);
2872    } else
2873        m_children.append(root);
2874}
2875
2876void AccessibilityRenderObject::addCanvasChildren()
2877{
2878    if (!node() || !node()->hasTagName(canvasTag))
2879        return;
2880
2881    // If it's a canvas, it won't have rendered children, but it might have accessible fallback content.
2882    // Clear m_haveChildren because AccessibilityNodeObject::addChildren will expect it to be false.
2883    ASSERT(!m_children.size());
2884    m_haveChildren = false;
2885    AccessibilityNodeObject::addChildren();
2886}
2887
2888void AccessibilityRenderObject::addAttachmentChildren()
2889{
2890    if (!isAttachment())
2891        return;
2892
2893    // FrameView's need to be inserted into the AX hierarchy when encountered.
2894    Widget* widget = widgetForAttachmentView();
2895    if (!widget || !widget->isFrameView())
2896        return;
2897
2898    AccessibilityObject* axWidget = axObjectCache()->getOrCreate(widget);
2899    if (!axWidget->accessibilityIsIgnored())
2900        m_children.append(axWidget);
2901}
2902
2903#if PLATFORM(MAC)
2904void AccessibilityRenderObject::updateAttachmentViewParents()
2905{
2906    // Only the unignored parent should set the attachment parent, because that's what is reflected in the AX
2907    // hierarchy to the client.
2908    if (accessibilityIsIgnored())
2909        return;
2910
2911    size_t length = m_children.size();
2912    for (size_t k = 0; k < length; k++) {
2913        if (m_children[k]->isAttachment())
2914            m_children[k]->overrideAttachmentParent(this);
2915    }
2916}
2917#endif
2918
2919// Hidden children are those that are not rendered or visible, but are specifically marked as aria-hidden=false,
2920// meaning that they should be exposed to the AX hierarchy.
2921void AccessibilityRenderObject::addHiddenChildren()
2922{
2923    Node* node = this->node();
2924    if (!node)
2925        return;
2926
2927    // First do a quick run through to determine if we have any hidden nodes (most often we will not).
2928    // If we do have hidden nodes, we need to determine where to insert them so they match DOM order as close as possible.
2929    bool shouldInsertHiddenNodes = false;
2930    for (Node* child = node->firstChild(); child; child = child->nextSibling()) {
2931        if (!child->renderer() && isNodeAriaVisible(child)) {
2932            shouldInsertHiddenNodes = true;
2933            break;
2934        }
2935    }
2936
2937    if (!shouldInsertHiddenNodes)
2938        return;
2939
2940    // Iterate through all of the children, including those that may have already been added, and
2941    // try to insert hidden nodes in the correct place in the DOM order.
2942    unsigned insertionIndex = 0;
2943    for (Node* child = node->firstChild(); child; child = child->nextSibling()) {
2944        if (child->renderer()) {
2945            // Find out where the last render sibling is located within m_children.
2946            AccessibilityObject* childObject = axObjectCache()->get(child->renderer());
2947            if (childObject && childObject->accessibilityIsIgnored()) {
2948                AccessibilityChildrenVector children = childObject->children();
2949                if (children.size())
2950                    childObject = children.last().get();
2951                else
2952                    childObject = 0;
2953            }
2954
2955            if (childObject)
2956                insertionIndex = m_children.find(childObject) + 1;
2957            continue;
2958        }
2959
2960        if (!isNodeAriaVisible(child))
2961            continue;
2962
2963        unsigned previousSize = m_children.size();
2964        if (insertionIndex > previousSize)
2965            insertionIndex = previousSize;
2966
2967        insertChild(axObjectCache()->getOrCreate(child), insertionIndex);
2968        insertionIndex += (m_children.size() - previousSize);
2969    }
2970}
2971
2972void AccessibilityRenderObject::addChildren()
2973{
2974    // If the need to add more children in addition to existing children arises,
2975    // childrenChanged should have been called, leaving the object with no children.
2976    ASSERT(!m_haveChildren);
2977
2978    m_haveChildren = true;
2979
2980    if (!canHaveChildren())
2981        return;
2982
2983    for (RefPtr<AccessibilityObject> obj = firstChild(); obj; obj = obj->nextSibling())
2984        addChild(obj.get());
2985
2986    addHiddenChildren();
2987    addAttachmentChildren();
2988    addImageMapChildren();
2989    addTextFieldChildren();
2990    addCanvasChildren();
2991    addRemoteSVGChildren();
2992
2993#if PLATFORM(MAC)
2994    updateAttachmentViewParents();
2995#endif
2996}
2997
2998bool AccessibilityRenderObject::canHaveChildren() const
2999{
3000    if (!m_renderer)
3001        return false;
3002
3003    return AccessibilityNodeObject::canHaveChildren();
3004}
3005
3006const AtomicString& AccessibilityRenderObject::ariaLiveRegionStatus() const
3007{
3008    DEFINE_STATIC_LOCAL(const AtomicString, liveRegionStatusAssertive, ("assertive", AtomicString::ConstructFromLiteral));
3009    DEFINE_STATIC_LOCAL(const AtomicString, liveRegionStatusPolite, ("polite", AtomicString::ConstructFromLiteral));
3010    DEFINE_STATIC_LOCAL(const AtomicString, liveRegionStatusOff, ("off", AtomicString::ConstructFromLiteral));
3011
3012    const AtomicString& liveRegionStatus = getAttribute(aria_liveAttr);
3013    // These roles have implicit live region status.
3014    if (liveRegionStatus.isEmpty()) {
3015        switch (roleValue()) {
3016        case ApplicationAlertDialogRole:
3017        case ApplicationAlertRole:
3018            return liveRegionStatusAssertive;
3019        case ApplicationLogRole:
3020        case ApplicationStatusRole:
3021            return liveRegionStatusPolite;
3022        case ApplicationTimerRole:
3023        case ApplicationMarqueeRole:
3024            return liveRegionStatusOff;
3025        default:
3026            break;
3027        }
3028    }
3029
3030    return liveRegionStatus;
3031}
3032
3033const AtomicString& AccessibilityRenderObject::ariaLiveRegionRelevant() const
3034{
3035    DEFINE_STATIC_LOCAL(const AtomicString, defaultLiveRegionRelevant, ("additions text", AtomicString::ConstructFromLiteral));
3036    const AtomicString& relevant = getAttribute(aria_relevantAttr);
3037
3038    // Default aria-relevant = "additions text".
3039    if (relevant.isEmpty())
3040        return defaultLiveRegionRelevant;
3041
3042    return relevant;
3043}
3044
3045bool AccessibilityRenderObject::ariaLiveRegionAtomic() const
3046{
3047    return elementAttributeValue(aria_atomicAttr);
3048}
3049
3050bool AccessibilityRenderObject::ariaLiveRegionBusy() const
3051{
3052    return elementAttributeValue(aria_busyAttr);
3053}
3054
3055void AccessibilityRenderObject::ariaSelectedRows(AccessibilityChildrenVector& result)
3056{
3057    // Get all the rows.
3058    AccessibilityChildrenVector allRows;
3059    if (isTree())
3060        ariaTreeRows(allRows);
3061    else if (isAccessibilityTable() && toAccessibilityTable(this)->supportsSelectedRows())
3062        allRows = toAccessibilityTable(this)->rows();
3063
3064    // Determine which rows are selected.
3065    bool isMulti = isMultiSelectable();
3066
3067    // Prefer active descendant over aria-selected.
3068    AccessibilityObject* activeDesc = activeDescendant();
3069    if (activeDesc && (activeDesc->isTreeItem() || activeDesc->isTableRow())) {
3070        result.append(activeDesc);
3071        if (!isMulti)
3072            return;
3073    }
3074
3075    unsigned count = allRows.size();
3076    for (unsigned k = 0; k < count; ++k) {
3077        if (allRows[k]->isSelected()) {
3078            result.append(allRows[k]);
3079            if (!isMulti)
3080                break;
3081        }
3082    }
3083}
3084
3085void AccessibilityRenderObject::ariaListboxSelectedChildren(AccessibilityChildrenVector& result)
3086{
3087    bool isMulti = isMultiSelectable();
3088
3089    AccessibilityChildrenVector childObjects = children();
3090    unsigned childrenSize = childObjects.size();
3091    for (unsigned k = 0; k < childrenSize; ++k) {
3092        // Every child should have aria-role option, and if so, check for selected attribute/state.
3093        AccessibilityObject* child = childObjects[k].get();
3094        if (child->isSelected() && child->ariaRoleAttribute() == ListBoxOptionRole) {
3095            result.append(child);
3096            if (!isMulti)
3097                return;
3098        }
3099    }
3100}
3101
3102void AccessibilityRenderObject::selectedChildren(AccessibilityChildrenVector& result)
3103{
3104    ASSERT(result.isEmpty());
3105
3106    // only listboxes should be asked for their selected children.
3107    AccessibilityRole role = roleValue();
3108    if (role == ListBoxRole) // native list boxes would be AccessibilityListBoxes, so only check for aria list boxes
3109        ariaListboxSelectedChildren(result);
3110    else if (role == TreeRole || role == TreeGridRole || role == TableRole)
3111        ariaSelectedRows(result);
3112}
3113
3114void AccessibilityRenderObject::ariaListboxVisibleChildren(AccessibilityChildrenVector& result)
3115{
3116    if (!hasChildren())
3117        addChildren();
3118
3119    AccessibilityObject::AccessibilityChildrenVector children = this->children();
3120    size_t size = children.size();
3121    for (size_t i = 0; i < size; i++) {
3122        if (!children[i]->isOffScreen())
3123            result.append(children[i]);
3124    }
3125}
3126
3127void AccessibilityRenderObject::visibleChildren(AccessibilityChildrenVector& result)
3128{
3129    ASSERT(result.isEmpty());
3130
3131    // only listboxes are asked for their visible children.
3132    if (ariaRoleAttribute() != ListBoxRole) { // native list boxes would be AccessibilityListBoxes, so only check for aria list boxes
3133        ASSERT_NOT_REACHED();
3134        return;
3135    }
3136    return ariaListboxVisibleChildren(result);
3137}
3138
3139void AccessibilityRenderObject::tabChildren(AccessibilityChildrenVector& result)
3140{
3141    ASSERT(roleValue() == TabListRole);
3142
3143    AccessibilityObject::AccessibilityChildrenVector children = this->children();
3144    size_t size = children.size();
3145    for (size_t i = 0; i < size; ++i) {
3146        if (children[i]->isTabItem())
3147            result.append(children[i]);
3148    }
3149}
3150
3151const String& AccessibilityRenderObject::actionVerb() const
3152{
3153    // FIXME: Need to add verbs for select elements.
3154    DEFINE_STATIC_LOCAL(const String, buttonAction, (AXButtonActionVerb()));
3155    DEFINE_STATIC_LOCAL(const String, textFieldAction, (AXTextFieldActionVerb()));
3156    DEFINE_STATIC_LOCAL(const String, radioButtonAction, (AXRadioButtonActionVerb()));
3157    DEFINE_STATIC_LOCAL(const String, checkedCheckBoxAction, (AXCheckedCheckBoxActionVerb()));
3158    DEFINE_STATIC_LOCAL(const String, uncheckedCheckBoxAction, (AXUncheckedCheckBoxActionVerb()));
3159    DEFINE_STATIC_LOCAL(const String, linkAction, (AXLinkActionVerb()));
3160    DEFINE_STATIC_LOCAL(const String, noAction, ());
3161
3162    switch (roleValue()) {
3163    case ButtonRole:
3164    case ToggleButtonRole:
3165        return buttonAction;
3166    case TextFieldRole:
3167    case TextAreaRole:
3168        return textFieldAction;
3169    case RadioButtonRole:
3170        return radioButtonAction;
3171    case CheckBoxRole:
3172        return isChecked() ? checkedCheckBoxAction : uncheckedCheckBoxAction;
3173    case LinkRole:
3174    case WebCoreLinkRole:
3175        return linkAction;
3176    default:
3177        return noAction;
3178    }
3179}
3180
3181void AccessibilityRenderObject::setAccessibleName(const AtomicString& name)
3182{
3183    // Setting the accessible name can store the value in the DOM
3184    if (!m_renderer)
3185        return;
3186
3187    Node* domNode = 0;
3188    // For web areas, set the aria-label on the HTML element.
3189    if (isWebArea())
3190        domNode = m_renderer->document()->documentElement();
3191    else
3192        domNode = m_renderer->node();
3193
3194    if (domNode && domNode->isElementNode())
3195        toElement(domNode)->setAttribute(aria_labelAttr, name);
3196}
3197
3198static bool isLinkable(const AccessibilityRenderObject& object)
3199{
3200    if (!object.renderer())
3201        return false;
3202
3203    // See https://wiki.mozilla.org/Accessibility/AT-Windows-API for the elements
3204    // Mozilla considers linkable.
3205    return object.isLink() || object.isImage() || object.renderer()->isText();
3206}
3207
3208String AccessibilityRenderObject::stringValueForMSAA() const
3209{
3210    if (isLinkable(*this)) {
3211        Element* anchor = anchorElement();
3212        if (anchor && anchor->hasTagName(aTag))
3213            return static_cast<HTMLAnchorElement*>(anchor)->href();
3214    }
3215
3216    return stringValue();
3217}
3218
3219bool AccessibilityRenderObject::isLinked() const
3220{
3221    if (!isLinkable(*this))
3222        return false;
3223
3224    Element* anchor = anchorElement();
3225    if (!anchor || !anchor->hasTagName(aTag))
3226        return false;
3227
3228    return !static_cast<HTMLAnchorElement*>(anchor)->href().isEmpty();
3229}
3230
3231bool AccessibilityRenderObject::hasBoldFont() const
3232{
3233    if (!m_renderer)
3234        return false;
3235
3236    return m_renderer->style()->fontDescription().weight() >= FontWeightBold;
3237}
3238
3239bool AccessibilityRenderObject::hasItalicFont() const
3240{
3241    if (!m_renderer)
3242        return false;
3243
3244    return m_renderer->style()->fontDescription().italic() == FontItalicOn;
3245}
3246
3247bool AccessibilityRenderObject::hasPlainText() const
3248{
3249    if (!m_renderer)
3250        return false;
3251
3252    RenderStyle* style = m_renderer->style();
3253
3254    return style->fontDescription().weight() == FontWeightNormal
3255        && style->fontDescription().italic() == FontItalicOff
3256        && style->textDecorationsInEffect() == TextDecorationNone;
3257}
3258
3259bool AccessibilityRenderObject::hasSameFont(RenderObject* renderer) const
3260{
3261    if (!m_renderer || !renderer)
3262        return false;
3263
3264    return m_renderer->style()->fontDescription().families() == renderer->style()->fontDescription().families();
3265}
3266
3267bool AccessibilityRenderObject::hasSameFontColor(RenderObject* renderer) const
3268{
3269    if (!m_renderer || !renderer)
3270        return false;
3271
3272    return m_renderer->style()->visitedDependentColor(CSSPropertyColor) == renderer->style()->visitedDependentColor(CSSPropertyColor);
3273}
3274
3275bool AccessibilityRenderObject::hasSameStyle(RenderObject* renderer) const
3276{
3277    if (!m_renderer || !renderer)
3278        return false;
3279
3280    return m_renderer->style() == renderer->style();
3281}
3282
3283bool AccessibilityRenderObject::hasUnderline() const
3284{
3285    if (!m_renderer)
3286        return false;
3287
3288    return m_renderer->style()->textDecorationsInEffect() & TextDecorationUnderline;
3289}
3290
3291String AccessibilityRenderObject::nameForMSAA() const
3292{
3293    if (m_renderer && m_renderer->isText())
3294        return textUnderElement();
3295
3296    return title();
3297}
3298
3299static bool shouldReturnTagNameAsRoleForMSAA(const Element& element)
3300{
3301    // See "document structure",
3302    // https://wiki.mozilla.org/Accessibility/AT-Windows-API
3303    // FIXME: Add the other tag names that should be returned as the role.
3304    return element.hasTagName(h1Tag) || element.hasTagName(h2Tag)
3305        || element.hasTagName(h3Tag) || element.hasTagName(h4Tag)
3306        || element.hasTagName(h5Tag) || element.hasTagName(h6Tag);
3307}
3308
3309String AccessibilityRenderObject::stringRoleForMSAA() const
3310{
3311    if (!m_renderer)
3312        return String();
3313
3314    Node* node = m_renderer->node();
3315    if (!node || !node->isElementNode())
3316        return String();
3317
3318    Element* element = toElement(node);
3319    if (!shouldReturnTagNameAsRoleForMSAA(*element))
3320        return String();
3321
3322    return element->tagName();
3323}
3324
3325String AccessibilityRenderObject::positionalDescriptionForMSAA() const
3326{
3327    // See "positional descriptions",
3328    // https://wiki.mozilla.org/Accessibility/AT-Windows-API
3329    if (isHeading())
3330        return "L" + String::number(headingLevel());
3331
3332    // FIXME: Add positional descriptions for other elements.
3333    return String();
3334}
3335
3336String AccessibilityRenderObject::descriptionForMSAA() const
3337{
3338    String description = positionalDescriptionForMSAA();
3339    if (!description.isEmpty())
3340        return description;
3341
3342    description = accessibilityDescription();
3343    if (!description.isEmpty()) {
3344        // From the Mozilla MSAA implementation:
3345        // "Signal to screen readers that this description is speakable and is not
3346        // a formatted positional information description. Don't localize the
3347        // 'Description: ' part of this string, it will be parsed out by assistive
3348        // technologies."
3349        return "Description: " + description;
3350    }
3351
3352    return String();
3353}
3354
3355static AccessibilityRole msaaRoleForRenderer(const RenderObject* renderer)
3356{
3357    if (!renderer)
3358        return UnknownRole;
3359
3360    if (renderer->isText())
3361        return EditableTextRole;
3362
3363    if (renderer->isBoxModelObject() && toRenderBoxModelObject(renderer)->isListItem())
3364        return ListItemRole;
3365
3366    return UnknownRole;
3367}
3368
3369AccessibilityRole AccessibilityRenderObject::roleValueForMSAA() const
3370{
3371    if (m_roleForMSAA != UnknownRole)
3372        return m_roleForMSAA;
3373
3374    m_roleForMSAA = msaaRoleForRenderer(m_renderer);
3375
3376    if (m_roleForMSAA == UnknownRole)
3377        m_roleForMSAA = roleValue();
3378
3379    return m_roleForMSAA;
3380}
3381
3382String AccessibilityRenderObject::passwordFieldValue() const
3383{
3384#if PLATFORM(GTK)
3385    ASSERT(isPasswordField());
3386
3387    // Look for the RenderText object in the RenderObject tree for this input field.
3388    RenderObject* renderer = node()->renderer();
3389    while (renderer && !renderer->isText())
3390        renderer = renderer->firstChild();
3391
3392    if (!renderer || !renderer->isText())
3393        return String();
3394
3395    // Return the text that is actually being rendered in the input field.
3396    return static_cast<RenderText*>(renderer)->textWithoutTranscoding();
3397#else
3398    // It seems only GTK is interested in this at the moment.
3399    return String();
3400#endif
3401}
3402
3403ScrollableArea* AccessibilityRenderObject::getScrollableAreaIfScrollable() const
3404{
3405    // If the parent is a scroll view, then this object isn't really scrollable, the parent ScrollView should handle the scrolling.
3406    if (parentObject() && parentObject()->isAccessibilityScrollView())
3407        return 0;
3408
3409    if (!m_renderer || !m_renderer->isBox())
3410        return 0;
3411
3412    RenderBox* box = toRenderBox(m_renderer);
3413    if (!box->canBeScrolledAndHasScrollableArea())
3414        return 0;
3415
3416    return box->layer();
3417}
3418
3419void AccessibilityRenderObject::scrollTo(const IntPoint& point) const
3420{
3421    if (!m_renderer || !m_renderer->isBox())
3422        return;
3423
3424    RenderBox* box = toRenderBox(m_renderer);
3425    if (!box->canBeScrolledAndHasScrollableArea())
3426        return;
3427
3428    RenderLayer* layer = box->layer();
3429    layer->scrollToOffset(toIntSize(point), RenderLayer::ScrollOffsetClamped);
3430}
3431
3432#if ENABLE(MATHML)
3433bool AccessibilityRenderObject::isMathElement() const
3434{
3435    Node* node = this->node();
3436    if (!m_renderer || !node)
3437        return false;
3438
3439    return node->isElementNode() && toElement(node)->isMathMLElement();
3440}
3441
3442bool AccessibilityRenderObject::isMathFraction() const
3443{
3444    if (!m_renderer || !m_renderer->isRenderMathMLBlock())
3445        return false;
3446
3447    return toRenderMathMLBlock(m_renderer)->isRenderMathMLFraction();
3448}
3449
3450bool AccessibilityRenderObject::isMathFenced() const
3451{
3452    if (!m_renderer || !m_renderer->isRenderMathMLBlock())
3453        return false;
3454
3455    return toRenderMathMLBlock(m_renderer)->isRenderMathMLFenced();
3456}
3457
3458bool AccessibilityRenderObject::isMathSubscriptSuperscript() const
3459{
3460    if (!m_renderer || !m_renderer->isRenderMathMLBlock())
3461        return false;
3462
3463    return toRenderMathMLBlock(m_renderer)->isRenderMathMLSubSup();
3464}
3465
3466bool AccessibilityRenderObject::isMathRow() const
3467{
3468    if (!m_renderer || !m_renderer->isRenderMathMLBlock())
3469        return false;
3470
3471    return toRenderMathMLBlock(m_renderer)->isRenderMathMLRow();
3472}
3473
3474bool AccessibilityRenderObject::isMathUnderOver() const
3475{
3476    if (!m_renderer || !m_renderer->isRenderMathMLBlock())
3477        return false;
3478
3479    return toRenderMathMLBlock(m_renderer)->isRenderMathMLUnderOver();
3480}
3481
3482bool AccessibilityRenderObject::isMathSquareRoot() const
3483{
3484    if (!m_renderer || !m_renderer->isRenderMathMLBlock())
3485        return false;
3486
3487    return toRenderMathMLBlock(m_renderer)->isRenderMathMLSquareRoot();
3488}
3489
3490bool AccessibilityRenderObject::isMathRoot() const
3491{
3492    if (!m_renderer || !m_renderer->isRenderMathMLBlock())
3493        return false;
3494
3495    return toRenderMathMLBlock(m_renderer)->isRenderMathMLRoot();
3496}
3497
3498bool AccessibilityRenderObject::isMathOperator() const
3499{
3500    if (!m_renderer || !m_renderer->isRenderMathMLBlock())
3501        return false;
3502
3503    // Ensure that this is actually a render MathML operator because
3504    // MathML will create MathMLBlocks and use the original node as the node
3505    // of this new block that is not tied to the DOM.
3506    if (!toRenderMathMLBlock(m_renderer)->isRenderMathMLOperator())
3507        return false;
3508
3509    return isMathElement() && node()->hasTagName(MathMLNames::moTag);
3510}
3511
3512bool AccessibilityRenderObject::isMathFenceOperator() const
3513{
3514    if (!m_renderer || !m_renderer->isRenderMathMLBlock())
3515        return false;
3516
3517    if (!toRenderMathMLBlock(m_renderer)->isRenderMathMLOperator())
3518        return false;
3519
3520    RenderMathMLOperator* mathOperator = toRenderMathMLOperator(toRenderMathMLBlock(m_renderer));
3521    return mathOperator->operatorType() == RenderMathMLOperator::Fence;
3522}
3523
3524bool AccessibilityRenderObject::isMathSeparatorOperator() const
3525{
3526    if (!m_renderer || !m_renderer->isRenderMathMLBlock())
3527        return false;
3528
3529    if (!toRenderMathMLBlock(m_renderer)->isRenderMathMLOperator())
3530        return false;
3531
3532    RenderMathMLOperator* mathOperator = toRenderMathMLOperator(toRenderMathMLBlock(m_renderer));
3533    return mathOperator->operatorType() == RenderMathMLOperator::Separator;
3534}
3535
3536bool AccessibilityRenderObject::isMathText() const
3537{
3538    return node() && node()->hasTagName(MathMLNames::mtextTag);
3539}
3540
3541bool AccessibilityRenderObject::isMathNumber() const
3542{
3543    return node() && node()->hasTagName(MathMLNames::mnTag);
3544}
3545
3546bool AccessibilityRenderObject::isMathIdentifier() const
3547{
3548    return node() && node()->hasTagName(MathMLNames::miTag);
3549}
3550
3551bool AccessibilityRenderObject::isMathMultiscript() const
3552{
3553    return node() && node()->hasTagName(MathMLNames::mmultiscriptsTag);
3554}
3555
3556bool AccessibilityRenderObject::isMathTable() const
3557{
3558    return node() && node()->hasTagName(MathMLNames::mtableTag);
3559}
3560
3561bool AccessibilityRenderObject::isMathTableRow() const
3562{
3563    return node() && node()->hasTagName(MathMLNames::mtrTag);
3564}
3565
3566bool AccessibilityRenderObject::isMathTableCell() const
3567{
3568    return node() && node()->hasTagName(MathMLNames::mtdTag);
3569}
3570
3571bool AccessibilityRenderObject::isIgnoredElementWithinMathTree() const
3572{
3573    if (!m_renderer)
3574        return true;
3575
3576    // Ignore items that were created for layout purposes only.
3577    if (m_renderer->isRenderMathMLBlock() && toRenderMathMLBlock(m_renderer)->ignoreInAccessibilityTree())
3578        return true;
3579
3580    // Ignore anonymous renderers inside math blocks.
3581    if (m_renderer->isAnonymous()) {
3582        for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) {
3583            if (parent->isMathElement())
3584                return true;
3585        }
3586    }
3587
3588    // Only math elements that we explicitly recognize should be included
3589    // We don't want things like <mstyle> to appear in the tree.
3590    if (isMathElement()) {
3591        if (isMathFraction() || isMathFenced() || isMathSubscriptSuperscript() || isMathRow()
3592            || isMathUnderOver() || isMathRoot() || isMathText() || isMathNumber()
3593            || isMathOperator() || isMathFenceOperator() || isMathSeparatorOperator()
3594            || isMathIdentifier() || isMathTable() || isMathTableRow() || isMathTableCell() || isMathMultiscript())
3595            return false;
3596        return true;
3597    }
3598
3599    return false;
3600}
3601
3602AccessibilityObject* AccessibilityRenderObject::mathRadicandObject()
3603{
3604    if (!isMathRoot())
3605        return 0;
3606
3607    AccessibilityObject::AccessibilityChildrenVector children = this->children();
3608    if (children.size() < 1)
3609        return 0;
3610
3611    // The radicand is the value being rooted and must be listed first.
3612    return children[0].get();
3613}
3614
3615AccessibilityObject* AccessibilityRenderObject::mathRootIndexObject()
3616{
3617    if (!isMathRoot())
3618        return 0;
3619
3620    AccessibilityObject::AccessibilityChildrenVector children = this->children();
3621    if (children.size() != 2)
3622        return 0;
3623
3624    // The index in a root is the value which determines if it's a square, cube, etc, root
3625    // and must be listed second.
3626    return children[1].get();
3627}
3628
3629AccessibilityObject* AccessibilityRenderObject::mathNumeratorObject()
3630{
3631    if (!isMathFraction())
3632        return 0;
3633
3634    AccessibilityObject::AccessibilityChildrenVector children = this->children();
3635    if (children.size() != 2)
3636        return 0;
3637
3638    return children[0].get();
3639}
3640
3641AccessibilityObject* AccessibilityRenderObject::mathDenominatorObject()
3642{
3643    if (!isMathFraction())
3644        return 0;
3645
3646    AccessibilityObject::AccessibilityChildrenVector children = this->children();
3647    if (children.size() != 2)
3648        return 0;
3649
3650    return children[1].get();
3651}
3652
3653AccessibilityObject* AccessibilityRenderObject::mathUnderObject()
3654{
3655    if (!isMathUnderOver() || !node())
3656        return 0;
3657
3658    AccessibilityChildrenVector children = this->children();
3659    if (children.size() < 2)
3660        return 0;
3661
3662    if (node()->hasTagName(MathMLNames::munderTag) || node()->hasTagName(MathMLNames::munderoverTag))
3663        return children[1].get();
3664
3665    return 0;
3666}
3667
3668AccessibilityObject* AccessibilityRenderObject::mathOverObject()
3669{
3670    if (!isMathUnderOver() || !node())
3671        return 0;
3672
3673    AccessibilityChildrenVector children = this->children();
3674    if (children.size() < 2)
3675        return 0;
3676
3677    if (node()->hasTagName(MathMLNames::moverTag))
3678        return children[1].get();
3679    if (node()->hasTagName(MathMLNames::munderoverTag))
3680        return children[2].get();
3681
3682    return 0;
3683}
3684
3685AccessibilityObject* AccessibilityRenderObject::mathBaseObject()
3686{
3687    if (!isMathSubscriptSuperscript() && !isMathUnderOver() && !isMathMultiscript())
3688        return 0;
3689
3690    AccessibilityChildrenVector children = this->children();
3691    // The base object in question is always the first child.
3692    if (children.size() > 0)
3693        return children[0].get();
3694
3695    return 0;
3696}
3697
3698AccessibilityObject* AccessibilityRenderObject::mathSubscriptObject()
3699{
3700    if (!isMathSubscriptSuperscript() || !node())
3701        return 0;
3702
3703    AccessibilityChildrenVector children = this->children();
3704    if (children.size() < 2)
3705        return 0;
3706
3707    if (node()->hasTagName(MathMLNames::msubTag) || node()->hasTagName(MathMLNames::msubsupTag))
3708        return children[1].get();
3709
3710    return 0;
3711}
3712
3713AccessibilityObject* AccessibilityRenderObject::mathSuperscriptObject()
3714{
3715    if (!isMathSubscriptSuperscript() || !node())
3716        return 0;
3717
3718    AccessibilityChildrenVector children = this->children();
3719    if (children.size() < 2)
3720        return 0;
3721
3722    if (node()->hasTagName(MathMLNames::msupTag))
3723        return children[1].get();
3724    if (node()->hasTagName(MathMLNames::msubsupTag))
3725        return children[2].get();
3726
3727    return 0;
3728}
3729
3730String AccessibilityRenderObject::mathFencedOpenString() const
3731{
3732    if (!isMathFenced())
3733        return String();
3734
3735    return getAttribute(MathMLNames::openAttr);
3736}
3737
3738String AccessibilityRenderObject::mathFencedCloseString() const
3739{
3740    if (!isMathFenced())
3741        return String();
3742
3743    return getAttribute(MathMLNames::closeAttr);
3744}
3745
3746void AccessibilityRenderObject::mathPrescripts(AccessibilityMathMultiscriptPairs& prescripts)
3747{
3748    if (!isMathMultiscript() || !node())
3749        return;
3750
3751    bool foundPrescript = false;
3752    pair<AccessibilityObject*, AccessibilityObject*> prescriptPair;
3753    for (Node* child = node()->firstChild(); child; child = child->nextSibling()) {
3754        if (foundPrescript) {
3755            AccessibilityObject* axChild = axObjectCache()->getOrCreate(child);
3756            if (axChild && axChild->isMathElement()) {
3757                if (!prescriptPair.first)
3758                    prescriptPair.first = axChild;
3759                else {
3760                    prescriptPair.second = axChild;
3761                    prescripts.append(prescriptPair);
3762                    prescriptPair.first = 0;
3763                    prescriptPair.second = 0;
3764                }
3765            }
3766        } else if (child->hasTagName(MathMLNames::mprescriptsTag))
3767            foundPrescript = true;
3768    }
3769
3770    // Handle the odd number of pre scripts case.
3771    if (prescriptPair.first)
3772        prescripts.append(prescriptPair);
3773}
3774
3775void AccessibilityRenderObject::mathPostscripts(AccessibilityMathMultiscriptPairs& postscripts)
3776{
3777    if (!isMathMultiscript() || !node())
3778        return;
3779
3780    // In Multiscripts, the post-script elements start after the first element (which is the base)
3781    // and continue until a <mprescripts> tag is found
3782    pair<AccessibilityObject*, AccessibilityObject*> postscriptPair;
3783    bool foundBaseElement = false;
3784    for (Node* child = node()->firstChild(); child; child = child->nextSibling()) {
3785        if (child->hasTagName(MathMLNames::mprescriptsTag))
3786            break;
3787
3788        AccessibilityObject* axChild = axObjectCache()->getOrCreate(child);
3789        if (axChild && axChild->isMathElement()) {
3790            if (!foundBaseElement)
3791                foundBaseElement = true;
3792            else if (!postscriptPair.first)
3793                postscriptPair.first = axChild;
3794            else {
3795                postscriptPair.second = axChild;
3796                postscripts.append(postscriptPair);
3797                postscriptPair.first = 0;
3798                postscriptPair.second = 0;
3799            }
3800        }
3801    }
3802
3803    // Handle the odd number of post scripts case.
3804    if (postscriptPair.first)
3805        postscripts.append(postscriptPair);
3806}
3807
3808int AccessibilityRenderObject::mathLineThickness() const
3809{
3810    if (!isMathFraction())
3811        return -1;
3812
3813    return toRenderMathMLFraction(m_renderer)->lineThickness();
3814}
3815
3816#endif
3817
3818} // namespace WebCore
3819