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