2 * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
30 #import "WebAccessibilityObjectWrapperMac.h"
32 #if HAVE(ACCESSIBILITY)
34 #import "AXObjectCache.h"
35 #import "AccessibilityARIAGridRow.h"
36 #import "AccessibilityList.h"
37 #import "AccessibilityListBox.h"
38 #import "AccessibilityRenderObject.h"
39 #import "AccessibilityScrollView.h"
40 #import "AccessibilitySpinButton.h"
41 #import "AccessibilityTable.h"
42 #import "AccessibilityTableCell.h"
43 #import "AccessibilityTableColumn.h"
44 #import "AccessibilityTableRow.h"
46 #import "ChromeClient.h"
48 #import "ContextMenuController.h"
51 #import "FontCascade.h"
52 #import "FrameLoaderClient.h"
53 #import "FrameSelection.h"
54 #import "HTMLAnchorElement.h"
55 #import "HTMLAreaElement.h"
56 #import "HTMLFrameOwnerElement.h"
57 #import "HTMLImageElement.h"
58 #import "HTMLInputElement.h"
60 #import "HTMLTextAreaElement.h"
61 #import "LocalizedStrings.h"
64 #import "RenderTextControl.h"
65 #import "RenderView.h"
66 #import "RenderWidget.h"
67 #import "ScrollView.h"
68 #import "TextCheckerClient.h"
69 #import "TextCheckingHelper.h"
70 #import "TextIterator.h"
71 #import "VisibleUnits.h"
72 #import "WebCoreFrameView.h"
73 #import "WebCoreObjCExtras.h"
74 #import "WebCoreSystemInterface.h"
75 #import "htmlediting.h"
76 #import <wtf/ObjcRuntimeExtras.h>
78 using namespace WebCore;
79 using namespace HTMLNames;
82 #ifndef NSAccessibilitySelectedCellsAttribute
83 #define NSAccessibilitySelectedCellsAttribute @"AXSelectedCells"
86 #ifndef NSAccessibilityVisibleCellsAttribute
87 #define NSAccessibilityVisibleCellsAttribute @"AXVisibleCells"
90 #ifndef NSAccessibilityRowIndexRangeAttribute
91 #define NSAccessibilityRowIndexRangeAttribute @"AXRowIndexRange"
94 #ifndef NSAccessibilityColumnIndexRangeAttribute
95 #define NSAccessibilityColumnIndexRangeAttribute @"AXColumnIndexRange"
98 #ifndef NSAccessibilityCellForColumnAndRowParameterizedAttribute
99 #define NSAccessibilityCellForColumnAndRowParameterizedAttribute @"AXCellForColumnAndRow"
102 #ifndef NSAccessibilityCellRole
103 #define NSAccessibilityCellRole @"AXCell"
107 #ifndef NSAccessibilityContentListSubrole
108 #define NSAccessibilityContentListSubrole @"AXContentList"
111 #ifndef NSAccessibilityDefinitionListSubrole
112 #define NSAccessibilityDefinitionListSubrole @"AXDefinitionList"
115 #ifndef NSAccessibilityDescriptionListSubrole
116 #define NSAccessibilityDescriptionListSubrole @"AXDescriptionList"
119 #ifndef NSAccessibilityContentSeparatorSubrole
120 #define NSAccessibilityContentSeparatorSubrole @"AXContentSeparator"
123 #ifndef NSAccessibilityRubyBaseSubRole
124 #define NSAccessibilityRubyBaseSubrole @"AXRubyBase"
127 #ifndef NSAccessibilityRubyBlockSubrole
128 #define NSAccessibilityRubyBlockSubrole @"AXRubyBlock"
131 #ifndef NSAccessibilityRubyInlineSubrole
132 #define NSAccessibilityRubyInlineSubrole @"AXRubyInline"
135 #ifndef NSAccessibilityRubyRunSubrole
136 #define NSAccessibilityRubyRunSubrole @"AXRubyRun"
139 #ifndef NSAccessibilityRubyTextSubrole
140 #define NSAccessibilityRubyTextSubrole @"AXRubyText"
144 #ifndef NSAccessibilityBlockQuoteLevelAttribute
145 #define NSAccessibilityBlockQuoteLevelAttribute @"AXBlockQuoteLevel"
148 #ifndef NSAccessibilityAccessKeyAttribute
149 #define NSAccessibilityAccessKeyAttribute @"AXAccessKey"
152 #ifndef NSAccessibilityValueAutofilledAttribute
153 #define NSAccessibilityValueAutofilledAttribute @"AXValueAutofilled"
156 #ifndef NSAccessibilityLanguageAttribute
157 #define NSAccessibilityLanguageAttribute @"AXLanguage"
160 #ifndef NSAccessibilityRequiredAttribute
161 #define NSAccessibilityRequiredAttribute @"AXRequired"
164 #ifndef NSAccessibilityInvalidAttribute
165 #define NSAccessibilityInvalidAttribute @"AXInvalid"
168 #ifndef NSAccessibilityOwnsAttribute
169 #define NSAccessibilityOwnsAttribute @"AXOwns"
172 #ifndef NSAccessibilityGrabbedAttribute
173 #define NSAccessibilityGrabbedAttribute @"AXGrabbed"
176 #ifndef NSAccessibilityDropEffectsAttribute
177 #define NSAccessibilityDropEffectsAttribute @"AXDropEffects"
180 #ifndef NSAccessibilityARIALiveAttribute
181 #define NSAccessibilityARIALiveAttribute @"AXARIALive"
184 #ifndef NSAccessibilityARIAAtomicAttribute
185 #define NSAccessibilityARIAAtomicAttribute @"AXARIAAtomic"
188 #ifndef NSAccessibilityARIARelevantAttribute
189 #define NSAccessibilityARIARelevantAttribute @"AXARIARelevant"
192 #ifndef NSAccessibilityElementBusyAttribute
193 #define NSAccessibilityElementBusyAttribute @"AXElementBusy"
196 #ifndef NSAccessibilityARIAPosInSetAttribute
197 #define NSAccessibilityARIAPosInSetAttribute @"AXARIAPosInSet"
200 #ifndef NSAccessibilityARIASetSizeAttribute
201 #define NSAccessibilityARIASetSizeAttribute @"AXARIASetSize"
204 #ifndef NSAccessibilityLoadingProgressAttribute
205 #define NSAccessibilityLoadingProgressAttribute @"AXLoadingProgress"
208 #ifndef NSAccessibilityHasPopupAttribute
209 #define NSAccessibilityHasPopupAttribute @"AXHasPopup"
212 #ifndef NSAccessibilityPlaceholderValueAttribute
213 #define NSAccessibilityPlaceholderValueAttribute @"AXPlaceholderValue"
216 #define NSAccessibilityTextMarkerIsValidParameterizedAttribute @"AXTextMarkerIsValid"
217 #define NSAccessibilityIndexForTextMarkerParameterizedAttribute @"AXIndexForTextMarker"
218 #define NSAccessibilityTextMarkerForIndexParameterizedAttribute @"AXTextMarkerForIndex"
220 #ifndef NSAccessibilityScrollToVisibleAction
221 #define NSAccessibilityScrollToVisibleAction @"AXScrollToVisible"
224 #ifndef NSAccessibilityPathAttribute
225 #define NSAccessibilityPathAttribute @"AXPath"
228 #ifndef NSAccessibilityExpandedTextValueAttribute
229 #define NSAccessibilityExpandedTextValueAttribute @"AXExpandedTextValue"
232 #define NSAccessibilityDOMIdentifierAttribute @"AXDOMIdentifier"
233 #define NSAccessibilityDOMClassListAttribute @"AXDOMClassList"
236 #ifndef NSAccessibilityImmediateDescendantsOnly
237 #define NSAccessibilityImmediateDescendantsOnly @"AXImmediateDescendantsOnly"
240 #ifndef NSAccessibilityUIElementCountForSearchPredicateParameterizedAttribute
241 #define NSAccessibilityUIElementCountForSearchPredicateParameterizedAttribute @"AXUIElementCountForSearchPredicate"
244 #ifndef NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute
245 #define NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute @"AXUIElementsForSearchPredicate"
249 #ifndef NSAccessibilityAnyTypeSearchKey
250 #define NSAccessibilityAnyTypeSearchKey @"AXAnyTypeSearchKey"
253 #ifndef NSAccessibilityBlockquoteSameLevelSearchKey
254 #define NSAccessibilityBlockquoteSameLevelSearchKey @"AXBlockquoteSameLevelSearchKey"
257 #ifndef NSAccessibilityBlockquoteSearchKey
258 #define NSAccessibilityBlockquoteSearchKey @"AXBlockquoteSearchKey"
261 #ifndef NSAccessibilityBoldFontSearchKey
262 #define NSAccessibilityBoldFontSearchKey @"AXBoldFontSearchKey"
265 #ifndef NSAccessibilityButtonSearchKey
266 #define NSAccessibilityButtonSearchKey @"AXButtonSearchKey"
269 #ifndef NSAccessibilityCheckBoxSearchKey
270 #define NSAccessibilityCheckBoxSearchKey @"AXCheckBoxSearchKey"
273 #ifndef NSAccessibilityControlSearchKey
274 #define NSAccessibilityControlSearchKey @"AXControlSearchKey"
277 #ifndef NSAccessibilityDifferentTypeSearchKey
278 #define NSAccessibilityDifferentTypeSearchKey @"AXDifferentTypeSearchKey"
281 #ifndef NSAccessibilityFontChangeSearchKey
282 #define NSAccessibilityFontChangeSearchKey @"AXFontChangeSearchKey"
285 #ifndef NSAccessibilityFontColorChangeSearchKey
286 #define NSAccessibilityFontColorChangeSearchKey @"AXFontColorChangeSearchKey"
289 #ifndef NSAccessibilityFrameSearchKey
290 #define NSAccessibilityFrameSearchKey @"AXFrameSearchKey"
293 #ifndef NSAccessibilityGraphicSearchKey
294 #define NSAccessibilityGraphicSearchKey @"AXGraphicSearchKey"
297 #ifndef NSAccessibilityHeadingLevel1SearchKey
298 #define NSAccessibilityHeadingLevel1SearchKey @"AXHeadingLevel1SearchKey"
301 #ifndef NSAccessibilityHeadingLevel2SearchKey
302 #define NSAccessibilityHeadingLevel2SearchKey @"AXHeadingLevel2SearchKey"
305 #ifndef NSAccessibilityHeadingLevel3SearchKey
306 #define NSAccessibilityHeadingLevel3SearchKey @"AXHeadingLevel3SearchKey"
309 #ifndef NSAccessibilityHeadingLevel4SearchKey
310 #define NSAccessibilityHeadingLevel4SearchKey @"AXHeadingLevel4SearchKey"
313 #ifndef NSAccessibilityHeadingLevel5SearchKey
314 #define NSAccessibilityHeadingLevel5SearchKey @"AXHeadingLevel5SearchKey"
317 #ifndef NSAccessibilityHeadingLevel6SearchKey
318 #define NSAccessibilityHeadingLevel6SearchKey @"AXHeadingLevel6SearchKey"
321 #ifndef NSAccessibilityHeadingSameLevelSearchKey
322 #define NSAccessibilityHeadingSameLevelSearchKey @"AXHeadingSameLevelSearchKey"
325 #ifndef NSAccessibilityHeadingSearchKey
326 #define NSAccessibilityHeadingSearchKey @"AXHeadingSearchKey"
329 #ifndef NSAccessibilityHighlightedSearchKey
330 #define NSAccessibilityHighlightedSearchKey @"AXHighlightedSearchKey"
333 #ifndef NSAccessibilityItalicFontSearchKey
334 #define NSAccessibilityItalicFontSearchKey @"AXItalicFontSearchKey"
337 #ifndef NSAccessibilityLandmarkSearchKey
338 #define NSAccessibilityLandmarkSearchKey @"AXLandmarkSearchKey"
341 #ifndef NSAccessibilityLinkSearchKey
342 #define NSAccessibilityLinkSearchKey @"AXLinkSearchKey"
345 #ifndef NSAccessibilityListSearchKey
346 #define NSAccessibilityListSearchKey @"AXListSearchKey"
349 #ifndef NSAccessibilityLiveRegionSearchKey
350 #define NSAccessibilityLiveRegionSearchKey @"AXLiveRegionSearchKey"
353 #ifndef NSAccessibilityMisspelledWordSearchKey
354 #define NSAccessibilityMisspelledWordSearchKey @"AXMisspelledWordSearchKey"
357 #ifndef NSAccessibilityOutlineSearchKey
358 #define NSAccessibilityOutlineSearchKey @"AXOutlineSearchKey"
361 #ifndef NSAccessibilityPlainTextSearchKey
362 #define NSAccessibilityPlainTextSearchKey @"AXPlainTextSearchKey"
365 #ifndef NSAccessibilityRadioGroupSearchKey
366 #define NSAccessibilityRadioGroupSearchKey @"AXRadioGroupSearchKey"
369 #ifndef NSAccessibilitySameTypeSearchKey
370 #define NSAccessibilitySameTypeSearchKey @"AXSameTypeSearchKey"
373 #ifndef NSAccessibilityStaticTextSearchKey
374 #define NSAccessibilityStaticTextSearchKey @"AXStaticTextSearchKey"
377 #ifndef NSAccessibilityStyleChangeSearchKey
378 #define NSAccessibilityStyleChangeSearchKey @"AXStyleChangeSearchKey"
381 #ifndef NSAccessibilityTableSameLevelSearchKey
382 #define NSAccessibilityTableSameLevelSearchKey @"AXTableSameLevelSearchKey"
385 #ifndef NSAccessibilityTableSearchKey
386 #define NSAccessibilityTableSearchKey @"AXTableSearchKey"
389 #ifndef NSAccessibilityTextFieldSearchKey
390 #define NSAccessibilityTextFieldSearchKey @"AXTextFieldSearchKey"
393 #ifndef NSAccessibilityUnderlineSearchKey
394 #define NSAccessibilityUnderlineSearchKey @"AXUnderlineSearchKey"
397 #ifndef NSAccessibilityUnvisitedLinkSearchKey
398 #define NSAccessibilityUnvisitedLinkSearchKey @"AXUnvisitedLinkSearchKey"
401 #ifndef NSAccessibilityVisitedLinkSearchKey
402 #define NSAccessibilityVisitedLinkSearchKey @"AXVisitedLinkSearchKey"
406 #ifndef NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute
407 #define NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute @"AXEndTextMarkerForBounds"
410 #ifndef NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute
411 #define NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute @"AXStartTextMarkerForBounds"
414 #ifndef NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute
415 #define NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute @"AXLineTextMarkerRangeForTextMarker"
419 #ifndef NSAccessibilitySelectTextActivity
420 #define NSAccessibilitySelectTextActivity @"AXSelectTextActivity"
423 #ifndef NSAccessibilitySelectTextActivityFindAndReplace
424 #define NSAccessibilitySelectTextActivityFindAndReplace @"AXSelectTextActivityFindAndReplace"
427 #ifndef NSAccessibilitySelectTextActivityFindAndSelect
428 #define NSAccessibilitySelectTextActivityFindAndSelect @"AXSelectTextActivityFindAndSelect"
431 #ifndef kAXSelectTextActivityFindAndCapitalize
432 #define kAXSelectTextActivityFindAndCapitalize @"AXSelectTextActivityFindAndCapitalize"
435 #ifndef kAXSelectTextActivityFindAndLowercase
436 #define kAXSelectTextActivityFindAndLowercase @"AXSelectTextActivityFindAndLowercase"
439 #ifndef kAXSelectTextActivityFindAndUppercase
440 #define kAXSelectTextActivityFindAndUppercase @"AXSelectTextActivityFindAndUppercase"
443 #ifndef NSAccessibilitySelectTextAmbiguityResolution
444 #define NSAccessibilitySelectTextAmbiguityResolution @"AXSelectTextAmbiguityResolution"
447 #ifndef NSAccessibilitySelectTextAmbiguityResolutionClosestAfterSelection
448 #define NSAccessibilitySelectTextAmbiguityResolutionClosestAfterSelection @"AXSelectTextAmbiguityResolutionClosestAfterSelection"
451 #ifndef NSAccessibilitySelectTextAmbiguityResolutionClosestBeforeSelection
452 #define NSAccessibilitySelectTextAmbiguityResolutionClosestBeforeSelection @"AXSelectTextAmbiguityResolutionClosestBeforeSelection"
455 #ifndef NSAccessibilitySelectTextAmbiguityResolutionClosestToSelection
456 #define NSAccessibilitySelectTextAmbiguityResolutionClosestToSelection @"AXSelectTextAmbiguityResolutionClosestToSelection"
459 #ifndef NSAccessibilitySelectTextReplacementString
460 #define NSAccessibilitySelectTextReplacementString @"AXSelectTextReplacementString"
463 #ifndef NSAccessibilitySelectTextSearchStrings
464 #define NSAccessibilitySelectTextSearchStrings @"AXSelectTextSearchStrings"
467 #ifndef NSAccessibilitySelectTextWithCriteriaParameterizedAttribute
468 #define NSAccessibilitySelectTextWithCriteriaParameterizedAttribute @"AXSelectTextWithCriteria"
472 #define NSAccessibilityMathRootRadicandAttribute @"AXMathRootRadicand"
473 #define NSAccessibilityMathRootIndexAttribute @"AXMathRootIndex"
474 #define NSAccessibilityMathFractionDenominatorAttribute @"AXMathFractionDenominator"
475 #define NSAccessibilityMathFractionNumeratorAttribute @"AXMathFractionNumerator"
476 #define NSAccessibilityMathBaseAttribute @"AXMathBase"
477 #define NSAccessibilityMathSubscriptAttribute @"AXMathSubscript"
478 #define NSAccessibilityMathSuperscriptAttribute @"AXMathSuperscript"
479 #define NSAccessibilityMathUnderAttribute @"AXMathUnder"
480 #define NSAccessibilityMathOverAttribute @"AXMathOver"
481 #define NSAccessibilityMathFencedOpenAttribute @"AXMathFencedOpen"
482 #define NSAccessibilityMathFencedCloseAttribute @"AXMathFencedClose"
483 #define NSAccessibilityMathLineThicknessAttribute @"AXMathLineThickness"
484 #define NSAccessibilityMathPrescriptsAttribute @"AXMathPrescripts"
485 #define NSAccessibilityMathPostscriptsAttribute @"AXMathPostscripts"
487 #ifndef NSAccessibilityPreventKeyboardDOMEventDispatchAttribute
488 #define NSAccessibilityPreventKeyboardDOMEventDispatchAttribute @"AXPreventKeyboardDOMEventDispatch"
491 #ifndef NSAccessibilityCaretBrowsingEnabledAttribute
492 #define NSAccessibilityCaretBrowsingEnabledAttribute @"AXCaretBrowsingEnabled"
495 @implementation WebAccessibilityObjectWrapper
497 - (void)unregisterUniqueIdForUIElement
499 wkUnregisterUniqueIdForElement(self);
504 // Send unregisterUniqueIdForUIElement unconditionally because if it is
505 // ever accidentally not done (via other bugs in our AX implementation) you
506 // end up with a crash like <rdar://problem/4273149>. It is safe and not
507 // expensive to send even if the object is not registered.
508 [self unregisterUniqueIdForUIElement];
514 ASSERT(m_object->isAttachment());
515 Widget* widget = m_object->widgetForAttachmentView();
518 return NSAccessibilityUnignoredDescendant(widget->platformWidget());
521 #pragma mark SystemInterface wrappers
523 static inline BOOL AXObjectIsTextMarker(id obj)
525 return obj != nil && CFGetTypeID(obj) == wkGetAXTextMarkerTypeID();
528 static inline BOOL AXObjectIsTextMarkerRange(id obj)
530 return obj != nil && CFGetTypeID(obj) == wkGetAXTextMarkerRangeTypeID();
533 static id AXTextMarkerRange(id startMarker, id endMarker)
535 ASSERT(startMarker != nil);
536 ASSERT(endMarker != nil);
537 ASSERT(CFGetTypeID(startMarker) == wkGetAXTextMarkerTypeID());
538 ASSERT(CFGetTypeID(endMarker) == wkGetAXTextMarkerTypeID());
539 return CFBridgingRelease(wkCreateAXTextMarkerRange((CFTypeRef)startMarker, (CFTypeRef)endMarker));
542 static id AXTextMarkerRangeStart(id range)
544 ASSERT(range != nil);
545 ASSERT(CFGetTypeID(range) == wkGetAXTextMarkerRangeTypeID());
546 return CFBridgingRelease(wkCopyAXTextMarkerRangeStart(range));
549 static id AXTextMarkerRangeEnd(id range)
551 ASSERT(range != nil);
552 ASSERT(CFGetTypeID(range) == wkGetAXTextMarkerRangeTypeID());
553 return CFBridgingRelease(wkCopyAXTextMarkerRangeEnd(range));
556 #pragma mark Other helpers
558 - (IntRect)screenToContents:(const IntRect&)rect
560 Document* document = m_object->document();
564 FrameView* frameView = document->view();
568 IntPoint startPoint = frameView->screenToContents(rect.minXMaxYCorner());
569 IntPoint endPoint = frameView->screenToContents(rect.maxXMinYCorner());
570 return IntRect(startPoint.x(), startPoint.y(), endPoint.x() - startPoint.x(), endPoint.y() - startPoint.y());
573 #pragma mark Search helpers
575 typedef HashMap<String, AccessibilitySearchKey> AccessibilitySearchKeyMap;
577 struct SearchKeyEntry {
579 AccessibilitySearchKey value;
582 static AccessibilitySearchKeyMap* createAccessibilitySearchKeyMap()
584 const SearchKeyEntry searchKeys[] = {
585 { NSAccessibilityAnyTypeSearchKey, AnyTypeSearchKey },
586 { NSAccessibilityBlockquoteSameLevelSearchKey, BlockquoteSameLevelSearchKey },
587 { NSAccessibilityBlockquoteSearchKey, BlockquoteSearchKey },
588 { NSAccessibilityBoldFontSearchKey, BoldFontSearchKey },
589 { NSAccessibilityButtonSearchKey, ButtonSearchKey },
590 { NSAccessibilityCheckBoxSearchKey, CheckBoxSearchKey },
591 { NSAccessibilityControlSearchKey, ControlSearchKey },
592 { NSAccessibilityDifferentTypeSearchKey, DifferentTypeSearchKey },
593 { NSAccessibilityFontChangeSearchKey, FontChangeSearchKey },
594 { NSAccessibilityFontColorChangeSearchKey, FontColorChangeSearchKey },
595 { NSAccessibilityFrameSearchKey, FrameSearchKey },
596 { NSAccessibilityGraphicSearchKey, GraphicSearchKey },
597 { NSAccessibilityHeadingLevel1SearchKey, HeadingLevel1SearchKey },
598 { NSAccessibilityHeadingLevel2SearchKey, HeadingLevel2SearchKey },
599 { NSAccessibilityHeadingLevel3SearchKey, HeadingLevel3SearchKey },
600 { NSAccessibilityHeadingLevel4SearchKey, HeadingLevel4SearchKey },
601 { NSAccessibilityHeadingLevel5SearchKey, HeadingLevel5SearchKey },
602 { NSAccessibilityHeadingLevel6SearchKey, HeadingLevel6SearchKey },
603 { NSAccessibilityHeadingSameLevelSearchKey, HeadingSameLevelSearchKey },
604 { NSAccessibilityHeadingSearchKey, HeadingSearchKey },
605 { NSAccessibilityHighlightedSearchKey, HighlightedSearchKey },
606 { NSAccessibilityItalicFontSearchKey, ItalicFontSearchKey },
607 { NSAccessibilityLandmarkSearchKey, LandmarkSearchKey },
608 { NSAccessibilityLinkSearchKey, LinkSearchKey },
609 { NSAccessibilityListSearchKey, ListSearchKey },
610 { NSAccessibilityLiveRegionSearchKey, LiveRegionSearchKey },
611 { NSAccessibilityMisspelledWordSearchKey, MisspelledWordSearchKey },
612 { NSAccessibilityOutlineSearchKey, OutlineSearchKey },
613 { NSAccessibilityPlainTextSearchKey, PlainTextSearchKey },
614 { NSAccessibilityRadioGroupSearchKey, RadioGroupSearchKey },
615 { NSAccessibilitySameTypeSearchKey, SameTypeSearchKey },
616 { NSAccessibilityStaticTextSearchKey, StaticTextSearchKey },
617 { NSAccessibilityStyleChangeSearchKey, StyleChangeSearchKey },
618 { NSAccessibilityTableSameLevelSearchKey, TableSameLevelSearchKey },
619 { NSAccessibilityTableSearchKey, TableSearchKey },
620 { NSAccessibilityTextFieldSearchKey, TextFieldSearchKey },
621 { NSAccessibilityUnderlineSearchKey, UnderlineSearchKey },
622 { NSAccessibilityUnvisitedLinkSearchKey, UnvisitedLinkSearchKey },
623 { NSAccessibilityVisitedLinkSearchKey, VisitedLinkSearchKey }
626 AccessibilitySearchKeyMap* searchKeyMap = new AccessibilitySearchKeyMap;
627 for (size_t i = 0; i < WTF_ARRAY_LENGTH(searchKeys); i++)
628 searchKeyMap->set(searchKeys[i].key, searchKeys[i].value);
633 static AccessibilitySearchKey accessibilitySearchKeyForString(const String& value)
636 return AnyTypeSearchKey;
638 static const AccessibilitySearchKeyMap* searchKeyMap = createAccessibilitySearchKeyMap();
640 AccessibilitySearchKey searchKey = searchKeyMap->get(value);
642 return searchKey ? searchKey : AnyTypeSearchKey;
645 static AccessibilitySearchCriteria accessibilitySearchCriteriaForSearchPredicateParameterizedAttribute(const NSDictionary *parameterizedAttribute)
647 NSString *directionParameter = [parameterizedAttribute objectForKey:@"AXDirection"];
648 NSNumber *immediateDescendantsOnlyParameter = [parameterizedAttribute objectForKey:NSAccessibilityImmediateDescendantsOnly];
649 NSNumber *resultsLimitParameter = [parameterizedAttribute objectForKey:@"AXResultsLimit"];
650 NSString *searchTextParameter = [parameterizedAttribute objectForKey:@"AXSearchText"];
651 WebAccessibilityObjectWrapper *startElementParameter = [parameterizedAttribute objectForKey:@"AXStartElement"];
652 NSNumber *visibleOnlyParameter = [parameterizedAttribute objectForKey:@"AXVisibleOnly"];
653 id searchKeyParameter = [parameterizedAttribute objectForKey:@"AXSearchKey"];
655 AccessibilitySearchDirection direction = SearchDirectionNext;
656 if ([directionParameter isKindOfClass:[NSString class]])
657 direction = [directionParameter isEqualToString:@"AXDirectionNext"] ? SearchDirectionNext : SearchDirectionPrevious;
659 bool immediateDescendantsOnly = false;
660 if ([immediateDescendantsOnlyParameter isKindOfClass:[NSNumber class]])
661 immediateDescendantsOnly = [immediateDescendantsOnlyParameter boolValue];
663 unsigned resultsLimit = 0;
664 if ([resultsLimitParameter isKindOfClass:[NSNumber class]])
665 resultsLimit = [resultsLimitParameter unsignedIntValue];
668 if ([searchTextParameter isKindOfClass:[NSString class]])
669 searchText = searchTextParameter;
671 AccessibilityObject *startElement = nullptr;
672 if ([startElementParameter isKindOfClass:[WebAccessibilityObjectWrapper class]])
673 startElement = [startElementParameter accessibilityObject];
675 bool visibleOnly = false;
676 if ([visibleOnlyParameter isKindOfClass:[NSNumber class]])
677 visibleOnly = [visibleOnlyParameter boolValue];
679 AccessibilitySearchCriteria criteria = AccessibilitySearchCriteria(startElement, direction, searchText, resultsLimit, visibleOnly, immediateDescendantsOnly);
681 if ([searchKeyParameter isKindOfClass:[NSString class]])
682 criteria.searchKeys.append(accessibilitySearchKeyForString(searchKeyParameter));
683 else if ([searchKeyParameter isKindOfClass:[NSArray class]]) {
684 size_t searchKeyCount = static_cast<size_t>([searchKeyParameter count]);
685 criteria.searchKeys.reserveInitialCapacity(searchKeyCount);
686 for (size_t i = 0; i < searchKeyCount; ++i) {
687 NSString *searchKey = [searchKeyParameter objectAtIndex:i];
688 if ([searchKey isKindOfClass:[NSString class]])
689 criteria.searchKeys.uncheckedAppend(accessibilitySearchKeyForString(searchKey));
696 #pragma mark Select text helpers
698 static AccessibilitySelectTextCriteria accessibilitySelectTextCriteriaForCriteriaParameterizedAttribute(const NSDictionary *parameterizedAttribute)
700 NSString *activityParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextActivity];
701 NSString *ambiguityResolutionParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextAmbiguityResolution];
702 NSString *replacementStringParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextReplacementString];
703 NSArray *searchStringsParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextSearchStrings];
705 AccessibilitySelectTextActivity activity = FindAndSelectActivity;
706 if ([activityParameter isKindOfClass:[NSString class]]) {
707 if ([activityParameter isEqualToString:NSAccessibilitySelectTextActivityFindAndReplace])
708 activity = FindAndReplaceActivity;
709 else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndCapitalize])
710 activity = FindAndCapitalize;
711 else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndLowercase])
712 activity = FindAndLowercase;
713 else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndUppercase])
714 activity = FindAndUppercase;
717 AccessibilitySelectTextAmbiguityResolution ambiguityResolution = ClosestToSelectionAmbiguityResolution;
718 if ([ambiguityResolutionParameter isKindOfClass:[NSString class]]) {
719 if ([ambiguityResolutionParameter isEqualToString:NSAccessibilitySelectTextAmbiguityResolutionClosestAfterSelection])
720 ambiguityResolution = ClosestAfterSelectionAmbiguityResolution;
721 else if ([ambiguityResolutionParameter isEqualToString:NSAccessibilitySelectTextAmbiguityResolutionClosestBeforeSelection])
722 ambiguityResolution = ClosestBeforeSelectionAmbiguityResolution;
725 String replacementString;
726 if ([replacementStringParameter isKindOfClass:[NSString class]])
727 replacementString = replacementStringParameter;
729 AccessibilitySelectTextCriteria criteria(activity, ambiguityResolution, replacementString);
731 if ([searchStringsParameter isKindOfClass:[NSArray class]]) {
732 size_t searchStringsCount = static_cast<size_t>([searchStringsParameter count]);
733 criteria.searchStrings.reserveInitialCapacity(searchStringsCount);
734 for (NSString *searchString in searchStringsParameter) {
735 if ([searchString isKindOfClass:[NSString class]])
736 criteria.searchStrings.uncheckedAppend(searchString);
743 #pragma mark Text Marker helpers
745 static id textMarkerForVisiblePosition(AXObjectCache* cache, const VisiblePosition& visiblePos)
749 TextMarkerData textMarkerData;
750 cache->textMarkerDataForVisiblePosition(textMarkerData, visiblePos);
751 if (!textMarkerData.axID)
754 return CFBridgingRelease(wkCreateAXTextMarker(&textMarkerData, sizeof(textMarkerData)));
757 - (id)textMarkerForVisiblePosition:(const VisiblePosition &)visiblePos
759 return textMarkerForVisiblePosition(m_object->axObjectCache(), visiblePos);
762 static VisiblePosition visiblePositionForTextMarker(AXObjectCache* cache, CFTypeRef textMarker)
767 return VisiblePosition();
768 TextMarkerData textMarkerData;
769 if (!wkGetBytesFromAXTextMarker(textMarker, &textMarkerData, sizeof(textMarkerData)))
770 return VisiblePosition();
772 return cache->visiblePositionForTextMarkerData(textMarkerData);
775 - (VisiblePosition)visiblePositionForTextMarker:(id)textMarker
777 return visiblePositionForTextMarker(m_object->axObjectCache(), textMarker);
780 static VisiblePosition visiblePositionForStartOfTextMarkerRange(AXObjectCache *cache, id textMarkerRange)
782 return visiblePositionForTextMarker(cache, AXTextMarkerRangeStart(textMarkerRange));
785 static VisiblePosition visiblePositionForEndOfTextMarkerRange(AXObjectCache *cache, id textMarkerRange)
787 return visiblePositionForTextMarker(cache, AXTextMarkerRangeEnd(textMarkerRange));
790 static id textMarkerRangeFromMarkers(id textMarker1, id textMarker2)
792 if (!textMarker1 || !textMarker2)
795 return AXTextMarkerRange(textMarker1, textMarker2);
798 // When modifying attributed strings, the range can come from a source which may provide faulty information (e.g. the spell checker).
799 // To protect against such cases the range should be validated before adding or removing attributes.
800 static BOOL AXAttributedStringRangeIsValid(NSAttributedString* attrString, NSRange range)
802 return (range.location < [attrString length] && NSMaxRange(range) <= [attrString length]);
805 static void AXAttributeStringSetFont(NSMutableAttributedString* attrString, NSString* attribute, NSFont* font, NSRange range)
807 if (!AXAttributedStringRangeIsValid(attrString, range))
811 NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
812 [font fontName] , NSAccessibilityFontNameKey,
813 [font familyName] , NSAccessibilityFontFamilyKey,
814 [font displayName] , NSAccessibilityVisibleNameKey,
815 [NSNumber numberWithFloat:[font pointSize]] , NSAccessibilityFontSizeKey,
818 [attrString addAttribute:attribute value:dict range:range];
820 [attrString removeAttribute:attribute range:range];
824 static CGColorRef CreateCGColorIfDifferent(NSColor* nsColor, CGColorRef existingColor)
826 // get color information assuming NSDeviceRGBColorSpace
827 NSColor* rgbColor = [nsColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
829 rgbColor = [NSColor blackColor];
830 CGFloat components[4];
831 [rgbColor getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]];
833 // create a new CGColorRef to return
834 CGColorSpaceRef cgColorSpace = CGColorSpaceCreateDeviceRGB();
835 CGColorRef cgColor = CGColorCreate(cgColorSpace, components);
836 CGColorSpaceRelease(cgColorSpace);
838 // check for match with existing color
839 if (existingColor && CGColorEqualToColor(cgColor, existingColor)) {
840 CGColorRelease(cgColor);
847 static void AXAttributeStringSetColor(NSMutableAttributedString* attrString, NSString* attribute, NSColor* color, NSRange range)
849 if (!AXAttributedStringRangeIsValid(attrString, range))
853 CGColorRef existingColor = (CGColorRef) [attrString attribute:attribute atIndex:range.location effectiveRange:nil];
854 CGColorRef cgColor = CreateCGColorIfDifferent(color, existingColor);
856 [attrString addAttribute:attribute value:(id)cgColor range:range];
857 CGColorRelease(cgColor);
860 [attrString removeAttribute:attribute range:range];
863 static void AXAttributeStringSetNumber(NSMutableAttributedString* attrString, NSString* attribute, NSNumber* number, NSRange range)
865 if (!AXAttributedStringRangeIsValid(attrString, range))
869 [attrString addAttribute:attribute value:number range:range];
871 [attrString removeAttribute:attribute range:range];
874 static void AXAttributeStringSetStyle(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
876 const RenderStyle& style = renderer->style();
878 // set basic font info
879 AXAttributeStringSetFont(attrString, NSAccessibilityFontTextAttribute, style.fontCascade().primaryFont().getNSFont(), range);
882 AXAttributeStringSetColor(attrString, NSAccessibilityForegroundColorTextAttribute, nsColor(style.visitedDependentColor(CSSPropertyColor)), range);
883 AXAttributeStringSetColor(attrString, NSAccessibilityBackgroundColorTextAttribute, nsColor(style.visitedDependentColor(CSSPropertyBackgroundColor)), range);
885 // set super/sub scripting
886 EVerticalAlign alignment = style.verticalAlign();
887 if (alignment == SUB)
888 AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:(-1)], range);
889 else if (alignment == SUPER)
890 AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:1], range);
892 [attrString removeAttribute:NSAccessibilitySuperscriptTextAttribute range:range];
895 if (style.textShadow())
896 AXAttributeStringSetNumber(attrString, NSAccessibilityShadowTextAttribute, [NSNumber numberWithBool:YES], range);
898 [attrString removeAttribute:NSAccessibilityShadowTextAttribute range:range];
900 // set underline and strikethrough
901 int decor = style.textDecorationsInEffect();
902 if ((decor & TextDecorationUnderline) == 0) {
903 [attrString removeAttribute:NSAccessibilityUnderlineTextAttribute range:range];
904 [attrString removeAttribute:NSAccessibilityUnderlineColorTextAttribute range:range];
907 if ((decor & TextDecorationLineThrough) == 0) {
908 [attrString removeAttribute:NSAccessibilityStrikethroughTextAttribute range:range];
909 [attrString removeAttribute:NSAccessibilityStrikethroughColorTextAttribute range:range];
912 if ((decor & (TextDecorationUnderline | TextDecorationLineThrough)) != 0) {
913 // FIXME: Should the underline style be reported here?
914 Color underlineColor, overlineColor, linethroughColor;
915 TextDecorationStyle underlineStyle, overlineStyle, linethroughStyle;
916 renderer->getTextDecorationColorsAndStyles(decor, underlineColor, overlineColor, linethroughColor, underlineStyle, overlineStyle, linethroughStyle);
918 if ((decor & TextDecorationUnderline) != 0) {
919 AXAttributeStringSetNumber(attrString, NSAccessibilityUnderlineTextAttribute, [NSNumber numberWithBool:YES], range);
920 AXAttributeStringSetColor(attrString, NSAccessibilityUnderlineColorTextAttribute, nsColor(underlineColor), range);
923 if ((decor & TextDecorationLineThrough) != 0) {
924 AXAttributeStringSetNumber(attrString, NSAccessibilityStrikethroughTextAttribute, [NSNumber numberWithBool:YES], range);
925 AXAttributeStringSetColor(attrString, NSAccessibilityStrikethroughColorTextAttribute, nsColor(linethroughColor), range);
929 // Indicate background highlighting.
930 for (Node* node = renderer->node(); node; node = node->parentNode()) {
931 if (node->hasTagName(markTag))
932 AXAttributeStringSetNumber(attrString, @"AXHighlight", [NSNumber numberWithBool:YES], range);
936 static void AXAttributeStringSetBlockquoteLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
938 if (!AXAttributedStringRangeIsValid(attrString, range))
941 AccessibilityObject* obj = renderer->document().axObjectCache()->getOrCreate(renderer);
942 int quoteLevel = obj->blockquoteLevel();
945 [attrString addAttribute:NSAccessibilityBlockQuoteLevelAttribute value:[NSNumber numberWithInt:quoteLevel] range:range];
947 [attrString removeAttribute:NSAccessibilityBlockQuoteLevelAttribute range:range];
950 static void AXAttributeStringSetSpelling(NSMutableAttributedString* attrString, Node* node, StringView text, NSRange range)
952 if (unifiedTextCheckerEnabled(node->document().frame())) {
953 // Check the spelling directly since document->markersForNode() does not store the misspelled marking when the cursor is in a word.
954 TextCheckerClient* checker = node->document().frame()->editor().textChecker();
956 // checkTextOfParagraph is the only spelling/grammar checker implemented in WK1 and WK2
957 Vector<TextCheckingResult> results;
958 checkTextOfParagraph(*checker, text, TextCheckingTypeSpelling, results);
960 size_t size = results.size();
961 NSNumber* trueValue = [NSNumber numberWithBool:YES];
962 for (unsigned i = 0; i < size; i++) {
963 const TextCheckingResult& result = results[i];
964 AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, trueValue, NSMakeRange(result.location + range.location, result.length));
966 AXAttributeStringSetNumber(attrString, NSAccessibilityMarkedMisspelledTextAttribute, trueValue, NSMakeRange(result.location + range.location, result.length));
972 for (unsigned currentPosition = 0; currentPosition < text.length(); ) {
973 int misspellingLocation = -1;
974 int misspellingLength = 0;
975 node->document().frame()->editor().textChecker()->checkSpellingOfString(text.substring(currentPosition), &misspellingLocation, &misspellingLength);
976 if (misspellingLocation == -1 || !misspellingLength)
979 NSRange spellRange = NSMakeRange(range.location + currentPosition + misspellingLocation, misspellingLength);
980 AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, [NSNumber numberWithBool:YES], spellRange);
982 AXAttributeStringSetNumber(attrString, NSAccessibilityMarkedMisspelledTextAttribute, [NSNumber numberWithBool:YES], spellRange);
985 currentPosition += misspellingLocation + misspellingLength;
989 static void AXAttributeStringSetexpandedTextValue(NSMutableAttributedString *attrString, RenderObject* renderer, NSRange range)
991 if (!renderer || !AXAttributedStringRangeIsValid(attrString, range))
993 AccessibilityObject* axObject = renderer->document().axObjectCache()->getOrCreate(renderer);
994 if (axObject->supportsExpandedTextValue())
995 [attrString addAttribute:NSAccessibilityExpandedTextValueAttribute value:axObject->expandedTextValue() range:range];
997 [attrString removeAttribute:NSAccessibilityExpandedTextValueAttribute range:range];
1000 static void AXAttributeStringSetHeadingLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
1005 if (!AXAttributedStringRangeIsValid(attrString, range))
1008 // Sometimes there are objects between the text and the heading.
1009 // In those cases the parent hierarchy should be queried to see if there is a heading level.
1010 int parentHeadingLevel = 0;
1011 AccessibilityObject* parentObject = renderer->document().axObjectCache()->getOrCreate(renderer->parent());
1012 for (; parentObject; parentObject = parentObject->parentObject()) {
1013 parentHeadingLevel = parentObject->headingLevel();
1014 if (parentHeadingLevel)
1018 if (parentHeadingLevel)
1019 [attrString addAttribute:@"AXHeadingLevel" value:[NSNumber numberWithInt:parentHeadingLevel] range:range];
1021 [attrString removeAttribute:@"AXHeadingLevel" range:range];
1024 static void AXAttributeStringSetElement(NSMutableAttributedString* attrString, NSString* attribute, AccessibilityObject* object, NSRange range)
1026 if (!AXAttributedStringRangeIsValid(attrString, range))
1029 if (is<AccessibilityRenderObject>(object)) {
1030 // make a serializable AX object
1032 RenderObject* renderer = downcast<AccessibilityRenderObject>(*object).renderer();
1036 AXObjectCache* cache = renderer->document().axObjectCache();
1040 AXUIElementRef axElement = wkCreateAXUIElementRef(object->wrapper());
1042 [attrString addAttribute:attribute value:(id)axElement range:range];
1043 CFRelease(axElement);
1046 [attrString removeAttribute:attribute range:range];
1049 static void AXAttributedStringAppendText(NSMutableAttributedString* attrString, Node* node, StringView text)
1051 // skip invisible text
1052 RenderObject* renderer = node->renderer();
1056 // easier to calculate the range before appending the string
1057 NSRange attrStringRange = NSMakeRange([attrString length], text.length());
1059 // append the string from this node
1060 [[attrString mutableString] appendString:text.createNSStringWithoutCopying().get()];
1062 // add new attributes and remove irrelevant inherited ones
1063 // NOTE: color attributes are handled specially because -[NSMutableAttributedString addAttribute: value: range:] does not merge
1064 // identical colors. Workaround is to not replace an existing color attribute if it matches what we are adding. This also means
1065 // we cannot just pre-remove all inherited attributes on the appended string, so we have to remove the irrelevant ones individually.
1067 // remove inherited attachment from prior AXAttributedStringAppendReplaced
1068 [attrString removeAttribute:NSAccessibilityAttachmentTextAttribute range:attrStringRange];
1070 [attrString removeAttribute:NSAccessibilityMarkedMisspelledTextAttribute range:attrStringRange];
1072 [attrString removeAttribute:NSAccessibilityMisspelledTextAttribute range:attrStringRange];
1074 // set new attributes
1075 AXAttributeStringSetStyle(attrString, renderer, attrStringRange);
1076 AXAttributeStringSetHeadingLevel(attrString, renderer, attrStringRange);
1077 AXAttributeStringSetBlockquoteLevel(attrString, renderer, attrStringRange);
1078 AXAttributeStringSetexpandedTextValue(attrString, renderer, attrStringRange);
1079 AXAttributeStringSetElement(attrString, NSAccessibilityLinkTextAttribute, AccessibilityObject::anchorElementForNode(node), attrStringRange);
1081 // do spelling last because it tends to break up the range
1082 AXAttributeStringSetSpelling(attrString, node, text, attrStringRange);
1085 static NSString* nsStringForReplacedNode(Node* replacedNode)
1087 // we should always be given a rendered node and a replaced node, but be safe
1088 // replaced nodes are either attachments (widgets) or images
1089 if (!replacedNode || !isRendererReplacedElement(replacedNode->renderer()) || replacedNode->isTextNode()) {
1090 ASSERT_NOT_REACHED();
1094 // create an AX object, but skip it if it is not supposed to be seen
1095 RefPtr<AccessibilityObject> obj = replacedNode->renderer()->document().axObjectCache()->getOrCreate(replacedNode->renderer());
1096 if (obj->accessibilityIsIgnored())
1099 // use the attachmentCharacter to represent the replaced node
1100 const UniChar attachmentChar = NSAttachmentCharacter;
1101 return [NSString stringWithCharacters:&attachmentChar length:1];
1104 - (NSAttributedString*)doAXAttributedStringForTextMarkerRange:(id)textMarkerRange
1109 // extract the start and end VisiblePosition
1110 VisiblePosition startVisiblePosition = visiblePositionForStartOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);
1111 if (startVisiblePosition.isNull())
1114 VisiblePosition endVisiblePosition = visiblePositionForEndOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);
1115 if (endVisiblePosition.isNull())
1118 VisiblePositionRange visiblePositionRange(startVisiblePosition, endVisiblePosition);
1119 // iterate over the range to build the AX attributed string
1120 NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] init];
1121 TextIterator it(makeRange(startVisiblePosition, endVisiblePosition).get());
1122 while (!it.atEnd()) {
1123 // locate the node and starting offset for this range
1125 Node* node = it.range()->startContainer(exception);
1126 ASSERT(node == it.range()->endContainer(exception));
1127 int offset = it.range()->startOffset(exception);
1129 // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX)
1130 if (it.text().length()) {
1131 // Add the text of the list marker item if necessary.
1132 String listMarkerText = m_object->listMarkerTextForNodeAndPosition(node, VisiblePosition(it.range()->startPosition()));
1133 if (!listMarkerText.isEmpty())
1134 AXAttributedStringAppendText(attrString, node, listMarkerText);
1135 AXAttributedStringAppendText(attrString, node, it.text());
1137 Node* replacedNode = node->traverseToChildAt(offset);
1138 NSString *attachmentString = nsStringForReplacedNode(replacedNode);
1139 if (attachmentString) {
1140 NSRange attrStringRange = NSMakeRange([attrString length], [attachmentString length]);
1142 // append the placeholder string
1143 [[attrString mutableString] appendString:attachmentString];
1145 // remove all inherited attributes
1146 [attrString setAttributes:nil range:attrStringRange];
1148 // add the attachment attribute
1149 AccessibilityObject* obj = replacedNode->renderer()->document().axObjectCache()->getOrCreate(replacedNode->renderer());
1150 AXAttributeStringSetElement(attrString, NSAccessibilityAttachmentTextAttribute, obj, attrStringRange);
1156 return [attrString autorelease];
1159 static id textMarkerRangeFromVisiblePositions(AXObjectCache *cache, const VisiblePosition& startPosition, const VisiblePosition& endPosition)
1161 id startTextMarker = textMarkerForVisiblePosition(cache, startPosition);
1162 id endTextMarker = textMarkerForVisiblePosition(cache, endPosition);
1163 return textMarkerRangeFromMarkers(startTextMarker, endTextMarker);
1166 - (id)textMarkerRangeFromVisiblePositions:(const VisiblePosition&)startPosition endPosition:(const VisiblePosition&)endPosition
1168 return textMarkerRangeFromVisiblePositions(m_object->axObjectCache(), startPosition, endPosition);
1171 - (NSArray*)accessibilityActionNames
1173 if (![self updateObjectBackingStore])
1176 // All elements should get ShowMenu and ScrollToVisible.
1177 // But certain earlier VoiceOver versions do not support scroll to visible, and it confuses them to see it in the list.
1178 static NSArray *defaultElementActions = [[NSArray alloc] initWithObjects:NSAccessibilityShowMenuAction, NSAccessibilityScrollToVisibleAction, nil];
1180 // Action elements allow Press.
1181 // The order is important to VoiceOver, which expects the 'default' action to be the first action. In this case the default action should be press.
1182 static NSArray *actionElementActions = [[NSArray alloc] initWithObjects:NSAccessibilityPressAction, NSAccessibilityShowMenuAction, NSAccessibilityScrollToVisibleAction, nil];
1184 // Menu elements allow Press and Cancel.
1185 static NSArray *menuElementActions = [[actionElementActions arrayByAddingObject:NSAccessibilityCancelAction] retain];
1187 // Slider elements allow Increment/Decrement.
1188 static NSArray *sliderActions = [[defaultElementActions arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:NSAccessibilityIncrementAction, NSAccessibilityDecrementAction, nil]] retain];
1191 if (m_object->supportsPressAction())
1192 actions = actionElementActions;
1193 else if (m_object->isMenuRelated())
1194 actions = menuElementActions;
1195 else if (m_object->isSlider())
1196 actions = sliderActions;
1197 else if (m_object->isAttachment())
1198 actions = [[self attachmentView] accessibilityActionNames];
1200 actions = defaultElementActions;
1205 - (NSArray*)additionalAccessibilityAttributeNames
1210 NSMutableArray *additional = [NSMutableArray array];
1211 if (m_object->supportsARIAOwns())
1212 [additional addObject:NSAccessibilityOwnsAttribute];
1214 if (m_object->isToggleButton())
1215 [additional addObject:NSAccessibilityValueAttribute];
1217 if (m_object->supportsExpanded())
1218 [additional addObject:NSAccessibilityExpandedAttribute];
1220 if (m_object->isScrollbar())
1221 [additional addObject:NSAccessibilityOrientationAttribute];
1223 if (m_object->supportsARIADragging())
1224 [additional addObject:NSAccessibilityGrabbedAttribute];
1226 if (m_object->supportsARIADropping())
1227 [additional addObject:NSAccessibilityDropEffectsAttribute];
1229 if (is<AccessibilityTable>(*m_object) && downcast<AccessibilityTable>(*m_object).isExposableThroughAccessibility() && downcast<AccessibilityTable>(*m_object).supportsSelectedRows())
1230 [additional addObject:NSAccessibilitySelectedRowsAttribute];
1232 if (m_object->supportsARIALiveRegion()) {
1233 [additional addObject:NSAccessibilityARIALiveAttribute];
1234 [additional addObject:NSAccessibilityARIARelevantAttribute];
1237 if (m_object->supportsARIASetSize())
1238 [additional addObject:NSAccessibilityARIASetSizeAttribute];
1239 if (m_object->supportsARIAPosInSet())
1240 [additional addObject:NSAccessibilityARIAPosInSetAttribute];
1242 if (m_object->sortDirection() != SortDirectionNone)
1243 [additional addObject:NSAccessibilitySortDirectionAttribute];
1245 // If an object is a child of a live region, then add these
1246 if (m_object->isInsideARIALiveRegion())
1247 [additional addObject:NSAccessibilityARIAAtomicAttribute];
1248 // All objects should expose the ARIA busy attribute (ARIA 1.1 with ISSUE-538).
1249 [additional addObject:NSAccessibilityElementBusyAttribute];
1251 // Popup buttons on the Mac expose the value attribute.
1252 if (m_object->isPopUpButton()) {
1253 [additional addObject:NSAccessibilityValueAttribute];
1256 if (m_object->supportsRequiredAttribute()) {
1257 [additional addObject:NSAccessibilityRequiredAttribute];
1260 if (m_object->ariaHasPopup())
1261 [additional addObject:NSAccessibilityHasPopupAttribute];
1263 if (m_object->isMathRoot()) {
1264 // The index of a square root is always known, so there's no object associated with it.
1265 if (!m_object->isMathSquareRoot())
1266 [additional addObject:NSAccessibilityMathRootIndexAttribute];
1267 [additional addObject:NSAccessibilityMathRootRadicandAttribute];
1268 } else if (m_object->isMathFraction()) {
1269 [additional addObject:NSAccessibilityMathFractionNumeratorAttribute];
1270 [additional addObject:NSAccessibilityMathFractionDenominatorAttribute];
1271 [additional addObject:NSAccessibilityMathLineThicknessAttribute];
1272 } else if (m_object->isMathSubscriptSuperscript()) {
1273 [additional addObject:NSAccessibilityMathBaseAttribute];
1274 [additional addObject:NSAccessibilityMathSubscriptAttribute];
1275 [additional addObject:NSAccessibilityMathSuperscriptAttribute];
1276 } else if (m_object->isMathUnderOver()) {
1277 [additional addObject:NSAccessibilityMathBaseAttribute];
1278 [additional addObject:NSAccessibilityMathUnderAttribute];
1279 [additional addObject:NSAccessibilityMathOverAttribute];
1280 } else if (m_object->isMathFenced()) {
1281 [additional addObject:NSAccessibilityMathFencedOpenAttribute];
1282 [additional addObject:NSAccessibilityMathFencedCloseAttribute];
1283 } else if (m_object->isMathMultiscript()) {
1284 [additional addObject:NSAccessibilityMathBaseAttribute];
1285 [additional addObject:NSAccessibilityMathPrescriptsAttribute];
1286 [additional addObject:NSAccessibilityMathPostscriptsAttribute];
1289 if (m_object->supportsPath())
1290 [additional addObject:NSAccessibilityPathAttribute];
1292 if (m_object->supportsExpandedTextValue())
1293 [additional addObject:NSAccessibilityExpandedTextValueAttribute];
1298 - (NSArray*)accessibilityAttributeNames
1300 if (![self updateObjectBackingStore])
1303 if (m_object->isAttachment())
1304 return [[self attachmentView] accessibilityAttributeNames];
1306 static NSArray* attributes = nil;
1307 static NSArray* anchorAttrs = nil;
1308 static NSArray* webAreaAttrs = nil;
1309 static NSArray* textAttrs = nil;
1310 static NSArray* listAttrs = nil;
1311 static NSArray* listBoxAttrs = nil;
1312 static NSArray* rangeAttrs = nil;
1313 static NSArray* commonMenuAttrs = nil;
1314 static NSArray* menuAttrs = nil;
1315 static NSArray* menuBarAttrs = nil;
1316 static NSArray* menuItemAttrs = nil;
1317 static NSArray* menuButtonAttrs = nil;
1318 static NSArray* controlAttrs = nil;
1319 static NSArray* tableAttrs = nil;
1320 static NSArray* tableRowAttrs = nil;
1321 static NSArray* tableColAttrs = nil;
1322 static NSArray* tableCellAttrs = nil;
1323 static NSArray* groupAttrs = nil;
1324 static NSArray* inputImageAttrs = nil;
1325 static NSArray* passwordFieldAttrs = nil;
1326 static NSArray* tabListAttrs = nil;
1327 static NSArray* comboBoxAttrs = nil;
1328 static NSArray* outlineAttrs = nil;
1329 static NSArray* outlineRowAttrs = nil;
1330 static NSArray* buttonAttrs = nil;
1331 static NSArray* scrollViewAttrs = nil;
1332 static NSArray* incrementorAttrs = nil;
1333 NSMutableArray* tempArray;
1334 if (attributes == nil) {
1335 attributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1336 NSAccessibilitySubroleAttribute,
1337 NSAccessibilityRoleDescriptionAttribute,
1338 NSAccessibilityChildrenAttribute,
1339 NSAccessibilityHelpAttribute,
1340 NSAccessibilityParentAttribute,
1341 NSAccessibilityPositionAttribute,
1342 NSAccessibilitySizeAttribute,
1343 NSAccessibilityTitleAttribute,
1344 NSAccessibilityDescriptionAttribute,
1345 NSAccessibilityValueAttribute,
1346 NSAccessibilityFocusedAttribute,
1347 NSAccessibilityEnabledAttribute,
1348 NSAccessibilityWindowAttribute,
1349 @"AXSelectedTextMarkerRange",
1350 @"AXStartTextMarker",
1353 NSAccessibilityLinkedUIElementsAttribute,
1354 NSAccessibilitySelectedAttribute,
1355 NSAccessibilityBlockQuoteLevelAttribute,
1356 NSAccessibilityTopLevelUIElementAttribute,
1357 NSAccessibilityLanguageAttribute,
1358 NSAccessibilityDOMIdentifierAttribute,
1359 NSAccessibilityDOMClassListAttribute,
1362 if (commonMenuAttrs == nil) {
1363 commonMenuAttrs = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1364 NSAccessibilityRoleDescriptionAttribute,
1365 NSAccessibilityChildrenAttribute,
1366 NSAccessibilityParentAttribute,
1367 NSAccessibilityEnabledAttribute,
1368 NSAccessibilityPositionAttribute,
1369 NSAccessibilitySizeAttribute,
1372 if (anchorAttrs == nil) {
1373 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1374 [tempArray addObject:NSAccessibilityURLAttribute];
1375 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1376 anchorAttrs = [[NSArray alloc] initWithArray:tempArray];
1377 [tempArray release];
1379 if (webAreaAttrs == nil) {
1380 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1381 // WebAreas should not expose AXSubrole.
1382 [tempArray removeObject:NSAccessibilitySubroleAttribute];
1383 [tempArray addObject:@"AXLinkUIElements"];
1384 [tempArray addObject:@"AXLoaded"];
1385 [tempArray addObject:@"AXLayoutCount"];
1386 [tempArray addObject:NSAccessibilityLoadingProgressAttribute];
1387 [tempArray addObject:NSAccessibilityURLAttribute];
1388 [tempArray addObject:NSAccessibilityCaretBrowsingEnabledAttribute];
1389 [tempArray addObject:NSAccessibilityPreventKeyboardDOMEventDispatchAttribute];
1390 webAreaAttrs = [[NSArray alloc] initWithArray:tempArray];
1391 [tempArray release];
1393 if (textAttrs == nil) {
1394 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1395 [tempArray addObject:NSAccessibilityNumberOfCharactersAttribute];
1396 [tempArray addObject:NSAccessibilitySelectedTextAttribute];
1397 [tempArray addObject:NSAccessibilitySelectedTextRangeAttribute];
1398 [tempArray addObject:NSAccessibilityVisibleCharacterRangeAttribute];
1399 [tempArray addObject:NSAccessibilityInsertionPointLineNumberAttribute];
1400 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1401 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1402 [tempArray addObject:NSAccessibilityRequiredAttribute];
1403 [tempArray addObject:NSAccessibilityInvalidAttribute];
1404 [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1405 [tempArray addObject:NSAccessibilityValueAutofilledAttribute];
1406 textAttrs = [[NSArray alloc] initWithArray:tempArray];
1407 [tempArray release];
1409 if (listAttrs == nil) {
1410 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1411 [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1412 [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1413 [tempArray addObject:NSAccessibilityOrientationAttribute];
1414 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1415 listAttrs = [[NSArray alloc] initWithArray:tempArray];
1416 [tempArray release];
1418 if (listBoxAttrs == nil) {
1419 tempArray = [[NSMutableArray alloc] initWithArray:listAttrs];
1420 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1421 [tempArray addObject:NSAccessibilityRequiredAttribute];
1422 [tempArray addObject:NSAccessibilityInvalidAttribute];
1423 listBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1424 [tempArray release];
1426 if (rangeAttrs == nil) {
1427 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1428 [tempArray addObject:NSAccessibilityMinValueAttribute];
1429 [tempArray addObject:NSAccessibilityMaxValueAttribute];
1430 [tempArray addObject:NSAccessibilityOrientationAttribute];
1431 [tempArray addObject:NSAccessibilityValueDescriptionAttribute];
1432 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1433 rangeAttrs = [[NSArray alloc] initWithArray:tempArray];
1434 [tempArray release];
1436 if (menuBarAttrs == nil) {
1437 tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1438 [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1439 [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1440 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1441 menuBarAttrs = [[NSArray alloc] initWithArray:tempArray];
1442 [tempArray release];
1444 if (menuAttrs == nil) {
1445 tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1446 [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1447 [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1448 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1449 menuAttrs = [[NSArray alloc] initWithArray:tempArray];
1450 [tempArray release];
1452 if (menuItemAttrs == nil) {
1453 tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1454 [tempArray addObject:NSAccessibilityTitleAttribute];
1455 [tempArray addObject:NSAccessibilityDescriptionAttribute];
1456 [tempArray addObject:NSAccessibilityHelpAttribute];
1457 [tempArray addObject:NSAccessibilitySelectedAttribute];
1458 [tempArray addObject:NSAccessibilityValueAttribute];
1459 [tempArray addObject:(NSString*)kAXMenuItemCmdCharAttribute];
1460 [tempArray addObject:(NSString*)kAXMenuItemCmdVirtualKeyAttribute];
1461 [tempArray addObject:(NSString*)kAXMenuItemCmdGlyphAttribute];
1462 [tempArray addObject:(NSString*)kAXMenuItemCmdModifiersAttribute];
1463 [tempArray addObject:(NSString*)kAXMenuItemMarkCharAttribute];
1464 [tempArray addObject:(NSString*)kAXMenuItemPrimaryUIElementAttribute];
1465 [tempArray addObject:NSAccessibilityServesAsTitleForUIElementsAttribute];
1466 [tempArray addObject:NSAccessibilityFocusedAttribute];
1467 menuItemAttrs = [[NSArray alloc] initWithArray:tempArray];
1468 [tempArray release];
1470 if (menuButtonAttrs == nil) {
1471 menuButtonAttrs = [[NSArray alloc] initWithObjects:NSAccessibilityRoleAttribute,
1472 NSAccessibilityRoleDescriptionAttribute,
1473 NSAccessibilityParentAttribute,
1474 NSAccessibilityPositionAttribute,
1475 NSAccessibilitySizeAttribute,
1476 NSAccessibilityWindowAttribute,
1477 NSAccessibilityEnabledAttribute,
1478 NSAccessibilityFocusedAttribute,
1479 NSAccessibilityTitleAttribute,
1480 NSAccessibilityChildrenAttribute, nil];
1482 if (controlAttrs == nil) {
1483 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1484 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1485 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1486 [tempArray addObject:NSAccessibilityRequiredAttribute];
1487 [tempArray addObject:NSAccessibilityInvalidAttribute];
1488 controlAttrs = [[NSArray alloc] initWithArray:tempArray];
1489 [tempArray release];
1491 if (incrementorAttrs == nil) {
1492 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1493 [tempArray addObject:NSAccessibilityIncrementButtonAttribute];
1494 [tempArray addObject:NSAccessibilityDecrementButtonAttribute];
1495 [tempArray addObject:NSAccessibilityValueDescriptionAttribute];
1496 [tempArray addObject:NSAccessibilityMinValueAttribute];
1497 [tempArray addObject:NSAccessibilityMaxValueAttribute];
1498 incrementorAttrs = [[NSArray alloc] initWithArray:tempArray];
1499 [tempArray release];
1501 if (buttonAttrs == nil) {
1502 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1503 // Buttons should not expose AXValue.
1504 [tempArray removeObject:NSAccessibilityValueAttribute];
1505 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1506 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1507 buttonAttrs = [[NSArray alloc] initWithArray:tempArray];
1508 [tempArray release];
1510 if (comboBoxAttrs == nil) {
1511 tempArray = [[NSMutableArray alloc] initWithArray:controlAttrs];
1512 [tempArray addObject:NSAccessibilityExpandedAttribute];
1513 comboBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1514 [tempArray release];
1516 if (tableAttrs == nil) {
1517 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1518 [tempArray addObject:NSAccessibilityRowsAttribute];
1519 [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1520 [tempArray addObject:NSAccessibilityColumnsAttribute];
1521 [tempArray addObject:NSAccessibilityVisibleColumnsAttribute];
1522 [tempArray addObject:NSAccessibilityVisibleCellsAttribute];
1523 [tempArray addObject:NSAccessibilityColumnHeaderUIElementsAttribute];
1524 [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];
1525 [tempArray addObject:NSAccessibilityHeaderAttribute];
1526 [tempArray addObject:NSAccessibilityColumnCountAttribute];
1527 [tempArray addObject:NSAccessibilityRowCountAttribute];
1528 tableAttrs = [[NSArray alloc] initWithArray:tempArray];
1529 [tempArray release];
1531 if (tableRowAttrs == nil) {
1532 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1533 [tempArray addObject:NSAccessibilityIndexAttribute];
1534 tableRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1535 [tempArray release];
1537 if (tableColAttrs == nil) {
1538 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1539 [tempArray addObject:NSAccessibilityIndexAttribute];
1540 [tempArray addObject:NSAccessibilityHeaderAttribute];
1541 [tempArray addObject:NSAccessibilityRowsAttribute];
1542 [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1543 tableColAttrs = [[NSArray alloc] initWithArray:tempArray];
1544 [tempArray release];
1546 if (tableCellAttrs == nil) {
1547 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1548 [tempArray addObject:NSAccessibilityRowIndexRangeAttribute];
1549 [tempArray addObject:NSAccessibilityColumnIndexRangeAttribute];
1550 [tempArray addObject:NSAccessibilityColumnHeaderUIElementsAttribute];
1551 [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];
1552 tableCellAttrs = [[NSArray alloc] initWithArray:tempArray];
1553 [tempArray release];
1555 if (groupAttrs == nil) {
1556 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1557 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1558 groupAttrs = [[NSArray alloc] initWithArray:tempArray];
1559 [tempArray release];
1561 if (inputImageAttrs == nil) {
1562 tempArray = [[NSMutableArray alloc] initWithArray:buttonAttrs];
1563 [tempArray addObject:NSAccessibilityURLAttribute];
1564 inputImageAttrs = [[NSArray alloc] initWithArray:tempArray];
1565 [tempArray release];
1567 if (passwordFieldAttrs == nil) {
1568 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1569 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1570 [tempArray addObject:NSAccessibilityRequiredAttribute];
1571 [tempArray addObject:NSAccessibilityInvalidAttribute];
1572 [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1573 [tempArray addObject:NSAccessibilityValueAutofilledAttribute];
1574 passwordFieldAttrs = [[NSArray alloc] initWithArray:tempArray];
1575 [tempArray release];
1577 if (tabListAttrs == nil) {
1578 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1579 [tempArray addObject:NSAccessibilityTabsAttribute];
1580 [tempArray addObject:NSAccessibilityContentsAttribute];
1581 tabListAttrs = [[NSArray alloc] initWithArray:tempArray];
1582 [tempArray release];
1584 if (outlineAttrs == nil) {
1585 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1586 [tempArray addObject:NSAccessibilitySelectedRowsAttribute];
1587 [tempArray addObject:NSAccessibilityRowsAttribute];
1588 [tempArray addObject:NSAccessibilityColumnsAttribute];
1589 outlineAttrs = [[NSArray alloc] initWithArray:tempArray];
1590 [tempArray release];
1592 if (outlineRowAttrs == nil) {
1593 tempArray = [[NSMutableArray alloc] initWithArray:tableRowAttrs];
1594 [tempArray addObject:NSAccessibilityDisclosingAttribute];
1595 [tempArray addObject:NSAccessibilityDisclosedByRowAttribute];
1596 [tempArray addObject:NSAccessibilityDisclosureLevelAttribute];
1597 [tempArray addObject:NSAccessibilityDisclosedRowsAttribute];
1598 outlineRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1599 [tempArray release];
1601 if (scrollViewAttrs == nil) {
1602 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1603 [tempArray addObject:NSAccessibilityContentsAttribute];
1604 [tempArray addObject:NSAccessibilityHorizontalScrollBarAttribute];
1605 [tempArray addObject:NSAccessibilityVerticalScrollBarAttribute];
1606 scrollViewAttrs = [[NSArray alloc] initWithArray:tempArray];
1607 [tempArray release];
1610 NSArray *objectAttributes = attributes;
1612 if (m_object->isPasswordField())
1613 objectAttributes = passwordFieldAttrs;
1615 else if (m_object->isWebArea())
1616 objectAttributes = webAreaAttrs;
1618 else if (m_object->isTextControl())
1619 objectAttributes = textAttrs;
1621 else if (m_object->isLink() || m_object->isImage())
1622 objectAttributes = anchorAttrs;
1624 else if (is<AccessibilityTable>(*m_object) && downcast<AccessibilityTable>(*m_object).isExposableThroughAccessibility())
1625 objectAttributes = tableAttrs;
1626 else if (m_object->isTableColumn())
1627 objectAttributes = tableColAttrs;
1628 else if (m_object->isTableCell())
1629 objectAttributes = tableCellAttrs;
1630 else if (m_object->isTableRow()) {
1631 // An ARIA table row can be collapsed and expanded, so it needs the extra attributes.
1632 if (m_object->isARIATreeGridRow())
1633 objectAttributes = outlineRowAttrs;
1635 objectAttributes = tableRowAttrs;
1638 else if (m_object->isTree())
1639 objectAttributes = outlineAttrs;
1640 else if (m_object->isTreeItem())
1641 objectAttributes = outlineRowAttrs;
1643 else if (m_object->isListBox())
1644 objectAttributes = listBoxAttrs;
1645 else if (m_object->isList())
1646 objectAttributes = listAttrs;
1648 else if (m_object->isComboBox())
1649 objectAttributes = comboBoxAttrs;
1651 else if (m_object->isProgressIndicator() || m_object->isSlider())
1652 objectAttributes = rangeAttrs;
1654 // These are processed in order because an input image is a button, and a button is a control.
1655 else if (m_object->isInputImage())
1656 objectAttributes = inputImageAttrs;
1657 else if (m_object->isButton())
1658 objectAttributes = buttonAttrs;
1659 else if (m_object->isControl())
1660 objectAttributes = controlAttrs;
1662 else if (m_object->isGroup() || m_object->isListItem())
1663 objectAttributes = groupAttrs;
1664 else if (m_object->isTabList())
1665 objectAttributes = tabListAttrs;
1666 else if (m_object->isScrollView())
1667 objectAttributes = scrollViewAttrs;
1668 else if (m_object->isSpinButton())
1669 objectAttributes = incrementorAttrs;
1671 else if (m_object->isMenu())
1672 objectAttributes = menuAttrs;
1673 else if (m_object->isMenuBar())
1674 objectAttributes = menuBarAttrs;
1675 else if (m_object->isMenuButton())
1676 objectAttributes = menuButtonAttrs;
1677 else if (m_object->isMenuItem())
1678 objectAttributes = menuItemAttrs;
1680 NSArray *additionalAttributes = [self additionalAccessibilityAttributeNames];
1681 if ([additionalAttributes count])
1682 objectAttributes = [objectAttributes arrayByAddingObjectsFromArray:additionalAttributes];
1684 return objectAttributes;
1687 - (VisiblePositionRange)visiblePositionRangeForTextMarkerRange:(id)textMarkerRange
1689 if (!textMarkerRange)
1690 return VisiblePositionRange();
1691 AXObjectCache* cache = m_object->axObjectCache();
1692 return VisiblePositionRange(visiblePositionForStartOfTextMarkerRange(cache, textMarkerRange), visiblePositionForEndOfTextMarkerRange(cache, textMarkerRange));
1695 - (NSArray*)renderWidgetChildren
1697 Widget* widget = m_object->widget();
1700 #pragma clang diagnostic push
1701 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1702 return [(widget->platformWidget()) accessibilityAttributeValue: NSAccessibilityChildrenAttribute];
1703 #pragma clang diagnostic pop
1706 - (id)remoteAccessibilityParentObject
1711 Document* document = m_object->document();
1715 Frame* frame = document->frame();
1719 return frame->loader().client().accessibilityRemoteObject();
1722 static void convertToVector(NSArray* array, AccessibilityObject::AccessibilityChildrenVector& vector)
1724 unsigned length = [array count];
1725 vector.reserveInitialCapacity(length);
1726 for (unsigned i = 0; i < length; ++i) {
1727 AccessibilityObject* obj = [[array objectAtIndex:i] accessibilityObject];
1733 static NSMutableArray* convertToNSArray(const AccessibilityObject::AccessibilityChildrenVector& vector)
1735 NSMutableArray* array = [NSMutableArray arrayWithCapacity:vector.size()];
1736 for (const auto& child : vector) {
1737 WebAccessibilityObjectWrapper* wrapper = child->wrapper();
1740 // we want to return the attachment view instead of the object representing the attachment.
1741 // otherwise, we get palindrome errors in the AX hierarchy
1742 if (child->isAttachment() && [wrapper attachmentView])
1743 [array addObject:[wrapper attachmentView]];
1745 [array addObject:wrapper];
1751 static NSMutableArray *convertStringsToNSArray(const Vector<String>& vector)
1753 NSMutableArray *array = [NSMutableArray arrayWithCapacity:vector.size()];
1754 for (const auto& string : vector)
1755 [array addObject:string];
1759 - (id)textMarkerRangeForSelection
1761 VisibleSelection selection = m_object->selection();
1762 if (selection.isNone())
1764 return [self textMarkerRangeFromVisiblePositions:selection.visibleStart() endPosition:selection.visibleEnd()];
1767 - (CGPoint)convertPointToScreenSpace:(FloatPoint &)point
1769 FrameView* frameView = m_object->documentFrameView();
1771 // WebKit1 code path... platformWidget() exists.
1772 if (frameView && frameView->platformWidget()) {
1773 NSPoint nsPoint = (NSPoint)point;
1774 NSView* view = frameView->documentView();
1775 #pragma clang diagnostic push
1776 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1777 nsPoint = [[view window] convertBaseToScreen:[view convertPoint:nsPoint toView:nil]];
1778 #pragma clang diagnostic pop
1779 return CGPointMake(nsPoint.x, nsPoint.y);
1782 // Find the appropriate scroll view to use to convert the contents to the window.
1783 ScrollView* scrollView = nullptr;
1784 AccessibilityObject* parent = nullptr;
1785 for (parent = m_object->parentObject(); parent; parent = parent->parentObject()) {
1786 if (is<AccessibilityScrollView>(*parent)) {
1787 scrollView = downcast<AccessibilityScrollView>(*parent).scrollView();
1792 IntPoint intPoint = flooredIntPoint(point);
1794 intPoint = scrollView->contentsToRootView(intPoint);
1796 Page* page = m_object->page();
1798 // If we have an empty chrome client (like SVG) then we should use the page
1799 // of the scroll view parent to help us get to the screen rect.
1800 if (parent && page && page->chrome().client().isEmptyChromeClient())
1801 page = parent->page();
1804 IntRect rect = IntRect(intPoint, IntSize(0, 0));
1805 intPoint = page->chrome().rootViewToScreen(rect).location();
1812 static void WebTransformCGPathToNSBezierPath(void *info, const CGPathElement *element)
1814 NSBezierPath *bezierPath = (NSBezierPath *)info;
1815 switch (element->type) {
1816 case kCGPathElementMoveToPoint:
1817 [bezierPath moveToPoint:NSPointFromCGPoint(element->points[0])];
1819 case kCGPathElementAddLineToPoint:
1820 [bezierPath lineToPoint:NSPointFromCGPoint(element->points[0])];
1822 case kCGPathElementAddCurveToPoint:
1823 [bezierPath curveToPoint:NSPointFromCGPoint(element->points[0]) controlPoint1:NSPointFromCGPoint(element->points[1]) controlPoint2:NSPointFromCGPoint(element->points[2])];
1825 case kCGPathElementCloseSubpath:
1826 [bezierPath closePath];
1833 - (NSBezierPath *)bezierPathFromPath:(CGPathRef)path
1835 NSBezierPath *bezierPath = [NSBezierPath bezierPath];
1836 CGPathApply(path, bezierPath, WebTransformCGPathToNSBezierPath);
1840 - (NSBezierPath *)path
1842 Path path = m_object->elementPath();
1846 CGPathRef transformedPath = [self convertPathToScreenSpace:path];
1847 return [self bezierPathFromPath:transformedPath];
1850 - (NSValue *)position
1852 IntRect rect = snappedIntRect(m_object->elementRect());
1854 // The Cocoa accessibility API wants the lower-left corner.
1855 FloatPoint floatPoint = FloatPoint(rect.x(), rect.maxY());
1857 CGPoint cgPoint = [self convertPointToScreenSpace:floatPoint];
1859 return [NSValue valueWithPoint:NSMakePoint(cgPoint.x, cgPoint.y)];
1862 typedef HashMap<int, NSString*> AccessibilityRoleMap;
1864 static const AccessibilityRoleMap& createAccessibilityRoleMap()
1867 AccessibilityRole value;
1871 static const RoleEntry roles[] = {
1872 { UnknownRole, NSAccessibilityUnknownRole },
1873 { ButtonRole, NSAccessibilityButtonRole },
1874 { RadioButtonRole, NSAccessibilityRadioButtonRole },
1875 { CheckBoxRole, NSAccessibilityCheckBoxRole },
1876 { SliderRole, NSAccessibilitySliderRole },
1877 { TabGroupRole, NSAccessibilityTabGroupRole },
1878 { TextFieldRole, NSAccessibilityTextFieldRole },
1879 { StaticTextRole, NSAccessibilityStaticTextRole },
1880 { TextAreaRole, NSAccessibilityTextAreaRole },
1881 { ScrollAreaRole, NSAccessibilityScrollAreaRole },
1882 { PopUpButtonRole, NSAccessibilityPopUpButtonRole },
1883 { MenuButtonRole, NSAccessibilityMenuButtonRole },
1884 { TableRole, NSAccessibilityTableRole },
1885 { ApplicationRole, NSAccessibilityApplicationRole },
1886 { GroupRole, NSAccessibilityGroupRole },
1887 { RadioGroupRole, NSAccessibilityRadioGroupRole },
1888 { ListRole, NSAccessibilityListRole },
1889 { DirectoryRole, NSAccessibilityListRole },
1890 { ScrollBarRole, NSAccessibilityScrollBarRole },
1891 { ValueIndicatorRole, NSAccessibilityValueIndicatorRole },
1892 { ImageRole, NSAccessibilityImageRole },
1893 { MenuBarRole, NSAccessibilityMenuBarRole },
1894 { MenuRole, NSAccessibilityMenuRole },
1895 { MenuItemRole, NSAccessibilityMenuItemRole },
1896 { MenuItemCheckboxRole, NSAccessibilityMenuItemRole },
1897 { MenuItemRadioRole, NSAccessibilityMenuItemRole },
1898 { ColumnRole, NSAccessibilityColumnRole },
1899 { RowRole, NSAccessibilityRowRole },
1900 { ToolbarRole, NSAccessibilityToolbarRole },
1901 { BusyIndicatorRole, NSAccessibilityBusyIndicatorRole },
1902 { ProgressIndicatorRole, NSAccessibilityProgressIndicatorRole },
1903 { WindowRole, NSAccessibilityWindowRole },
1904 { DrawerRole, NSAccessibilityDrawerRole },
1905 { SystemWideRole, NSAccessibilitySystemWideRole },
1906 { OutlineRole, NSAccessibilityOutlineRole },
1907 { IncrementorRole, NSAccessibilityIncrementorRole },
1908 { BrowserRole, NSAccessibilityBrowserRole },
1909 { ComboBoxRole, NSAccessibilityComboBoxRole },
1910 { SplitGroupRole, NSAccessibilitySplitGroupRole },
1911 { SplitterRole, NSAccessibilitySplitterRole },
1912 { ColorWellRole, NSAccessibilityColorWellRole },
1913 { GrowAreaRole, NSAccessibilityGrowAreaRole },
1914 { SheetRole, NSAccessibilitySheetRole },
1915 { HelpTagRole, NSAccessibilityHelpTagRole },
1916 { MatteRole, NSAccessibilityMatteRole },
1917 { RulerRole, NSAccessibilityRulerRole },
1918 { RulerMarkerRole, NSAccessibilityRulerMarkerRole },
1919 { LinkRole, NSAccessibilityLinkRole },
1920 { DisclosureTriangleRole, NSAccessibilityDisclosureTriangleRole },
1921 { GridRole, NSAccessibilityGridRole },
1922 { WebCoreLinkRole, NSAccessibilityLinkRole },
1923 { ImageMapLinkRole, NSAccessibilityLinkRole },
1924 { ImageMapRole, @"AXImageMap" },
1925 { ListMarkerRole, @"AXListMarker" },
1926 { WebAreaRole, @"AXWebArea" },
1927 { HeadingRole, @"AXHeading" },
1928 { ListBoxRole, NSAccessibilityListRole },
1929 { ListBoxOptionRole, NSAccessibilityStaticTextRole },
1930 { CellRole, NSAccessibilityCellRole },
1931 { TableHeaderContainerRole, NSAccessibilityGroupRole },
1932 { ColumnHeaderRole, NSAccessibilityCellRole },
1933 { RowHeaderRole, NSAccessibilityCellRole },
1934 { DefinitionRole, NSAccessibilityGroupRole },
1935 { DescriptionListDetailRole, NSAccessibilityGroupRole },
1936 { DescriptionListTermRole, NSAccessibilityGroupRole },
1937 { DescriptionListRole, NSAccessibilityListRole },
1938 { SliderThumbRole, NSAccessibilityValueIndicatorRole },
1939 { LandmarkApplicationRole, NSAccessibilityGroupRole },
1940 { LandmarkBannerRole, NSAccessibilityGroupRole },
1941 { LandmarkComplementaryRole, NSAccessibilityGroupRole },
1942 { LandmarkContentInfoRole, NSAccessibilityGroupRole },
1943 { LandmarkMainRole, NSAccessibilityGroupRole },
1944 { LandmarkNavigationRole, NSAccessibilityGroupRole },
1945 { LandmarkSearchRole, NSAccessibilityGroupRole },
1946 { ApplicationAlertRole, NSAccessibilityGroupRole },
1947 { ApplicationAlertDialogRole, NSAccessibilityGroupRole },
1948 { ApplicationDialogRole, NSAccessibilityGroupRole },
1949 { ApplicationLogRole, NSAccessibilityGroupRole },
1950 { ApplicationMarqueeRole, NSAccessibilityGroupRole },
1951 { ApplicationStatusRole, NSAccessibilityGroupRole },
1952 { ApplicationTimerRole, NSAccessibilityGroupRole },
1953 { DocumentRole, NSAccessibilityGroupRole },
1954 { DocumentArticleRole, NSAccessibilityGroupRole },
1955 { DocumentMathRole, NSAccessibilityGroupRole },
1956 { DocumentNoteRole, NSAccessibilityGroupRole },
1957 { DocumentRegionRole, NSAccessibilityGroupRole },
1958 { UserInterfaceTooltipRole, NSAccessibilityGroupRole },
1959 { TabRole, NSAccessibilityRadioButtonRole },
1960 { TabListRole, NSAccessibilityTabGroupRole },
1961 { TabPanelRole, NSAccessibilityGroupRole },
1962 { TreeRole, NSAccessibilityOutlineRole },
1963 { TreeItemRole, NSAccessibilityRowRole },
1964 { ListItemRole, NSAccessibilityGroupRole },
1965 { ParagraphRole, NSAccessibilityGroupRole },
1966 { LabelRole, NSAccessibilityGroupRole },
1967 { DivRole, NSAccessibilityGroupRole },
1968 { FormRole, NSAccessibilityGroupRole },
1969 { SpinButtonRole, NSAccessibilityIncrementorRole },
1970 { FooterRole, NSAccessibilityGroupRole },
1971 { ToggleButtonRole, NSAccessibilityCheckBoxRole },
1972 { CanvasRole, NSAccessibilityImageRole },
1973 { SVGRootRole, NSAccessibilityGroupRole },
1974 { LegendRole, NSAccessibilityGroupRole },
1975 { MathElementRole, NSAccessibilityGroupRole },
1976 { AudioRole, NSAccessibilityGroupRole },
1977 { VideoRole, NSAccessibilityGroupRole },
1978 { HorizontalRuleRole, NSAccessibilitySplitterRole },
1979 { BlockquoteRole, NSAccessibilityGroupRole },
1980 { SwitchRole, NSAccessibilityCheckBoxRole },
1981 { SearchFieldRole, NSAccessibilityTextFieldRole },
1982 { PreRole, NSAccessibilityGroupRole },
1983 { RubyBaseRole, NSAccessibilityGroupRole },
1984 { RubyBlockRole, NSAccessibilityGroupRole },
1985 { RubyInlineRole, NSAccessibilityGroupRole },
1986 { RubyRunRole, NSAccessibilityGroupRole },
1987 { RubyTextRole, NSAccessibilityGroupRole },
1988 { DetailsRole, NSAccessibilityGroupRole },
1989 { SummaryRole, NSAccessibilityGroupRole },
1991 AccessibilityRoleMap& roleMap = *new AccessibilityRoleMap;
1993 const unsigned numRoles = sizeof(roles) / sizeof(roles[0]);
1994 for (unsigned i = 0; i < numRoles; ++i)
1995 roleMap.set(roles[i].value, roles[i].string);
1999 static NSString* roleValueToNSString(AccessibilityRole value)
2002 static const AccessibilityRoleMap& roleMap = createAccessibilityRoleMap();
2003 return roleMap.get(value);
2008 #pragma clang diagnostic push
2009 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2010 if (m_object->isAttachment())
2011 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleAttribute];
2012 #pragma clang diagnostic pop
2013 AccessibilityRole role = m_object->roleValue();
2014 if (role == CanvasRole && m_object->canvasHasFallbackContent())
2016 NSString* string = roleValueToNSString(role);
2019 return NSAccessibilityUnknownRole;
2022 #pragma clang diagnostic push
2023 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2024 - (NSString*)subrole
2026 if (m_object->isPasswordField())
2027 return NSAccessibilitySecureTextFieldSubrole;
2028 if (m_object->isSearchField())
2029 return NSAccessibilitySearchFieldSubrole;
2031 if (m_object->isAttachment()) {
2032 NSView* attachView = [self attachmentView];
2033 if ([[attachView accessibilityAttributeNames] containsObject:NSAccessibilitySubroleAttribute])
2034 return [attachView accessibilityAttributeValue:NSAccessibilitySubroleAttribute];
2037 AccessibilityRole role = m_object->roleValue();
2038 if (role == HorizontalRuleRole)
2039 return NSAccessibilityContentSeparatorSubrole;
2040 if (role == ToggleButtonRole)
2041 return NSAccessibilityToggleSubrole;
2043 if (is<AccessibilitySpinButtonPart>(*m_object)) {
2044 if (downcast<AccessibilitySpinButtonPart>(*m_object).isIncrementor())
2045 return NSAccessibilityIncrementArrowSubrole;
2047 return NSAccessibilityDecrementArrowSubrole;
2050 if (m_object->isFileUploadButton())
2051 return @"AXFileUploadButton";
2053 if (m_object->isTreeItem())
2054 return NSAccessibilityOutlineRowSubrole;
2056 if (m_object->isFieldset())
2057 return @"AXFieldset";
2059 if (is<AccessibilityList>(*m_object)) {
2060 auto& listObject = downcast<AccessibilityList>(*m_object);
2061 if (listObject.isUnorderedList() || listObject.isOrderedList())
2062 return NSAccessibilityContentListSubrole;
2063 if (listObject.isDescriptionList()) {
2064 return NSAccessibilityDescriptionListSubrole;
2068 // ARIA content subroles.
2070 case LandmarkApplicationRole:
2071 return @"AXLandmarkApplication";
2072 case LandmarkBannerRole:
2073 return @"AXLandmarkBanner";
2074 case LandmarkComplementaryRole:
2075 return @"AXLandmarkComplementary";
2076 // Footer roles should appear as content info types.
2078 case LandmarkContentInfoRole:
2079 return @"AXLandmarkContentInfo";
2080 case LandmarkMainRole:
2081 return @"AXLandmarkMain";
2082 case LandmarkNavigationRole:
2083 return @"AXLandmarkNavigation";
2084 case LandmarkSearchRole:
2085 return @"AXLandmarkSearch";
2086 case ApplicationAlertRole:
2087 return @"AXApplicationAlert";
2088 case ApplicationAlertDialogRole:
2089 return @"AXApplicationAlertDialog";
2090 case ApplicationDialogRole:
2091 return @"AXApplicationDialog";
2092 case ApplicationLogRole:
2093 return @"AXApplicationLog";
2094 case ApplicationMarqueeRole:
2095 return @"AXApplicationMarquee";
2096 case ApplicationStatusRole:
2097 return @"AXApplicationStatus";
2098 case ApplicationTimerRole:
2099 return @"AXApplicationTimer";
2101 return @"AXDocument";
2102 case DocumentArticleRole:
2103 return @"AXDocumentArticle";
2104 case DocumentMathRole:
2105 return @"AXDocumentMath";
2106 case DocumentNoteRole:
2107 return @"AXDocumentNote";
2108 case DocumentRegionRole:
2109 return @"AXDocumentRegion";
2110 case UserInterfaceTooltipRole:
2111 return @"AXUserInterfaceTooltip";
2113 return @"AXTabPanel";
2114 case DefinitionRole:
2115 return @"AXDefinition";
2116 case DescriptionListTermRole:
2118 case DescriptionListDetailRole:
2119 return @"AXDescription";
2120 // Default doesn't return anything, so roles defined below can be chosen.
2125 if (role == MathElementRole) {
2126 if (m_object->isMathFraction())
2127 return @"AXMathFraction";
2128 if (m_object->isMathFenced())
2129 return @"AXMathFenced";
2130 if (m_object->isMathSubscriptSuperscript())
2131 return @"AXMathSubscriptSuperscript";
2132 if (m_object->isMathRow())
2133 return @"AXMathRow";
2134 if (m_object->isMathUnderOver())
2135 return @"AXMathUnderOver";
2136 if (m_object->isMathSquareRoot())
2137 return @"AXMathSquareRoot";
2138 if (m_object->isMathRoot())
2139 return @"AXMathRoot";
2140 if (m_object->isMathText())
2141 return @"AXMathText";
2142 if (m_object->isMathNumber())
2143 return @"AXMathNumber";
2144 if (m_object->isMathIdentifier())
2145 return @"AXMathIdentifier";
2146 if (m_object->isMathTable())
2147 return @"AXMathTable";
2148 if (m_object->isMathTableRow())
2149 return @"AXMathTableRow";
2150 if (m_object->isMathTableCell())
2151 return @"AXMathTableCell";
2152 if (m_object->isMathFenceOperator())
2153 return @"AXMathFenceOperator";
2154 if (m_object->isMathSeparatorOperator())
2155 return @"AXMathSeparatorOperator";
2156 if (m_object->isMathOperator())
2157 return @"AXMathOperator";
2158 if (m_object->isMathMultiscript())
2159 return @"AXMathMultiscript";
2162 if (role == VideoRole)
2164 if (role == AudioRole)
2166 if (role == DetailsRole)
2167 return @"AXDetails";
2168 if (role == SummaryRole)
2169 return @"AXSummary";
2171 if (m_object->isMediaTimeline())
2172 return NSAccessibilityTimelineSubrole;
2174 if (m_object->isSwitch())
2175 return NSAccessibilitySwitchSubrole;
2180 return NSAccessibilityRubyBaseSubrole;
2182 return NSAccessibilityRubyBlockSubrole;
2183 case RubyInlineRole:
2184 return NSAccessibilityRubyInlineSubrole;
2186 return NSAccessibilityRubyRunSubrole;
2188 return NSAccessibilityRubyTextSubrole;
2195 #pragma clang diagnostic pop
2197 - (NSString*)roleDescription
2202 #pragma clang diagnostic push
2203 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2204 // attachments have the AXImage role, but a different subrole
2205 if (m_object->isAttachment())
2206 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute];
2207 #pragma clang diagnostic pop
2209 const AtomicString& overrideRoleDescription = m_object->roleDescription();
2210 if (!overrideRoleDescription.isNull())
2211 return overrideRoleDescription;
2213 NSString* axRole = [self role];
2215 if ([axRole isEqualToString:NSAccessibilityGroupRole]) {
2217 NSString *ariaLandmarkRoleDescription = [self ariaLandmarkRoleDescription];
2218 if (ariaLandmarkRoleDescription)
2219 return ariaLandmarkRoleDescription;
2221 switch (m_object->roleValue()) {
2223 return localizedMediaControlElementString("AudioElement");
2224 case DefinitionRole:
2225 return AXDefinitionText();
2226 case DescriptionListTermRole:
2227 return AXDescriptionListTermText();
2228 case DescriptionListDetailRole:
2229 return AXDescriptionListDetailText();
2231 return AXFooterRoleDescriptionText();
2233 return localizedMediaControlElementString("VideoElement");
2235 return NSAccessibilityRoleDescription(NSAccessibilityGroupRole, [self subrole]);
2239 if ([axRole isEqualToString:@"AXWebArea"])
2240 return AXWebAreaText();
2242 if ([axRole isEqualToString:@"AXLink"])
2243 return AXLinkText();
2245 if ([axRole isEqualToString:@"AXListMarker"])
2246 return AXListMarkerText();
2248 if ([axRole isEqualToString:@"AXImageMap"])
2249 return AXImageMapText();
2251 if ([axRole isEqualToString:@"AXHeading"])
2252 return AXHeadingText();
2254 if (m_object->isFileUploadButton())
2255 return AXFileUploadButtonText();
2257 // Only returning for DL (not UL or OL) because description changed with HTML5 from 'definition list' to
2258 // superset 'description list' and does not return the same values in AX API on some OS versions.
2259 if (is<AccessibilityList>(*m_object)) {
2260 if (downcast<AccessibilityList>(*m_object).isDescriptionList())
2261 return AXDescriptionListText();
2264 if (m_object->roleValue() == HorizontalRuleRole)
2265 return AXHorizontalRuleDescriptionText();
2267 // AppKit also returns AXTab for the role description for a tab item.
2268 if (m_object->isTabItem())
2269 return NSAccessibilityRoleDescription(@"AXTab", nil);
2271 // We should try the system default role description for all other roles.
2272 // If we get the same string back, then as a last resort, return unknown.
2273 NSString* defaultRoleDescription = NSAccessibilityRoleDescription(axRole, [self subrole]);
2275 // On earlier Mac versions (Lion), using a non-standard subrole would result in a role description
2276 // being returned that looked like AXRole:AXSubrole. To make all platforms have the same role descriptions
2277 // we should fallback on a role description ignoring the subrole in these cases.
2278 if ([defaultRoleDescription isEqualToString:[NSString stringWithFormat:@"%@:%@", axRole, [self subrole]]])
2279 defaultRoleDescription = NSAccessibilityRoleDescription(axRole, nil);
2281 if (![defaultRoleDescription isEqualToString:axRole])
2282 return defaultRoleDescription;
2284 return NSAccessibilityRoleDescription(NSAccessibilityUnknownRole, nil);
2287 - (NSString *)computedRoleString
2291 return m_object->computedRoleString();
2294 - (id)scrollViewParent
2296 if (!is<AccessibilityScrollView>(m_object))
2299 // If this scroll view provides it's parent object (because it's a sub-frame), then
2300 // we should not find the remoteAccessibilityParent.
2301 if (m_object->parentObject())
2304 ScrollView* scroll = downcast<AccessibilityScrollView>(*m_object).scrollView();
2308 if (scroll->platformWidget())
2309 return NSAccessibilityUnignoredAncestor(scroll->platformWidget());
2311 return [self remoteAccessibilityParentObject];
2314 // FIXME: split up this function in a better way.
2315 // suggestions: Use a hash table that maps attribute names to function calls,
2316 // or maybe pointers to member functions
2317 - (id)accessibilityAttributeValue:(NSString*)attributeName
2319 if (![self updateObjectBackingStore])
2322 if ([attributeName isEqualToString: NSAccessibilityRoleAttribute])
2325 if ([attributeName isEqualToString: NSAccessibilitySubroleAttribute])
2326 return [self subrole];
2328 if ([attributeName isEqualToString: NSAccessibilityRoleDescriptionAttribute])
2329 return [self roleDescription];
2331 // AXARIARole is only used by DumpRenderTree (so far).
2332 if ([attributeName isEqualToString:@"AXARIARole"])
2333 return [self computedRoleString];
2335 if ([attributeName isEqualToString: NSAccessibilityParentAttribute]) {
2337 // This will return the parent of the AXWebArea, if this is a web area.
2338 id scrollViewParent = [self scrollViewParent];
2339 if (scrollViewParent)
2340 return scrollViewParent;
2342 // Tree item (changed to AXRows) can only report the tree (AXOutline) as its parent.
2343 if (m_object->isTreeItem()) {
2344 AccessibilityObject* parent = m_object->parentObjectUnignored();
2346 if (parent->isTree())
2347 return parent->wrapper();
2348 parent = parent->parentObjectUnignored();
2352 AccessibilityObject* parent = m_object->parentObjectUnignored();
2356 // In WebKit1, the scroll view is provided by the system (the attachment view), so the parent
2357 // should be reported directly as such.
2358 if (m_object->isWebArea() && parent->isAttachment())
2359 return [parent->wrapper() attachmentView];
2361 return parent->wrapper();
2364 if ([attributeName isEqualToString: NSAccessibilityChildrenAttribute]) {
2365 if (m_object->children().isEmpty()) {
2366 NSArray* children = [self renderWidgetChildren];
2367 if (children != nil)
2371 // The tree's (AXOutline) children are supposed to be its rows and columns.
2372 // The ARIA spec doesn't have columns, so we just need rows.
2373 if (m_object->isTree())
2374 return [self accessibilityAttributeValue:NSAccessibilityRowsAttribute];
2376 // A tree item should only expose its content as its children (not its rows)
2377 if (m_object->isTreeItem()) {
2378 AccessibilityObject::AccessibilityChildrenVector contentCopy;
2379 m_object->ariaTreeItemContent(contentCopy);
2380 return convertToNSArray(contentCopy);
2383 return convertToNSArray(m_object->children());
2386 if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {
2387 if (m_object->isListBox()) {
2388 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2389 m_object->selectedChildren(selectedChildrenCopy);
2390 return convertToNSArray(selectedChildrenCopy);
2395 if ([attributeName isEqualToString: NSAccessibilityVisibleChildrenAttribute]) {
2396 if (m_object->isListBox()) {
2397 AccessibilityObject::AccessibilityChildrenVector visibleChildrenCopy;
2398 m_object->visibleChildren(visibleChildrenCopy);
2399 return convertToNSArray(visibleChildrenCopy);
2401 else if (m_object->isList())
2402 return [self accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
2408 if (m_object->isWebArea()) {
2409 if ([attributeName isEqualToString:@"AXLinkUIElements"]) {
2410 AccessibilityObject::AccessibilityChildrenVector links;
2411 downcast<AccessibilityRenderObject>(*m_object).getDocumentLinks(links);
2412 return convertToNSArray(links);
2414 if ([attributeName isEqualToString:@"AXLoaded"])
2415 return [NSNumber numberWithBool:m_object->isLoaded()];
2416 if ([attributeName isEqualToString:@"AXLayoutCount"])
2417 return [NSNumber numberWithInt:m_object->layoutCount()];
2418 if ([attributeName isEqualToString:NSAccessibilityLoadingProgressAttribute])
2419 return [NSNumber numberWithDouble:m_object->estimatedLoadingProgress()];
2422 if (m_object->isTextControl()) {
2423 if ([attributeName isEqualToString: NSAccessibilityNumberOfCharactersAttribute]) {
2424 int length = m_object->textLength();
2427 return [NSNumber numberWithUnsignedInt:length];
2429 if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
2430 String selectedText = m_object->selectedText();
2431 if (selectedText.isNull())
2433 return (NSString*)selectedText;
2435 if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
2436 PlainTextRange textRange = m_object->selectedTextRange();
2437 if (textRange.isNull())
2438 return [NSValue valueWithRange:NSMakeRange(0, 0)];
2439 return [NSValue valueWithRange:NSMakeRange(textRange.start, textRange.length)];
2441 // TODO: Get actual visible range. <rdar://problem/4712101>
2442 if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
2443 return m_object->isPasswordField() ? nil : [NSValue valueWithRange: NSMakeRange(0, m_object->textLength())];
2444 if ([attributeName isEqualToString: NSAccessibilityInsertionPointLineNumberAttribute]) {
2445 // if selectionEnd > 0, then there is selected text and this question should not be answered
2446 if (m_object->isPasswordField() || m_object->selectionEnd() > 0)
2449 AccessibilityObject* focusedObject = m_object->focusedUIElement();
2450 if (focusedObject != m_object)
2453 VisiblePosition focusedPosition = focusedObject->visiblePositionForIndex(focusedObject->selectionStart(), true);
2454 int lineNumber = m_object->lineForPosition(focusedPosition);
2458 return [NSNumber numberWithInt:lineNumber];
2462 if ([attributeName isEqualToString: NSAccessibilityURLAttribute]) {
2463 URL url = m_object->url();
2469 // Only native spin buttons have increment and decrement buttons.
2470 if (is<AccessibilitySpinButton>(*m_object)) {
2471 if ([attributeName isEqualToString:NSAccessibilityIncrementButtonAttribute])
2472 return downcast<AccessibilitySpinButton>(*m_object).incrementButton()->wrapper();
2473 if ([attributeName isEqualToString:NSAccessibilityDecrementButtonAttribute])
2474 return downcast<AccessibilitySpinButton>(*m_object).decrementButton()->wrapper();
2477 if ([attributeName isEqualToString: @"AXVisited"])
2478 return [NSNumber numberWithBool: m_object->isVisited()];
2480 if ([attributeName isEqualToString: NSAccessibilityTitleAttribute]) {
2481 if (m_object->isAttachment()) {
2482 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityTitleAttribute])
2483 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityTitleAttribute];
2486 // Meter elements should communicate their content via AXValueDescription.
2487 if (m_object->isMeter())
2488 return [NSString string];
2490 return [self baseAccessibilityTitle];
2493 if ([attributeName isEqualToString: NSAccessibilityDescriptionAttribute]) {
2494 if (m_object->isAttachment()) {
2495 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityDescriptionAttribute])
2496 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityDescriptionAttribute];
2498 return [self baseAccessibilityDescription];
2501 if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
2502 if (m_object->isAttachment()) {
2503 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityValueAttribute])
2504 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityValueAttribute];
2506 if (m_object->supportsRangeValue())
2507 return [NSNumber numberWithFloat:m_object->valueForRange()];
2508 if (m_object->roleValue() == SliderThumbRole)
2509 return [NSNumber numberWithFloat:m_object->parentObject()->valueForRange()];
2510 if (m_object->isHeading())
2511 return [NSNumber numberWithInt:m_object->headingLevel()];
2513 if (m_object->isCheckboxOrRadio() || m_object->isMenuItem() || m_object->isSwitch() || m_object->isToggleButton()) {
2514 switch (m_object->checkboxOrRadioValue()) {
2515 case ButtonStateOff:
2516 return [NSNumber numberWithInt:0];
2518 return [NSNumber numberWithInt:1];
2519 case ButtonStateMixed:
2520 return [NSNumber numberWithInt:2];
2524 // radio groups return the selected radio button as the AXValue
2525 if (m_object->isRadioGroup()) {
2526 AccessibilityObject* radioButton = m_object->selectedRadioButton();
2529 return radioButton->wrapper();
2532 if (m_object->isTabList()) {
2533 AccessibilityObject* tabItem = m_object->selectedTabItem();
2536 return tabItem->wrapper();
2539 if (m_object->isTabItem())
2540 return [NSNumber numberWithInt:m_object->isSelected()];
2542 if (m_object->isColorWell()) {
2544 m_object->colorValue(r, g, b);
2545 return [NSString stringWithFormat:@"rgb %7.5f %7.5f %7.5f 1", r / 255., g / 255., b / 255.];
2548 return m_object->stringValue();
2551 if ([attributeName isEqualToString:(NSString *)kAXMenuItemMarkCharAttribute]) {
2552 const unichar ch = 0x2713; // ✓ used on Mac for selected menu items.
2553 return (m_object->isChecked()) ? [NSString stringWithCharacters:&ch length:1] : nil;
2556 if ([attributeName isEqualToString: NSAccessibilityMinValueAttribute]) {
2557 // Indeterminate progress indicator should return 0.
2558 if (m_object->isProgressIndicator() && !m_object->hasAttribute(aria_valuenowAttr))
2560 return [NSNumber numberWithFloat:m_object->minValueForRange()];
2563 if ([attributeName isEqualToString: NSAccessibilityMaxValueAttribute]) {
2564 // Indeterminate progress indicator should return 0.
2565 if (m_object->isProgressIndicator() && !m_object->hasAttribute(aria_valuenowAttr))
2567 return [NSNumber numberWithFloat:m_object->maxValueForRange()];
2570 if ([attributeName isEqualToString: NSAccessibilityHelpAttribute])
2571 return [self baseAccessibilityHelpText];
2573 if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
2574 return [NSNumber numberWithBool: m_object->isFocused()];
2576 if ([attributeName isEqualToString: NSAccessibilityEnabledAttribute])
2577 return [NSNumber numberWithBool: m_object->isEnabled()];
2579 if ([attributeName isEqualToString: NSAccessibilitySizeAttribute]) {
2580 IntSize s = m_object->elementRect().pixelSnappedSize();
2581 return [NSValue valueWithSize: NSMakeSize(s.width(), s.height())];
2584 if ([attributeName isEqualToString: NSAccessibilityPositionAttribute])
2585 return [self position];
2586 if ([attributeName isEqualToString:NSAccessibilityPathAttribute])
2589 if ([attributeName isEqualToString: NSAccessibilityWindowAttribute] ||
2590 [attributeName isEqualToString: NSAccessibilityTopLevelUIElementAttribute]) {
2592 id remoteParent = [self remoteAccessibilityParentObject];
2594 return [remoteParent accessibilityAttributeValue:attributeName];
2596 FrameView* fv = m_object->documentFrameView();
2598 return [fv->platformWidget() window];
2602 if ([attributeName isEqualToString:NSAccessibilityAccessKeyAttribute]) {
2603 AtomicString accessKey = m_object->accessKey();
2604 if (accessKey.isNull())
2609 if ([attributeName isEqualToString:NSAccessibilityTabsAttribute]) {
2610 if (m_object->isTabList()) {
2611 AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2612 m_object->tabChildren(tabsChildren);
2613 return convertToNSArray(tabsChildren);
2617 if ([attributeName isEqualToString:NSAccessibilityContentsAttribute]) {
2618 // The contents of a tab list are all the children except the tabs.
2619 if (m_object->isTabList()) {
2620 const auto& children = m_object->children();
2621 AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2622 m_object->tabChildren(tabsChildren);
2624 AccessibilityObject::AccessibilityChildrenVector contents;
2625 unsigned childrenSize = children.size();
2626 for (unsigned k = 0; k < childrenSize; ++k) {
2627 if (tabsChildren.find(children[k]) == WTF::notFound)
2628 contents.append(children[k]);
2630 return convertToNSArray(contents);
2631 } else if (m_object->isScrollView()) {
2632 // A scrollView's contents are everything except the scroll bars.
2633 AccessibilityObject::AccessibilityChildrenVector contents;
2634 for (const auto& child : m_object->children()) {
2635 if (!child->isScrollbar())
2636 contents.append(child);
2638 return convertToNSArray(contents);
2642 if (is<AccessibilityTable>(*m_object) && downcast<AccessibilityTable>(*m_object).isExposableThroughAccessibility()) {
2643 auto& table = downcast<AccessibilityTable>(*m_object);
2644 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute])
2645 return convertToNSArray(table.rows());
2647 if ([attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
2648 AccessibilityObject::AccessibilityChildrenVector visibleRows;
2649 table.visibleRows(visibleRows);
2650 return convertToNSArray(visibleRows);
2653 // TODO: distinguish between visible and non-visible columns
2654 if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute] ||
2655 [attributeName isEqualToString:NSAccessibilityVisibleColumnsAttribute]) {
2656 return convertToNSArray(table.columns());
2659 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2660 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2661 m_object->selectedChildren(selectedChildrenCopy);
2662 return convertToNSArray(selectedChildrenCopy);
2665 // HTML tables don't support these
2666 if ([attributeName isEqualToString:NSAccessibilitySelectedColumnsAttribute] ||
2667 [attributeName isEqualToString:NSAccessibilitySelectedCellsAttribute])
2670 if ([attributeName isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute]) {
2671 AccessibilityObject::AccessibilityChildrenVector columnHeaders;
2672 table.columnHeaders(columnHeaders);
2673 return convertToNSArray(columnHeaders);
2676 if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2677 AccessibilityObject* headerContainer = table.headerContainer();
2678 if (headerContainer)
2679 return headerContainer->wrapper();
2683 if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
2684 AccessibilityObject::AccessibilityChildrenVector rowHeaders;
2685 table.rowHeaders(rowHeaders);
2686 return convertToNSArray(rowHeaders);
2689 if ([attributeName isEqualToString:NSAccessibilityVisibleCellsAttribute]) {
2690 AccessibilityObject::AccessibilityChildrenVector cells;
2692 return convertToNSArray(cells);
2695 if ([attributeName isEqualToString:NSAccessibilityColumnCountAttribute])
2696 return @(table.columnCount());
2698 if ([attributeName isEqualToString:NSAccessibilityRowCountAttribute])
2699 return @(table.rowCount());
2702 if (is<AccessibilityTableColumn>(*m_object)) {
2703 auto& column = downcast<AccessibilityTableColumn>(*m_object);
2704 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2705 return [NSNumber numberWithInt:column.columnIndex()];
2707 // rows attribute for a column is the list of all the elements in that column at each row
2708 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] ||
2709 [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
2710 return convertToNSArray(column.children());
2712 if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2713 AccessibilityObject* header = column.headerObject();
2716 return header->wrapper();
2720 if (is<AccessibilityTableCell>(*m_object)) {
2721 auto& cell = downcast<AccessibilityTableCell>(*m_object);
2722 if ([attributeName isEqualToString:NSAccessibilityRowIndexRangeAttribute]) {
2723 std::pair<unsigned, unsigned> rowRange;
2724 cell.rowIndexRange(rowRange);
2725 return [NSValue valueWithRange:NSMakeRange(rowRange.first, rowRange.second)];
2727 if ([attributeName isEqualToString:NSAccessibilityColumnIndexRangeAttribute]) {
2728 std::pair<unsigned, unsigned> columnRange;
2729 cell.columnIndexRange(columnRange);
2730 return [NSValue valueWithRange:NSMakeRange(columnRange.first, columnRange.second)];
2732 if ([attributeName isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute]) {
2733 AccessibilityObject::AccessibilityChildrenVector columnHeaders;
2734 cell.columnHeaders(columnHeaders);
2735 return convertToNSArray(columnHeaders);
2737 if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
2738 AccessibilityObject::AccessibilityChildrenVector rowHeaders;
2739 cell.rowHeaders(rowHeaders);
2740 return convertToNSArray(rowHeaders);
2744 if (m_object->isTree()) {
2745 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2746 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2747 m_object->selectedChildren(selectedChildrenCopy);
2748 return convertToNSArray(selectedChildrenCopy);
2750 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute]) {
2751 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2752 m_object->ariaTreeRows(rowsCopy);
2753 return convertToNSArray(rowsCopy);
2756 // TreeRoles do not support columns, but Mac AX expects to be able to ask about columns at the least.
2757 if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute])
2758 return [NSArray array];
2761 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute]) {
2762 if (m_object->isTreeItem()) {
2763 AccessibilityObject* parent = m_object->parentObject();
2764 for (; parent && !parent->isTree(); parent = parent->parentObject())
2770 // Find the index of this item by iterating the parents.
2771 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2772 parent->ariaTreeRows(rowsCopy);
2773 size_t count = rowsCopy.size();
2774 for (size_t k = 0; k < count; ++k)
2775 if (rowsCopy[k]->wrapper() == self)
2776 return [NSNumber numberWithUnsignedInt:k];
2780 if (is<AccessibilityTableRow>(*m_object)) {
2781 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2782 return [NSNumber numberWithInt:downcast<AccessibilityTableRow>(*m_object).rowIndex()];
2786 // The rows that are considered inside this row.
2787 if ([attributeName isEqualToString:NSAccessibilityDisclosedRowsAttribute]) {
2788 if (m_object->isTreeItem()) {
2789 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2790 m_object->ariaTreeItemDisclosedRows(rowsCopy);
2791 return convertToNSArray(rowsCopy);
2792 } else if (is<AccessibilityARIAGridRow>(*m_object)) {
2793 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2794 downcast<AccessibilityARIAGridRow>(*m_object).disclosedRows(rowsCopy);
2795 return convertToNSArray(rowsCopy);
2799 // The row that contains this row. It should be the same as the first parent that is a treeitem.
2800 if ([attributeName isEqualToString:NSAccessibilityDisclosedByRowAttribute]) {
2801 if (m_object->isTreeItem()) {
2802 AccessibilityObject* parent = m_object->parentObject();
2804 if (parent->isTreeItem())
2805 return parent->wrapper();
2806 // If the parent is the tree itself, then this value == nil.
2807 if (parent->isTree())
2809 parent = parent->parentObject();
2812 } else if (is<AccessibilityARIAGridRow>(*m_object)) {
2813 AccessibilityObject* row = downcast<AccessibilityARIAGridRow>(*m_object).disclosedByRow();
2816 return row->wrapper();
2820 if ([attributeName isEqualToString:NSAccessibilityDisclosureLevelAttribute]) {
2821 // Convert from 1-based level (from aria-level spec) to 0-based level (Mac)
2822 int level = m_object->hierarchicalLevel();
2825 return [NSNumber numberWithInt:level];
2827 if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
2828 return [NSNumber numberWithBool:m_object->isExpanded()];
2830 if ((m_object->isListBox() || m_object->isList()) && [attributeName isEqualToString:NSAccessibilityOrientationAttribute])
2831 return NSAccessibilityVerticalOrientationValue;
2833 if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
2834 return [self textMarkerRangeForSelection];
2836 if (m_object->renderer()) {
2837 if ([attributeName isEqualToString: @"AXStartTextMarker"])
2838 return [self textMarkerForVisiblePosition:startOfDocument(&m_object->renderer()->document())];
2839 if ([attributeName isEqualToString: @"AXEndTextMarker"])
2840 return [self textMarkerForVisiblePosition:endOfDocument(&m_object->renderer()->document())];
2843 if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute])
2844 return [NSNumber numberWithInt:m_object->blockquoteLevel()];
2845 if ([attributeName isEqualToString:@"AXTableLevel"])
2846 return [NSNumber numberWithInt:m_object->tableLevel()];
2848 if ([attributeName isEqualToString: NSAccessibilityLinkedUIElementsAttribute]) {
2849 AccessibilityObject::AccessibilityChildrenVector linkedUIElements;
2850 m_object->linkedUIElements(linkedUIElements);
2851 return convertToNSArray(linkedUIElements);
2854 if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
2855 return [NSNumber numberWithBool:m_object->isSelected()];
2857 if ([attributeName isEqualToString: NSAccessibilityServesAsTitleForUIElementsAttribute] && m_object->isMenuButton()) {
2858 AccessibilityObject* uiElement = downcast<AccessibilityRenderObject>(*m_object).menuForMenuButton();
2860 return [NSArray arrayWithObject:uiElement->wrapper()];
2863 if ([attributeName isEqualToString:NSAccessibilityTitleUIElementAttribute]) {
2864 if (!m_object->exposesTitleUIElement())
2867 AccessibilityObject* obj = m_object->titleUIElement();
2869 return obj->wrapper();
2873 if ([attributeName isEqualToString:NSAccessibilityValueDescriptionAttribute]) {
2874 if (m_object->isMeter())
2875 return [self baseAccessibilityTitle];
2877 return m_object->valueDescription();
2880 if ([attributeName isEqualToString:NSAccessibilityOrientationAttribute]) {
2881 AccessibilityOrientation elementOrientation = m_object->orientation();
2882 if (elementOrientation == AccessibilityOrientationVertical)
2883 return NSAccessibilityVerticalOrientationValue;
2884 if (elementOrientation == AccessibilityOrientationHorizontal)
2885 return NSAccessibilityHorizontalOrientationValue;
2889 if ([attributeName isEqualToString:NSAccessibilityHorizontalScrollBarAttribute]) {
2890 AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationHorizontal);
2892 return scrollBar->wrapper();
2895 if ([attributeName isEqualToString:NSAccessibilityVerticalScrollBarAttribute]) {
2896 AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationVertical);
2898 return scrollBar->wrapper();
2902 if ([attributeName isEqualToString:NSAccessibilitySortDirectionAttribute]) {
2903 switch (m_object->sortDirection()) {
2904 case SortDirectionAscending:
2905 return NSAccessibilityAscendingSortDirectionValue;
2906 case SortDirectionDescending:
2907 return NSAccessibilityDescendingSortDirectionValue;
2909 return NSAccessibilityUnknownSortDirectionValue;
2913 if ([attributeName isEqualToString:NSAccessibilityLanguageAttribute])
2914 return m_object->language();
2916 if ([attributeName isEqualToString:NSAccessibilityExpandedAttribute])
2917 return [NSNumber numberWithBool:m_object->isExpanded()];
2919 if ([attributeName isEqualToString:NSAccessibilityRequiredAttribute])
2920 return [NSNumber numberWithBool:m_object->isRequired()];
2922 if ([attributeName isEqualToString:NSAccessibilityInvalidAttribute])
2923 return m_object->invalidStatus();
2925 if ([attributeName isEqualToString:NSAccessibilityOwnsAttribute]) {
2926 AccessibilityObject::AccessibilityChildrenVector ariaOwns;
2927 m_object->ariaOwnsElements(ariaOwns);
2928 return convertToNSArray(ariaOwns);
2931 if ([attributeName isEqualToString:NSAccessibilityARIAPosInSetAttribute])
2932 return [NSNumber numberWithInt:m_object->ariaPosInSet()];
2933 if ([attributeName isEqualToString:NSAccessibilityARIASetSizeAttribute])
2934 return [NSNumber numberWithInt:m_object->ariaSetSize()];
2936 if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
2937 return [NSNumber numberWithBool:m_object->isARIAGrabbed()];
2939 if ([attributeName isEqualToString:NSAccessibilityDropEffectsAttribute]) {
2940 Vector<String> dropEffects;
2941 m_object->determineARIADropEffects(dropEffects);
2942 return convertStringsToNSArray(dropEffects);
2945 if ([attributeName isEqualToString:NSAccessibilityPlaceholderValueAttribute])
2946 return m_object->placeholderValue();
2948 if ([attributeName isEqualToString:NSAccessibilityValueAutofilledAttribute])
2949 return @(m_object->isValueAutofilled());
2951 if ([attributeName isEqualToString:NSAccessibilityHasPopupAttribute])
2952 return [NSNumber numberWithBool:m_object->ariaHasPopup()];
2954 // ARIA Live region attributes.
2955 if ([attributeName isEqualToString:NSAccessibilityARIALiveAttribute])
2956 return m_object->ariaLiveRegionStatus();
2957 if ([attributeName isEqualToString:NSAccessibilityARIARelevantAttribute])
2958 return m_object->ariaLiveRegionRelevant();
2959 if ([attributeName isEqualToString:NSAccessibilityARIAAtomicAttribute])
2960 return [NSNumber numberWithBool:m_object->ariaLiveRegionAtomic()];
2961 if ([attributeName isEqualToString:NSAccessibilityElementBusyAttribute])
2962 return [NSNumber numberWithBool:m_object->ariaLiveRegionBusy()];
2964 // MathML Attributes.
2965 if (m_object->isMathElement()) {
2966 if ([attributeName isEqualToString:NSAccessibilityMathRootIndexAttribute])
2967 return (m_object->mathRootIndexObject()) ? m_object->mathRootIndexObject()->wrapper() : 0;
2968 if ([attributeName isEqualToString:NSAccessibilityMathRootRadicandAttribute])
2969 return (m_object->mathRadicandObject()) ? m_object->mathRadicandObject()->wrapper() : 0;
2970 if ([attributeName isEqualToString:NSAccessibilityMathFractionNumeratorAttribute])
2971 return (m_object->mathNumeratorObject()) ? m_object->mathNumeratorObject()->wrapper() : 0;
2972 if ([attributeName isEqualToString:NSAccessibilityMathFractionDenominatorAttribute])
2973 return (m_object->mathDenominatorObject()) ? m_object->mathDenominatorObject()->wrapper() : 0;
2974 if ([attributeName isEqualToString:NSAccessibilityMathBaseAttribute])
2975 return (m_object->mathBaseObject()) ? m_object->mathBaseObject()->wrapper() : 0;
2976 if ([attributeName isEqualToString:NSAccessibilityMathSubscriptAttribute])
2977 return (m_object->mathSubscriptObject()) ? m_object->mathSubscriptObject()->wrapper() : 0;
2978 if ([attributeName isEqualToString:NSAccessibilityMathSuperscriptAttribute])
2979 return (m_object->mathSuperscriptObject()) ? m_object->mathSuperscriptObject()->wrapper() : 0;
2980 if ([attributeName isEqualToString:NSAccessibilityMathUnderAttribute])
2981 return (m_object->mathUnderObject()) ? m_object->mathUnderObject()->wrapper() : 0;
2982 if ([attributeName isEqualToString:NSAccessibilityMathOverAttribute])
2983 return (m_object->mathOverObject()) ? m_object->mathOverObject()->wrapper() : 0;
2984 if ([attributeName isEqualToString:NSAccessibilityMathFencedOpenAttribute])
2985 return m_object->mathFencedOpenString();
2986 if ([attributeName isEqualToString:NSAccessibilityMathFencedCloseAttribute])
2987 return m_object->mathFencedCloseString();
2988 if ([attributeName isEqualToString:NSAccessibilityMathLineThicknessAttribute])
2989 return [NSNumber numberWithInteger:m_object->mathLineThickness()];
2990 if ([attributeName isEqualToString:NSAccessibilityMathPostscriptsAttribute])
2991 return [self accessibilityMathPostscriptPairs];
2992 if ([attributeName isEqualToString:NSAccessibilityMathPrescriptsAttribute])
2993 return [self accessibilityMathPrescriptPairs];
2996 if ([attributeName isEqualToString:NSAccessibilityExpandedTextValueAttribute])
2997 return m_object->expandedTextValue();
2999 if ([attributeName isEqualToString:NSAccessibilityDOMIdentifierAttribute])
3000 return m_object->identifierAttribute();
3001 if ([attributeName isEqualToString:NSAccessibilityDOMClassListAttribute]) {
3002 Vector<String> classList;
3003 m_object->classList(classList);
3004 return convertStringsToNSArray(classList);
3007 // this is used only by DumpRenderTree for testing
3008 if ([attributeName isEqualToString:@"AXClickPoint"])
3009 return [NSValue valueWithPoint:m_object->clickPoint()];
3011 // This is used by DRT to verify CSS3 speech works.
3012 if ([attributeName isEqualToString:@"AXDRTSpeechAttribute"]) {
3013 ESpeak speakProperty = m_object->speakProperty();
3014 switch (speakProperty) {
3018 return @"spell-out";
3021 case SpeakLiteralPunctuation:
3022 return @"literal-punctuation";
3023 case SpeakNoPunctuation:
3024 return @"no-punctuation";
3031 // Used by DRT to find an accessible node by its element id.
3032 if ([attributeName isEqualToString:@"AXDRTElementIdAttribute"])
3033 return m_object->getAttribute(idAttr);
3035 if (m_object->isWebArea() && [attributeName isEqualToString:NSAccessibilityPreventKeyboardDOMEventDispatchAttribute])
3036 return [NSNumber numberWithBool:m_object->preventKeyboardDOMEventDispatch()];
3038 if (m_object->isWebArea() && [attributeName isEqualToString:NSAccessibilityCaretBrowsingEnabledAttribute])
3039 return [NSNumber numberWithBool:m_object->caretBrowsingEnabled()];
3044 - (NSString *)accessibilityPlatformMathSubscriptKey
3046 return NSAccessibilityMathSubscriptAttribute;
3049 - (NSString *)accessibilityPlatformMathSuperscriptKey
3051 return NSAccessibilityMathSuperscriptAttribute;
3054 - (id)accessibilityFocusedUIElement
3056 if (![self updateObjectBackingStore])