9fff8f140d93f53dd9779c32cbc7282bbe72b4c5
[WebKit-https.git] / Source / WebCore / accessibility / AccessibilityObject.cpp
1 /*
2  * Copyright (C) 2008, 2009, 2011 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 "AccessibilityObject.h"
31
32 #include "AXObjectCache.h"
33 #include "AccessibilityRenderObject.h"
34 #include "AccessibilityScrollView.h"
35 #include "AccessibilityTable.h"
36 #include "DOMTokenList.h"
37 #include "Editor.h"
38 #include "FloatRect.h"
39 #include "FocusController.h"
40 #include "Frame.h"
41 #include "FrameLoader.h"
42 #include "FrameSelection.h"
43 #include "HTMLNames.h"
44 #include "HTMLParserIdioms.h"
45 #include "HitTestResult.h"
46 #include "LocalizedStrings.h"
47 #include "MainFrame.h"
48 #include "MathMLNames.h"
49 #include "NodeList.h"
50 #include "NodeTraversal.h"
51 #include "Page.h"
52 #include "RenderImage.h"
53 #include "RenderLayer.h"
54 #include "RenderListItem.h"
55 #include "RenderListMarker.h"
56 #include "RenderMenuList.h"
57 #include "RenderText.h"
58 #include "RenderTextControl.h"
59 #include "RenderTheme.h"
60 #include "RenderView.h"
61 #include "RenderWidget.h"
62 #include "RenderedPosition.h"
63 #include "Settings.h"
64 #include "TextCheckerClient.h"
65 #include "TextCheckingHelper.h"
66 #include "TextIterator.h"
67 #include "UserGestureIndicator.h"
68 #include "VisibleUnits.h"
69 #include "htmlediting.h"
70 #include <wtf/NeverDestroyed.h>
71 #include <wtf/StdLibExtras.h>
72 #include <wtf/text/StringBuilder.h>
73 #include <wtf/text/WTFString.h>
74 #include <wtf/unicode/CharacterNames.h>
75
76 namespace WebCore {
77
78 using namespace HTMLNames;
79
80 AccessibilityObject::AccessibilityObject()
81     : m_id(0)
82     , m_haveChildren(false)
83     , m_role(UnknownRole)
84     , m_lastKnownIsIgnoredValue(DefaultBehavior)
85 #if PLATFORM(GTK) || (PLATFORM(EFL) && HAVE(ACCESSIBILITY))
86     , m_wrapper(0)
87 #endif
88 {
89 }
90
91 AccessibilityObject::~AccessibilityObject()
92 {
93     ASSERT(isDetached());
94 }
95
96 void AccessibilityObject::detach(AccessibilityDetachmentType detachmentType, AXObjectCache* cache)
97 {
98     // Menu close events need to notify the platform. No element is used in the notification because it's a destruction event.
99     if (detachmentType == ElementDestroyed && roleValue() == MenuRole && cache)
100         cache->postNotification(nullptr, &cache->document(), AXObjectCache::AXMenuClosed);
101     
102     // Clear any children and call detachFromParent on them so that
103     // no children are left with dangling pointers to their parent.
104     clearChildren();
105
106 #if HAVE(ACCESSIBILITY)
107     setWrapper(0);
108 #endif
109 }
110
111 bool AccessibilityObject::isDetached() const
112 {
113 #if HAVE(ACCESSIBILITY)
114     return !wrapper();
115 #else
116     return true;
117 #endif
118 }
119
120 bool AccessibilityObject::isAccessibilityObjectSearchMatchAtIndex(AccessibilityObject* axObject, AccessibilitySearchCriteria* criteria, size_t index)
121 {
122     switch (criteria->searchKeys[index]) {
123     // The AnyTypeSearchKey matches any non-null AccessibilityObject.
124     case AnyTypeSearchKey:
125         return true;
126         
127     case BlockquoteSameLevelSearchKey:
128         return criteria->startObject
129             && axObject->isBlockquote()
130             && axObject->blockquoteLevel() == criteria->startObject->blockquoteLevel();
131         
132     case BlockquoteSearchKey:
133         return axObject->isBlockquote();
134         
135     case BoldFontSearchKey:
136         return axObject->hasBoldFont();
137         
138     case ButtonSearchKey:
139         return axObject->isButton();
140         
141     case CheckBoxSearchKey:
142         return axObject->isCheckbox();
143         
144     case ControlSearchKey:
145         return axObject->isControl();
146         
147     case DifferentTypeSearchKey:
148         return criteria->startObject
149             && axObject->roleValue() != criteria->startObject->roleValue();
150         
151     case FontChangeSearchKey:
152         return criteria->startObject
153             && !axObject->hasSameFont(criteria->startObject->renderer());
154         
155     case FontColorChangeSearchKey:
156         return criteria->startObject
157             && !axObject->hasSameFontColor(criteria->startObject->renderer());
158         
159     case FrameSearchKey:
160         return axObject->isWebArea();
161         
162     case GraphicSearchKey:
163         return axObject->isImage();
164         
165     case HeadingLevel1SearchKey:
166         return axObject->headingLevel() == 1;
167         
168     case HeadingLevel2SearchKey:
169         return axObject->headingLevel() == 2;
170         
171     case HeadingLevel3SearchKey:
172         return axObject->headingLevel() == 3;
173         
174     case HeadingLevel4SearchKey:
175         return axObject->headingLevel() == 4;
176         
177     case HeadingLevel5SearchKey:
178         return axObject->headingLevel() == 5;
179         
180     case HeadingLevel6SearchKey:
181         return axObject->headingLevel() == 6;
182         
183     case HeadingSameLevelSearchKey:
184         return criteria->startObject
185             && axObject->isHeading()
186             && axObject->headingLevel() == criteria->startObject->headingLevel();
187         
188     case HeadingSearchKey:
189         return axObject->isHeading();
190     
191     case HighlightedSearchKey:
192         return axObject->hasHighlighting();
193             
194     case ItalicFontSearchKey:
195         return axObject->hasItalicFont();
196         
197     case LandmarkSearchKey:
198         return axObject->isLandmark();
199         
200     case LinkSearchKey:
201         return axObject->isLink();
202         
203     case ListSearchKey:
204         return axObject->isList();
205         
206     case LiveRegionSearchKey:
207         return axObject->supportsARIALiveRegion();
208         
209     case MisspelledWordSearchKey:
210         return axObject->hasMisspelling();
211         
212     case OutlineSearchKey:
213         return axObject->isTree();
214         
215     case PlainTextSearchKey:
216         return axObject->hasPlainText();
217         
218     case RadioGroupSearchKey:
219         return axObject->isRadioGroup();
220         
221     case SameTypeSearchKey:
222         return criteria->startObject
223             && axObject->roleValue() == criteria->startObject->roleValue();
224         
225     case StaticTextSearchKey:
226         return axObject->isStaticText();
227         
228     case StyleChangeSearchKey:
229         return criteria->startObject
230             && !axObject->hasSameStyle(criteria->startObject->renderer());
231         
232     case TableSameLevelSearchKey:
233         return criteria->startObject
234             && axObject->isAccessibilityTable()
235             && axObject->tableLevel() == criteria->startObject->tableLevel();
236         
237     case TableSearchKey:
238         return axObject->isAccessibilityTable();
239         
240     case TextFieldSearchKey:
241         return axObject->isTextControl();
242         
243     case UnderlineSearchKey:
244         return axObject->hasUnderline();
245         
246     case UnvisitedLinkSearchKey:
247         return axObject->isUnvisited();
248         
249     case VisitedLinkSearchKey:
250         return axObject->isVisited();
251         
252     default:
253         return false;
254     }
255 }
256
257 bool AccessibilityObject::isAccessibilityObjectSearchMatch(AccessibilityObject* axObject, AccessibilitySearchCriteria* criteria)
258 {
259     if (!axObject || !criteria)
260         return false;
261     
262     size_t length = criteria->searchKeys.size();
263     for (size_t i = 0; i < length; ++i) {
264         if (isAccessibilityObjectSearchMatchAtIndex(axObject, criteria, i)) {
265             if (criteria->visibleOnly && !axObject->isOnscreen())
266                 return false;
267             return true;
268         }
269     }
270     return false;
271 }
272
273 bool AccessibilityObject::isAccessibilityTextSearchMatch(AccessibilityObject* axObject, AccessibilitySearchCriteria* criteria)
274 {
275     if (!axObject || !criteria)
276         return false;
277     
278     return axObject->accessibilityObjectContainsText(&criteria->searchText);
279 }
280
281 bool AccessibilityObject::accessibilityObjectContainsText(String* text) const
282 {
283     // If text is null or empty we return true.
284     return !text
285         || text->isEmpty()
286         || title().contains(*text, false)
287         || accessibilityDescription().contains(*text, false)
288         || stringValue().contains(*text, false);
289 }
290
291 bool AccessibilityObject::isBlockquote() const
292 {
293     return node() && node()->hasTagName(blockquoteTag);
294 }
295
296 bool AccessibilityObject::isTextControl() const
297 {
298     switch (roleValue()) {
299     case TextAreaRole:
300     case TextFieldRole:
301     case ComboBoxRole:
302         return true;
303     default:
304         return false;
305     }
306 }
307     
308 bool AccessibilityObject::isARIATextControl() const
309 {
310     return ariaRoleAttribute() == TextAreaRole || ariaRoleAttribute() == TextFieldRole;
311 }
312
313 bool AccessibilityObject::isLandmark() const
314 {
315     AccessibilityRole role = roleValue();
316     
317     return role == LandmarkApplicationRole
318         || role == LandmarkBannerRole
319         || role == LandmarkComplementaryRole
320         || role == LandmarkContentInfoRole
321         || role == LandmarkMainRole
322         || role == LandmarkNavigationRole
323         || role == LandmarkSearchRole;
324 }
325
326 bool AccessibilityObject::hasMisspelling() const
327 {
328     if (!node())
329         return false;
330     
331     Frame* frame = node()->document().frame();
332     if (!frame)
333         return false;
334     
335     Editor& editor = frame->editor();
336     
337     TextCheckerClient* textChecker = editor.textChecker();
338     if (!textChecker)
339         return false;
340     
341     bool isMisspelled = false;
342
343     if (unifiedTextCheckerEnabled(frame)) {
344         Vector<TextCheckingResult> results;
345         checkTextOfParagraph(*textChecker, stringValue(), TextCheckingTypeSpelling, results);
346         if (!results.isEmpty())
347             isMisspelled = true;
348         return isMisspelled;
349     }
350
351     int misspellingLength = 0;
352     int misspellingLocation = -1;
353     textChecker->checkSpellingOfString(stringValue(), &misspellingLocation, &misspellingLength);
354     if (misspellingLength || misspellingLocation != -1)
355         isMisspelled = true;
356     
357     return isMisspelled;
358 }
359
360 int AccessibilityObject::blockquoteLevel() const
361 {
362     int level = 0;
363     for (Node* elementNode = node(); elementNode; elementNode = elementNode->parentNode()) {
364         if (elementNode->hasTagName(blockquoteTag))
365             ++level;
366     }
367     
368     return level;
369 }
370
371 AccessibilityObject* AccessibilityObject::parentObjectUnignored() const
372 {
373     AccessibilityObject* parent;
374     for (parent = parentObject(); parent && parent->accessibilityIsIgnored(); parent = parent->parentObject()) {
375     }
376     
377     return parent;
378 }
379
380 AccessibilityObject* AccessibilityObject::firstAccessibleObjectFromNode(const Node* node)
381 {
382     if (!node)
383         return 0;
384
385     AXObjectCache* cache = node->document().axObjectCache();
386     if (!cache)
387         return nullptr;
388     
389     AccessibilityObject* accessibleObject = cache->getOrCreate(node->renderer());
390     while (accessibleObject && accessibleObject->accessibilityIsIgnored()) {
391         node = NodeTraversal::next(node);
392
393         while (node && !node->renderer())
394             node = NodeTraversal::nextSkippingChildren(node);
395
396         if (!node)
397             return 0;
398
399         accessibleObject = cache->getOrCreate(node->renderer());
400     }
401
402     return accessibleObject;
403 }
404
405 static void appendAccessibilityObject(AccessibilityObject* object, AccessibilityObject::AccessibilityChildrenVector& results)
406 {
407     // Find the next descendant of this attachment object so search can continue through frames.
408     if (object->isAttachment()) {
409         Widget* widget = object->widgetForAttachmentView();
410         if (!widget || !widget->isFrameView())
411             return;
412         
413         Document* doc = toFrameView(widget)->frame().document();
414         if (!doc || !doc->hasLivingRenderTree())
415             return;
416         
417         object = object->axObjectCache()->getOrCreate(doc);
418     }
419
420     if (object)
421         results.append(object);
422 }
423     
424 static void appendChildrenToArray(AccessibilityObject* object, bool isForward, AccessibilityObject* startObject, AccessibilityObject::AccessibilityChildrenVector& results)
425 {
426     // A table's children includes elements whose own children are also the table's children (due to the way the Mac exposes tables).
427     // The rows from the table should be queried, since those are direct descendants of the table, and they contain content.
428     const auto& searchChildren = object->isAccessibilityTable() ? toAccessibilityTable(object)->rows() : object->children();
429
430     size_t childrenSize = searchChildren.size();
431
432     size_t startIndex = isForward ? childrenSize : 0;
433     size_t endIndex = isForward ? 0 : childrenSize;
434
435     size_t searchPosition = startObject ? searchChildren.find(startObject) : WTF::notFound;
436     if (searchPosition != WTF::notFound) {
437         if (isForward)
438             endIndex = searchPosition + 1;
439         else
440             endIndex = searchPosition;
441     }
442
443     // This is broken into two statements so that it's easier read.
444     if (isForward) {
445         for (size_t i = startIndex; i > endIndex; i--)
446             appendAccessibilityObject(searchChildren.at(i - 1).get(), results);
447     } else {
448         for (size_t i = startIndex; i < endIndex; i++)
449             appendAccessibilityObject(searchChildren.at(i).get(), results);
450     }
451 }
452
453 // Returns true if the number of results is now >= the number of results desired.
454 bool AccessibilityObject::objectMatchesSearchCriteriaWithResultLimit(AccessibilityObject* object, AccessibilitySearchCriteria* criteria, AccessibilityChildrenVector& results)
455 {
456     if (isAccessibilityObjectSearchMatch(object, criteria) && isAccessibilityTextSearchMatch(object, criteria)) {
457         results.append(object);
458         
459         // Enough results were found to stop searching.
460         if (results.size() >= criteria->resultsLimit)
461             return true;
462     }
463     
464     return false;
465 }
466
467 void AccessibilityObject::findMatchingObjects(AccessibilitySearchCriteria* criteria, AccessibilityChildrenVector& results)
468 {
469     ASSERT(criteria);
470     
471     if (!criteria)
472         return;
473
474     if (AXObjectCache* cache = axObjectCache())
475         cache->startCachingComputedObjectAttributesUntilTreeMutates();
476
477     // This search mechanism only searches the elements before/after the starting object.
478     // It does this by stepping up the parent chain and at each level doing a DFS.
479     
480     // If there's no start object, it means we want to search everything.
481     AccessibilityObject* startObject = criteria->startObject;
482     if (!startObject)
483         startObject = this;
484     
485     bool isForward = criteria->searchDirection == SearchDirectionNext;
486     
487     // The first iteration of the outer loop will examine the children of the start object for matches. However, when
488     // iterating backwards, the start object children should not be considered, so the loop is skipped ahead. We make an
489     // exception when no start object was specified because we want to search everything regardless of search direction.
490     AccessibilityObject* previousObject = 0;
491     if (!isForward && startObject != this) {
492         previousObject = startObject;
493         startObject = startObject->parentObjectUnignored();
494     }
495     
496     // The outer loop steps up the parent chain each time (unignored is important here because otherwise elements would be searched twice)
497     for (AccessibilityObject* stopSearchElement = parentObjectUnignored(); startObject != stopSearchElement; startObject = startObject->parentObjectUnignored()) {
498
499         // Only append the children after/before the previous element, so that the search does not check elements that are 
500         // already behind/ahead of start element.
501         AccessibilityChildrenVector searchStack;
502         if (!criteria->immediateDescendantsOnly || startObject == this)
503             appendChildrenToArray(startObject, isForward, previousObject, searchStack);
504
505         // This now does a DFS at the current level of the parent.
506         while (!searchStack.isEmpty()) {
507             AccessibilityObject* searchObject = searchStack.last().get();
508             searchStack.removeLast();
509             
510             if (objectMatchesSearchCriteriaWithResultLimit(searchObject, criteria, results))
511                 break;
512             
513             if (!criteria->immediateDescendantsOnly)
514                 appendChildrenToArray(searchObject, isForward, 0, searchStack);
515         }
516         
517         if (results.size() >= criteria->resultsLimit)
518             break;
519
520         // When moving backwards, the parent object needs to be checked, because technically it's "before" the starting element.
521         if (!isForward && startObject != this && objectMatchesSearchCriteriaWithResultLimit(startObject, criteria, results))
522             break;
523
524         previousObject = startObject;
525     }
526 }
527
528 // Returns the range that is fewer positions away from the reference range.
529 // NOTE: The after range is expected to ACTUALLY be after the reference range and the before
530 // range is expected to ACTUALLY be before. These are not checked for performance reasons.
531 static PassRefPtr<Range> rangeClosestToRange(Range* referenceRange, PassRefPtr<Range> afterRange, PassRefPtr<Range> beforeRange)
532 {
533     ASSERT(referenceRange);
534     ASSERT(!afterRange || afterRange->startPosition() > referenceRange->startPosition());
535     ASSERT(!beforeRange || beforeRange->endPosition() < referenceRange->endPosition());
536     
537     if (!referenceRange || (!afterRange && !beforeRange))
538         return nullptr;
539     if (afterRange && !beforeRange)
540         return afterRange;
541     if (!afterRange && beforeRange)
542         return beforeRange;
543     
544     unsigned positionsToAfterRange = Position::positionCountBetweenPositions(afterRange->startPosition(), referenceRange->startPosition());
545     unsigned positionsToBeforeRange = Position::positionCountBetweenPositions(afterRange->endPosition(), referenceRange->endPosition());
546     
547     return positionsToAfterRange < positionsToBeforeRange ? afterRange : beforeRange;
548 }
549
550 PassRefPtr<Range> AccessibilityObject::rangeOfStringClosestToRangeInDirection(Range* referenceRange, AccessibilitySearchDirection searchDirection, Vector<String>& searchStrings) const
551 {
552     Frame* frame = this->frame();
553     if (!frame)
554         return nullptr;
555     
556     if (!referenceRange)
557         return nullptr;
558     
559     bool isBackwardSearch = searchDirection == SearchDirectionPrevious;
560     FindOptions findOptions = AtWordStarts | CaseInsensitive | StartInSelection;
561     if (isBackwardSearch)
562         findOptions |= Backwards;
563     
564     RefPtr<Range> closestStringRange = nullptr;
565     for (const auto& searchString : searchStrings) {
566         if (RefPtr<Range> searchStringRange = frame->editor().rangeOfString(searchString, referenceRange, findOptions)) {
567             if (!closestStringRange)
568                 closestStringRange = searchStringRange;
569             else {
570                 // If searching backward, use the trailing range edges to correctly determine which
571                 // range is closest. Similarly, if searching forward, use the leading range edges.
572                 Position closestStringPosition = isBackwardSearch ? closestStringRange->endPosition() : closestStringRange->startPosition();
573                 Position searchStringPosition = isBackwardSearch ? searchStringRange->endPosition() : searchStringRange->startPosition();
574                 
575                 int closestPositionOffset = closestStringPosition.computeOffsetInContainerNode();
576                 int searchPositionOffset = searchStringPosition.computeOffsetInContainerNode();
577                 Node* closestContainerNode = closestStringPosition.containerNode();
578                 Node* searchContainerNode = searchStringPosition.containerNode();
579                 
580                 short result = Range::compareBoundaryPoints(closestContainerNode, closestPositionOffset, searchContainerNode, searchPositionOffset, ASSERT_NO_EXCEPTION);
581                 if ((!isBackwardSearch && result > 0) || (isBackwardSearch && result < 0))
582                     closestStringRange = searchStringRange;
583             }
584         }
585     }
586     return closestStringRange;
587 }
588
589 // Returns the range of the entire document if there is no selection.
590 PassRefPtr<Range> AccessibilityObject::selectionRange() const
591 {
592     Frame* frame = this->frame();
593     if (!frame)
594         return nullptr;
595     
596     const VisibleSelection& selection = frame->selection().selection();
597     if (!selection.isNone())
598         return selection.firstRange();
599     
600     return Range::create(*frame->document());
601 }
602
603 String AccessibilityObject::selectText(AccessibilitySelectTextCriteria* criteria)
604 {
605     ASSERT(criteria);
606     
607     if (!criteria)
608         return String();
609     
610     Frame* frame = this->frame();
611     if (!frame)
612         return String();
613     
614     AccessibilitySelectTextActivity& activity = criteria->activity;
615     AccessibilitySelectTextAmbiguityResolution& ambiguityResolution = criteria->ambiguityResolution;
616     String& replacementString = criteria->replacementString;
617     Vector<String>& searchStrings = criteria->searchStrings;
618     
619     RefPtr<Range> selectedStringRange = selectionRange();
620     
621     RefPtr<Range> closestAfterStringRange = nullptr;
622     RefPtr<Range> closestBeforeStringRange = nullptr;
623     // Search forward if necessary.
624     if (ambiguityResolution == ClosestAfterSelectionAmbiguityResolution || ambiguityResolution == ClosestToSelectionAmbiguityResolution)
625         closestAfterStringRange = rangeOfStringClosestToRangeInDirection(selectedStringRange.get(), SearchDirectionNext, searchStrings);
626     // Search backward if necessary.
627     if (ambiguityResolution == ClosestBeforeSelectionAmbiguityResolution || ambiguityResolution == ClosestToSelectionAmbiguityResolution)
628         closestBeforeStringRange = rangeOfStringClosestToRangeInDirection(selectedStringRange.get(), SearchDirectionPrevious, searchStrings);
629     
630     // Determine which candidate is closest to the selection and perform the activity.
631     if (RefPtr<Range> closestStringRange = rangeClosestToRange(selectedStringRange.get(), closestAfterStringRange, closestBeforeStringRange)) {
632         String closestString = closestStringRange->text();
633         bool replaceSelection = false;
634         if (frame->selection().setSelectedRange(closestStringRange.get(), DOWNSTREAM, true)) {
635             switch (activity) {
636             case FindAndCapitalize: {
637                 replacementString = closestString;
638                 makeCapitalized(&replacementString, 0);
639                 replaceSelection = true;
640                 break;
641             }
642             case FindAndUppercase:
643                 replacementString = closestString.upper();
644                 replaceSelection = true;
645                 break;
646             case FindAndLowercase:
647                 replacementString = closestString.lower();
648                 replaceSelection = true;
649                 break;
650             case FindAndReplaceActivity:
651                 replaceSelection = true;
652                 break;
653             case FindAndSelectActivity:
654                 break;
655             }
656             
657             if (replaceSelection)
658                 frame->editor().replaceSelectionWithText(replacementString, true, true);
659             return closestString;
660         }
661     }
662     
663     return String();
664 }
665
666 bool AccessibilityObject::hasAttributesRequiredForInclusion() const
667 {
668     // These checks are simplified in the interest of execution speed.
669     if (!getAttribute(aria_helpAttr).isEmpty()
670         || !getAttribute(aria_describedbyAttr).isEmpty()
671         || !getAttribute(altAttr).isEmpty()
672         || !getAttribute(titleAttr).isEmpty())
673         return true;
674
675 #if ENABLE(MATHML)
676     if (!getAttribute(MathMLNames::alttextAttr).isEmpty())
677         return true;
678 #endif
679
680     return false;
681 }
682
683 bool AccessibilityObject::isARIAInput(AccessibilityRole ariaRole)
684 {
685     return ariaRole == RadioButtonRole || ariaRole == CheckBoxRole || ariaRole == TextFieldRole;
686 }    
687     
688 bool AccessibilityObject::isARIAControl(AccessibilityRole ariaRole)
689 {
690     return isARIAInput(ariaRole) || ariaRole == TextAreaRole || ariaRole == ButtonRole 
691     || ariaRole == ComboBoxRole || ariaRole == SliderRole; 
692 }
693     
694 bool AccessibilityObject::isRangeControl() const
695 {
696     switch (roleValue()) {
697     case ProgressIndicatorRole:
698     case SliderRole:
699     case ScrollBarRole:
700     case SpinButtonRole:
701         return true;
702     default:
703         return false;
704     }
705 }
706
707 bool AccessibilityObject::isMeter() const
708 {
709 #if ENABLE(METER_ELEMENT)
710     RenderObject* renderer = this->renderer();
711     return renderer && renderer->isMeter();
712 #else
713     return false;
714 #endif
715 }
716
717 IntPoint AccessibilityObject::clickPoint()
718 {
719     LayoutRect rect = elementRect();
720     return roundedIntPoint(LayoutPoint(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2));
721 }
722
723 IntRect AccessibilityObject::boundingBoxForQuads(RenderObject* obj, const Vector<FloatQuad>& quads)
724 {
725     ASSERT(obj);
726     if (!obj)
727         return IntRect();
728     
729     FloatRect result;
730     for (const auto& quad : quads) {
731         FloatRect r = quad.enclosingBoundingBox();
732         if (!r.isEmpty()) {
733             if (obj->style().hasAppearance())
734                 obj->theme().adjustRepaintRect(*obj, r);
735             result.unite(r);
736         }
737     }
738     return pixelSnappedIntRect(LayoutRect(result));
739 }
740     
741 bool AccessibilityObject::press()
742 {
743     // The presence of the actionElement will confirm whether we should even attempt a press.
744     Element* actionElem = actionElement();
745     if (!actionElem)
746         return false;
747     if (Frame* f = actionElem->document().frame())
748         f->loader().resetMultipleFormSubmissionProtection();
749     
750     // Hit test at this location to determine if there is a sub-node element that should act
751     // as the target of the action.
752     Element* hitTestElement = nullptr;
753     if (Document* document = this->document()) {
754         RenderView* renderView = document->renderView();
755         RenderLayer* layer = renderView->layer();
756         
757         HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::AccessibilityHitTest);
758         HitTestResult hitTestResult = HitTestResult(clickPoint());
759         layer->hitTest(request, hitTestResult);
760         if (hitTestResult.innerNode()) {
761             Node* innerNode = hitTestResult.innerNode()->deprecatedShadowAncestorNode();
762             if (innerNode->isElementNode())
763                 hitTestElement = toElement(innerNode);
764         }
765     }
766     
767     
768     // Prefer the actionElement instead of this node, if the actionElement is inside this node.
769     Element* pressElement = this->element();
770     if (!pressElement || actionElem->isDescendantOf(pressElement))
771         pressElement = actionElem;
772     
773     // Prefer the hit test element, if it is inside the target element.
774     if (hitTestElement && hitTestElement->isDescendantOf(pressElement))
775         pressElement = hitTestElement;
776     
777     UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture);
778     pressElement->accessKeyAction(true);
779     return true;
780 }
781
782 Frame* AccessibilityObject::frame() const
783 {
784     Node* node = this->node();
785     if (!node)
786         return nullptr;
787     
788     return node->document().frame();
789 }
790
791 MainFrame* AccessibilityObject::mainFrame() const
792 {
793     Document* document = topDocument();
794     if (!document)
795         return nullptr;
796     
797     Frame* frame = document->frame();
798     if (!frame)
799         return nullptr;
800     
801     return &frame->mainFrame();
802 }
803
804 Document* AccessibilityObject::topDocument() const
805 {
806     if (!document())
807         return nullptr;
808     return &document()->topDocument();
809 }
810
811 String AccessibilityObject::language() const
812 {
813     const AtomicString& lang = getAttribute(langAttr);
814     if (!lang.isEmpty())
815         return lang;
816
817     AccessibilityObject* parent = parentObject();
818     
819     // as a last resort, fall back to the content language specified in the meta tag
820     if (!parent) {
821         Document* doc = document();
822         if (doc)
823             return doc->contentLanguage();
824         return nullAtom;
825     }
826     
827     return parent->language();
828 }
829     
830 VisiblePositionRange AccessibilityObject::visiblePositionRangeForUnorderedPositions(const VisiblePosition& visiblePos1, const VisiblePosition& visiblePos2) const
831 {
832     if (visiblePos1.isNull() || visiblePos2.isNull())
833         return VisiblePositionRange();
834
835     // If there's no common tree scope between positions, return early.
836     if (!commonTreeScope(visiblePos1.deepEquivalent().deprecatedNode(), visiblePos2.deepEquivalent().deprecatedNode()))
837         return VisiblePositionRange();
838     
839     VisiblePosition startPos;
840     VisiblePosition endPos;
841     bool alreadyInOrder;
842
843     // upstream is ordered before downstream for the same position
844     if (visiblePos1 == visiblePos2 && visiblePos2.affinity() == UPSTREAM)
845         alreadyInOrder = false;
846
847     // use selection order to see if the positions are in order
848     else
849         alreadyInOrder = VisibleSelection(visiblePos1, visiblePos2).isBaseFirst();
850
851     if (alreadyInOrder) {
852         startPos = visiblePos1;
853         endPos = visiblePos2;
854     } else {
855         startPos = visiblePos2;
856         endPos = visiblePos1;
857     }
858
859     return VisiblePositionRange(startPos, endPos);
860 }
861
862 VisiblePositionRange AccessibilityObject::positionOfLeftWord(const VisiblePosition& visiblePos) const
863 {
864     VisiblePosition startPosition = startOfWord(visiblePos, LeftWordIfOnBoundary);
865     VisiblePosition endPosition = endOfWord(startPosition);
866     return VisiblePositionRange(startPosition, endPosition);
867 }
868
869 VisiblePositionRange AccessibilityObject::positionOfRightWord(const VisiblePosition& visiblePos) const
870 {
871     VisiblePosition startPosition = startOfWord(visiblePos, RightWordIfOnBoundary);
872     VisiblePosition endPosition = endOfWord(startPosition);
873     return VisiblePositionRange(startPosition, endPosition);
874 }
875
876 static VisiblePosition updateAXLineStartForVisiblePosition(const VisiblePosition& visiblePosition)
877 {
878     // A line in the accessibility sense should include floating objects, such as aligned image, as part of a line.
879     // So let's update the position to include that.
880     VisiblePosition tempPosition;
881     VisiblePosition startPosition = visiblePosition;
882     while (true) {
883         tempPosition = startPosition.previous();
884         if (tempPosition.isNull())
885             break;
886         Position p = tempPosition.deepEquivalent();
887         RenderObject* renderer = p.deprecatedNode()->renderer();
888         if (!renderer || (renderer->isRenderBlock() && !p.deprecatedEditingOffset()))
889             break;
890         if (!RenderedPosition(tempPosition).isNull())
891             break;
892         startPosition = tempPosition;
893     }
894
895     return startPosition;
896 }
897
898 VisiblePositionRange AccessibilityObject::leftLineVisiblePositionRange(const VisiblePosition& visiblePos) const
899 {
900     if (visiblePos.isNull())
901         return VisiblePositionRange();
902
903     // make a caret selection for the position before marker position (to make sure
904     // we move off of a line start)
905     VisiblePosition prevVisiblePos = visiblePos.previous();
906     if (prevVisiblePos.isNull())
907         return VisiblePositionRange();
908
909     VisiblePosition startPosition = startOfLine(prevVisiblePos);
910
911     // keep searching for a valid line start position.  Unless the VisiblePosition is at the very beginning, there should
912     // always be a valid line range.  However, startOfLine will return null for position next to a floating object,
913     // since floating object doesn't really belong to any line.
914     // This check will reposition the marker before the floating object, to ensure we get a line start.
915     if (startPosition.isNull()) {
916         while (startPosition.isNull() && prevVisiblePos.isNotNull()) {
917             prevVisiblePos = prevVisiblePos.previous();
918             startPosition = startOfLine(prevVisiblePos);
919         }
920     } else
921         startPosition = updateAXLineStartForVisiblePosition(startPosition);
922
923     VisiblePosition endPosition = endOfLine(prevVisiblePos);
924     return VisiblePositionRange(startPosition, endPosition);
925 }
926
927 VisiblePositionRange AccessibilityObject::rightLineVisiblePositionRange(const VisiblePosition& visiblePos) const
928 {
929     if (visiblePos.isNull())
930         return VisiblePositionRange();
931
932     // make sure we move off of a line end
933     VisiblePosition nextVisiblePos = visiblePos.next();
934     if (nextVisiblePos.isNull())
935         return VisiblePositionRange();
936
937     VisiblePosition startPosition = startOfLine(nextVisiblePos);
938
939     // fetch for a valid line start position
940     if (startPosition.isNull()) {
941         startPosition = visiblePos;
942         nextVisiblePos = nextVisiblePos.next();
943     } else
944         startPosition = updateAXLineStartForVisiblePosition(startPosition);
945
946     VisiblePosition endPosition = endOfLine(nextVisiblePos);
947
948     // as long as the position hasn't reached the end of the doc,  keep searching for a valid line end position
949     // Unless the VisiblePosition is at the very end, there should always be a valid line range.  However, endOfLine will
950     // return null for position by a floating object, since floating object doesn't really belong to any line.
951     // This check will reposition the marker after the floating object, to ensure we get a line end.
952     while (endPosition.isNull() && nextVisiblePos.isNotNull()) {
953         nextVisiblePos = nextVisiblePos.next();
954         endPosition = endOfLine(nextVisiblePos);
955     }
956
957     return VisiblePositionRange(startPosition, endPosition);
958 }
959
960 VisiblePositionRange AccessibilityObject::sentenceForPosition(const VisiblePosition& visiblePos) const
961 {
962     // FIXME: FO 2 IMPLEMENT (currently returns incorrect answer)
963     // Related? <rdar://problem/3927736> Text selection broken in 8A336
964     VisiblePosition startPosition = startOfSentence(visiblePos);
965     VisiblePosition endPosition = endOfSentence(startPosition);
966     return VisiblePositionRange(startPosition, endPosition);
967 }
968
969 VisiblePositionRange AccessibilityObject::paragraphForPosition(const VisiblePosition& visiblePos) const
970 {
971     VisiblePosition startPosition = startOfParagraph(visiblePos);
972     VisiblePosition endPosition = endOfParagraph(startPosition);
973     return VisiblePositionRange(startPosition, endPosition);
974 }
975
976 static VisiblePosition startOfStyleRange(const VisiblePosition& visiblePos)
977 {
978     RenderObject* renderer = visiblePos.deepEquivalent().deprecatedNode()->renderer();
979     RenderObject* startRenderer = renderer;
980     RenderStyle* style = &renderer->style();
981
982     // traverse backward by renderer to look for style change
983     for (RenderObject* r = renderer->previousInPreOrder(); r; r = r->previousInPreOrder()) {
984         // skip non-leaf nodes
985         if (r->firstChildSlow())
986             continue;
987
988         // stop at style change
989         if (&r->style() != style)
990             break;
991
992         // remember match
993         startRenderer = r;
994     }
995
996     return firstPositionInOrBeforeNode(startRenderer->node());
997 }
998
999 static VisiblePosition endOfStyleRange(const VisiblePosition& visiblePos)
1000 {
1001     RenderObject* renderer = visiblePos.deepEquivalent().deprecatedNode()->renderer();
1002     RenderObject* endRenderer = renderer;
1003     const RenderStyle& style = renderer->style();
1004
1005     // traverse forward by renderer to look for style change
1006     for (RenderObject* r = renderer->nextInPreOrder(); r; r = r->nextInPreOrder()) {
1007         // skip non-leaf nodes
1008         if (r->firstChildSlow())
1009             continue;
1010
1011         // stop at style change
1012         if (&r->style() != &style)
1013             break;
1014
1015         // remember match
1016         endRenderer = r;
1017     }
1018
1019     return lastPositionInOrAfterNode(endRenderer->node());
1020 }
1021
1022 VisiblePositionRange AccessibilityObject::styleRangeForPosition(const VisiblePosition& visiblePos) const
1023 {
1024     if (visiblePos.isNull())
1025         return VisiblePositionRange();
1026
1027     return VisiblePositionRange(startOfStyleRange(visiblePos), endOfStyleRange(visiblePos));
1028 }
1029
1030 // NOTE: Consider providing this utility method as AX API
1031 VisiblePositionRange AccessibilityObject::visiblePositionRangeForRange(const PlainTextRange& range) const
1032 {
1033     unsigned textLength = getLengthForTextRange();
1034     if (range.start + range.length > textLength)
1035         return VisiblePositionRange();
1036
1037     VisiblePosition startPosition = visiblePositionForIndex(range.start);
1038     startPosition.setAffinity(DOWNSTREAM);
1039     VisiblePosition endPosition = visiblePositionForIndex(range.start + range.length);
1040     return VisiblePositionRange(startPosition, endPosition);
1041 }
1042
1043 VisiblePositionRange AccessibilityObject::lineRangeForPosition(const VisiblePosition& visiblePosition) const
1044 {
1045     VisiblePosition startPosition = startOfLine(visiblePosition);
1046     VisiblePosition endPosition = endOfLine(visiblePosition);
1047     return VisiblePositionRange(startPosition, endPosition);
1048 }
1049
1050 static bool replacedNodeNeedsCharacter(Node* replacedNode)
1051 {
1052     // we should always be given a rendered node and a replaced node, but be safe
1053     // replaced nodes are either attachments (widgets) or images
1054     if (!replacedNode || !isRendererReplacedElement(replacedNode->renderer()) || replacedNode->isTextNode())
1055         return false;
1056
1057     // create an AX object, but skip it if it is not supposed to be seen
1058     AccessibilityObject* object = replacedNode->renderer()->document().axObjectCache()->getOrCreate(replacedNode);
1059     if (object->accessibilityIsIgnored())
1060         return false;
1061
1062     return true;
1063 }
1064
1065 // Finds a RenderListItem parent give a node.
1066 static RenderListItem* renderListItemContainerForNode(Node* node)
1067 {
1068     for (; node; node = node->parentNode()) {
1069         RenderBoxModelObject* renderer = node->renderBoxModelObject();
1070         if (renderer && renderer->isListItem())
1071             return toRenderListItem(renderer);
1072     }
1073     return 0;
1074 }
1075     
1076 // Returns the text associated with a list marker if this node is contained within a list item.
1077 String AccessibilityObject::listMarkerTextForNodeAndPosition(Node* node, const VisiblePosition& visiblePositionStart) const
1078 {
1079     // If the range does not contain the start of the line, the list marker text should not be included.
1080     if (!isStartOfLine(visiblePositionStart))
1081         return String();
1082
1083     RenderListItem* listItem = renderListItemContainerForNode(node);
1084     if (!listItem)
1085         return String();
1086         
1087     // If this is in a list item, we need to manually add the text for the list marker 
1088     // because a RenderListMarker does not have a Node equivalent and thus does not appear
1089     // when iterating text.
1090     return listItem->markerTextWithSuffix();
1091 }
1092
1093 String AccessibilityObject::stringForVisiblePositionRange(const VisiblePositionRange& visiblePositionRange) const
1094 {
1095     if (visiblePositionRange.isNull())
1096         return String();
1097
1098     StringBuilder builder;
1099     RefPtr<Range> range = makeRange(visiblePositionRange.start, visiblePositionRange.end);
1100     for (TextIterator it(range.get()); !it.atEnd(); it.advance()) {
1101         // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX)
1102         if (it.text().length()) {
1103             // Add a textual representation for list marker text.
1104             builder.append(listMarkerTextForNodeAndPosition(it.node(), visiblePositionRange.start));
1105             it.appendTextToStringBuilder(builder);
1106         } else {
1107             // locate the node and starting offset for this replaced range
1108             Node* node = it.range()->startContainer();
1109             ASSERT(node == it.range()->endContainer());
1110             int offset = it.range()->startOffset();
1111             if (replacedNodeNeedsCharacter(node->childNode(offset)))
1112                 builder.append(objectReplacementCharacter);
1113         }
1114     }
1115
1116     return builder.toString();
1117 }
1118
1119 int AccessibilityObject::lengthForVisiblePositionRange(const VisiblePositionRange& visiblePositionRange) const
1120 {
1121     // FIXME: Multi-byte support
1122     if (visiblePositionRange.isNull())
1123         return -1;
1124     
1125     int length = 0;
1126     RefPtr<Range> range = makeRange(visiblePositionRange.start, visiblePositionRange.end);
1127     for (TextIterator it(range.get()); !it.atEnd(); it.advance()) {
1128         // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX)
1129         if (it.text().length())
1130             length += it.text().length();
1131         else {
1132             // locate the node and starting offset for this replaced range
1133             int exception = 0;
1134             Node* node = it.range()->startContainer(exception);
1135             ASSERT(node == it.range()->endContainer(exception));
1136             int offset = it.range()->startOffset(exception);
1137
1138             if (replacedNodeNeedsCharacter(node->childNode(offset)))
1139                 length++;
1140         }
1141     }
1142     
1143     return length;
1144 }
1145
1146 VisiblePosition AccessibilityObject::visiblePositionForBounds(const IntRect& rect, AccessibilityVisiblePositionForBounds visiblePositionForBounds) const
1147 {
1148     if (rect.isEmpty())
1149         return VisiblePosition();
1150     
1151     MainFrame* mainFrame = this->mainFrame();
1152     if (!mainFrame)
1153         return VisiblePosition();
1154     
1155     // FIXME: Add support for right-to-left languages.
1156     IntPoint corner = (visiblePositionForBounds == FirstVisiblePositionForBounds) ? rect.minXMinYCorner() : rect.maxXMaxYCorner();
1157     VisiblePosition position = mainFrame->visiblePositionForPoint(corner);
1158     
1159     if (rect.contains(position.absoluteCaretBounds().center()))
1160         return position;
1161     
1162     // If the initial position is located outside the bounds adjust it incrementally as needed.
1163     VisiblePosition nextPosition = position.next();
1164     VisiblePosition previousPosition = position.previous();
1165     while (nextPosition.isNotNull() || previousPosition.isNotNull()) {
1166         if (rect.contains(nextPosition.absoluteCaretBounds().center()))
1167             return nextPosition;
1168         if (rect.contains(previousPosition.absoluteCaretBounds().center()))
1169             return previousPosition;
1170         
1171         nextPosition = nextPosition.next();
1172         previousPosition = previousPosition.previous();
1173     }
1174     
1175     return VisiblePosition();
1176 }
1177
1178 VisiblePosition AccessibilityObject::nextWordEnd(const VisiblePosition& visiblePos) const
1179 {
1180     if (visiblePos.isNull())
1181         return VisiblePosition();
1182
1183     // make sure we move off of a word end
1184     VisiblePosition nextVisiblePos = visiblePos.next();
1185     if (nextVisiblePos.isNull())
1186         return VisiblePosition();
1187
1188     return endOfWord(nextVisiblePos, LeftWordIfOnBoundary);
1189 }
1190
1191 VisiblePosition AccessibilityObject::previousWordStart(const VisiblePosition& visiblePos) const
1192 {
1193     if (visiblePos.isNull())
1194         return VisiblePosition();
1195
1196     // make sure we move off of a word start
1197     VisiblePosition prevVisiblePos = visiblePos.previous();
1198     if (prevVisiblePos.isNull())
1199         return VisiblePosition();
1200
1201     return startOfWord(prevVisiblePos, RightWordIfOnBoundary);
1202 }
1203
1204 VisiblePosition AccessibilityObject::nextLineEndPosition(const VisiblePosition& visiblePos) const
1205 {
1206     if (visiblePos.isNull())
1207         return VisiblePosition();
1208
1209     // to make sure we move off of a line end
1210     VisiblePosition nextVisiblePos = visiblePos.next();
1211     if (nextVisiblePos.isNull())
1212         return VisiblePosition();
1213
1214     VisiblePosition endPosition = endOfLine(nextVisiblePos);
1215
1216     // as long as the position hasn't reached the end of the doc,  keep searching for a valid line end position
1217     // There are cases like when the position is next to a floating object that'll return null for end of line. This code will avoid returning null.
1218     while (endPosition.isNull() && nextVisiblePos.isNotNull()) {
1219         nextVisiblePos = nextVisiblePos.next();
1220         endPosition = endOfLine(nextVisiblePos);
1221     }
1222
1223     return endPosition;
1224 }
1225
1226 VisiblePosition AccessibilityObject::previousLineStartPosition(const VisiblePosition& visiblePos) const
1227 {
1228     if (visiblePos.isNull())
1229         return VisiblePosition();
1230
1231     // make sure we move off of a line start
1232     VisiblePosition prevVisiblePos = visiblePos.previous();
1233     if (prevVisiblePos.isNull())
1234         return VisiblePosition();
1235
1236     VisiblePosition startPosition = startOfLine(prevVisiblePos);
1237
1238     // as long as the position hasn't reached the beginning of the doc,  keep searching for a valid line start position
1239     // There are cases like when the position is next to a floating object that'll return null for start of line. This code will avoid returning null.
1240     if (startPosition.isNull()) {
1241         while (startPosition.isNull() && prevVisiblePos.isNotNull()) {
1242             prevVisiblePos = prevVisiblePos.previous();
1243             startPosition = startOfLine(prevVisiblePos);
1244         }
1245     } else
1246         startPosition = updateAXLineStartForVisiblePosition(startPosition);
1247
1248     return startPosition;
1249 }
1250
1251 VisiblePosition AccessibilityObject::nextSentenceEndPosition(const VisiblePosition& visiblePos) const
1252 {
1253     // FIXME: FO 2 IMPLEMENT (currently returns incorrect answer)
1254     // Related? <rdar://problem/3927736> Text selection broken in 8A336
1255     if (visiblePos.isNull())
1256         return VisiblePosition();
1257
1258     // make sure we move off of a sentence end
1259     VisiblePosition nextVisiblePos = visiblePos.next();
1260     if (nextVisiblePos.isNull())
1261         return VisiblePosition();
1262
1263     // an empty line is considered a sentence. If it's skipped, then the sentence parser will not
1264     // see this empty line.  Instead, return the end position of the empty line.
1265     VisiblePosition endPosition;
1266     
1267     String lineString = plainText(makeRange(startOfLine(nextVisiblePos), endOfLine(nextVisiblePos)).get());
1268     if (lineString.isEmpty())
1269         endPosition = nextVisiblePos;
1270     else
1271         endPosition = endOfSentence(nextVisiblePos);
1272
1273     return endPosition;
1274 }
1275
1276 VisiblePosition AccessibilityObject::previousSentenceStartPosition(const VisiblePosition& visiblePos) const
1277 {
1278     // FIXME: FO 2 IMPLEMENT (currently returns incorrect answer)
1279     // Related? <rdar://problem/3927736> Text selection broken in 8A336
1280     if (visiblePos.isNull())
1281         return VisiblePosition();
1282
1283     // make sure we move off of a sentence start
1284     VisiblePosition previousVisiblePos = visiblePos.previous();
1285     if (previousVisiblePos.isNull())
1286         return VisiblePosition();
1287
1288     // treat empty line as a separate sentence.
1289     VisiblePosition startPosition;
1290     
1291     String lineString = plainText(makeRange(startOfLine(previousVisiblePos), endOfLine(previousVisiblePos)).get());
1292     if (lineString.isEmpty())
1293         startPosition = previousVisiblePos;
1294     else
1295         startPosition = startOfSentence(previousVisiblePos);
1296
1297     return startPosition;
1298 }
1299
1300 VisiblePosition AccessibilityObject::nextParagraphEndPosition(const VisiblePosition& visiblePos) const
1301 {
1302     if (visiblePos.isNull())
1303         return VisiblePosition();
1304
1305     // make sure we move off of a paragraph end
1306     VisiblePosition nextPos = visiblePos.next();
1307     if (nextPos.isNull())
1308         return VisiblePosition();
1309
1310     return endOfParagraph(nextPos);
1311 }
1312
1313 VisiblePosition AccessibilityObject::previousParagraphStartPosition(const VisiblePosition& visiblePos) const
1314 {
1315     if (visiblePos.isNull())
1316         return VisiblePosition();
1317
1318     // make sure we move off of a paragraph start
1319     VisiblePosition previousPos = visiblePos.previous();
1320     if (previousPos.isNull())
1321         return VisiblePosition();
1322
1323     return startOfParagraph(previousPos);
1324 }
1325
1326 AccessibilityObject* AccessibilityObject::accessibilityObjectForPosition(const VisiblePosition& visiblePos) const
1327 {
1328     if (visiblePos.isNull())
1329         return 0;
1330
1331     RenderObject* obj = visiblePos.deepEquivalent().deprecatedNode()->renderer();
1332     if (!obj)
1333         return 0;
1334
1335     return obj->document().axObjectCache()->getOrCreate(obj);
1336 }
1337     
1338 // If you call node->hasEditableStyle() since that will return true if an ancestor is editable.
1339 // This only returns true if this is the element that actually has the contentEditable attribute set.
1340 bool AccessibilityObject::hasContentEditableAttributeSet() const
1341 {
1342     return contentEditableAttributeIsEnabled(element());
1343 }
1344
1345 bool AccessibilityObject::contentEditableAttributeIsEnabled(Element* element)
1346 {
1347     if (!element)
1348         return false;
1349     
1350     if (!element->hasAttribute(contenteditableAttr))
1351         return false;
1352     
1353     const AtomicString& contentEditableValue = element->fastGetAttribute(contenteditableAttr);
1354     // Both "true" (case-insensitive) and the empty string count as true.
1355     return contentEditableValue.isEmpty() || equalIgnoringCase(contentEditableValue, "true");
1356 }
1357     
1358 #if HAVE(ACCESSIBILITY)
1359 int AccessibilityObject::lineForPosition(const VisiblePosition& visiblePos) const
1360 {
1361     if (visiblePos.isNull() || !node())
1362         return -1;
1363
1364     // If the position is not in the same editable region as this AX object, return -1.
1365     Node* containerNode = visiblePos.deepEquivalent().containerNode();
1366     if (!containerNode->containsIncludingShadowDOM(node()) && !node()->containsIncludingShadowDOM(containerNode))
1367         return -1;
1368
1369     int lineCount = -1;
1370     VisiblePosition currentVisiblePos = visiblePos;
1371     VisiblePosition savedVisiblePos;
1372
1373     // move up until we get to the top
1374     // FIXME: This only takes us to the top of the rootEditableElement, not the top of the
1375     // top document.
1376     do {
1377         savedVisiblePos = currentVisiblePos;
1378         VisiblePosition prevVisiblePos = previousLinePosition(currentVisiblePos, 0, HasEditableAXRole);
1379         currentVisiblePos = prevVisiblePos;
1380         ++lineCount;
1381     }  while (currentVisiblePos.isNotNull() && !(inSameLine(currentVisiblePos, savedVisiblePos)));
1382
1383     return lineCount;
1384 }
1385 #endif
1386
1387 // NOTE: Consider providing this utility method as AX API
1388 PlainTextRange AccessibilityObject::plainTextRangeForVisiblePositionRange(const VisiblePositionRange& positionRange) const
1389 {
1390     int index1 = index(positionRange.start);
1391     int index2 = index(positionRange.end);
1392     if (index1 < 0 || index2 < 0 || index1 > index2)
1393         return PlainTextRange();
1394
1395     return PlainTextRange(index1, index2 - index1);
1396 }
1397
1398 // The composed character range in the text associated with this accessibility object that
1399 // is specified by the given screen coordinates. This parameterized attribute returns the
1400 // complete range of characters (including surrogate pairs of multi-byte glyphs) at the given
1401 // screen coordinates.
1402 // NOTE: This varies from AppKit when the point is below the last line. AppKit returns an
1403 // an error in that case. We return textControl->text().length(), 1. Does this matter?
1404 PlainTextRange AccessibilityObject::doAXRangeForPosition(const IntPoint& point) const
1405 {
1406     int i = index(visiblePositionForPoint(point));
1407     if (i < 0)
1408         return PlainTextRange();
1409
1410     return PlainTextRange(i, 1);
1411 }
1412
1413 // Given a character index, the range of text associated with this accessibility object
1414 // over which the style in effect at that character index applies.
1415 PlainTextRange AccessibilityObject::doAXStyleRangeForIndex(unsigned index) const
1416 {
1417     VisiblePositionRange range = styleRangeForPosition(visiblePositionForIndex(index, false));
1418     return plainTextRangeForVisiblePositionRange(range);
1419 }
1420
1421 // Given an indexed character, the line number of the text associated with this accessibility
1422 // object that contains the character.
1423 unsigned AccessibilityObject::doAXLineForIndex(unsigned index)
1424 {
1425     return lineForPosition(visiblePositionForIndex(index, false));
1426 }
1427
1428 #if HAVE(ACCESSIBILITY)
1429 void AccessibilityObject::updateBackingStore()
1430 {
1431     // Updating the layout may delete this object.
1432     if (Document* document = this->document()) {
1433         if (!document->view()->isInLayout())
1434             document->updateLayoutIgnorePendingStylesheets();
1435     }
1436     
1437     updateChildrenIfNecessary();
1438 }
1439 #endif
1440     
1441 ScrollView* AccessibilityObject::scrollViewAncestor() const
1442 {
1443     for (const AccessibilityObject* scrollParent = this; scrollParent; scrollParent = scrollParent->parentObject()) {
1444         if (scrollParent->isAccessibilityScrollView())
1445             return toAccessibilityScrollView(scrollParent)->scrollView();
1446     }
1447     
1448     return nullptr;
1449 }
1450     
1451 Document* AccessibilityObject::document() const
1452 {
1453     FrameView* frameView = documentFrameView();
1454     if (!frameView)
1455         return 0;
1456     
1457     return frameView->frame().document();
1458 }
1459     
1460 Page* AccessibilityObject::page() const
1461 {
1462     Document* document = this->document();
1463     if (!document)
1464         return 0;
1465     return document->page();
1466 }
1467
1468 FrameView* AccessibilityObject::documentFrameView() const 
1469
1470     const AccessibilityObject* object = this;
1471     while (object && !object->isAccessibilityRenderObject()) 
1472         object = object->parentObject();
1473         
1474     if (!object)
1475         return 0;
1476
1477     return object->documentFrameView();
1478 }
1479
1480 #if HAVE(ACCESSIBILITY)
1481 const AccessibilityObject::AccessibilityChildrenVector& AccessibilityObject::children(bool updateChildrenIfNeeded)
1482 {
1483     if (updateChildrenIfNeeded)
1484         updateChildrenIfNecessary();
1485
1486     return m_children;
1487 }
1488 #endif
1489
1490 void AccessibilityObject::updateChildrenIfNecessary()
1491 {
1492     if (!hasChildren())
1493         addChildren();    
1494 }
1495     
1496 void AccessibilityObject::clearChildren()
1497 {
1498     // Some objects have weak pointers to their parents and those associations need to be detached.
1499     for (const auto& child : m_children)
1500         child->detachFromParent();
1501     
1502     m_children.clear();
1503     m_haveChildren = false;
1504 }
1505
1506 AccessibilityObject* AccessibilityObject::anchorElementForNode(Node* node)
1507 {
1508     RenderObject* obj = node->renderer();
1509     if (!obj)
1510         return 0;
1511     
1512     RefPtr<AccessibilityObject> axObj = obj->document().axObjectCache()->getOrCreate(obj);
1513     Element* anchor = axObj->anchorElement();
1514     if (!anchor)
1515         return 0;
1516     
1517     RenderObject* anchorRenderer = anchor->renderer();
1518     if (!anchorRenderer)
1519         return 0;
1520     
1521     return anchorRenderer->document().axObjectCache()->getOrCreate(anchorRenderer);
1522 }
1523
1524 AccessibilityObject* AccessibilityObject::headingElementForNode(Node* node)
1525 {
1526     if (!node)
1527         return 0;
1528     
1529     RenderObject* renderObject = node->renderer();
1530     if (!renderObject)
1531         return 0;
1532     
1533     AccessibilityObject* axObject = renderObject->document().axObjectCache()->getOrCreate(renderObject);
1534     for (; axObject && axObject->roleValue() != HeadingRole; axObject = axObject->parentObject()) { }
1535     
1536     return axObject;
1537 }
1538
1539 void AccessibilityObject::ariaTreeRows(AccessibilityChildrenVector& result)
1540 {
1541     for (const auto& child : children()) {
1542         // Add tree items as the rows.
1543         if (child->roleValue() == TreeItemRole)
1544             result.append(child);
1545
1546         // Now see if this item also has rows hiding inside of it.
1547         child->ariaTreeRows(result);
1548     }
1549 }
1550     
1551 void AccessibilityObject::ariaTreeItemContent(AccessibilityChildrenVector& result)
1552 {
1553     // The ARIA tree item content are the item that are not other tree items or their containing groups.
1554     for (const auto& child : children()) {
1555         AccessibilityRole role = child->roleValue();
1556         if (role == TreeItemRole || role == GroupRole)
1557             continue;
1558         
1559         result.append(child);
1560     }
1561 }
1562
1563 void AccessibilityObject::ariaTreeItemDisclosedRows(AccessibilityChildrenVector& result)
1564 {
1565     for (const auto& obj : children()) {
1566         // Add tree items as the rows.
1567         if (obj->roleValue() == TreeItemRole)
1568             result.append(obj);
1569         // If it's not a tree item, then descend into the group to find more tree items.
1570         else 
1571             obj->ariaTreeRows(result);
1572     }    
1573 }
1574     
1575 const String AccessibilityObject::defaultLiveRegionStatusForRole(AccessibilityRole role)
1576 {
1577     switch (role) {
1578     case ApplicationAlertDialogRole:
1579     case ApplicationAlertRole:
1580         return ASCIILiteral("assertive");
1581     case ApplicationLogRole:
1582     case ApplicationStatusRole:
1583         return ASCIILiteral("polite");
1584     case ApplicationTimerRole:
1585     case ApplicationMarqueeRole:
1586         return ASCIILiteral("off");
1587     default:
1588         return nullAtom;
1589     }
1590 }
1591     
1592 #if HAVE(ACCESSIBILITY)
1593 const String& AccessibilityObject::actionVerb() const
1594 {
1595 #if !PLATFORM(IOS)
1596     // FIXME: Need to add verbs for select elements.
1597     static NeverDestroyed<const String> buttonAction(AXButtonActionVerb());
1598     static NeverDestroyed<const String> textFieldAction(AXTextFieldActionVerb());
1599     static NeverDestroyed<const String> radioButtonAction(AXRadioButtonActionVerb());
1600     static NeverDestroyed<const String> checkedCheckBoxAction(AXCheckedCheckBoxActionVerb());
1601     static NeverDestroyed<const String> uncheckedCheckBoxAction(AXUncheckedCheckBoxActionVerb());
1602     static NeverDestroyed<const String> linkAction(AXLinkActionVerb());
1603     static NeverDestroyed<const String> menuListAction(AXMenuListActionVerb());
1604     static NeverDestroyed<const String> menuListPopupAction(AXMenuListPopupActionVerb());
1605     static NeverDestroyed<const String> listItemAction(AXListItemActionVerb());
1606
1607     switch (roleValue()) {
1608     case ButtonRole:
1609     case ToggleButtonRole:
1610         return buttonAction;
1611     case TextFieldRole:
1612     case TextAreaRole:
1613         return textFieldAction;
1614     case RadioButtonRole:
1615         return radioButtonAction;
1616     case CheckBoxRole:
1617         return isChecked() ? checkedCheckBoxAction : uncheckedCheckBoxAction;
1618     case LinkRole:
1619     case WebCoreLinkRole:
1620         return linkAction;
1621     case PopUpButtonRole:
1622         return menuListAction;
1623     case MenuListPopupRole:
1624         return menuListPopupAction;
1625     case ListItemRole:
1626         return listItemAction;
1627     default:
1628         return nullAtom;
1629     }
1630 #else
1631     return nullAtom;
1632 #endif
1633 }
1634 #endif
1635
1636 bool AccessibilityObject::ariaIsMultiline() const
1637 {
1638     return equalIgnoringCase(getAttribute(aria_multilineAttr), "true");
1639 }
1640
1641 String AccessibilityObject::invalidStatus() const
1642 {
1643     String grammarValue = ASCIILiteral("grammar");
1644     String falseValue = ASCIILiteral("false");
1645     String spellingValue = ASCIILiteral("spelling");
1646     String trueValue = ASCIILiteral("true");
1647     String undefinedValue = ASCIILiteral("undefined");
1648
1649     // aria-invalid can return false (default), grammar, spelling, or true.
1650     String ariaInvalid = stripLeadingAndTrailingHTMLSpaces(getAttribute(aria_invalidAttr));
1651     
1652     // If "false", "undefined" [sic, string value], empty, or missing, return "false".
1653     if (ariaInvalid.isEmpty() || ariaInvalid == falseValue || ariaInvalid == undefinedValue)
1654         return falseValue;
1655     // Besides true/false/undefined, the only tokens defined by WAI-ARIA 1.0...
1656     // ...for @aria-invalid are "grammar" and "spelling".
1657     if (ariaInvalid == grammarValue)
1658         return grammarValue;
1659     if (ariaInvalid == spellingValue)
1660         return spellingValue;
1661     // Any other non empty string should be treated as "true".
1662     return trueValue;
1663 }
1664  
1665 bool AccessibilityObject::hasTagName(const QualifiedName& tagName) const
1666 {
1667     Node* node = this->node();
1668     return node && node->isElementNode() && toElement(*node).hasTagName(tagName);
1669 }
1670     
1671 bool AccessibilityObject::hasAttribute(const QualifiedName& attribute) const
1672 {
1673     Node* elementNode = node();
1674     if (!elementNode)
1675         return false;
1676     
1677     if (!elementNode->isElementNode())
1678         return false;
1679     
1680     Element* element = toElement(elementNode);
1681     return element->fastHasAttribute(attribute);
1682 }
1683     
1684 const AtomicString& AccessibilityObject::getAttribute(const QualifiedName& attribute) const
1685 {
1686     if (Element* element = this->element())
1687         return element->fastGetAttribute(attribute);
1688     return nullAtom;
1689 }
1690     
1691 // Lacking concrete evidence of orientation, horizontal means width > height. vertical is height > width;
1692 AccessibilityOrientation AccessibilityObject::orientation() const
1693 {
1694     LayoutRect bounds = elementRect();
1695     if (bounds.size().width() > bounds.size().height())
1696         return AccessibilityOrientationHorizontal;
1697     if (bounds.size().height() > bounds.size().width())
1698         return AccessibilityOrientationVertical;
1699
1700     // A tie goes to horizontal.
1701     return AccessibilityOrientationHorizontal;
1702 }    
1703
1704 bool AccessibilityObject::isDescendantOfObject(const AccessibilityObject* axObject) const
1705 {
1706     if (!axObject || !axObject->hasChildren())
1707         return false;
1708
1709     for (const AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) {
1710         if (parent == axObject)
1711             return true;
1712     }
1713     return false;
1714 }
1715
1716 bool AccessibilityObject::isAncestorOfObject(const AccessibilityObject* axObject) const
1717 {
1718     if (!axObject)
1719         return false;
1720
1721     return this == axObject || axObject->isDescendantOfObject(this);
1722 }
1723
1724 AccessibilityObject* AccessibilityObject::firstAnonymousBlockChild() const
1725 {
1726     for (AccessibilityObject* child = firstChild(); child; child = child->nextSibling()) {
1727         if (child->renderer() && child->renderer()->isAnonymousBlock())
1728             return child;
1729     }
1730     return 0;
1731 }
1732
1733 typedef HashMap<String, AccessibilityRole, CaseFoldingHash> ARIARoleMap;
1734 typedef HashMap<AccessibilityRole, String, DefaultHash<int>::Hash, WTF::UnsignedWithZeroKeyHashTraits<int>> ARIAReverseRoleMap;
1735
1736 static ARIARoleMap* gAriaRoleMap = nullptr;
1737 static ARIAReverseRoleMap* gAriaReverseRoleMap = nullptr;
1738
1739 struct RoleEntry {
1740     String ariaRole;
1741     AccessibilityRole webcoreRole;
1742 };
1743
1744 static void initializeRoleMap()
1745 {
1746     if (gAriaRoleMap)
1747         return;
1748     ASSERT(!gAriaReverseRoleMap);
1749
1750     const RoleEntry roles[] = {
1751         { "alert", ApplicationAlertRole },
1752         { "alertdialog", ApplicationAlertDialogRole },
1753         { "application", LandmarkApplicationRole },
1754         { "article", DocumentArticleRole },
1755         { "banner", LandmarkBannerRole },
1756         { "button", ButtonRole },
1757         { "checkbox", CheckBoxRole },
1758         { "complementary", LandmarkComplementaryRole },
1759         { "contentinfo", LandmarkContentInfoRole },
1760         { "dialog", ApplicationDialogRole },
1761         { "directory", DirectoryRole },
1762         { "grid", TableRole },
1763         { "gridcell", CellRole },
1764         { "columnheader", ColumnHeaderRole },
1765         { "combobox", ComboBoxRole },
1766         { "definition", DefinitionRole },
1767         { "document", DocumentRole },
1768         { "rowheader", RowHeaderRole },
1769         { "group", GroupRole },
1770         { "heading", HeadingRole },
1771         { "img", ImageRole },
1772         { "link", WebCoreLinkRole },
1773         { "list", ListRole },        
1774         { "listitem", ListItemRole },        
1775         { "listbox", ListBoxRole },
1776         { "log", ApplicationLogRole },
1777         // "option" isn't here because it may map to different roles depending on the parent element's role
1778         { "main", LandmarkMainRole },
1779         { "marquee", ApplicationMarqueeRole },
1780         { "math", DocumentMathRole },
1781         { "menu", MenuRole },
1782         { "menubar", MenuBarRole },
1783         { "menuitem", MenuItemRole },
1784         { "menuitemcheckbox", MenuItemCheckboxRole },
1785         { "menuitemradio", MenuItemRadioRole },
1786         { "none", PresentationalRole },
1787         { "note", DocumentNoteRole },
1788         { "navigation", LandmarkNavigationRole },
1789         { "option", ListBoxOptionRole },
1790         { "presentation", PresentationalRole },
1791         { "progressbar", ProgressIndicatorRole },
1792         { "radio", RadioButtonRole },
1793         { "radiogroup", RadioGroupRole },
1794         { "region", DocumentRegionRole },
1795         { "row", RowRole },
1796         { "scrollbar", ScrollBarRole },
1797         { "search", LandmarkSearchRole },
1798         { "separator", SplitterRole },
1799         { "slider", SliderRole },
1800         { "spinbutton", SpinButtonRole },
1801         { "status", ApplicationStatusRole },
1802         { "tab", TabRole },
1803         { "tablist", TabListRole },
1804         { "tabpanel", TabPanelRole },
1805         { "text", StaticTextRole },
1806         { "textbox", TextAreaRole },
1807         { "timer", ApplicationTimerRole },
1808         { "toolbar", ToolbarRole },
1809         { "tooltip", UserInterfaceTooltipRole },
1810         { "tree", TreeRole },
1811         { "treegrid", TreeGridRole },
1812         { "treeitem", TreeItemRole }
1813     };
1814
1815     gAriaRoleMap = new ARIARoleMap;
1816     gAriaReverseRoleMap = new ARIAReverseRoleMap;
1817     size_t roleLength = WTF_ARRAY_LENGTH(roles);
1818     for (size_t i = 0; i < roleLength; ++i) {
1819         gAriaRoleMap->set(roles[i].ariaRole, roles[i].webcoreRole);
1820         gAriaReverseRoleMap->set(roles[i].webcoreRole, roles[i].ariaRole);
1821     }
1822 }
1823
1824 static ARIARoleMap& ariaRoleMap()
1825 {
1826     initializeRoleMap();
1827     return *gAriaRoleMap;
1828 }
1829
1830 static ARIAReverseRoleMap& reverseAriaRoleMap()
1831 {
1832     initializeRoleMap();
1833     return *gAriaReverseRoleMap;
1834 }
1835
1836 AccessibilityRole AccessibilityObject::ariaRoleToWebCoreRole(const String& value)
1837 {
1838     ASSERT(!value.isEmpty());
1839     
1840     Vector<String> roleVector;
1841     value.split(' ', roleVector);
1842     AccessibilityRole role = UnknownRole;
1843     for (const auto& roleName : roleVector) {
1844         role = ariaRoleMap().get(roleName);
1845         if (role)
1846             return role;
1847     }
1848     
1849     return role;
1850 }
1851
1852 String AccessibilityObject::computedRoleString() const
1853 {
1854     // FIXME: Need a few special cases that aren't in the RoleMap: option, etc. http://webkit.org/b/128296
1855     AccessibilityRole role = roleValue();
1856     if (role == HorizontalRuleRole)
1857         role = SplitterRole;
1858     
1859     return reverseAriaRoleMap().get(role);
1860 }
1861
1862 bool AccessibilityObject::hasHighlighting() const
1863 {
1864     for (Node* node = this->node(); node; node = node->parentNode()) {
1865         if (node->hasTagName(markTag))
1866             return true;
1867     }
1868     
1869     return false;
1870 }
1871
1872 Element* AccessibilityObject::element() const
1873 {
1874     Node* node = this->node();
1875     if (node && node->isElementNode())
1876         return toElement(node);
1877     return 0;
1878 }
1879
1880 const AtomicString& AccessibilityObject::placeholderValue() const
1881 {
1882     const AtomicString& placeholder = getAttribute(placeholderAttr);
1883     if (!placeholder.isEmpty())
1884         return placeholder;
1885     
1886     return nullAtom;
1887 }
1888     
1889 bool AccessibilityObject::isInsideARIALiveRegion() const
1890 {
1891     if (supportsARIALiveRegion())
1892         return true;
1893     
1894     for (AccessibilityObject* axParent = parentObject(); axParent; axParent = axParent->parentObject()) {
1895         if (axParent->supportsARIALiveRegion())
1896             return true;
1897     }
1898     
1899     return false;
1900 }
1901
1902 bool AccessibilityObject::supportsARIAAttributes() const
1903 {
1904     // This returns whether the element supports any global ARIA attributes.
1905     return supportsARIALiveRegion()
1906         || supportsARIADragging()
1907         || supportsARIADropping()
1908         || supportsARIAFlowTo()
1909         || supportsARIAOwns()
1910         || hasAttribute(aria_atomicAttr)
1911         || hasAttribute(aria_busyAttr)
1912         || hasAttribute(aria_controlsAttr)
1913         || hasAttribute(aria_describedbyAttr)
1914         || hasAttribute(aria_disabledAttr)
1915         || hasAttribute(aria_haspopupAttr)
1916         || hasAttribute(aria_invalidAttr)
1917         || hasAttribute(aria_labelAttr)
1918         || hasAttribute(aria_labelledbyAttr)
1919         || hasAttribute(aria_relevantAttr);
1920 }
1921     
1922 bool AccessibilityObject::liveRegionStatusIsEnabled(const AtomicString& liveRegionStatus)
1923 {
1924     return equalIgnoringCase(liveRegionStatus, "polite") || equalIgnoringCase(liveRegionStatus, "assertive");
1925 }
1926     
1927 bool AccessibilityObject::supportsARIALiveRegion() const
1928 {
1929     return liveRegionStatusIsEnabled(ariaLiveRegionStatus());
1930 }
1931
1932 AccessibilityObject* AccessibilityObject::elementAccessibilityHitTest(const IntPoint& point) const
1933
1934     // Send the hit test back into the sub-frame if necessary.
1935     if (isAttachment()) {
1936         Widget* widget = widgetForAttachmentView();
1937         // Normalize the point for the widget's bounds.
1938         if (widget && widget->isFrameView()) {
1939             if (AXObjectCache* cache = axObjectCache())
1940                 return cache->getOrCreate(widget)->accessibilityHitTest(IntPoint(point - widget->frameRect().location()));
1941         }
1942     }
1943     
1944     // Check if there are any mock elements that need to be handled.
1945     for (const auto& child : m_children) {
1946         if (child->isMockObject() && child->elementRect().contains(point))
1947             return child->elementAccessibilityHitTest(point);
1948     }
1949
1950     return const_cast<AccessibilityObject*>(this); 
1951 }
1952     
1953 AXObjectCache* AccessibilityObject::axObjectCache() const
1954 {
1955     Document* doc = document();
1956     if (doc)
1957         return doc->axObjectCache();
1958     return nullptr;
1959 }
1960     
1961 AccessibilityObject* AccessibilityObject::focusedUIElement() const
1962 {
1963     Document* doc = document();
1964     if (!doc)
1965         return 0;
1966     
1967     Page* page = doc->page();
1968     if (!page)
1969         return 0;
1970     
1971     return AXObjectCache::focusedUIElementForPage(page);
1972 }
1973     
1974 AccessibilitySortDirection AccessibilityObject::sortDirection() const
1975 {
1976     const AtomicString& sortAttribute = getAttribute(aria_sortAttr);
1977     if (equalIgnoringCase(sortAttribute, "ascending"))
1978         return SortDirectionAscending;
1979     if (equalIgnoringCase(sortAttribute, "descending"))
1980         return SortDirectionDescending;
1981     if (equalIgnoringCase(sortAttribute, "other"))
1982         return SortDirectionOther;
1983     
1984     return SortDirectionNone;
1985 }
1986
1987 bool AccessibilityObject::supportsRangeValue() const
1988 {
1989     return isProgressIndicator()
1990         || isSlider()
1991         || isScrollbar()
1992         || isSpinButton();
1993 }
1994     
1995 bool AccessibilityObject::supportsARIASetSize() const
1996 {
1997     return hasAttribute(aria_setsizeAttr);
1998 }
1999
2000 bool AccessibilityObject::supportsARIAPosInSet() const
2001 {
2002     return hasAttribute(aria_posinsetAttr);
2003 }
2004     
2005 int AccessibilityObject::ariaSetSize() const
2006 {
2007     return getAttribute(aria_setsizeAttr).toInt();
2008 }
2009
2010 int AccessibilityObject::ariaPosInSet() const
2011 {
2012     return getAttribute(aria_posinsetAttr).toInt();
2013 }
2014     
2015 String AccessibilityObject::identifierAttribute() const
2016 {
2017     return getAttribute(idAttr);
2018 }
2019     
2020 void AccessibilityObject::classList(Vector<String>& classList) const
2021 {
2022     Node* node = this->node();
2023     if (!node || !node->isElementNode())
2024         return;
2025     
2026     Element* element = toElement(node);
2027     DOMTokenList* list = element->classList();
2028     if (!list)
2029         return;
2030     unsigned length = list->length();
2031     for (unsigned k = 0; k < length; k++)
2032         classList.append(list->item(k).string());
2033 }
2034
2035     
2036 bool AccessibilityObject::supportsARIAExpanded() const
2037 {
2038     // Undefined values should not result in this attribute being exposed to ATs according to ARIA.
2039     const AtomicString& expanded = getAttribute(aria_expandedAttr);
2040     if (equalIgnoringCase(expanded, "true") || equalIgnoringCase(expanded, "false"))
2041         return true;
2042     switch (roleValue()) {
2043     case ComboBoxRole:
2044     case DisclosureTriangleRole:
2045         return true;
2046     default:
2047         return false;
2048     }
2049 }
2050     
2051 bool AccessibilityObject::isExpanded() const
2052 {
2053     if (equalIgnoringCase(getAttribute(aria_expandedAttr), "true"))
2054         return true;
2055     
2056     return false;  
2057 }
2058
2059 bool AccessibilityObject::supportsChecked() const
2060 {
2061     switch (roleValue()) {
2062     case CheckBoxRole:
2063     case MenuItemCheckboxRole:
2064     case MenuItemRadioRole:
2065     case RadioButtonRole:
2066         return true;
2067     default:
2068         return false;
2069     }
2070 }
2071
2072 AccessibilityButtonState AccessibilityObject::checkboxOrRadioValue() const
2073 {
2074     // If this is a real checkbox or radio button, AccessibilityRenderObject will handle.
2075     // If it's an ARIA checkbox or radio, the aria-checked attribute should be used.
2076
2077     const AtomicString& result = getAttribute(aria_checkedAttr);
2078     if (equalIgnoringCase(result, "true"))
2079         return ButtonStateOn;
2080     if (equalIgnoringCase(result, "mixed")) {
2081         // ARIA says that radio and menuitemradio elements must NOT expose button state mixed.
2082         AccessibilityRole ariaRole = ariaRoleAttribute();
2083         if (ariaRole == RadioButtonRole || ariaRole == MenuItemRadioRole)
2084             return ButtonStateOff;
2085         return ButtonStateMixed;
2086     }
2087     
2088     if (equalIgnoringCase(getAttribute(indeterminateAttr), "true"))
2089         return ButtonStateMixed;
2090     
2091     return ButtonStateOff;
2092 }
2093
2094 // This is a 1-dimensional scroll offset helper function that's applied
2095 // separately in the horizontal and vertical directions, because the
2096 // logic is the same. The goal is to compute the best scroll offset
2097 // in order to make an object visible within a viewport.
2098 //
2099 // In case the whole object cannot fit, you can specify a
2100 // subfocus - a smaller region within the object that should
2101 // be prioritized. If the whole object can fit, the subfocus is
2102 // ignored.
2103 //
2104 // Example: the viewport is scrolled to the right just enough
2105 // that the object is in view.
2106 //   Before:
2107 //   +----------Viewport---------+
2108 //                         +---Object---+
2109 //                         +--SubFocus--+
2110 //
2111 //   After:
2112 //          +----------Viewport---------+
2113 //                         +---Object---+
2114 //                         +--SubFocus--+
2115 //
2116 // When constraints cannot be fully satisfied, the min
2117 // (left/top) position takes precedence over the max (right/bottom).
2118 //
2119 // Note that the return value represents the ideal new scroll offset.
2120 // This may be out of range - the calling function should clip this
2121 // to the available range.
2122 static int computeBestScrollOffset(int currentScrollOffset,
2123                                    int subfocusMin, int subfocusMax,
2124                                    int objectMin, int objectMax,
2125                                    int viewportMin, int viewportMax) {
2126     int viewportSize = viewportMax - viewportMin;
2127
2128     // If the focus size is larger than the viewport size, shrink it in the
2129     // direction of subfocus.
2130     if (objectMax - objectMin > viewportSize) {
2131         // Subfocus must be within focus:
2132         subfocusMin = std::max(subfocusMin, objectMin);
2133         subfocusMax = std::min(subfocusMax, objectMax);
2134
2135         // Subfocus must be no larger than the viewport size; favor top/left.
2136         if (subfocusMax - subfocusMin > viewportSize)
2137             subfocusMax = subfocusMin + viewportSize;
2138
2139         if (subfocusMin + viewportSize > objectMax)
2140             objectMin = objectMax - viewportSize;
2141         else {
2142             objectMin = subfocusMin;
2143             objectMax = subfocusMin + viewportSize;
2144         }
2145     }
2146
2147     // Exit now if the focus is already within the viewport.
2148     if (objectMin - currentScrollOffset >= viewportMin
2149         && objectMax - currentScrollOffset <= viewportMax)
2150         return currentScrollOffset;
2151
2152     // Scroll left if we're too far to the right.
2153     if (objectMax - currentScrollOffset > viewportMax)
2154         return objectMax - viewportMax;
2155
2156     // Scroll right if we're too far to the left.
2157     if (objectMin - currentScrollOffset < viewportMin)
2158         return objectMin - viewportMin;
2159
2160     ASSERT_NOT_REACHED();
2161
2162     // This shouldn't happen.
2163     return currentScrollOffset;
2164 }
2165
2166 bool AccessibilityObject::isOnscreen() const
2167 {   
2168     bool isOnscreen = true;
2169
2170     // To figure out if the element is onscreen, we start by building of a stack starting with the
2171     // element, and then include every scrollable parent in the hierarchy.
2172     Vector<const AccessibilityObject*> objects;
2173     
2174     objects.append(this);
2175     for (AccessibilityObject* parentObject = this->parentObject(); parentObject; parentObject = parentObject->parentObject()) {
2176         if (parentObject->getScrollableAreaIfScrollable())
2177             objects.append(parentObject);
2178     }
2179
2180     // Now, go back through that chain and make sure each inner object is within the
2181     // visible bounds of the outer object.
2182     size_t levels = objects.size() - 1;
2183     
2184     for (size_t i = levels; i >= 1; i--) {
2185         const AccessibilityObject* outer = objects[i];
2186         const AccessibilityObject* inner = objects[i - 1];
2187         // FIXME: unclear if we need LegacyIOSDocumentVisibleRect.
2188         const IntRect outerRect = i < levels ? pixelSnappedIntRect(outer->boundingBoxRect()) : outer->getScrollableAreaIfScrollable()->visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect);
2189         const IntRect innerRect = pixelSnappedIntRect(inner->isAccessibilityScrollView() ? inner->parentObject()->boundingBoxRect() : inner->boundingBoxRect());
2190         
2191         if (!outerRect.intersects(innerRect)) {
2192             isOnscreen = false;
2193             break;
2194         }
2195     }
2196     
2197     return isOnscreen;
2198 }
2199
2200 void AccessibilityObject::scrollToMakeVisible() const
2201 {
2202     IntRect objectRect = pixelSnappedIntRect(boundingBoxRect());
2203     objectRect.setLocation(IntPoint());
2204     scrollToMakeVisibleWithSubFocus(objectRect);
2205 }
2206
2207 void AccessibilityObject::scrollToMakeVisibleWithSubFocus(const IntRect& subfocus) const
2208 {
2209     // Search up the parent chain until we find the first one that's scrollable.
2210     AccessibilityObject* scrollParent = parentObject();
2211     ScrollableArea* scrollableArea;
2212     for (scrollableArea = 0;
2213          scrollParent && !(scrollableArea = scrollParent->getScrollableAreaIfScrollable());
2214          scrollParent = scrollParent->parentObject()) { }
2215     if (!scrollableArea)
2216         return;
2217
2218     LayoutRect objectRect = boundingBoxRect();
2219     IntPoint scrollPosition = scrollableArea->scrollPosition();
2220     // FIXME: unclear if we need LegacyIOSDocumentVisibleRect.
2221     IntRect scrollVisibleRect = scrollableArea->visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect);
2222
2223     int desiredX = computeBestScrollOffset(
2224         scrollPosition.x(),
2225         objectRect.x() + subfocus.x(), objectRect.x() + subfocus.maxX(),
2226         objectRect.x(), objectRect.maxX(),
2227         0, scrollVisibleRect.width());
2228     int desiredY = computeBestScrollOffset(
2229         scrollPosition.y(),
2230         objectRect.y() + subfocus.y(), objectRect.y() + subfocus.maxY(),
2231         objectRect.y(), objectRect.maxY(),
2232         0, scrollVisibleRect.height());
2233
2234     scrollParent->scrollTo(IntPoint(desiredX, desiredY));
2235
2236     // Recursively make sure the scroll parent itself is visible.
2237     if (scrollParent->parentObject())
2238         scrollParent->scrollToMakeVisible();
2239 }
2240
2241 void AccessibilityObject::scrollToGlobalPoint(const IntPoint& globalPoint) const
2242 {
2243     // Search up the parent chain and create a vector of all scrollable parent objects
2244     // and ending with this object itself.
2245     Vector<const AccessibilityObject*> objects;
2246
2247     objects.append(this);
2248     for (AccessibilityObject* parentObject = this->parentObject(); parentObject; parentObject = parentObject->parentObject()) {
2249         if (parentObject->getScrollableAreaIfScrollable())
2250             objects.append(parentObject);
2251     }
2252
2253     objects.reverse();
2254
2255     // Start with the outermost scrollable (the main window) and try to scroll the
2256     // next innermost object to the given point.
2257     int offsetX = 0, offsetY = 0;
2258     IntPoint point = globalPoint;
2259     size_t levels = objects.size() - 1;
2260     for (size_t i = 0; i < levels; i++) {
2261         const AccessibilityObject* outer = objects[i];
2262         const AccessibilityObject* inner = objects[i + 1];
2263
2264         ScrollableArea* scrollableArea = outer->getScrollableAreaIfScrollable();
2265
2266         LayoutRect innerRect = inner->isAccessibilityScrollView() ? inner->parentObject()->boundingBoxRect() : inner->boundingBoxRect();
2267         LayoutRect objectRect = innerRect;
2268         IntPoint scrollPosition = scrollableArea->scrollPosition();
2269
2270         // Convert the object rect into local coordinates.
2271         objectRect.move(offsetX, offsetY);
2272         if (!outer->isAccessibilityScrollView())
2273             objectRect.move(scrollPosition.x(), scrollPosition.y());
2274
2275         int desiredX = computeBestScrollOffset(
2276             0,
2277             objectRect.x(), objectRect.maxX(),
2278             objectRect.x(), objectRect.maxX(),
2279             point.x(), point.x());
2280         int desiredY = computeBestScrollOffset(
2281             0,
2282             objectRect.y(), objectRect.maxY(),
2283             objectRect.y(), objectRect.maxY(),
2284             point.y(), point.y());
2285         outer->scrollTo(IntPoint(desiredX, desiredY));
2286
2287         if (outer->isAccessibilityScrollView() && !inner->isAccessibilityScrollView()) {
2288             // If outer object we just scrolled is a scroll view (main window or iframe) but the
2289             // inner object is not, keep track of the coordinate transformation to apply to
2290             // future nested calculations.
2291             scrollPosition = scrollableArea->scrollPosition();
2292             offsetX -= (scrollPosition.x() + point.x());
2293             offsetY -= (scrollPosition.y() + point.y());
2294             point.move(scrollPosition.x() - innerRect.x(),
2295                        scrollPosition.y() - innerRect.y());
2296         } else if (inner->isAccessibilityScrollView()) {
2297             // Otherwise, if the inner object is a scroll view, reset the coordinate transformation.
2298             offsetX = 0;
2299             offsetY = 0;
2300         }
2301     }
2302 }
2303
2304 bool AccessibilityObject::lastKnownIsIgnoredValue()
2305 {
2306     if (m_lastKnownIsIgnoredValue == DefaultBehavior)
2307         m_lastKnownIsIgnoredValue = accessibilityIsIgnored() ? IgnoreObject : IncludeObject;
2308
2309     return m_lastKnownIsIgnoredValue == IgnoreObject;
2310 }
2311
2312 void AccessibilityObject::setLastKnownIsIgnoredValue(bool isIgnored)
2313 {
2314     m_lastKnownIsIgnoredValue = isIgnored ? IgnoreObject : IncludeObject;
2315 }
2316
2317 void AccessibilityObject::notifyIfIgnoredValueChanged()
2318 {
2319     bool isIgnored = accessibilityIsIgnored();
2320     if (lastKnownIsIgnoredValue() != isIgnored) {
2321         if (AXObjectCache* cache = axObjectCache())
2322             cache->childrenChanged(parentObject());
2323         setLastKnownIsIgnoredValue(isIgnored);
2324     }
2325 }
2326
2327 bool AccessibilityObject::ariaPressedIsPresent() const
2328 {
2329     return !getAttribute(aria_pressedAttr).isEmpty();
2330 }
2331
2332 TextIteratorBehavior AccessibilityObject::textIteratorBehaviorForTextRange() const
2333 {
2334     TextIteratorBehavior behavior = TextIteratorIgnoresStyleVisibility;
2335     
2336 #if PLATFORM(GTK) || PLATFORM(EFL)
2337     // We need to emit replaced elements for GTK, and present
2338     // them with the 'object replacement character' (0xFFFC).
2339     behavior = static_cast<TextIteratorBehavior>(behavior | TextIteratorEmitsObjectReplacementCharacters);
2340 #endif
2341     
2342     return behavior;
2343 }
2344     
2345 AccessibilityRole AccessibilityObject::buttonRoleType() const
2346 {
2347     // If aria-pressed is present, then it should be exposed as a toggle button.
2348     // http://www.w3.org/TR/wai-aria/states_and_properties#aria-pressed
2349     if (ariaPressedIsPresent())
2350         return ToggleButtonRole;
2351     if (ariaHasPopup())
2352         return PopUpButtonRole;
2353     // We don't contemplate RadioButtonRole, as it depends on the input
2354     // type.
2355
2356     return ButtonRole;
2357 }
2358
2359 bool AccessibilityObject::isButton() const
2360 {
2361     AccessibilityRole role = roleValue();
2362
2363     return role == ButtonRole || role == PopUpButtonRole || role == ToggleButtonRole;
2364 }
2365
2366 bool AccessibilityObject::accessibilityIsIgnoredByDefault() const
2367 {
2368     return defaultObjectInclusion() == IgnoreObject;
2369 }
2370
2371 // ARIA component of hidden definition.
2372 // http://www.w3.org/TR/wai-aria/terms#def_hidden
2373 bool AccessibilityObject::isARIAHidden() const
2374 {
2375     for (const AccessibilityObject* object = this; object; object = object->parentObject()) {
2376         if (equalIgnoringCase(object->getAttribute(aria_hiddenAttr), "true"))
2377             return true;
2378     }
2379     return false;
2380 }
2381
2382 // DOM component of hidden definition.
2383 // http://www.w3.org/TR/wai-aria/terms#def_hidden
2384 bool AccessibilityObject::isDOMHidden() const
2385 {
2386     RenderObject* renderer = this->renderer();
2387     if (!renderer)
2388         return true;
2389     
2390     const RenderStyle& style = renderer->style();
2391     return style.display() == NONE || style.visibility() != VISIBLE;
2392 }
2393
2394 AccessibilityObjectInclusion AccessibilityObject::defaultObjectInclusion() const
2395 {
2396     if (isARIAHidden())
2397         return IgnoreObject;
2398     
2399     if (isPresentationalChildOfAriaRole())
2400         return IgnoreObject;
2401     
2402     return accessibilityPlatformIncludesObject();
2403 }
2404     
2405 bool AccessibilityObject::accessibilityIsIgnored() const
2406 {
2407     AXComputedObjectAttributeCache* attributeCache = nullptr;
2408     if (AXObjectCache* cache = axObjectCache())
2409         attributeCache = cache->computedObjectAttributeCache();
2410     
2411     if (attributeCache) {
2412         AccessibilityObjectInclusion ignored = attributeCache->getIgnored(axObjectID());
2413         switch (ignored) {
2414         case IgnoreObject:
2415             return true;
2416         case IncludeObject:
2417             return false;
2418         case DefaultBehavior:
2419             break;
2420         }
2421     }
2422
2423     bool result = computeAccessibilityIsIgnored();
2424
2425     if (attributeCache)
2426         attributeCache->setIgnored(axObjectID(), result ? IgnoreObject : IncludeObject);
2427
2428     return result;
2429 }
2430
2431 void AccessibilityObject::elementsFromAttribute(Vector<Element*>& elements, const QualifiedName& attribute) const
2432 {
2433     Node* node = this->node();
2434     if (!node || !node->isElementNode())
2435         return;
2436
2437     TreeScope& treeScope = node->treeScope();
2438
2439     String idList = getAttribute(attribute).string();
2440     if (idList.isEmpty())
2441         return;
2442
2443     idList.replace('\n', ' ');
2444     Vector<String> idVector;
2445     idList.split(' ', idVector);
2446
2447     for (const auto& idName : idVector) {
2448         if (Element* idElement = treeScope.getElementById(idName))
2449             elements.append(idElement);
2450     }
2451 }
2452
2453 } // namespace WebCore