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"
124 #ifndef NSAccessibilityBlockQuoteLevelAttribute
125 #define NSAccessibilityBlockQuoteLevelAttribute @"AXBlockQuoteLevel"
128 #ifndef NSAccessibilityAccessKeyAttribute
129 #define NSAccessibilityAccessKeyAttribute @"AXAccessKey"
132 #ifndef NSAccessibilityValueAutofilledAttribute
133 #define NSAccessibilityValueAutofilledAttribute @"AXValueAutofilled"
136 #ifndef NSAccessibilityLanguageAttribute
137 #define NSAccessibilityLanguageAttribute @"AXLanguage"
140 #ifndef NSAccessibilityRequiredAttribute
141 #define NSAccessibilityRequiredAttribute @"AXRequired"
144 #ifndef NSAccessibilityInvalidAttribute
145 #define NSAccessibilityInvalidAttribute @"AXInvalid"
148 #ifndef NSAccessibilityOwnsAttribute
149 #define NSAccessibilityOwnsAttribute @"AXOwns"
152 #ifndef NSAccessibilityGrabbedAttribute
153 #define NSAccessibilityGrabbedAttribute @"AXGrabbed"
156 #ifndef NSAccessibilityDropEffectsAttribute
157 #define NSAccessibilityDropEffectsAttribute @"AXDropEffects"
160 #ifndef NSAccessibilityARIALiveAttribute
161 #define NSAccessibilityARIALiveAttribute @"AXARIALive"
164 #ifndef NSAccessibilityARIAAtomicAttribute
165 #define NSAccessibilityARIAAtomicAttribute @"AXARIAAtomic"
168 #ifndef NSAccessibilityARIARelevantAttribute
169 #define NSAccessibilityARIARelevantAttribute @"AXARIARelevant"
172 #ifndef NSAccessibilityElementBusyAttribute
173 #define NSAccessibilityElementBusyAttribute @"AXElementBusy"
176 #ifndef NSAccessibilityARIAPosInSetAttribute
177 #define NSAccessibilityARIAPosInSetAttribute @"AXARIAPosInSet"
180 #ifndef NSAccessibilityARIASetSizeAttribute
181 #define NSAccessibilityARIASetSizeAttribute @"AXARIASetSize"
184 #ifndef NSAccessibilityLoadingProgressAttribute
185 #define NSAccessibilityLoadingProgressAttribute @"AXLoadingProgress"
188 #ifndef NSAccessibilityHasPopupAttribute
189 #define NSAccessibilityHasPopupAttribute @"AXHasPopup"
192 #ifndef NSAccessibilityPlaceholderValueAttribute
193 #define NSAccessibilityPlaceholderValueAttribute @"AXPlaceholderValue"
196 #define NSAccessibilityTextMarkerIsValidParameterizedAttribute @"AXTextMarkerIsValid"
197 #define NSAccessibilityIndexForTextMarkerParameterizedAttribute @"AXIndexForTextMarker"
198 #define NSAccessibilityTextMarkerForIndexParameterizedAttribute @"AXTextMarkerForIndex"
200 #ifndef NSAccessibilityScrollToVisibleAction
201 #define NSAccessibilityScrollToVisibleAction @"AXScrollToVisible"
204 #ifndef NSAccessibilityPathAttribute
205 #define NSAccessibilityPathAttribute @"AXPath"
208 #ifndef NSAccessibilityExpandedTextValueAttribute
209 #define NSAccessibilityExpandedTextValueAttribute @"AXExpandedTextValue"
212 #define NSAccessibilityDOMIdentifierAttribute @"AXDOMIdentifier"
213 #define NSAccessibilityDOMClassListAttribute @"AXDOMClassList"
216 #ifndef NSAccessibilityImmediateDescendantsOnly
217 #define NSAccessibilityImmediateDescendantsOnly @"AXImmediateDescendantsOnly"
220 #ifndef NSAccessibilityUIElementCountForSearchPredicateParameterizedAttribute
221 #define NSAccessibilityUIElementCountForSearchPredicateParameterizedAttribute @"AXUIElementCountForSearchPredicate"
224 #ifndef NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute
225 #define NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute @"AXUIElementsForSearchPredicate"
229 #ifndef NSAccessibilityAnyTypeSearchKey
230 #define NSAccessibilityAnyTypeSearchKey @"AXAnyTypeSearchKey"
233 #ifndef NSAccessibilityBlockquoteSameLevelSearchKey
234 #define NSAccessibilityBlockquoteSameLevelSearchKey @"AXBlockquoteSameLevelSearchKey"
237 #ifndef NSAccessibilityBlockquoteSearchKey
238 #define NSAccessibilityBlockquoteSearchKey @"AXBlockquoteSearchKey"
241 #ifndef NSAccessibilityBoldFontSearchKey
242 #define NSAccessibilityBoldFontSearchKey @"AXBoldFontSearchKey"
245 #ifndef NSAccessibilityButtonSearchKey
246 #define NSAccessibilityButtonSearchKey @"AXButtonSearchKey"
249 #ifndef NSAccessibilityCheckBoxSearchKey
250 #define NSAccessibilityCheckBoxSearchKey @"AXCheckBoxSearchKey"
253 #ifndef NSAccessibilityControlSearchKey
254 #define NSAccessibilityControlSearchKey @"AXControlSearchKey"
257 #ifndef NSAccessibilityDifferentTypeSearchKey
258 #define NSAccessibilityDifferentTypeSearchKey @"AXDifferentTypeSearchKey"
261 #ifndef NSAccessibilityFontChangeSearchKey
262 #define NSAccessibilityFontChangeSearchKey @"AXFontChangeSearchKey"
265 #ifndef NSAccessibilityFontColorChangeSearchKey
266 #define NSAccessibilityFontColorChangeSearchKey @"AXFontColorChangeSearchKey"
269 #ifndef NSAccessibilityFrameSearchKey
270 #define NSAccessibilityFrameSearchKey @"AXFrameSearchKey"
273 #ifndef NSAccessibilityGraphicSearchKey
274 #define NSAccessibilityGraphicSearchKey @"AXGraphicSearchKey"
277 #ifndef NSAccessibilityHeadingLevel1SearchKey
278 #define NSAccessibilityHeadingLevel1SearchKey @"AXHeadingLevel1SearchKey"
281 #ifndef NSAccessibilityHeadingLevel2SearchKey
282 #define NSAccessibilityHeadingLevel2SearchKey @"AXHeadingLevel2SearchKey"
285 #ifndef NSAccessibilityHeadingLevel3SearchKey
286 #define NSAccessibilityHeadingLevel3SearchKey @"AXHeadingLevel3SearchKey"
289 #ifndef NSAccessibilityHeadingLevel4SearchKey
290 #define NSAccessibilityHeadingLevel4SearchKey @"AXHeadingLevel4SearchKey"
293 #ifndef NSAccessibilityHeadingLevel5SearchKey
294 #define NSAccessibilityHeadingLevel5SearchKey @"AXHeadingLevel5SearchKey"
297 #ifndef NSAccessibilityHeadingLevel6SearchKey
298 #define NSAccessibilityHeadingLevel6SearchKey @"AXHeadingLevel6SearchKey"
301 #ifndef NSAccessibilityHeadingSameLevelSearchKey
302 #define NSAccessibilityHeadingSameLevelSearchKey @"AXHeadingSameLevelSearchKey"
305 #ifndef NSAccessibilityHeadingSearchKey
306 #define NSAccessibilityHeadingSearchKey @"AXHeadingSearchKey"
309 #ifndef NSAccessibilityHighlightedSearchKey
310 #define NSAccessibilityHighlightedSearchKey @"AXHighlightedSearchKey"
313 #ifndef NSAccessibilityItalicFontSearchKey
314 #define NSAccessibilityItalicFontSearchKey @"AXItalicFontSearchKey"
317 #ifndef NSAccessibilityLandmarkSearchKey
318 #define NSAccessibilityLandmarkSearchKey @"AXLandmarkSearchKey"
321 #ifndef NSAccessibilityLinkSearchKey
322 #define NSAccessibilityLinkSearchKey @"AXLinkSearchKey"
325 #ifndef NSAccessibilityListSearchKey
326 #define NSAccessibilityListSearchKey @"AXListSearchKey"
329 #ifndef NSAccessibilityLiveRegionSearchKey
330 #define NSAccessibilityLiveRegionSearchKey @"AXLiveRegionSearchKey"
333 #ifndef NSAccessibilityMisspelledWordSearchKey
334 #define NSAccessibilityMisspelledWordSearchKey @"AXMisspelledWordSearchKey"
337 #ifndef NSAccessibilityOutlineSearchKey
338 #define NSAccessibilityOutlineSearchKey @"AXOutlineSearchKey"
341 #ifndef NSAccessibilityPlainTextSearchKey
342 #define NSAccessibilityPlainTextSearchKey @"AXPlainTextSearchKey"
345 #ifndef NSAccessibilityRadioGroupSearchKey
346 #define NSAccessibilityRadioGroupSearchKey @"AXRadioGroupSearchKey"
349 #ifndef NSAccessibilitySameTypeSearchKey
350 #define NSAccessibilitySameTypeSearchKey @"AXSameTypeSearchKey"
353 #ifndef NSAccessibilityStaticTextSearchKey
354 #define NSAccessibilityStaticTextSearchKey @"AXStaticTextSearchKey"
357 #ifndef NSAccessibilityStyleChangeSearchKey
358 #define NSAccessibilityStyleChangeSearchKey @"AXStyleChangeSearchKey"
361 #ifndef NSAccessibilityTableSameLevelSearchKey
362 #define NSAccessibilityTableSameLevelSearchKey @"AXTableSameLevelSearchKey"
365 #ifndef NSAccessibilityTableSearchKey
366 #define NSAccessibilityTableSearchKey @"AXTableSearchKey"
369 #ifndef NSAccessibilityTextFieldSearchKey
370 #define NSAccessibilityTextFieldSearchKey @"AXTextFieldSearchKey"
373 #ifndef NSAccessibilityUnderlineSearchKey
374 #define NSAccessibilityUnderlineSearchKey @"AXUnderlineSearchKey"
377 #ifndef NSAccessibilityUnvisitedLinkSearchKey
378 #define NSAccessibilityUnvisitedLinkSearchKey @"AXUnvisitedLinkSearchKey"
381 #ifndef NSAccessibilityVisitedLinkSearchKey
382 #define NSAccessibilityVisitedLinkSearchKey @"AXVisitedLinkSearchKey"
386 #ifndef NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute
387 #define NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute @"AXEndTextMarkerForBounds"
390 #ifndef NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute
391 #define NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute @"AXStartTextMarkerForBounds"
394 #ifndef NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute
395 #define NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute @"AXLineTextMarkerRangeForTextMarker"
399 #ifndef NSAccessibilitySelectTextActivity
400 #define NSAccessibilitySelectTextActivity @"AXSelectTextActivity"
403 #ifndef NSAccessibilitySelectTextActivityFindAndReplace
404 #define NSAccessibilitySelectTextActivityFindAndReplace @"AXSelectTextActivityFindAndReplace"
407 #ifndef NSAccessibilitySelectTextActivityFindAndSelect
408 #define NSAccessibilitySelectTextActivityFindAndSelect @"AXSelectTextActivityFindAndSelect"
411 #ifndef kAXSelectTextActivityFindAndCapitalize
412 #define kAXSelectTextActivityFindAndCapitalize @"AXSelectTextActivityFindAndCapitalize"
415 #ifndef kAXSelectTextActivityFindAndLowercase
416 #define kAXSelectTextActivityFindAndLowercase @"AXSelectTextActivityFindAndLowercase"
419 #ifndef kAXSelectTextActivityFindAndUppercase
420 #define kAXSelectTextActivityFindAndUppercase @"AXSelectTextActivityFindAndUppercase"
423 #ifndef NSAccessibilitySelectTextAmbiguityResolution
424 #define NSAccessibilitySelectTextAmbiguityResolution @"AXSelectTextAmbiguityResolution"
427 #ifndef NSAccessibilitySelectTextAmbiguityResolutionClosestAfterSelection
428 #define NSAccessibilitySelectTextAmbiguityResolutionClosestAfterSelection @"AXSelectTextAmbiguityResolutionClosestAfterSelection"
431 #ifndef NSAccessibilitySelectTextAmbiguityResolutionClosestBeforeSelection
432 #define NSAccessibilitySelectTextAmbiguityResolutionClosestBeforeSelection @"AXSelectTextAmbiguityResolutionClosestBeforeSelection"
435 #ifndef NSAccessibilitySelectTextAmbiguityResolutionClosestToSelection
436 #define NSAccessibilitySelectTextAmbiguityResolutionClosestToSelection @"AXSelectTextAmbiguityResolutionClosestToSelection"
439 #ifndef NSAccessibilitySelectTextReplacementString
440 #define NSAccessibilitySelectTextReplacementString @"AXSelectTextReplacementString"
443 #ifndef NSAccessibilitySelectTextSearchStrings
444 #define NSAccessibilitySelectTextSearchStrings @"AXSelectTextSearchStrings"
447 #ifndef NSAccessibilitySelectTextWithCriteriaParameterizedAttribute
448 #define NSAccessibilitySelectTextWithCriteriaParameterizedAttribute @"AXSelectTextWithCriteria"
452 #define NSAccessibilityMathRootRadicandAttribute @"AXMathRootRadicand"
453 #define NSAccessibilityMathRootIndexAttribute @"AXMathRootIndex"
454 #define NSAccessibilityMathFractionDenominatorAttribute @"AXMathFractionDenominator"
455 #define NSAccessibilityMathFractionNumeratorAttribute @"AXMathFractionNumerator"
456 #define NSAccessibilityMathBaseAttribute @"AXMathBase"
457 #define NSAccessibilityMathSubscriptAttribute @"AXMathSubscript"
458 #define NSAccessibilityMathSuperscriptAttribute @"AXMathSuperscript"
459 #define NSAccessibilityMathUnderAttribute @"AXMathUnder"
460 #define NSAccessibilityMathOverAttribute @"AXMathOver"
461 #define NSAccessibilityMathFencedOpenAttribute @"AXMathFencedOpen"
462 #define NSAccessibilityMathFencedCloseAttribute @"AXMathFencedClose"
463 #define NSAccessibilityMathLineThicknessAttribute @"AXMathLineThickness"
464 #define NSAccessibilityMathPrescriptsAttribute @"AXMathPrescripts"
465 #define NSAccessibilityMathPostscriptsAttribute @"AXMathPostscripts"
467 #ifndef NSAccessibilityCaretBrowsingEnabledAttribute
468 #define NSAccessibilityCaretBrowsingEnabledAttribute @"AXCaretBrowsingEnabled"
471 @implementation WebAccessibilityObjectWrapper
473 - (void)unregisterUniqueIdForUIElement
475 wkUnregisterUniqueIdForElement(self);
480 // Send unregisterUniqueIdForUIElement unconditionally because if it is
481 // ever accidentally not done (via other bugs in our AX implementation) you
482 // end up with a crash like <rdar://problem/4273149>. It is safe and not
483 // expensive to send even if the object is not registered.
484 [self unregisterUniqueIdForUIElement];
490 ASSERT(m_object->isAttachment());
491 Widget* widget = m_object->widgetForAttachmentView();
494 return NSAccessibilityUnignoredDescendant(widget->platformWidget());
497 #pragma mark SystemInterface wrappers
499 static inline BOOL AXObjectIsTextMarker(id obj)
501 return obj != nil && CFGetTypeID(obj) == wkGetAXTextMarkerTypeID();
504 static inline BOOL AXObjectIsTextMarkerRange(id obj)
506 return obj != nil && CFGetTypeID(obj) == wkGetAXTextMarkerRangeTypeID();
509 static id AXTextMarkerRange(id startMarker, id endMarker)
511 ASSERT(startMarker != nil);
512 ASSERT(endMarker != nil);
513 ASSERT(CFGetTypeID(startMarker) == wkGetAXTextMarkerTypeID());
514 ASSERT(CFGetTypeID(endMarker) == wkGetAXTextMarkerTypeID());
515 return CFBridgingRelease(wkCreateAXTextMarkerRange((CFTypeRef)startMarker, (CFTypeRef)endMarker));
518 static id AXTextMarkerRangeStart(id range)
520 ASSERT(range != nil);
521 ASSERT(CFGetTypeID(range) == wkGetAXTextMarkerRangeTypeID());
522 return CFBridgingRelease(wkCopyAXTextMarkerRangeStart(range));
525 static id AXTextMarkerRangeEnd(id range)
527 ASSERT(range != nil);
528 ASSERT(CFGetTypeID(range) == wkGetAXTextMarkerRangeTypeID());
529 return CFBridgingRelease(wkCopyAXTextMarkerRangeEnd(range));
532 #pragma mark Other helpers
534 - (IntRect)screenToContents:(const IntRect&)rect
536 Document* document = m_object->document();
540 FrameView* frameView = document->view();
544 IntPoint startPoint = frameView->screenToContents(rect.minXMaxYCorner());
545 IntPoint endPoint = frameView->screenToContents(rect.maxXMinYCorner());
546 return IntRect(startPoint.x(), startPoint.y(), endPoint.x() - startPoint.x(), endPoint.y() - startPoint.y());
549 #pragma mark Search helpers
551 typedef HashMap<String, AccessibilitySearchKey> AccessibilitySearchKeyMap;
553 struct SearchKeyEntry {
555 AccessibilitySearchKey value;
558 static AccessibilitySearchKeyMap* createAccessibilitySearchKeyMap()
560 const SearchKeyEntry searchKeys[] = {
561 { NSAccessibilityAnyTypeSearchKey, AnyTypeSearchKey },
562 { NSAccessibilityBlockquoteSameLevelSearchKey, BlockquoteSameLevelSearchKey },
563 { NSAccessibilityBlockquoteSearchKey, BlockquoteSearchKey },
564 { NSAccessibilityBoldFontSearchKey, BoldFontSearchKey },
565 { NSAccessibilityButtonSearchKey, ButtonSearchKey },
566 { NSAccessibilityCheckBoxSearchKey, CheckBoxSearchKey },
567 { NSAccessibilityControlSearchKey, ControlSearchKey },
568 { NSAccessibilityDifferentTypeSearchKey, DifferentTypeSearchKey },
569 { NSAccessibilityFontChangeSearchKey, FontChangeSearchKey },
570 { NSAccessibilityFontColorChangeSearchKey, FontColorChangeSearchKey },
571 { NSAccessibilityFrameSearchKey, FrameSearchKey },
572 { NSAccessibilityGraphicSearchKey, GraphicSearchKey },
573 { NSAccessibilityHeadingLevel1SearchKey, HeadingLevel1SearchKey },
574 { NSAccessibilityHeadingLevel2SearchKey, HeadingLevel2SearchKey },
575 { NSAccessibilityHeadingLevel3SearchKey, HeadingLevel3SearchKey },
576 { NSAccessibilityHeadingLevel4SearchKey, HeadingLevel4SearchKey },
577 { NSAccessibilityHeadingLevel5SearchKey, HeadingLevel5SearchKey },
578 { NSAccessibilityHeadingLevel6SearchKey, HeadingLevel6SearchKey },
579 { NSAccessibilityHeadingSameLevelSearchKey, HeadingSameLevelSearchKey },
580 { NSAccessibilityHeadingSearchKey, HeadingSearchKey },
581 { NSAccessibilityHighlightedSearchKey, HighlightedSearchKey },
582 { NSAccessibilityItalicFontSearchKey, ItalicFontSearchKey },
583 { NSAccessibilityLandmarkSearchKey, LandmarkSearchKey },
584 { NSAccessibilityLinkSearchKey, LinkSearchKey },
585 { NSAccessibilityListSearchKey, ListSearchKey },
586 { NSAccessibilityLiveRegionSearchKey, LiveRegionSearchKey },
587 { NSAccessibilityMisspelledWordSearchKey, MisspelledWordSearchKey },
588 { NSAccessibilityOutlineSearchKey, OutlineSearchKey },
589 { NSAccessibilityPlainTextSearchKey, PlainTextSearchKey },
590 { NSAccessibilityRadioGroupSearchKey, RadioGroupSearchKey },
591 { NSAccessibilitySameTypeSearchKey, SameTypeSearchKey },
592 { NSAccessibilityStaticTextSearchKey, StaticTextSearchKey },
593 { NSAccessibilityStyleChangeSearchKey, StyleChangeSearchKey },
594 { NSAccessibilityTableSameLevelSearchKey, TableSameLevelSearchKey },
595 { NSAccessibilityTableSearchKey, TableSearchKey },
596 { NSAccessibilityTextFieldSearchKey, TextFieldSearchKey },
597 { NSAccessibilityUnderlineSearchKey, UnderlineSearchKey },
598 { NSAccessibilityUnvisitedLinkSearchKey, UnvisitedLinkSearchKey },
599 { NSAccessibilityVisitedLinkSearchKey, VisitedLinkSearchKey }
602 AccessibilitySearchKeyMap* searchKeyMap = new AccessibilitySearchKeyMap;
603 for (size_t i = 0; i < WTF_ARRAY_LENGTH(searchKeys); i++)
604 searchKeyMap->set(searchKeys[i].key, searchKeys[i].value);
609 static AccessibilitySearchKey accessibilitySearchKeyForString(const String& value)
612 return AnyTypeSearchKey;
614 static const AccessibilitySearchKeyMap* searchKeyMap = createAccessibilitySearchKeyMap();
616 AccessibilitySearchKey searchKey = searchKeyMap->get(value);
618 return searchKey ? searchKey : AnyTypeSearchKey;
621 static AccessibilitySearchCriteria accessibilitySearchCriteriaForSearchPredicateParameterizedAttribute(const NSDictionary *parameterizedAttribute)
623 NSString *directionParameter = [parameterizedAttribute objectForKey:@"AXDirection"];
624 NSNumber *immediateDescendantsOnlyParameter = [parameterizedAttribute objectForKey:NSAccessibilityImmediateDescendantsOnly];
625 NSNumber *resultsLimitParameter = [parameterizedAttribute objectForKey:@"AXResultsLimit"];
626 NSString *searchTextParameter = [parameterizedAttribute objectForKey:@"AXSearchText"];
627 WebAccessibilityObjectWrapper *startElementParameter = [parameterizedAttribute objectForKey:@"AXStartElement"];
628 NSNumber *visibleOnlyParameter = [parameterizedAttribute objectForKey:@"AXVisibleOnly"];
629 id searchKeyParameter = [parameterizedAttribute objectForKey:@"AXSearchKey"];
631 AccessibilitySearchDirection direction = SearchDirectionNext;
632 if ([directionParameter isKindOfClass:[NSString class]])
633 direction = [directionParameter isEqualToString:@"AXDirectionNext"] ? SearchDirectionNext : SearchDirectionPrevious;
635 bool immediateDescendantsOnly = false;
636 if ([immediateDescendantsOnlyParameter isKindOfClass:[NSNumber class]])
637 immediateDescendantsOnly = [immediateDescendantsOnlyParameter boolValue];
639 unsigned resultsLimit = 0;
640 if ([resultsLimitParameter isKindOfClass:[NSNumber class]])
641 resultsLimit = [resultsLimitParameter unsignedIntValue];
644 if ([searchTextParameter isKindOfClass:[NSString class]])
645 searchText = searchTextParameter;
647 AccessibilityObject *startElement = nullptr;
648 if ([startElementParameter isKindOfClass:[WebAccessibilityObjectWrapper class]])
649 startElement = [startElementParameter accessibilityObject];
651 bool visibleOnly = false;
652 if ([visibleOnlyParameter isKindOfClass:[NSNumber class]])
653 visibleOnly = [visibleOnlyParameter boolValue];
655 AccessibilitySearchCriteria criteria = AccessibilitySearchCriteria(startElement, direction, searchText, resultsLimit, visibleOnly, immediateDescendantsOnly);
657 if ([searchKeyParameter isKindOfClass:[NSString class]])
658 criteria.searchKeys.append(accessibilitySearchKeyForString(searchKeyParameter));
659 else if ([searchKeyParameter isKindOfClass:[NSArray class]]) {
660 size_t searchKeyCount = static_cast<size_t>([searchKeyParameter count]);
661 criteria.searchKeys.reserveInitialCapacity(searchKeyCount);
662 for (size_t i = 0; i < searchKeyCount; ++i) {
663 NSString *searchKey = [searchKeyParameter objectAtIndex:i];
664 if ([searchKey isKindOfClass:[NSString class]])
665 criteria.searchKeys.uncheckedAppend(accessibilitySearchKeyForString(searchKey));
672 #pragma mark Select text helpers
674 static AccessibilitySelectTextCriteria accessibilitySelectTextCriteriaForCriteriaParameterizedAttribute(const NSDictionary *parameterizedAttribute)
676 NSString *activityParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextActivity];
677 NSString *ambiguityResolutionParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextAmbiguityResolution];
678 NSString *replacementStringParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextReplacementString];
679 NSArray *searchStringsParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextSearchStrings];
681 AccessibilitySelectTextActivity activity = FindAndSelectActivity;
682 if ([activityParameter isKindOfClass:[NSString class]]) {
683 if ([activityParameter isEqualToString:NSAccessibilitySelectTextActivityFindAndReplace])
684 activity = FindAndReplaceActivity;
685 else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndCapitalize])
686 activity = FindAndCapitalize;
687 else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndLowercase])
688 activity = FindAndLowercase;
689 else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndUppercase])
690 activity = FindAndUppercase;
693 AccessibilitySelectTextAmbiguityResolution ambiguityResolution = ClosestToSelectionAmbiguityResolution;
694 if ([ambiguityResolutionParameter isKindOfClass:[NSString class]]) {
695 if ([ambiguityResolutionParameter isEqualToString:NSAccessibilitySelectTextAmbiguityResolutionClosestAfterSelection])
696 ambiguityResolution = ClosestAfterSelectionAmbiguityResolution;
697 else if ([ambiguityResolutionParameter isEqualToString:NSAccessibilitySelectTextAmbiguityResolutionClosestBeforeSelection])
698 ambiguityResolution = ClosestBeforeSelectionAmbiguityResolution;
701 String replacementString;
702 if ([replacementStringParameter isKindOfClass:[NSString class]])
703 replacementString = replacementStringParameter;
705 AccessibilitySelectTextCriteria criteria(activity, ambiguityResolution, replacementString);
707 if ([searchStringsParameter isKindOfClass:[NSArray class]]) {
708 size_t searchStringsCount = static_cast<size_t>([searchStringsParameter count]);
709 criteria.searchStrings.reserveInitialCapacity(searchStringsCount);
710 for (NSString *searchString in searchStringsParameter) {
711 if ([searchString isKindOfClass:[NSString class]])
712 criteria.searchStrings.uncheckedAppend(searchString);
719 #pragma mark Text Marker helpers
721 static id textMarkerForVisiblePosition(AXObjectCache* cache, const VisiblePosition& visiblePos)
725 TextMarkerData textMarkerData;
726 cache->textMarkerDataForVisiblePosition(textMarkerData, visiblePos);
727 if (!textMarkerData.axID)
730 return CFBridgingRelease(wkCreateAXTextMarker(&textMarkerData, sizeof(textMarkerData)));
733 - (id)textMarkerForVisiblePosition:(const VisiblePosition &)visiblePos
735 return textMarkerForVisiblePosition(m_object->axObjectCache(), visiblePos);
738 static VisiblePosition visiblePositionForTextMarker(AXObjectCache* cache, CFTypeRef textMarker)
743 return VisiblePosition();
744 TextMarkerData textMarkerData;
745 if (!wkGetBytesFromAXTextMarker(textMarker, &textMarkerData, sizeof(textMarkerData)))
746 return VisiblePosition();
748 return cache->visiblePositionForTextMarkerData(textMarkerData);
751 - (VisiblePosition)visiblePositionForTextMarker:(id)textMarker
753 return visiblePositionForTextMarker(m_object->axObjectCache(), textMarker);
756 static VisiblePosition visiblePositionForStartOfTextMarkerRange(AXObjectCache *cache, id textMarkerRange)
758 return visiblePositionForTextMarker(cache, AXTextMarkerRangeStart(textMarkerRange));
761 static VisiblePosition visiblePositionForEndOfTextMarkerRange(AXObjectCache *cache, id textMarkerRange)
763 return visiblePositionForTextMarker(cache, AXTextMarkerRangeEnd(textMarkerRange));
766 static id textMarkerRangeFromMarkers(id textMarker1, id textMarker2)
768 if (!textMarker1 || !textMarker2)
771 return AXTextMarkerRange(textMarker1, textMarker2);
774 // When modifying attributed strings, the range can come from a source which may provide faulty information (e.g. the spell checker).
775 // To protect against such cases the range should be validated before adding or removing attributes.
776 static BOOL AXAttributedStringRangeIsValid(NSAttributedString* attrString, NSRange range)
778 return (range.location < [attrString length] && NSMaxRange(range) <= [attrString length]);
781 static void AXAttributeStringSetFont(NSMutableAttributedString* attrString, NSString* attribute, NSFont* font, NSRange range)
783 if (!AXAttributedStringRangeIsValid(attrString, range))
787 NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
788 [font fontName] , NSAccessibilityFontNameKey,
789 [font familyName] , NSAccessibilityFontFamilyKey,
790 [font displayName] , NSAccessibilityVisibleNameKey,
791 [NSNumber numberWithFloat:[font pointSize]] , NSAccessibilityFontSizeKey,
794 [attrString addAttribute:attribute value:dict range:range];
796 [attrString removeAttribute:attribute range:range];
800 static CGColorRef CreateCGColorIfDifferent(NSColor* nsColor, CGColorRef existingColor)
802 // get color information assuming NSDeviceRGBColorSpace
803 NSColor* rgbColor = [nsColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
805 rgbColor = [NSColor blackColor];
806 CGFloat components[4];
807 [rgbColor getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]];
809 // create a new CGColorRef to return
810 CGColorSpaceRef cgColorSpace = CGColorSpaceCreateDeviceRGB();
811 CGColorRef cgColor = CGColorCreate(cgColorSpace, components);
812 CGColorSpaceRelease(cgColorSpace);
814 // check for match with existing color
815 if (existingColor && CGColorEqualToColor(cgColor, existingColor)) {
816 CGColorRelease(cgColor);
823 static void AXAttributeStringSetColor(NSMutableAttributedString* attrString, NSString* attribute, NSColor* color, NSRange range)
825 if (!AXAttributedStringRangeIsValid(attrString, range))
829 CGColorRef existingColor = (CGColorRef) [attrString attribute:attribute atIndex:range.location effectiveRange:nil];
830 CGColorRef cgColor = CreateCGColorIfDifferent(color, existingColor);
832 [attrString addAttribute:attribute value:(id)cgColor range:range];
833 CGColorRelease(cgColor);
836 [attrString removeAttribute:attribute range:range];
839 static void AXAttributeStringSetNumber(NSMutableAttributedString* attrString, NSString* attribute, NSNumber* number, NSRange range)
841 if (!AXAttributedStringRangeIsValid(attrString, range))
845 [attrString addAttribute:attribute value:number range:range];
847 [attrString removeAttribute:attribute range:range];
850 static void AXAttributeStringSetStyle(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
852 const RenderStyle& style = renderer->style();
854 // set basic font info
855 AXAttributeStringSetFont(attrString, NSAccessibilityFontTextAttribute, style.fontCascade().primaryFont().getNSFont(), range);
858 AXAttributeStringSetColor(attrString, NSAccessibilityForegroundColorTextAttribute, nsColor(style.visitedDependentColor(CSSPropertyColor)), range);
859 AXAttributeStringSetColor(attrString, NSAccessibilityBackgroundColorTextAttribute, nsColor(style.visitedDependentColor(CSSPropertyBackgroundColor)), range);
861 // set super/sub scripting
862 EVerticalAlign alignment = style.verticalAlign();
863 if (alignment == SUB)
864 AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:(-1)], range);
865 else if (alignment == SUPER)
866 AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:1], range);
868 [attrString removeAttribute:NSAccessibilitySuperscriptTextAttribute range:range];
871 if (style.textShadow())
872 AXAttributeStringSetNumber(attrString, NSAccessibilityShadowTextAttribute, [NSNumber numberWithBool:YES], range);
874 [attrString removeAttribute:NSAccessibilityShadowTextAttribute range:range];
876 // set underline and strikethrough
877 int decor = style.textDecorationsInEffect();
878 if ((decor & TextDecorationUnderline) == 0) {
879 [attrString removeAttribute:NSAccessibilityUnderlineTextAttribute range:range];
880 [attrString removeAttribute:NSAccessibilityUnderlineColorTextAttribute range:range];
883 if ((decor & TextDecorationLineThrough) == 0) {
884 [attrString removeAttribute:NSAccessibilityStrikethroughTextAttribute range:range];
885 [attrString removeAttribute:NSAccessibilityStrikethroughColorTextAttribute range:range];
888 if ((decor & (TextDecorationUnderline | TextDecorationLineThrough)) != 0) {
889 // FIXME: Should the underline style be reported here?
890 Color underlineColor, overlineColor, linethroughColor;
891 TextDecorationStyle underlineStyle, overlineStyle, linethroughStyle;
892 renderer->getTextDecorationColorsAndStyles(decor, underlineColor, overlineColor, linethroughColor, underlineStyle, overlineStyle, linethroughStyle);
894 if ((decor & TextDecorationUnderline) != 0) {
895 AXAttributeStringSetNumber(attrString, NSAccessibilityUnderlineTextAttribute, [NSNumber numberWithBool:YES], range);
896 AXAttributeStringSetColor(attrString, NSAccessibilityUnderlineColorTextAttribute, nsColor(underlineColor), range);
899 if ((decor & TextDecorationLineThrough) != 0) {
900 AXAttributeStringSetNumber(attrString, NSAccessibilityStrikethroughTextAttribute, [NSNumber numberWithBool:YES], range);
901 AXAttributeStringSetColor(attrString, NSAccessibilityStrikethroughColorTextAttribute, nsColor(linethroughColor), range);
905 // Indicate background highlighting.
906 for (Node* node = renderer->node(); node; node = node->parentNode()) {
907 if (node->hasTagName(markTag))
908 AXAttributeStringSetNumber(attrString, @"AXHighlight", [NSNumber numberWithBool:YES], range);
912 static void AXAttributeStringSetBlockquoteLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
914 if (!AXAttributedStringRangeIsValid(attrString, range))
917 AccessibilityObject* obj = renderer->document().axObjectCache()->getOrCreate(renderer);
918 int quoteLevel = obj->blockquoteLevel();
921 [attrString addAttribute:NSAccessibilityBlockQuoteLevelAttribute value:[NSNumber numberWithInt:quoteLevel] range:range];
923 [attrString removeAttribute:NSAccessibilityBlockQuoteLevelAttribute range:range];
926 static void AXAttributeStringSetSpelling(NSMutableAttributedString* attrString, Node* node, StringView text, NSRange range)
928 if (unifiedTextCheckerEnabled(node->document().frame())) {
929 // Check the spelling directly since document->markersForNode() does not store the misspelled marking when the cursor is in a word.
930 TextCheckerClient* checker = node->document().frame()->editor().textChecker();
932 // checkTextOfParagraph is the only spelling/grammar checker implemented in WK1 and WK2
933 Vector<TextCheckingResult> results;
934 checkTextOfParagraph(*checker, text, TextCheckingTypeSpelling, results);
936 size_t size = results.size();
937 NSNumber* trueValue = [NSNumber numberWithBool:YES];
938 for (unsigned i = 0; i < size; i++) {
939 const TextCheckingResult& result = results[i];
940 AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, trueValue, NSMakeRange(result.location + range.location, result.length));
942 AXAttributeStringSetNumber(attrString, NSAccessibilityMarkedMisspelledTextAttribute, trueValue, NSMakeRange(result.location + range.location, result.length));
948 for (unsigned currentPosition = 0; currentPosition < text.length(); ) {
949 int misspellingLocation = -1;
950 int misspellingLength = 0;
951 node->document().frame()->editor().textChecker()->checkSpellingOfString(text.substring(currentPosition), &misspellingLocation, &misspellingLength);
952 if (misspellingLocation == -1 || !misspellingLength)
955 NSRange spellRange = NSMakeRange(range.location + currentPosition + misspellingLocation, misspellingLength);
956 AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, [NSNumber numberWithBool:YES], spellRange);
958 AXAttributeStringSetNumber(attrString, NSAccessibilityMarkedMisspelledTextAttribute, [NSNumber numberWithBool:YES], spellRange);
961 currentPosition += misspellingLocation + misspellingLength;
965 static void AXAttributeStringSetexpandedTextValue(NSMutableAttributedString *attrString, RenderObject* renderer, NSRange range)
967 if (!renderer || !AXAttributedStringRangeIsValid(attrString, range))
969 AccessibilityObject* axObject = renderer->document().axObjectCache()->getOrCreate(renderer);
970 if (axObject->supportsExpandedTextValue())
971 [attrString addAttribute:NSAccessibilityExpandedTextValueAttribute value:axObject->expandedTextValue() range:range];
973 [attrString removeAttribute:NSAccessibilityExpandedTextValueAttribute range:range];
976 static void AXAttributeStringSetHeadingLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
981 if (!AXAttributedStringRangeIsValid(attrString, range))
984 // Sometimes there are objects between the text and the heading.
985 // In those cases the parent hierarchy should be queried to see if there is a heading level.
986 int parentHeadingLevel = 0;
987 AccessibilityObject* parentObject = renderer->document().axObjectCache()->getOrCreate(renderer->parent());
988 for (; parentObject; parentObject = parentObject->parentObject()) {
989 parentHeadingLevel = parentObject->headingLevel();
990 if (parentHeadingLevel)
994 if (parentHeadingLevel)
995 [attrString addAttribute:@"AXHeadingLevel" value:[NSNumber numberWithInt:parentHeadingLevel] range:range];
997 [attrString removeAttribute:@"AXHeadingLevel" range:range];
1000 static void AXAttributeStringSetElement(NSMutableAttributedString* attrString, NSString* attribute, AccessibilityObject* object, NSRange range)
1002 if (!AXAttributedStringRangeIsValid(attrString, range))
1005 if (is<AccessibilityRenderObject>(object)) {
1006 // make a serializable AX object
1008 RenderObject* renderer = downcast<AccessibilityRenderObject>(*object).renderer();
1012 AXObjectCache* cache = renderer->document().axObjectCache();
1016 AXUIElementRef axElement = wkCreateAXUIElementRef(object->wrapper());
1018 [attrString addAttribute:attribute value:(id)axElement range:range];
1019 CFRelease(axElement);
1022 [attrString removeAttribute:attribute range:range];
1025 static void AXAttributedStringAppendText(NSMutableAttributedString* attrString, Node* node, StringView text)
1027 // skip invisible text
1028 RenderObject* renderer = node->renderer();
1032 // easier to calculate the range before appending the string
1033 NSRange attrStringRange = NSMakeRange([attrString length], text.length());
1035 // append the string from this node
1036 [[attrString mutableString] appendString:text.createNSStringWithoutCopying().get()];
1038 // add new attributes and remove irrelevant inherited ones
1039 // NOTE: color attributes are handled specially because -[NSMutableAttributedString addAttribute: value: range:] does not merge
1040 // identical colors. Workaround is to not replace an existing color attribute if it matches what we are adding. This also means
1041 // we cannot just pre-remove all inherited attributes on the appended string, so we have to remove the irrelevant ones individually.
1043 // remove inherited attachment from prior AXAttributedStringAppendReplaced
1044 [attrString removeAttribute:NSAccessibilityAttachmentTextAttribute range:attrStringRange];
1046 [attrString removeAttribute:NSAccessibilityMarkedMisspelledTextAttribute range:attrStringRange];
1048 [attrString removeAttribute:NSAccessibilityMisspelledTextAttribute range:attrStringRange];
1050 // set new attributes
1051 AXAttributeStringSetStyle(attrString, renderer, attrStringRange);
1052 AXAttributeStringSetHeadingLevel(attrString, renderer, attrStringRange);
1053 AXAttributeStringSetBlockquoteLevel(attrString, renderer, attrStringRange);
1054 AXAttributeStringSetexpandedTextValue(attrString, renderer, attrStringRange);
1055 AXAttributeStringSetElement(attrString, NSAccessibilityLinkTextAttribute, AccessibilityObject::anchorElementForNode(node), attrStringRange);
1057 // do spelling last because it tends to break up the range
1058 AXAttributeStringSetSpelling(attrString, node, text, attrStringRange);
1061 static NSString* nsStringForReplacedNode(Node* replacedNode)
1063 // we should always be given a rendered node and a replaced node, but be safe
1064 // replaced nodes are either attachments (widgets) or images
1065 if (!replacedNode || !isRendererReplacedElement(replacedNode->renderer()) || replacedNode->isTextNode()) {
1066 ASSERT_NOT_REACHED();
1070 // create an AX object, but skip it if it is not supposed to be seen
1071 RefPtr<AccessibilityObject> obj = replacedNode->renderer()->document().axObjectCache()->getOrCreate(replacedNode->renderer());
1072 if (obj->accessibilityIsIgnored())
1075 // use the attachmentCharacter to represent the replaced node
1076 const UniChar attachmentChar = NSAttachmentCharacter;
1077 return [NSString stringWithCharacters:&attachmentChar length:1];
1080 - (NSAttributedString*)doAXAttributedStringForTextMarkerRange:(id)textMarkerRange
1085 // extract the start and end VisiblePosition
1086 VisiblePosition startVisiblePosition = visiblePositionForStartOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);
1087 if (startVisiblePosition.isNull())
1090 VisiblePosition endVisiblePosition = visiblePositionForEndOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);
1091 if (endVisiblePosition.isNull())
1094 VisiblePositionRange visiblePositionRange(startVisiblePosition, endVisiblePosition);
1095 // iterate over the range to build the AX attributed string
1096 NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] init];
1097 TextIterator it(makeRange(startVisiblePosition, endVisiblePosition).get());
1098 while (!it.atEnd()) {
1099 // locate the node and starting offset for this range
1101 Node* node = it.range()->startContainer(exception);
1102 ASSERT(node == it.range()->endContainer(exception));
1103 int offset = it.range()->startOffset(exception);
1105 // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX)
1106 if (it.text().length()) {
1107 // Add the text of the list marker item if necessary.
1108 String listMarkerText = m_object->listMarkerTextForNodeAndPosition(node, VisiblePosition(it.range()->startPosition()));
1109 if (!listMarkerText.isEmpty())
1110 AXAttributedStringAppendText(attrString, node, listMarkerText);
1111 AXAttributedStringAppendText(attrString, node, it.text());
1113 Node* replacedNode = node->traverseToChildAt(offset);
1114 NSString *attachmentString = nsStringForReplacedNode(replacedNode);
1115 if (attachmentString) {
1116 NSRange attrStringRange = NSMakeRange([attrString length], [attachmentString length]);
1118 // append the placeholder string
1119 [[attrString mutableString] appendString:attachmentString];
1121 // remove all inherited attributes
1122 [attrString setAttributes:nil range:attrStringRange];
1124 // add the attachment attribute
1125 AccessibilityObject* obj = replacedNode->renderer()->document().axObjectCache()->getOrCreate(replacedNode->renderer());
1126 AXAttributeStringSetElement(attrString, NSAccessibilityAttachmentTextAttribute, obj, attrStringRange);
1132 return [attrString autorelease];
1135 static id textMarkerRangeFromVisiblePositions(AXObjectCache *cache, VisiblePosition startPosition, VisiblePosition endPosition)
1137 id startTextMarker = textMarkerForVisiblePosition(cache, startPosition);
1138 id endTextMarker = textMarkerForVisiblePosition(cache, endPosition);
1139 return textMarkerRangeFromMarkers(startTextMarker, endTextMarker);
1142 - (id)textMarkerRangeFromVisiblePositions:(VisiblePosition)startPosition endPosition:(VisiblePosition)endPosition
1144 return textMarkerRangeFromVisiblePositions(m_object->axObjectCache(), startPosition, endPosition);
1147 - (NSArray*)accessibilityActionNames
1149 if (![self updateObjectBackingStore])
1152 // All elements should get ShowMenu and ScrollToVisible.
1153 // But certain earlier VoiceOver versions do not support scroll to visible, and it confuses them to see it in the list.
1154 static NSArray *defaultElementActions = [[NSArray alloc] initWithObjects:NSAccessibilityShowMenuAction, NSAccessibilityScrollToVisibleAction, nil];
1156 // Action elements allow Press.
1157 // 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.
1158 static NSArray *actionElementActions = [[NSArray alloc] initWithObjects:NSAccessibilityPressAction, NSAccessibilityShowMenuAction, NSAccessibilityScrollToVisibleAction, nil];
1160 // Menu elements allow Press and Cancel.
1161 static NSArray *menuElementActions = [[actionElementActions arrayByAddingObject:NSAccessibilityCancelAction] retain];
1163 // Slider elements allow Increment/Decrement.
1164 static NSArray *sliderActions = [[defaultElementActions arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:NSAccessibilityIncrementAction, NSAccessibilityDecrementAction, nil]] retain];
1167 if (m_object->supportsPressAction())
1168 actions = actionElementActions;
1169 else if (m_object->isMenuRelated())
1170 actions = menuElementActions;
1171 else if (m_object->isSlider())
1172 actions = sliderActions;
1173 else if (m_object->isAttachment())
1174 actions = [[self attachmentView] accessibilityActionNames];
1176 actions = defaultElementActions;
1181 - (NSArray*)additionalAccessibilityAttributeNames
1186 NSMutableArray *additional = [NSMutableArray array];
1187 if (m_object->supportsARIAOwns())
1188 [additional addObject:NSAccessibilityOwnsAttribute];
1190 if (m_object->supportsARIAExpanded())
1191 [additional addObject:NSAccessibilityExpandedAttribute];
1193 if (m_object->isScrollbar())
1194 [additional addObject:NSAccessibilityOrientationAttribute];
1196 if (m_object->supportsARIADragging())
1197 [additional addObject:NSAccessibilityGrabbedAttribute];
1199 if (m_object->supportsARIADropping())
1200 [additional addObject:NSAccessibilityDropEffectsAttribute];
1202 if (is<AccessibilityTable>(*m_object) && downcast<AccessibilityTable>(*m_object).isExposableThroughAccessibility() && downcast<AccessibilityTable>(*m_object).supportsSelectedRows())
1203 [additional addObject:NSAccessibilitySelectedRowsAttribute];
1205 if (m_object->supportsARIALiveRegion()) {
1206 [additional addObject:NSAccessibilityARIALiveAttribute];
1207 [additional addObject:NSAccessibilityARIARelevantAttribute];
1210 if (m_object->supportsARIASetSize())
1211 [additional addObject:NSAccessibilityARIASetSizeAttribute];
1212 if (m_object->supportsARIAPosInSet())
1213 [additional addObject:NSAccessibilityARIAPosInSetAttribute];
1215 if (m_object->sortDirection() != SortDirectionNone)
1216 [additional addObject:NSAccessibilitySortDirectionAttribute];
1218 // If an object is a child of a live region, then add these
1219 if (m_object->isInsideARIALiveRegion())
1220 [additional addObject:NSAccessibilityARIAAtomicAttribute];
1221 // All objects should expose the ARIA busy attribute (ARIA 1.1 with ISSUE-538).
1222 [additional addObject:NSAccessibilityElementBusyAttribute];
1224 // Popup buttons on the Mac expose the value attribute.
1225 if (m_object->isPopUpButton()) {
1226 [additional addObject:NSAccessibilityValueAttribute];
1229 if (m_object->supportsRequiredAttribute()) {
1230 [additional addObject:NSAccessibilityRequiredAttribute];
1233 if (m_object->ariaHasPopup())
1234 [additional addObject:NSAccessibilityHasPopupAttribute];
1236 if (m_object->isMathRoot()) {
1237 // The index of a square root is always known, so there's no object associated with it.
1238 if (!m_object->isMathSquareRoot())
1239 [additional addObject:NSAccessibilityMathRootIndexAttribute];
1240 [additional addObject:NSAccessibilityMathRootRadicandAttribute];
1241 } else if (m_object->isMathFraction()) {
1242 [additional addObject:NSAccessibilityMathFractionNumeratorAttribute];
1243 [additional addObject:NSAccessibilityMathFractionDenominatorAttribute];
1244 [additional addObject:NSAccessibilityMathLineThicknessAttribute];
1245 } else if (m_object->isMathSubscriptSuperscript()) {
1246 [additional addObject:NSAccessibilityMathBaseAttribute];
1247 [additional addObject:NSAccessibilityMathSubscriptAttribute];
1248 [additional addObject:NSAccessibilityMathSuperscriptAttribute];
1249 } else if (m_object->isMathUnderOver()) {
1250 [additional addObject:NSAccessibilityMathBaseAttribute];
1251 [additional addObject:NSAccessibilityMathUnderAttribute];
1252 [additional addObject:NSAccessibilityMathOverAttribute];
1253 } else if (m_object->isMathFenced()) {
1254 [additional addObject:NSAccessibilityMathFencedOpenAttribute];
1255 [additional addObject:NSAccessibilityMathFencedCloseAttribute];
1256 } else if (m_object->isMathMultiscript()) {
1257 [additional addObject:NSAccessibilityMathBaseAttribute];
1258 [additional addObject:NSAccessibilityMathPrescriptsAttribute];
1259 [additional addObject:NSAccessibilityMathPostscriptsAttribute];
1262 if (m_object->supportsPath())
1263 [additional addObject:NSAccessibilityPathAttribute];
1265 if (m_object->supportsExpandedTextValue())
1266 [additional addObject:NSAccessibilityExpandedTextValueAttribute];
1271 - (NSArray*)accessibilityAttributeNames
1273 if (![self updateObjectBackingStore])
1276 if (m_object->isAttachment())
1277 return [[self attachmentView] accessibilityAttributeNames];
1279 static NSArray* attributes = nil;
1280 static NSArray* anchorAttrs = nil;
1281 static NSArray* webAreaAttrs = nil;
1282 static NSArray* textAttrs = nil;
1283 static NSArray* listAttrs = nil;
1284 static NSArray* listBoxAttrs = nil;
1285 static NSArray* rangeAttrs = nil;
1286 static NSArray* commonMenuAttrs = nil;
1287 static NSArray* menuAttrs = nil;
1288 static NSArray* menuBarAttrs = nil;
1289 static NSArray* menuItemAttrs = nil;
1290 static NSArray* menuButtonAttrs = nil;
1291 static NSArray* controlAttrs = nil;
1292 static NSArray* tableAttrs = nil;
1293 static NSArray* tableRowAttrs = nil;
1294 static NSArray* tableColAttrs = nil;
1295 static NSArray* tableCellAttrs = nil;
1296 static NSArray* groupAttrs = nil;
1297 static NSArray* inputImageAttrs = nil;
1298 static NSArray* passwordFieldAttrs = nil;
1299 static NSArray* tabListAttrs = nil;
1300 static NSArray* comboBoxAttrs = nil;
1301 static NSArray* outlineAttrs = nil;
1302 static NSArray* outlineRowAttrs = nil;
1303 static NSArray* buttonAttrs = nil;
1304 static NSArray* scrollViewAttrs = nil;
1305 static NSArray* incrementorAttrs = nil;
1306 NSMutableArray* tempArray;
1307 if (attributes == nil) {
1308 attributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1309 NSAccessibilitySubroleAttribute,
1310 NSAccessibilityRoleDescriptionAttribute,
1311 NSAccessibilityChildrenAttribute,
1312 NSAccessibilityHelpAttribute,
1313 NSAccessibilityParentAttribute,
1314 NSAccessibilityPositionAttribute,
1315 NSAccessibilitySizeAttribute,
1316 NSAccessibilityTitleAttribute,
1317 NSAccessibilityDescriptionAttribute,
1318 NSAccessibilityValueAttribute,
1319 NSAccessibilityFocusedAttribute,
1320 NSAccessibilityEnabledAttribute,
1321 NSAccessibilityWindowAttribute,
1322 @"AXSelectedTextMarkerRange",
1323 @"AXStartTextMarker",
1326 NSAccessibilityLinkedUIElementsAttribute,
1327 NSAccessibilitySelectedAttribute,
1328 NSAccessibilityBlockQuoteLevelAttribute,
1329 NSAccessibilityTopLevelUIElementAttribute,
1330 NSAccessibilityLanguageAttribute,
1331 NSAccessibilityDOMIdentifierAttribute,
1332 NSAccessibilityDOMClassListAttribute,
1335 if (commonMenuAttrs == nil) {
1336 commonMenuAttrs = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1337 NSAccessibilityRoleDescriptionAttribute,
1338 NSAccessibilityChildrenAttribute,
1339 NSAccessibilityParentAttribute,
1340 NSAccessibilityEnabledAttribute,
1341 NSAccessibilityPositionAttribute,
1342 NSAccessibilitySizeAttribute,
1345 if (anchorAttrs == nil) {
1346 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1347 [tempArray addObject:NSAccessibilityURLAttribute];
1348 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1349 anchorAttrs = [[NSArray alloc] initWithArray:tempArray];
1350 [tempArray release];
1352 if (webAreaAttrs == nil) {
1353 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1354 // WebAreas should not expose AXSubrole.
1355 [tempArray removeObject:NSAccessibilitySubroleAttribute];
1356 [tempArray addObject:@"AXLinkUIElements"];
1357 [tempArray addObject:@"AXLoaded"];
1358 [tempArray addObject:@"AXLayoutCount"];
1359 [tempArray addObject:NSAccessibilityLoadingProgressAttribute];
1360 [tempArray addObject:NSAccessibilityURLAttribute];
1361 [tempArray addObject:NSAccessibilityCaretBrowsingEnabledAttribute];
1362 webAreaAttrs = [[NSArray alloc] initWithArray:tempArray];
1363 [tempArray release];
1365 if (textAttrs == nil) {
1366 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1367 [tempArray addObject:NSAccessibilityNumberOfCharactersAttribute];
1368 [tempArray addObject:NSAccessibilitySelectedTextAttribute];
1369 [tempArray addObject:NSAccessibilitySelectedTextRangeAttribute];
1370 [tempArray addObject:NSAccessibilityVisibleCharacterRangeAttribute];
1371 [tempArray addObject:NSAccessibilityInsertionPointLineNumberAttribute];
1372 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1373 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1374 [tempArray addObject:NSAccessibilityRequiredAttribute];
1375 [tempArray addObject:NSAccessibilityInvalidAttribute];
1376 [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1377 [tempArray addObject:NSAccessibilityValueAutofilledAttribute];
1378 textAttrs = [[NSArray alloc] initWithArray:tempArray];
1379 [tempArray release];
1381 if (listAttrs == nil) {
1382 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1383 [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1384 [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1385 [tempArray addObject:NSAccessibilityOrientationAttribute];
1386 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1387 listAttrs = [[NSArray alloc] initWithArray:tempArray];
1388 [tempArray release];
1390 if (listBoxAttrs == nil) {
1391 tempArray = [[NSMutableArray alloc] initWithArray:listAttrs];
1392 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1393 [tempArray addObject:NSAccessibilityRequiredAttribute];
1394 [tempArray addObject:NSAccessibilityInvalidAttribute];
1395 listBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1396 [tempArray release];
1398 if (rangeAttrs == nil) {
1399 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1400 [tempArray addObject:NSAccessibilityMinValueAttribute];
1401 [tempArray addObject:NSAccessibilityMaxValueAttribute];
1402 [tempArray addObject:NSAccessibilityOrientationAttribute];
1403 [tempArray addObject:NSAccessibilityValueDescriptionAttribute];
1404 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1405 rangeAttrs = [[NSArray alloc] initWithArray:tempArray];
1406 [tempArray release];
1408 if (menuBarAttrs == nil) {
1409 tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1410 [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1411 [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1412 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1413 menuBarAttrs = [[NSArray alloc] initWithArray:tempArray];
1414 [tempArray release];
1416 if (menuAttrs == nil) {
1417 tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1418 [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1419 [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1420 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1421 menuAttrs = [[NSArray alloc] initWithArray:tempArray];
1422 [tempArray release];
1424 if (menuItemAttrs == nil) {
1425 tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1426 [tempArray addObject:NSAccessibilityTitleAttribute];
1427 [tempArray addObject:NSAccessibilityDescriptionAttribute];
1428 [tempArray addObject:NSAccessibilityHelpAttribute];
1429 [tempArray addObject:NSAccessibilitySelectedAttribute];
1430 [tempArray addObject:NSAccessibilityValueAttribute];
1431 [tempArray addObject:(NSString*)kAXMenuItemCmdCharAttribute];
1432 [tempArray addObject:(NSString*)kAXMenuItemCmdVirtualKeyAttribute];
1433 [tempArray addObject:(NSString*)kAXMenuItemCmdGlyphAttribute];
1434 [tempArray addObject:(NSString*)kAXMenuItemCmdModifiersAttribute];
1435 [tempArray addObject:(NSString*)kAXMenuItemMarkCharAttribute];
1436 [tempArray addObject:(NSString*)kAXMenuItemPrimaryUIElementAttribute];
1437 [tempArray addObject:NSAccessibilityServesAsTitleForUIElementsAttribute];
1438 [tempArray addObject:NSAccessibilityFocusedAttribute];
1439 menuItemAttrs = [[NSArray alloc] initWithArray:tempArray];
1440 [tempArray release];
1442 if (menuButtonAttrs == nil) {
1443 menuButtonAttrs = [[NSArray alloc] initWithObjects:NSAccessibilityRoleAttribute,
1444 NSAccessibilityRoleDescriptionAttribute,
1445 NSAccessibilityParentAttribute,
1446 NSAccessibilityPositionAttribute,
1447 NSAccessibilitySizeAttribute,
1448 NSAccessibilityWindowAttribute,
1449 NSAccessibilityEnabledAttribute,
1450 NSAccessibilityFocusedAttribute,
1451 NSAccessibilityTitleAttribute,
1452 NSAccessibilityChildrenAttribute, nil];
1454 if (controlAttrs == nil) {
1455 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1456 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1457 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1458 [tempArray addObject:NSAccessibilityRequiredAttribute];
1459 [tempArray addObject:NSAccessibilityInvalidAttribute];
1460 controlAttrs = [[NSArray alloc] initWithArray:tempArray];
1461 [tempArray release];
1463 if (incrementorAttrs == nil) {
1464 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1465 [tempArray addObject:NSAccessibilityIncrementButtonAttribute];
1466 [tempArray addObject:NSAccessibilityDecrementButtonAttribute];
1467 [tempArray addObject:NSAccessibilityValueDescriptionAttribute];
1468 [tempArray addObject:NSAccessibilityMinValueAttribute];
1469 [tempArray addObject:NSAccessibilityMaxValueAttribute];
1470 incrementorAttrs = [[NSArray alloc] initWithArray:tempArray];
1471 [tempArray release];
1473 if (buttonAttrs == nil) {
1474 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1475 // Buttons should not expose AXValue.
1476 [tempArray removeObject:NSAccessibilityValueAttribute];
1477 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1478 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1479 buttonAttrs = [[NSArray alloc] initWithArray:tempArray];
1480 [tempArray release];
1482 if (comboBoxAttrs == nil) {
1483 tempArray = [[NSMutableArray alloc] initWithArray:controlAttrs];
1484 [tempArray addObject:NSAccessibilityExpandedAttribute];
1485 comboBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1486 [tempArray release];
1488 if (tableAttrs == nil) {
1489 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1490 [tempArray addObject:NSAccessibilityRowsAttribute];
1491 [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1492 [tempArray addObject:NSAccessibilityColumnsAttribute];
1493 [tempArray addObject:NSAccessibilityVisibleColumnsAttribute];
1494 [tempArray addObject:NSAccessibilityVisibleCellsAttribute];
1495 [tempArray addObject:NSAccessibilityColumnHeaderUIElementsAttribute];
1496 [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];
1497 [tempArray addObject:NSAccessibilityHeaderAttribute];
1498 [tempArray addObject:NSAccessibilityColumnCountAttribute];
1499 [tempArray addObject:NSAccessibilityRowCountAttribute];
1500 tableAttrs = [[NSArray alloc] initWithArray:tempArray];
1501 [tempArray release];
1503 if (tableRowAttrs == nil) {
1504 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1505 [tempArray addObject:NSAccessibilityIndexAttribute];
1506 tableRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1507 [tempArray release];
1509 if (tableColAttrs == nil) {
1510 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1511 [tempArray addObject:NSAccessibilityIndexAttribute];
1512 [tempArray addObject:NSAccessibilityHeaderAttribute];
1513 [tempArray addObject:NSAccessibilityRowsAttribute];
1514 [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1515 tableColAttrs = [[NSArray alloc] initWithArray:tempArray];
1516 [tempArray release];
1518 if (tableCellAttrs == nil) {
1519 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1520 [tempArray addObject:NSAccessibilityRowIndexRangeAttribute];
1521 [tempArray addObject:NSAccessibilityColumnIndexRangeAttribute];
1522 [tempArray addObject:NSAccessibilityColumnHeaderUIElementsAttribute];
1523 [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];
1524 tableCellAttrs = [[NSArray alloc] initWithArray:tempArray];
1525 [tempArray release];
1527 if (groupAttrs == nil) {
1528 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1529 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1530 groupAttrs = [[NSArray alloc] initWithArray:tempArray];
1531 [tempArray release];
1533 if (inputImageAttrs == nil) {
1534 tempArray = [[NSMutableArray alloc] initWithArray:buttonAttrs];
1535 [tempArray addObject:NSAccessibilityURLAttribute];
1536 inputImageAttrs = [[NSArray alloc] initWithArray:tempArray];
1537 [tempArray release];
1539 if (passwordFieldAttrs == nil) {
1540 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1541 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1542 [tempArray addObject:NSAccessibilityRequiredAttribute];
1543 [tempArray addObject:NSAccessibilityInvalidAttribute];
1544 [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1545 [tempArray addObject:NSAccessibilityValueAutofilledAttribute];
1546 passwordFieldAttrs = [[NSArray alloc] initWithArray:tempArray];
1547 [tempArray release];
1549 if (tabListAttrs == nil) {
1550 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1551 [tempArray addObject:NSAccessibilityTabsAttribute];
1552 [tempArray addObject:NSAccessibilityContentsAttribute];
1553 tabListAttrs = [[NSArray alloc] initWithArray:tempArray];
1554 [tempArray release];
1556 if (outlineAttrs == nil) {
1557 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1558 [tempArray addObject:NSAccessibilitySelectedRowsAttribute];
1559 [tempArray addObject:NSAccessibilityRowsAttribute];
1560 [tempArray addObject:NSAccessibilityColumnsAttribute];
1561 outlineAttrs = [[NSArray alloc] initWithArray:tempArray];
1562 [tempArray release];
1564 if (outlineRowAttrs == nil) {
1565 tempArray = [[NSMutableArray alloc] initWithArray:tableRowAttrs];
1566 [tempArray addObject:NSAccessibilityDisclosingAttribute];
1567 [tempArray addObject:NSAccessibilityDisclosedByRowAttribute];
1568 [tempArray addObject:NSAccessibilityDisclosureLevelAttribute];
1569 [tempArray addObject:NSAccessibilityDisclosedRowsAttribute];
1570 outlineRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1571 [tempArray release];
1573 if (scrollViewAttrs == nil) {
1574 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1575 [tempArray addObject:NSAccessibilityContentsAttribute];
1576 [tempArray addObject:NSAccessibilityHorizontalScrollBarAttribute];
1577 [tempArray addObject:NSAccessibilityVerticalScrollBarAttribute];
1578 scrollViewAttrs = [[NSArray alloc] initWithArray:tempArray];
1579 [tempArray release];
1582 NSArray *objectAttributes = attributes;
1584 if (m_object->isPasswordField())
1585 objectAttributes = passwordFieldAttrs;
1587 else if (m_object->isWebArea())
1588 objectAttributes = webAreaAttrs;
1590 else if (m_object->isTextControl())
1591 objectAttributes = textAttrs;
1593 else if (m_object->isLink() || m_object->isImage())
1594 objectAttributes = anchorAttrs;
1596 else if (is<AccessibilityTable>(*m_object) && downcast<AccessibilityTable>(*m_object).isExposableThroughAccessibility())
1597 objectAttributes = tableAttrs;
1598 else if (m_object->isTableColumn())
1599 objectAttributes = tableColAttrs;
1600 else if (m_object->isTableCell())
1601 objectAttributes = tableCellAttrs;
1602 else if (m_object->isTableRow()) {
1603 // An ARIA table row can be collapsed and expanded, so it needs the extra attributes.
1604 if (m_object->isARIATreeGridRow())
1605 objectAttributes = outlineRowAttrs;
1607 objectAttributes = tableRowAttrs;
1610 else if (m_object->isTree())
1611 objectAttributes = outlineAttrs;
1612 else if (m_object->isTreeItem())
1613 objectAttributes = outlineRowAttrs;
1615 else if (m_object->isListBox())
1616 objectAttributes = listBoxAttrs;
1617 else if (m_object->isList())
1618 objectAttributes = listAttrs;
1620 else if (m_object->isComboBox())
1621 objectAttributes = comboBoxAttrs;
1623 else if (m_object->isProgressIndicator() || m_object->isSlider())
1624 objectAttributes = rangeAttrs;
1626 // These are processed in order because an input image is a button, and a button is a control.
1627 else if (m_object->isInputImage())
1628 objectAttributes = inputImageAttrs;
1629 else if (m_object->isButton())
1630 objectAttributes = buttonAttrs;
1631 else if (m_object->isControl())
1632 objectAttributes = controlAttrs;
1634 else if (m_object->isGroup() || m_object->isListItem())
1635 objectAttributes = groupAttrs;
1636 else if (m_object->isTabList())
1637 objectAttributes = tabListAttrs;
1638 else if (m_object->isScrollView())
1639 objectAttributes = scrollViewAttrs;
1640 else if (m_object->isSpinButton())
1641 objectAttributes = incrementorAttrs;
1643 else if (m_object->isMenu())
1644 objectAttributes = menuAttrs;
1645 else if (m_object->isMenuBar())
1646 objectAttributes = menuBarAttrs;
1647 else if (m_object->isMenuButton())
1648 objectAttributes = menuButtonAttrs;
1649 else if (m_object->isMenuItem())
1650 objectAttributes = menuItemAttrs;
1652 NSArray *additionalAttributes = [self additionalAccessibilityAttributeNames];
1653 if ([additionalAttributes count])
1654 objectAttributes = [objectAttributes arrayByAddingObjectsFromArray:additionalAttributes];
1656 return objectAttributes;
1659 - (VisiblePositionRange)visiblePositionRangeForTextMarkerRange:(id)textMarkerRange
1661 if (!textMarkerRange)
1662 return VisiblePositionRange();
1663 AXObjectCache* cache = m_object->axObjectCache();
1664 return VisiblePositionRange(visiblePositionForStartOfTextMarkerRange(cache, textMarkerRange), visiblePositionForEndOfTextMarkerRange(cache, textMarkerRange));
1667 - (NSArray*)renderWidgetChildren
1669 Widget* widget = m_object->widget();
1672 #pragma clang diagnostic push
1673 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1674 return [(widget->platformWidget()) accessibilityAttributeValue: NSAccessibilityChildrenAttribute];
1675 #pragma clang diagnostic pop
1678 - (id)remoteAccessibilityParentObject
1683 Document* document = m_object->document();
1687 Frame* frame = document->frame();
1691 return frame->loader().client().accessibilityRemoteObject();
1694 static void convertToVector(NSArray* array, AccessibilityObject::AccessibilityChildrenVector& vector)
1696 unsigned length = [array count];
1697 vector.reserveInitialCapacity(length);
1698 for (unsigned i = 0; i < length; ++i) {
1699 AccessibilityObject* obj = [[array objectAtIndex:i] accessibilityObject];
1705 static NSMutableArray* convertToNSArray(const AccessibilityObject::AccessibilityChildrenVector& vector)
1707 NSMutableArray* array = [NSMutableArray arrayWithCapacity:vector.size()];
1708 for (const auto& child : vector) {
1709 WebAccessibilityObjectWrapper* wrapper = child->wrapper();
1712 // we want to return the attachment view instead of the object representing the attachment.
1713 // otherwise, we get palindrome errors in the AX hierarchy
1714 if (child->isAttachment() && [wrapper attachmentView])
1715 [array addObject:[wrapper attachmentView]];
1717 [array addObject:wrapper];
1723 static NSMutableArray *convertStringsToNSArray(const Vector<String>& vector)
1725 NSMutableArray *array = [NSMutableArray arrayWithCapacity:vector.size()];
1726 for (const auto& string : vector)
1727 [array addObject:string];
1731 - (id)textMarkerRangeForSelection
1733 VisibleSelection selection = m_object->selection();
1734 if (selection.isNone())
1736 return [self textMarkerRangeFromVisiblePositions:selection.visibleStart() endPosition:selection.visibleEnd()];
1739 - (CGPoint)convertPointToScreenSpace:(FloatPoint &)point
1741 FrameView* frameView = m_object->documentFrameView();
1743 // WebKit1 code path... platformWidget() exists.
1744 if (frameView && frameView->platformWidget()) {
1745 NSPoint nsPoint = (NSPoint)point;
1746 NSView* view = frameView->documentView();
1747 #pragma clang diagnostic push
1748 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1749 nsPoint = [[view window] convertBaseToScreen:[view convertPoint:nsPoint toView:nil]];
1750 #pragma clang diagnostic pop
1751 return CGPointMake(nsPoint.x, nsPoint.y);
1754 // Find the appropriate scroll view to use to convert the contents to the window.
1755 ScrollView* scrollView = nullptr;
1756 AccessibilityObject* parent = nullptr;
1757 for (parent = m_object->parentObject(); parent; parent = parent->parentObject()) {
1758 if (is<AccessibilityScrollView>(*parent)) {
1759 scrollView = downcast<AccessibilityScrollView>(*parent).scrollView();
1764 IntPoint intPoint = flooredIntPoint(point);
1766 intPoint = scrollView->contentsToRootView(intPoint);
1768 Page* page = m_object->page();
1770 // If we have an empty chrome client (like SVG) then we should use the page
1771 // of the scroll view parent to help us get to the screen rect.
1772 if (parent && page && page->chrome().client().isEmptyChromeClient())
1773 page = parent->page();
1776 IntRect rect = IntRect(intPoint, IntSize(0, 0));
1777 intPoint = page->chrome().rootViewToScreen(rect).location();
1784 static void WebTransformCGPathToNSBezierPath(void *info, const CGPathElement *element)
1786 NSBezierPath *bezierPath = (NSBezierPath *)info;
1787 switch (element->type) {
1788 case kCGPathElementMoveToPoint:
1789 [bezierPath moveToPoint:NSPointFromCGPoint(element->points[0])];
1791 case kCGPathElementAddLineToPoint:
1792 [bezierPath lineToPoint:NSPointFromCGPoint(element->points[0])];
1794 case kCGPathElementAddCurveToPoint:
1795 [bezierPath curveToPoint:NSPointFromCGPoint(element->points[0]) controlPoint1:NSPointFromCGPoint(element->points[1]) controlPoint2:NSPointFromCGPoint(element->points[2])];
1797 case kCGPathElementCloseSubpath:
1798 [bezierPath closePath];
1805 - (NSBezierPath *)bezierPathFromPath:(CGPathRef)path
1807 NSBezierPath *bezierPath = [NSBezierPath bezierPath];
1808 CGPathApply(path, bezierPath, WebTransformCGPathToNSBezierPath);
1812 - (NSBezierPath *)path
1814 Path path = m_object->elementPath();
1818 CGPathRef transformedPath = [self convertPathToScreenSpace:path];
1819 return [self bezierPathFromPath:transformedPath];
1822 - (NSValue *)position
1824 IntRect rect = snappedIntRect(m_object->elementRect());
1826 // The Cocoa accessibility API wants the lower-left corner.
1827 FloatPoint floatPoint = FloatPoint(rect.x(), rect.maxY());
1829 CGPoint cgPoint = [self convertPointToScreenSpace:floatPoint];
1831 return [NSValue valueWithPoint:NSMakePoint(cgPoint.x, cgPoint.y)];
1834 typedef HashMap<int, NSString*> AccessibilityRoleMap;
1836 static const AccessibilityRoleMap& createAccessibilityRoleMap()
1839 AccessibilityRole value;
1843 static const RoleEntry roles[] = {
1844 { UnknownRole, NSAccessibilityUnknownRole },
1845 { ButtonRole, NSAccessibilityButtonRole },
1846 { RadioButtonRole, NSAccessibilityRadioButtonRole },
1847 { CheckBoxRole, NSAccessibilityCheckBoxRole },
1848 { SliderRole, NSAccessibilitySliderRole },
1849 { TabGroupRole, NSAccessibilityTabGroupRole },
1850 { TextFieldRole, NSAccessibilityTextFieldRole },
1851 { StaticTextRole, NSAccessibilityStaticTextRole },
1852 { TextAreaRole, NSAccessibilityTextAreaRole },
1853 { ScrollAreaRole, NSAccessibilityScrollAreaRole },
1854 { PopUpButtonRole, NSAccessibilityPopUpButtonRole },
1855 { MenuButtonRole, NSAccessibilityMenuButtonRole },
1856 { TableRole, NSAccessibilityTableRole },
1857 { ApplicationRole, NSAccessibilityApplicationRole },
1858 { GroupRole, NSAccessibilityGroupRole },
1859 { RadioGroupRole, NSAccessibilityRadioGroupRole },
1860 { ListRole, NSAccessibilityListRole },
1861 { DirectoryRole, NSAccessibilityListRole },
1862 { ScrollBarRole, NSAccessibilityScrollBarRole },
1863 { ValueIndicatorRole, NSAccessibilityValueIndicatorRole },
1864 { ImageRole, NSAccessibilityImageRole },
1865 { MenuBarRole, NSAccessibilityMenuBarRole },
1866 { MenuRole, NSAccessibilityMenuRole },
1867 { MenuItemRole, NSAccessibilityMenuItemRole },
1868 { MenuItemCheckboxRole, NSAccessibilityMenuItemRole },
1869 { MenuItemRadioRole, NSAccessibilityMenuItemRole },
1870 { ColumnRole, NSAccessibilityColumnRole },
1871 { RowRole, NSAccessibilityRowRole },
1872 { ToolbarRole, NSAccessibilityToolbarRole },
1873 { BusyIndicatorRole, NSAccessibilityBusyIndicatorRole },
1874 { ProgressIndicatorRole, NSAccessibilityProgressIndicatorRole },
1875 { WindowRole, NSAccessibilityWindowRole },
1876 { DrawerRole, NSAccessibilityDrawerRole },
1877 { SystemWideRole, NSAccessibilitySystemWideRole },
1878 { OutlineRole, NSAccessibilityOutlineRole },
1879 { IncrementorRole, NSAccessibilityIncrementorRole },
1880 { BrowserRole, NSAccessibilityBrowserRole },
1881 { ComboBoxRole, NSAccessibilityComboBoxRole },
1882 { SplitGroupRole, NSAccessibilitySplitGroupRole },
1883 { SplitterRole, NSAccessibilitySplitterRole },
1884 { ColorWellRole, NSAccessibilityColorWellRole },
1885 { GrowAreaRole, NSAccessibilityGrowAreaRole },
1886 { SheetRole, NSAccessibilitySheetRole },
1887 { HelpTagRole, NSAccessibilityHelpTagRole },
1888 { MatteRole, NSAccessibilityMatteRole },
1889 { RulerRole, NSAccessibilityRulerRole },
1890 { RulerMarkerRole, NSAccessibilityRulerMarkerRole },
1891 { LinkRole, NSAccessibilityLinkRole },
1892 { DisclosureTriangleRole, NSAccessibilityDisclosureTriangleRole },
1893 { GridRole, NSAccessibilityGridRole },
1894 { WebCoreLinkRole, NSAccessibilityLinkRole },
1895 { ImageMapLinkRole, NSAccessibilityLinkRole },
1896 { ImageMapRole, @"AXImageMap" },
1897 { ListMarkerRole, @"AXListMarker" },
1898 { WebAreaRole, @"AXWebArea" },
1899 { HeadingRole, @"AXHeading" },
1900 { ListBoxRole, NSAccessibilityListRole },
1901 { ListBoxOptionRole, NSAccessibilityStaticTextRole },
1902 { CellRole, NSAccessibilityCellRole },
1903 { TableHeaderContainerRole, NSAccessibilityGroupRole },
1904 { RowHeaderRole, NSAccessibilityGroupRole },
1905 { DefinitionRole, NSAccessibilityGroupRole },
1906 { DescriptionListDetailRole, NSAccessibilityGroupRole },
1907 { DescriptionListTermRole, NSAccessibilityGroupRole },
1908 { DescriptionListRole, NSAccessibilityListRole },
1909 { SliderThumbRole, NSAccessibilityValueIndicatorRole },
1910 { LandmarkApplicationRole, NSAccessibilityGroupRole },
1911 { LandmarkBannerRole, NSAccessibilityGroupRole },
1912 { LandmarkComplementaryRole, NSAccessibilityGroupRole },
1913 { LandmarkContentInfoRole, NSAccessibilityGroupRole },
1914 { LandmarkMainRole, NSAccessibilityGroupRole },
1915 { LandmarkNavigationRole, NSAccessibilityGroupRole },
1916 { LandmarkSearchRole, NSAccessibilityGroupRole },
1917 { ApplicationAlertRole, NSAccessibilityGroupRole },
1918 { ApplicationAlertDialogRole, NSAccessibilityGroupRole },
1919 { ApplicationDialogRole, NSAccessibilityGroupRole },
1920 { ApplicationLogRole, NSAccessibilityGroupRole },
1921 { ApplicationMarqueeRole, NSAccessibilityGroupRole },
1922 { ApplicationStatusRole, NSAccessibilityGroupRole },
1923 { ApplicationTimerRole, NSAccessibilityGroupRole },
1924 { DocumentRole, NSAccessibilityGroupRole },
1925 { DocumentArticleRole, NSAccessibilityGroupRole },
1926 { DocumentMathRole, NSAccessibilityGroupRole },
1927 { DocumentNoteRole, NSAccessibilityGroupRole },
1928 { DocumentRegionRole, NSAccessibilityGroupRole },
1929 { UserInterfaceTooltipRole, NSAccessibilityGroupRole },
1930 { TabRole, NSAccessibilityRadioButtonRole },
1931 { TabListRole, NSAccessibilityTabGroupRole },
1932 { TabPanelRole, NSAccessibilityGroupRole },
1933 { TreeRole, NSAccessibilityOutlineRole },
1934 { TreeItemRole, NSAccessibilityRowRole },
1935 { ListItemRole, NSAccessibilityGroupRole },
1936 { ParagraphRole, NSAccessibilityGroupRole },
1937 { LabelRole, NSAccessibilityGroupRole },
1938 { DivRole, NSAccessibilityGroupRole },
1939 { FormRole, NSAccessibilityGroupRole },
1940 { SpinButtonRole, NSAccessibilityIncrementorRole },
1941 { FooterRole, NSAccessibilityGroupRole },
1942 { ToggleButtonRole, NSAccessibilityButtonRole },
1943 { CanvasRole, NSAccessibilityImageRole },
1944 { SVGRootRole, NSAccessibilityGroupRole },
1945 { LegendRole, NSAccessibilityGroupRole },
1946 { MathElementRole, NSAccessibilityGroupRole },
1947 { AudioRole, NSAccessibilityGroupRole },
1948 { VideoRole, NSAccessibilityGroupRole },
1949 { HorizontalRuleRole, NSAccessibilitySplitterRole },
1950 { BlockquoteRole, NSAccessibilityGroupRole },
1951 { SwitchRole, NSAccessibilityCheckBoxRole },
1952 { SearchFieldRole, NSAccessibilityTextFieldRole },
1954 AccessibilityRoleMap& roleMap = *new AccessibilityRoleMap;
1956 const unsigned numRoles = sizeof(roles) / sizeof(roles[0]);
1957 for (unsigned i = 0; i < numRoles; ++i)
1958 roleMap.set(roles[i].value, roles[i].string);
1962 static NSString* roleValueToNSString(AccessibilityRole value)
1965 static const AccessibilityRoleMap& roleMap = createAccessibilityRoleMap();
1966 return roleMap.get(value);
1971 #pragma clang diagnostic push
1972 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1973 if (m_object->isAttachment())
1974 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleAttribute];
1975 #pragma clang diagnostic pop
1976 AccessibilityRole role = m_object->roleValue();
1977 if (role == CanvasRole && m_object->canvasHasFallbackContent())
1979 NSString* string = roleValueToNSString(role);
1982 return NSAccessibilityUnknownRole;
1985 #pragma clang diagnostic push
1986 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1987 - (NSString*)subrole
1989 if (m_object->isPasswordField())
1990 return NSAccessibilitySecureTextFieldSubrole;
1991 if (m_object->isSearchField())
1992 return NSAccessibilitySearchFieldSubrole;
1994 if (m_object->isAttachment()) {
1995 NSView* attachView = [self attachmentView];
1996 if ([[attachView accessibilityAttributeNames] containsObject:NSAccessibilitySubroleAttribute]) {
1997 return [attachView accessibilityAttributeValue:NSAccessibilitySubroleAttribute];
2001 if (m_object->roleValue() == HorizontalRuleRole)
2002 return NSAccessibilityContentSeparatorSubrole;
2004 if (is<AccessibilitySpinButtonPart>(*m_object)) {
2005 if (downcast<AccessibilitySpinButtonPart>(*m_object).isIncrementor())
2006 return NSAccessibilityIncrementArrowSubrole;
2008 return NSAccessibilityDecrementArrowSubrole;
2011 if (m_object->isFileUploadButton())
2012 return @"AXFileUploadButton";
2014 if (m_object->isTreeItem())
2015 return NSAccessibilityOutlineRowSubrole;
2017 if (is<AccessibilityList>(*m_object)) {
2018 auto& listObject = downcast<AccessibilityList>(*m_object);
2019 if (listObject.isUnorderedList() || listObject.isOrderedList())
2020 return NSAccessibilityContentListSubrole;
2021 if (listObject.isDescriptionList()) {
2022 return NSAccessibilityDescriptionListSubrole;
2026 // ARIA content subroles.
2027 switch (m_object->roleValue()) {
2028 case LandmarkApplicationRole:
2029 return @"AXLandmarkApplication";
2030 case LandmarkBannerRole:
2031 return @"AXLandmarkBanner";
2032 case LandmarkComplementaryRole:
2033 return @"AXLandmarkComplementary";
2034 // Footer roles should appear as content info types.
2036 case LandmarkContentInfoRole:
2037 return @"AXLandmarkContentInfo";
2038 case LandmarkMainRole:
2039 return @"AXLandmarkMain";
2040 case LandmarkNavigationRole:
2041 return @"AXLandmarkNavigation";
2042 case LandmarkSearchRole:
2043 return @"AXLandmarkSearch";
2044 case ApplicationAlertRole:
2045 return @"AXApplicationAlert";
2046 case ApplicationAlertDialogRole:
2047 return @"AXApplicationAlertDialog";
2048 case ApplicationDialogRole:
2049 return @"AXApplicationDialog";
2050 case ApplicationLogRole:
2051 return @"AXApplicationLog";
2052 case ApplicationMarqueeRole:
2053 return @"AXApplicationMarquee";
2054 case ApplicationStatusRole:
2055 return @"AXApplicationStatus";
2056 case ApplicationTimerRole:
2057 return @"AXApplicationTimer";
2059 return @"AXDocument";
2060 case DocumentArticleRole:
2061 return @"AXDocumentArticle";
2062 case DocumentMathRole:
2063 return @"AXDocumentMath";
2064 case DocumentNoteRole:
2065 return @"AXDocumentNote";
2066 case DocumentRegionRole:
2067 return @"AXDocumentRegion";
2068 case UserInterfaceTooltipRole:
2069 return @"AXUserInterfaceTooltip";
2071 return @"AXTabPanel";
2072 case DefinitionRole:
2073 return @"AXDefinition";
2074 case DescriptionListTermRole:
2076 case DescriptionListDetailRole:
2077 return @"AXDescription";
2078 // Default doesn't return anything, so roles defined below can be chosen.
2083 if (m_object->roleValue() == MathElementRole) {
2084 if (m_object->isMathFraction())
2085 return @"AXMathFraction";
2086 if (m_object->isMathFenced())
2087 return @"AXMathFenced";
2088 if (m_object->isMathSubscriptSuperscript())
2089 return @"AXMathSubscriptSuperscript";
2090 if (m_object->isMathRow())
2091 return @"AXMathRow";
2092 if (m_object->isMathUnderOver())
2093 return @"AXMathUnderOver";
2094 if (m_object->isMathSquareRoot())
2095 return @"AXMathSquareRoot";
2096 if (m_object->isMathRoot())
2097 return @"AXMathRoot";
2098 if (m_object->isMathText())
2099 return @"AXMathText";
2100 if (m_object->isMathNumber())
2101 return @"AXMathNumber";
2102 if (m_object->isMathIdentifier())
2103 return @"AXMathIdentifier";
2104 if (m_object->isMathTable())
2105 return @"AXMathTable";
2106 if (m_object->isMathTableRow())
2107 return @"AXMathTableRow";
2108 if (m_object->isMathTableCell())
2109 return @"AXMathTableCell";
2110 if (m_object->isMathFenceOperator())
2111 return @"AXMathFenceOperator";
2112 if (m_object->isMathSeparatorOperator())
2113 return @"AXMathSeparatorOperator";
2114 if (m_object->isMathOperator())
2115 return @"AXMathOperator";
2116 if (m_object->isMathMultiscript())
2117 return @"AXMathMultiscript";
2120 if (m_object->roleValue() == VideoRole)
2122 if (m_object->roleValue() == AudioRole)
2125 if (m_object->isMediaTimeline())
2126 return NSAccessibilityTimelineSubrole;
2128 if (m_object->isSwitch())
2129 return NSAccessibilitySwitchSubrole;
2133 #pragma clang diagnostic pop
2135 - (NSString*)roleDescription
2140 #pragma clang diagnostic push
2141 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2142 // attachments have the AXImage role, but a different subrole
2143 if (m_object->isAttachment())
2144 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute];
2145 #pragma clang diagnostic pop
2147 NSString* axRole = [self role];
2149 if ([axRole isEqualToString:NSAccessibilityGroupRole]) {
2151 NSString *ariaLandmarkRoleDescription = [self ariaLandmarkRoleDescription];
2152 if (ariaLandmarkRoleDescription)
2153 return ariaLandmarkRoleDescription;
2155 switch (m_object->roleValue()) {
2157 return localizedMediaControlElementString("AudioElement");
2158 case DefinitionRole:
2159 return AXDefinitionText();
2160 case DescriptionListTermRole:
2161 return AXDescriptionListTermText();
2162 case DescriptionListDetailRole:
2163 return AXDescriptionListDetailText();
2165 return AXFooterRoleDescriptionText();
2167 return localizedMediaControlElementString("VideoElement");
2169 return NSAccessibilityRoleDescription(NSAccessibilityGroupRole, [self subrole]);
2173 if ([axRole isEqualToString:@"AXWebArea"])
2174 return AXWebAreaText();
2176 if ([axRole isEqualToString:@"AXLink"])
2177 return AXLinkText();
2179 if ([axRole isEqualToString:@"AXListMarker"])
2180 return AXListMarkerText();
2182 if ([axRole isEqualToString:@"AXImageMap"])
2183 return AXImageMapText();
2185 if ([axRole isEqualToString:@"AXHeading"])
2186 return AXHeadingText();
2188 if (m_object->isFileUploadButton())
2189 return AXFileUploadButtonText();
2191 // Only returning for DL (not UL or OL) because description changed with HTML5 from 'definition list' to
2192 // superset 'description list' and does not return the same values in AX API on some OS versions.
2193 if (is<AccessibilityList>(*m_object)) {
2194 if (downcast<AccessibilityList>(*m_object).isDescriptionList())
2195 return AXDescriptionListText();
2198 if (m_object->roleValue() == HorizontalRuleRole)
2199 return AXHorizontalRuleDescriptionText();
2201 // AppKit also returns AXTab for the role description for a tab item.
2202 if (m_object->isTabItem())
2203 return NSAccessibilityRoleDescription(@"AXTab", nil);
2205 // We should try the system default role description for all other roles.
2206 // If we get the same string back, then as a last resort, return unknown.
2207 NSString* defaultRoleDescription = NSAccessibilityRoleDescription(axRole, [self subrole]);
2209 // On earlier Mac versions (Lion), using a non-standard subrole would result in a role description
2210 // being returned that looked like AXRole:AXSubrole. To make all platforms have the same role descriptions
2211 // we should fallback on a role description ignoring the subrole in these cases.
2212 if ([defaultRoleDescription isEqualToString:[NSString stringWithFormat:@"%@:%@", axRole, [self subrole]]])
2213 defaultRoleDescription = NSAccessibilityRoleDescription(axRole, nil);
2215 if (![defaultRoleDescription isEqualToString:axRole])
2216 return defaultRoleDescription;
2218 return NSAccessibilityRoleDescription(NSAccessibilityUnknownRole, nil);
2221 - (NSString *)computedRoleString
2225 return m_object->computedRoleString();
2228 - (id)scrollViewParent
2230 if (!is<AccessibilityScrollView>(m_object))
2233 // If this scroll view provides it's parent object (because it's a sub-frame), then
2234 // we should not find the remoteAccessibilityParent.
2235 if (m_object->parentObject())
2238 ScrollView* scroll = downcast<AccessibilityScrollView>(*m_object).scrollView();
2242 if (scroll->platformWidget())
2243 return NSAccessibilityUnignoredAncestor(scroll->platformWidget());
2245 return [self remoteAccessibilityParentObject];
2248 // FIXME: split up this function in a better way.
2249 // suggestions: Use a hash table that maps attribute names to function calls,
2250 // or maybe pointers to member functions
2251 - (id)accessibilityAttributeValue:(NSString*)attributeName
2253 if (![self updateObjectBackingStore])
2256 if ([attributeName isEqualToString: NSAccessibilityRoleAttribute])
2259 if ([attributeName isEqualToString: NSAccessibilitySubroleAttribute])
2260 return [self subrole];
2262 if ([attributeName isEqualToString: NSAccessibilityRoleDescriptionAttribute])
2263 return [self roleDescription];
2265 // AXARIARole is only used by DumpRenderTree (so far).
2266 if ([attributeName isEqualToString:@"AXARIARole"])
2267 return [self computedRoleString];
2269 if ([attributeName isEqualToString: NSAccessibilityParentAttribute]) {
2271 // This will return the parent of the AXWebArea, if this is a web area.
2272 id scrollViewParent = [self scrollViewParent];
2273 if (scrollViewParent)
2274 return scrollViewParent;
2276 // Tree item (changed to AXRows) can only report the tree (AXOutline) as its parent.
2277 if (m_object->isTreeItem()) {
2278 AccessibilityObject* parent = m_object->parentObjectUnignored();
2280 if (parent->isTree())
2281 return parent->wrapper();
2282 parent = parent->parentObjectUnignored();
2286 AccessibilityObject* parent = m_object->parentObjectUnignored();
2290 // In WebKit1, the scroll view is provided by the system (the attachment view), so the parent
2291 // should be reported directly as such.
2292 if (m_object->isWebArea() && parent->isAttachment())
2293 return [parent->wrapper() attachmentView];
2295 return parent->wrapper();
2298 if ([attributeName isEqualToString: NSAccessibilityChildrenAttribute]) {
2299 if (m_object->children().isEmpty()) {
2300 NSArray* children = [self renderWidgetChildren];
2301 if (children != nil)
2305 // The tree's (AXOutline) children are supposed to be its rows and columns.
2306 // The ARIA spec doesn't have columns, so we just need rows.
2307 if (m_object->isTree())
2308 return [self accessibilityAttributeValue:NSAccessibilityRowsAttribute];
2310 // A tree item should only expose its content as its children (not its rows)
2311 if (m_object->isTreeItem()) {
2312 AccessibilityObject::AccessibilityChildrenVector contentCopy;
2313 m_object->ariaTreeItemContent(contentCopy);
2314 return convertToNSArray(contentCopy);
2317 return convertToNSArray(m_object->children());
2320 if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {
2321 if (m_object->isListBox()) {
2322 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2323 m_object->selectedChildren(selectedChildrenCopy);
2324 return convertToNSArray(selectedChildrenCopy);
2329 if ([attributeName isEqualToString: NSAccessibilityVisibleChildrenAttribute]) {
2330 if (m_object->isListBox()) {
2331 AccessibilityObject::AccessibilityChildrenVector visibleChildrenCopy;
2332 m_object->visibleChildren(visibleChildrenCopy);
2333 return convertToNSArray(visibleChildrenCopy);
2335 else if (m_object->isList())
2336 return [self accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
2342 if (m_object->isWebArea()) {
2343 if ([attributeName isEqualToString:@"AXLinkUIElements"]) {
2344 AccessibilityObject::AccessibilityChildrenVector links;
2345 downcast<AccessibilityRenderObject>(*m_object).getDocumentLinks(links);
2346 return convertToNSArray(links);
2348 if ([attributeName isEqualToString:@"AXLoaded"])
2349 return [NSNumber numberWithBool:m_object->isLoaded()];
2350 if ([attributeName isEqualToString:@"AXLayoutCount"])
2351 return [NSNumber numberWithInt:m_object->layoutCount()];
2352 if ([attributeName isEqualToString:NSAccessibilityLoadingProgressAttribute])
2353 return [NSNumber numberWithDouble:m_object->estimatedLoadingProgress()];
2356 if (m_object->isTextControl()) {
2357 if ([attributeName isEqualToString: NSAccessibilityNumberOfCharactersAttribute]) {
2358 int length = m_object->textLength();
2361 return [NSNumber numberWithUnsignedInt:length];
2363 if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
2364 String selectedText = m_object->selectedText();
2365 if (selectedText.isNull())
2367 return (NSString*)selectedText;
2369 if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
2370 PlainTextRange textRange = m_object->selectedTextRange();
2371 if (textRange.isNull())
2372 return [NSValue valueWithRange:NSMakeRange(0, 0)];
2373 return [NSValue valueWithRange:NSMakeRange(textRange.start, textRange.length)];
2375 // TODO: Get actual visible range. <rdar://problem/4712101>
2376 if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
2377 return m_object->isPasswordField() ? nil : [NSValue valueWithRange: NSMakeRange(0, m_object->textLength())];
2378 if ([attributeName isEqualToString: NSAccessibilityInsertionPointLineNumberAttribute]) {
2379 // if selectionEnd > 0, then there is selected text and this question should not be answered
2380 if (m_object->isPasswordField() || m_object->selectionEnd() > 0)
2383 AccessibilityObject* focusedObject = m_object->focusedUIElement();
2384 if (focusedObject != m_object)
2387 VisiblePosition focusedPosition = focusedObject->visiblePositionForIndex(focusedObject->selectionStart(), true);
2388 int lineNumber = m_object->lineForPosition(focusedPosition);
2392 return [NSNumber numberWithInt:lineNumber];
2396 if ([attributeName isEqualToString: NSAccessibilityURLAttribute]) {
2397 URL url = m_object->url();
2403 // Only native spin buttons have increment and decrement buttons.
2404 if (is<AccessibilitySpinButton>(*m_object)) {
2405 if ([attributeName isEqualToString:NSAccessibilityIncrementButtonAttribute])
2406 return downcast<AccessibilitySpinButton>(*m_object).incrementButton()->wrapper();
2407 if ([attributeName isEqualToString:NSAccessibilityDecrementButtonAttribute])
2408 return downcast<AccessibilitySpinButton>(*m_object).decrementButton()->wrapper();
2411 if ([attributeName isEqualToString: @"AXVisited"])
2412 return [NSNumber numberWithBool: m_object->isVisited()];
2414 if ([attributeName isEqualToString: NSAccessibilityTitleAttribute]) {
2415 if (m_object->isAttachment()) {
2416 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityTitleAttribute])
2417 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityTitleAttribute];
2420 // Meter elements should communicate their content via AXValueDescription.
2421 if (m_object->isMeter())
2422 return [NSString string];
2424 return [self baseAccessibilityTitle];
2427 if ([attributeName isEqualToString: NSAccessibilityDescriptionAttribute]) {
2428 if (m_object->isAttachment()) {
2429 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityDescriptionAttribute])
2430 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityDescriptionAttribute];
2432 return [self baseAccessibilityDescription];
2435 if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
2436 if (m_object->isAttachment()) {
2437 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityValueAttribute])
2438 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityValueAttribute];
2440 if (m_object->supportsRangeValue())
2441 return [NSNumber numberWithFloat:m_object->valueForRange()];
2442 if (m_object->roleValue() == SliderThumbRole)
2443 return [NSNumber numberWithFloat:m_object->parentObject()->valueForRange()];
2444 if (m_object->isHeading())
2445 return [NSNumber numberWithInt:m_object->headingLevel()];
2447 if (m_object->isCheckboxOrRadio() || m_object->isMenuItem() || m_object->isSwitch()) {
2448 switch (m_object->checkboxOrRadioValue()) {
2449 case ButtonStateOff:
2450 return [NSNumber numberWithInt:0];
2452 return [NSNumber numberWithInt:1];
2453 case ButtonStateMixed:
2454 return [NSNumber numberWithInt:2];
2458 // radio groups return the selected radio button as the AXValue
2459 if (m_object->isRadioGroup()) {
2460 AccessibilityObject* radioButton = m_object->selectedRadioButton();
2463 return radioButton->wrapper();
2466 if (m_object->isTabList()) {
2467 AccessibilityObject* tabItem = m_object->selectedTabItem();
2470 return tabItem->wrapper();
2473 if (m_object->isTabItem())
2474 return [NSNumber numberWithInt:m_object->isSelected()];
2476 if (m_object->isColorWell()) {
2478 m_object->colorValue(r, g, b);
2479 return [NSString stringWithFormat:@"rgb %7.5f %7.5f %7.5f 1", r / 255., g / 255., b / 255.];
2482 return m_object->stringValue();
2485 if ([attributeName isEqualToString:(NSString *)kAXMenuItemMarkCharAttribute]) {
2486 const unichar ch = 0x2713; // ✓ used on Mac for selected menu items.
2487 return (m_object->isChecked()) ? [NSString stringWithCharacters:&ch length:1] : nil;
2490 if ([attributeName isEqualToString: NSAccessibilityMinValueAttribute])
2491 return [NSNumber numberWithFloat:m_object->minValueForRange()];
2493 if ([attributeName isEqualToString: NSAccessibilityMaxValueAttribute])
2494 return [NSNumber numberWithFloat:m_object->maxValueForRange()];
2496 if ([attributeName isEqualToString: NSAccessibilityHelpAttribute])
2497 return [self baseAccessibilityHelpText];
2499 if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
2500 return [NSNumber numberWithBool: m_object->isFocused()];
2502 if ([attributeName isEqualToString: NSAccessibilityEnabledAttribute])
2503 return [NSNumber numberWithBool: m_object->isEnabled()];
2505 if ([attributeName isEqualToString: NSAccessibilitySizeAttribute]) {
2506 IntSize s = m_object->elementRect().pixelSnappedSize();
2507 return [NSValue valueWithSize: NSMakeSize(s.width(), s.height())];
2510 if ([attributeName isEqualToString: NSAccessibilityPositionAttribute])
2511 return [self position];
2512 if ([attributeName isEqualToString:NSAccessibilityPathAttribute])
2515 if ([attributeName isEqualToString: NSAccessibilityWindowAttribute] ||
2516 [attributeName isEqualToString: NSAccessibilityTopLevelUIElementAttribute]) {
2518 id remoteParent = [self remoteAccessibilityParentObject];
2520 return [remoteParent accessibilityAttributeValue:attributeName];
2522 FrameView* fv = m_object->documentFrameView();
2524 return [fv->platformWidget() window];
2528 if ([attributeName isEqualToString:NSAccessibilityAccessKeyAttribute]) {
2529 AtomicString accessKey = m_object->accessKey();
2530 if (accessKey.isNull())
2535 if ([attributeName isEqualToString:NSAccessibilityTabsAttribute]) {
2536 if (m_object->isTabList()) {
2537 AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2538 m_object->tabChildren(tabsChildren);
2539 return convertToNSArray(tabsChildren);
2543 if ([attributeName isEqualToString:NSAccessibilityContentsAttribute]) {
2544 // The contents of a tab list are all the children except the tabs.
2545 if (m_object->isTabList()) {
2546 const auto& children = m_object->children();
2547 AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2548 m_object->tabChildren(tabsChildren);
2550 AccessibilityObject::AccessibilityChildrenVector contents;
2551 unsigned childrenSize = children.size();
2552 for (unsigned k = 0; k < childrenSize; ++k) {
2553 if (tabsChildren.find(children[k]) == WTF::notFound)
2554 contents.append(children[k]);
2556 return convertToNSArray(contents);
2557 } else if (m_object->isScrollView()) {
2558 // A scrollView's contents are everything except the scroll bars.
2559 AccessibilityObject::AccessibilityChildrenVector contents;
2560 for (const auto& child : m_object->children()) {
2561 if (!child->isScrollbar())
2562 contents.append(child);
2564 return convertToNSArray(contents);
2568 if (is<AccessibilityTable>(*m_object) && downcast<AccessibilityTable>(*m_object).isExposableThroughAccessibility()) {
2569 auto& table = downcast<AccessibilityTable>(*m_object);
2570 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute])
2571 return convertToNSArray(table.rows());
2573 if ([attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
2574 AccessibilityObject::AccessibilityChildrenVector visibleRows;
2575 table.visibleRows(visibleRows);
2576 return convertToNSArray(visibleRows);
2579 // TODO: distinguish between visible and non-visible columns
2580 if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute] ||
2581 [attributeName isEqualToString:NSAccessibilityVisibleColumnsAttribute]) {
2582 return convertToNSArray(table.columns());
2585 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2586 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2587 m_object->selectedChildren(selectedChildrenCopy);
2588 return convertToNSArray(selectedChildrenCopy);
2591 // HTML tables don't support these
2592 if ([attributeName isEqualToString:NSAccessibilitySelectedColumnsAttribute] ||
2593 [attributeName isEqualToString:NSAccessibilitySelectedCellsAttribute])
2596 if ([attributeName isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute]) {
2597 AccessibilityObject::AccessibilityChildrenVector columnHeaders;
2598 table.columnHeaders(columnHeaders);
2599 return convertToNSArray(columnHeaders);
2602 if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2603 AccessibilityObject* headerContainer = table.headerContainer();
2604 if (headerContainer)
2605 return headerContainer->wrapper();
2609 if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
2610 AccessibilityObject::AccessibilityChildrenVector rowHeaders;
2611 table.rowHeaders(rowHeaders);
2612 return convertToNSArray(rowHeaders);
2615 if ([attributeName isEqualToString:NSAccessibilityVisibleCellsAttribute]) {
2616 AccessibilityObject::AccessibilityChildrenVector cells;
2618 return convertToNSArray(cells);
2621 if ([attributeName isEqualToString:NSAccessibilityColumnCountAttribute])
2622 return @(table.columnCount());
2624 if ([attributeName isEqualToString:NSAccessibilityRowCountAttribute])
2625 return @(table.rowCount());
2628 if (is<AccessibilityTableColumn>(*m_object)) {
2629 auto& column = downcast<AccessibilityTableColumn>(*m_object);
2630 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2631 return [NSNumber numberWithInt:column.columnIndex()];
2633 // rows attribute for a column is the list of all the elements in that column at each row
2634 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] ||
2635 [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
2636 return convertToNSArray(column.children());
2638 if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2639 AccessibilityObject* header = column.headerObject();
2642 return header->wrapper();
2646 if (is<AccessibilityTableCell>(*m_object)) {
2647 auto& cell = downcast<AccessibilityTableCell>(*m_object);
2648 if ([attributeName isEqualToString:NSAccessibilityRowIndexRangeAttribute]) {
2649 std::pair<unsigned, unsigned> rowRange;
2650 cell.rowIndexRange(rowRange);
2651 return [NSValue valueWithRange:NSMakeRange(rowRange.first, rowRange.second)];
2653 if ([attributeName isEqualToString:NSAccessibilityColumnIndexRangeAttribute]) {
2654 std::pair<unsigned, unsigned> columnRange;
2655 cell.columnIndexRange(columnRange);
2656 return [NSValue valueWithRange:NSMakeRange(columnRange.first, columnRange.second)];
2658 if ([attributeName isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute]) {
2659 AccessibilityObject::AccessibilityChildrenVector columnHeaders;
2660 cell.columnHeaders(columnHeaders);
2661 return convertToNSArray(columnHeaders);
2663 if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
2664 AccessibilityObject::AccessibilityChildrenVector rowHeaders;
2665 cell.rowHeaders(rowHeaders);
2666 return convertToNSArray(rowHeaders);
2670 if (m_object->isTree()) {
2671 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2672 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2673 m_object->selectedChildren(selectedChildrenCopy);
2674 return convertToNSArray(selectedChildrenCopy);
2676 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute]) {
2677 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2678 m_object->ariaTreeRows(rowsCopy);
2679 return convertToNSArray(rowsCopy);
2682 // TreeRoles do not support columns, but Mac AX expects to be able to ask about columns at the least.
2683 if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute])
2684 return [NSArray array];
2687 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute]) {
2688 if (m_object->isTreeItem()) {
2689 AccessibilityObject* parent = m_object->parentObject();
2690 for (; parent && !parent->isTree(); parent = parent->parentObject())
2696 // Find the index of this item by iterating the parents.
2697 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2698 parent->ariaTreeRows(rowsCopy);
2699 size_t count = rowsCopy.size();
2700 for (size_t k = 0; k < count; ++k)
2701 if (rowsCopy[k]->wrapper() == self)
2702 return [NSNumber numberWithUnsignedInt:k];
2706 if (is<AccessibilityTableRow>(*m_object)) {
2707 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2708 return [NSNumber numberWithInt:downcast<AccessibilityTableRow>(*m_object).rowIndex()];
2712 // The rows that are considered inside this row.
2713 if ([attributeName isEqualToString:NSAccessibilityDisclosedRowsAttribute]) {
2714 if (m_object->isTreeItem()) {
2715 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2716 m_object->ariaTreeItemDisclosedRows(rowsCopy);
2717 return convertToNSArray(rowsCopy);
2718 } else if (is<AccessibilityARIAGridRow>(*m_object)) {
2719 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2720 downcast<AccessibilityARIAGridRow>(*m_object).disclosedRows(rowsCopy);
2721 return convertToNSArray(rowsCopy);
2725 // The row that contains this row. It should be the same as the first parent that is a treeitem.
2726 if ([attributeName isEqualToString:NSAccessibilityDisclosedByRowAttribute]) {
2727 if (m_object->isTreeItem()) {
2728 AccessibilityObject* parent = m_object->parentObject();
2730 if (parent->isTreeItem())
2731 return parent->wrapper();
2732 // If the parent is the tree itself, then this value == nil.
2733 if (parent->isTree())
2735 parent = parent->parentObject();
2738 } else if (is<AccessibilityARIAGridRow>(*m_object)) {
2739 AccessibilityObject* row = downcast<AccessibilityARIAGridRow>(*m_object).disclosedByRow();
2742 return row->wrapper();
2746 if ([attributeName isEqualToString:NSAccessibilityDisclosureLevelAttribute]) {
2747 // Convert from 1-based level (from aria-level spec) to 0-based level (Mac)
2748 int level = m_object->hierarchicalLevel();
2751 return [NSNumber numberWithInt:level];
2753 if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
2754 return [NSNumber numberWithBool:m_object->isExpanded()];
2756 if ((m_object->isListBox() || m_object->isList()) && [attributeName isEqualToString:NSAccessibilityOrientationAttribute])
2757 return NSAccessibilityVerticalOrientationValue;
2759 if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
2760 return [self textMarkerRangeForSelection];
2762 if (m_object->renderer()) {
2763 if ([attributeName isEqualToString: @"AXStartTextMarker"])
2764 return [self textMarkerForVisiblePosition:startOfDocument(&m_object->renderer()->document())];
2765 if ([attributeName isEqualToString: @"AXEndTextMarker"])
2766 return [self textMarkerForVisiblePosition:endOfDocument(&m_object->renderer()->document())];
2769 if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute])
2770 return [NSNumber numberWithInt:m_object->blockquoteLevel()];
2771 if ([attributeName isEqualToString:@"AXTableLevel"])
2772 return [NSNumber numberWithInt:m_object->tableLevel()];
2774 if ([attributeName isEqualToString: NSAccessibilityLinkedUIElementsAttribute]) {
2775 AccessibilityObject::AccessibilityChildrenVector linkedUIElements;
2776 m_object->linkedUIElements(linkedUIElements);
2777 return convertToNSArray(linkedUIElements);
2780 if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
2781 return [NSNumber numberWithBool:m_object->isSelected()];
2783 if ([attributeName isEqualToString: NSAccessibilityServesAsTitleForUIElementsAttribute] && m_object->isMenuButton()) {
2784 AccessibilityObject* uiElement = downcast<AccessibilityRenderObject>(*m_object).menuForMenuButton();
2786 return [NSArray arrayWithObject:uiElement->wrapper()];
2789 if ([attributeName isEqualToString:NSAccessibilityTitleUIElementAttribute]) {
2790 if (!m_object->exposesTitleUIElement())
2793 AccessibilityObject* obj = m_object->titleUIElement();
2795 return obj->wrapper();
2799 if ([attributeName isEqualToString:NSAccessibilityValueDescriptionAttribute]) {
2800 if (m_object->isMeter())
2801 return [self baseAccessibilityTitle];
2803 return m_object->valueDescription();
2806 if ([attributeName isEqualToString:NSAccessibilityOrientationAttribute]) {
2807 AccessibilityOrientation elementOrientation = m_object->orientation();
2808 if (elementOrientation == AccessibilityOrientationVertical)
2809 return NSAccessibilityVerticalOrientationValue;
2810 if (elementOrientation == AccessibilityOrientationHorizontal)
2811 return NSAccessibilityHorizontalOrientationValue;
2815 if ([attributeName isEqualToString:NSAccessibilityHorizontalScrollBarAttribute]) {
2816 AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationHorizontal);
2818 return scrollBar->wrapper();
2821 if ([attributeName isEqualToString:NSAccessibilityVerticalScrollBarAttribute]) {
2822 AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationVertical);
2824 return scrollBar->wrapper();
2828 if ([attributeName isEqualToString:NSAccessibilitySortDirectionAttribute]) {
2829 switch (m_object->sortDirection()) {
2830 case SortDirectionAscending:
2831 return NSAccessibilityAscendingSortDirectionValue;
2832 case SortDirectionDescending:
2833 return NSAccessibilityDescendingSortDirectionValue;
2835 return NSAccessibilityUnknownSortDirectionValue;
2839 if ([attributeName isEqualToString:NSAccessibilityLanguageAttribute])
2840 return m_object->language();
2842 if ([attributeName isEqualToString:NSAccessibilityExpandedAttribute])
2843 return [NSNumber numberWithBool:m_object->isExpanded()];
2845 if ([attributeName isEqualToString:NSAccessibilityRequiredAttribute])
2846 return [NSNumber numberWithBool:m_object->isRequired()];
2848 if ([attributeName isEqualToString:NSAccessibilityInvalidAttribute])
2849 return m_object->invalidStatus();
2851 if ([attributeName isEqualToString:NSAccessibilityOwnsAttribute]) {
2852 AccessibilityObject::AccessibilityChildrenVector ariaOwns;
2853 m_object->ariaOwnsElements(ariaOwns);
2854 return convertToNSArray(ariaOwns);
2857 if ([attributeName isEqualToString:NSAccessibilityARIAPosInSetAttribute])
2858 return [NSNumber numberWithInt:m_object->ariaPosInSet()];
2859 if ([attributeName isEqualToString:NSAccessibilityARIASetSizeAttribute])
2860 return [NSNumber numberWithInt:m_object->ariaSetSize()];
2862 if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
2863 return [NSNumber numberWithBool:m_object->isARIAGrabbed()];
2865 if ([attributeName isEqualToString:NSAccessibilityDropEffectsAttribute]) {
2866 Vector<String> dropEffects;
2867 m_object->determineARIADropEffects(dropEffects);
2868 return convertStringsToNSArray(dropEffects);
2871 if ([attributeName isEqualToString:NSAccessibilityPlaceholderValueAttribute])
2872 return m_object->placeholderValue();
2874 if ([attributeName isEqualToString:NSAccessibilityValueAutofilledAttribute])
2875 return @(m_object->isValueAutofilled());
2877 if ([attributeName isEqualToString:NSAccessibilityHasPopupAttribute])
2878 return [NSNumber numberWithBool:m_object->ariaHasPopup()];
2880 // ARIA Live region attributes.
2881 if ([attributeName isEqualToString:NSAccessibilityARIALiveAttribute])
2882 return m_object->ariaLiveRegionStatus();
2883 if ([attributeName isEqualToString:NSAccessibilityARIARelevantAttribute])
2884 return m_object->ariaLiveRegionRelevant();
2885 if ([attributeName isEqualToString:NSAccessibilityARIAAtomicAttribute])
2886 return [NSNumber numberWithBool:m_object->ariaLiveRegionAtomic()];
2887 if ([attributeName isEqualToString:NSAccessibilityElementBusyAttribute])
2888 return [NSNumber numberWithBool:m_object->ariaLiveRegionBusy()];
2890 // MathML Attributes.
2891 if (m_object->isMathElement()) {
2892 if ([attributeName isEqualToString:NSAccessibilityMathRootIndexAttribute])
2893 return (m_object->mathRootIndexObject()) ? m_object->mathRootIndexObject()->wrapper() : 0;
2894 if ([attributeName isEqualToString:NSAccessibilityMathRootRadicandAttribute])
2895 return (m_object->mathRadicandObject()) ? m_object->mathRadicandObject()->wrapper() : 0;
2896 if ([attributeName isEqualToString:NSAccessibilityMathFractionNumeratorAttribute])
2897 return (m_object->mathNumeratorObject()) ? m_object->mathNumeratorObject()->wrapper() : 0;
2898 if ([attributeName isEqualToString:NSAccessibilityMathFractionDenominatorAttribute])
2899 return (m_object->mathDenominatorObject()) ? m_object->mathDenominatorObject()->wrapper() : 0;
2900 if ([attributeName isEqualToString:NSAccessibilityMathBaseAttribute])
2901 return (m_object->mathBaseObject()) ? m_object->mathBaseObject()->wrapper() : 0;
2902 if ([attributeName isEqualToString:NSAccessibilityMathSubscriptAttribute])
2903 return (m_object->mathSubscriptObject()) ? m_object->mathSubscriptObject()->wrapper() : 0;
2904 if ([attributeName isEqualToString:NSAccessibilityMathSuperscriptAttribute])
2905 return (m_object->mathSuperscriptObject()) ? m_object->mathSuperscriptObject()->wrapper() : 0;
2906 if ([attributeName isEqualToString:NSAccessibilityMathUnderAttribute])
2907 return (m_object->mathUnderObject()) ? m_object->mathUnderObject()->wrapper() : 0;
2908 if ([attributeName isEqualToString:NSAccessibilityMathOverAttribute])
2909 return (m_object->mathOverObject()) ? m_object->mathOverObject()->wrapper() : 0;
2910 if ([attributeName isEqualToString:NSAccessibilityMathFencedOpenAttribute])
2911 return m_object->mathFencedOpenString();
2912 if ([attributeName isEqualToString:NSAccessibilityMathFencedCloseAttribute])
2913 return m_object->mathFencedCloseString();
2914 if ([attributeName isEqualToString:NSAccessibilityMathLineThicknessAttribute])
2915 return [NSNumber numberWithInteger:m_object->mathLineThickness()];
2916 if ([attributeName isEqualToString:NSAccessibilityMathPostscriptsAttribute])
2917 return [self accessibilityMathPostscriptPairs];
2918 if ([attributeName isEqualToString:NSAccessibilityMathPrescriptsAttribute])
2919 return [self accessibilityMathPrescriptPairs];
2922 if ([attributeName isEqualToString:NSAccessibilityExpandedTextValueAttribute])
2923 return m_object->expandedTextValue();
2925 if ([attributeName isEqualToString:NSAccessibilityDOMIdentifierAttribute])
2926 return m_object->identifierAttribute();
2927 if ([attributeName isEqualToString:NSAccessibilityDOMClassListAttribute]) {
2928 Vector<String> classList;
2929 m_object->classList(classList);
2930 return convertStringsToNSArray(classList);
2933 // this is used only by DumpRenderTree for testing
2934 if ([attributeName isEqualToString:@"AXClickPoint"])
2935 return [NSValue valueWithPoint:m_object->clickPoint()];
2937 // This is used by DRT to verify CSS3 speech works.
2938 if ([attributeName isEqualToString:@"AXDRTSpeechAttribute"]) {
2939 ESpeak speakProperty = m_object->speakProperty();
2940 switch (speakProperty) {
2944 return @"spell-out";
2947 case SpeakLiteralPunctuation:
2948 return @"literal-punctuation";
2949 case SpeakNoPunctuation:
2950 return @"no-punctuation";
2957 // Used by DRT to find an accessible node by its element id.
2958 if ([attributeName isEqualToString:@"AXDRTElementIdAttribute"])
2959 return m_object->getAttribute(idAttr);
2961 if (m_object->isWebArea() && [attributeName isEqualToString:NSAccessibilityCaretBrowsingEnabledAttribute])
2962 return [NSNumber numberWithBool:m_object->caretBrowsingEnabled()];
2967 - (NSString *)accessibilityPlatformMathSubscriptKey
2969 return NSAccessibilityMathSubscriptAttribute;
2972 - (NSString *)accessibilityPlatformMathSuperscriptKey
2974 return NSAccessibilityMathSuperscriptAttribute;
2977 - (id)accessibilityFocusedUIElement
2979 if (![self updateObjectBackingStore])
2982 RefPtr<AccessibilityObject> focusedObj = m_object->focusedUIElement();
2987 return focusedObj->wrapper();
2990 - (id)accessibilityHitTest:(NSPoint)point
2992 if (![self updateObjectBackingStore])
2995 m_object->updateChildrenIfNecessary();
2996 RefPtr<AccessibilityObject> axObject = m_object->accessibilityHitTest(IntPoint(point));
2998 return NSAccessibilityUnignoredAncestor(axObject->wrapper());
2999 return NSAccessibilityUnignoredAncestor(self);
3002 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName
3004 if (![self updateObjectBackingStore])
3007 if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
3010 if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
3011 return m_object->canSetFocusAttribute();
3013 if ([attributeName isEqualToString: NSAccessibilityValueAttribute])
3014 return m_object->canSetValueAttribute();
3016 if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
3017 return m_object->canSetSelectedAttribute();
3019 if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute])
3020 return m_object->canSetSelectedChildrenAttribute();
3022 if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
3023 return m_object->canSetExpandedAttribute();
3025 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute])
3028 if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute] ||
3029 [attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute] ||
3030 [attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
3031 return m_object->canSetTextRangeAttributes();
3033 if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
3036 if (m_object->isWebArea() && [attributeName isEqualToString:NSAccessibilityCaretBrowsingEnabledAttribute])
3042 // accessibilityShouldUseUniqueId is an AppKit method we override so that
3043 // objects will be given a unique ID, and therefore allow AppKit to know when they
3044 // become obsolete (e.g. when the user navigates to a new web page, making this one
3045 // unrendered but not deallocated because it is in the back/forward cache).
3046 // It is important to call NSAccessibilityUnregisterUniqueIdForUIElement in the
3047 // appropriate place (e.g. dealloc) to remove these non-retained references from
3048 // AppKit's id mapping tables. We do this in detach by calling unregisterUniqueIdForUIElement.
3050 // Registering an object is also required for observing notifications. Only registered objects can be observed.
3051 - (BOOL)accessibilityIsIgnored
3053 if (![self updateObjectBackingStore])
3056 if (m_object->isAttachment())
3057 return [[self attachmentView] accessibilityIsIgnored];
3058 return m_object->accessibilityIsIgnored();
3061 - (NSArray* )accessibilityParameterizedAttributeNames
3063 if (![self updateObjectBackingStore])
3066 if (m_object->isAttachment())
3069 static NSArray* paramAttrs = nil;
3070 static NSArray* textParamAttrs = nil;
3071 static NSArray* tableParamAttrs = nil;
3072 static NSArray* webAreaParamAttrs = nil;
3073 if (paramAttrs == nil) {
3074 paramAttrs = [[NSArray alloc] initWithObjects:
3075 @"AXUIElementForTextMarker",
3076 @"AXTextMarkerRangeForUIElement",
3077 @"AXLineForTextMarker",
3078 @"AXTextMarkerRangeForLine",
3079 @"AXStringForTextMarkerRange",
3080 @"AXTextMarkerForPosition",
3081 @"AXBoundsForTextMarkerRange",
3082 @"AXAttributedStringForTextMarkerRange",
3083 @"AXTextMarkerRangeForUnorderedTextMarkers",
3084 @"AXNextTextMarkerForTextMarker",
3085 @"AXPreviousTextMarkerForTextMarker",
3086 @"AXLeftWordTextMarkerRangeForTextMarker",
3087 @"AXRightWordTextMarkerRangeForTextMarker",
3088 @"AXLeftLineTextMarkerRangeForTextMarker",
3089 @"AXRightLineTextMarkerRangeForTextMarker",
3090 @"AXSentenceTextMarkerRangeForTextMarker",
3091 @"AXParagraphTextMarkerRangeForTextMarker",
3092 @"AXNextWordEndTextMarkerForTextMarker",
3093 @"AXPreviousWordStartTextMarkerForTextMarker",
3094 @"AXNextLineEndTextMarkerForTextMarker",
3095 @"AXPreviousLineStartTextMarkerForTextMarker",
3096 @"AXNextSentenceEndTextMarkerForTextMarker",
3097 @"AXPreviousSentenceStartTextMarkerForTextMarker",
3098 @"AXNextParagraphEndTextMarkerForTextMarker",
3099 @"AXPreviousParagraphStartTextMarkerForTextMarker",
3100 @"AXStyleTextMarkerRangeForTextMarker",
3101 @"AXLengthForTextMarkerRange",
3102 NSAccessibilityBoundsForRangeParameterizedAttribute,
3103 NSAccessibilityStringForRangeParameterizedAttribute,
3104 NSAccessibilityUIElementCountForSearchPredicateParameterizedAttribute,
3105 NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute,
3106 NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute,
3107 NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute,
3108 NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute,
3109 NSAccessibilitySelectTextWithCriteriaParameterizedAttribute,
3113 if (textParamAttrs == nil) {
3114 NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
3115 [tempArray addObject:(NSString*)kAXLineForIndexParameterizedAttribute];
3116 [tempArray addObject:(NSString*)kAXRangeForLineParameterizedAttribute];
3117 [tempArray addObject:(NSString*)kAXStringForRangeParameterizedAttribute];
3118 [tempArray addObject:(NSString*)kAXRangeForPositionParameterizedAttribute];
3119 [tempArray addObject:(NSString*)kAXRangeForIndexParameterizedAttribute];
3120 [tempArray addObject:(NSString*)kAXBoundsForRangeParameterizedAttribute];
3121 [tempArray addObject:(NSString*)kAXRTFForRangeParameterizedAttribute];
3122 [tempArray addObject:(NSString*)kAXAttributedStringForRangeParameterizedAttribute];
3123 [tempArray addObject:(NSString*)kAXStyleRangeForIndexParameterizedAttribute];
3124 textParamAttrs = [[NSArray alloc] initWithArray:tempArray];
3125 [tempArray release];
3127 if (tableParamAttrs == nil) {
3128 NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
3129 [tempArray addObject:NSAccessibilityCellForColumnAndRowParameterizedAttribute];
3130 tableParamAttrs = [[NSArray alloc] initWithArray:tempArray];
3131 [tempArray release];
3133 if (!webAreaParamAttrs) {
3134 NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
3135 [tempArray addObject:NSAccessibilityTextMarkerForIndexParameterizedAttribute];
3136 [tempArray addObject:NSAccessibilityTextMarkerIsValidParameterizedAttribute];
3137 [tempArray addObject:NSAccessibilityIndexForTextMarkerParameterizedAttribute];
3138 webAreaParamAttrs = [[NSArray alloc] initWithArray:tempArray];
3139 [tempArray release];
3142 if (m_object->isPasswordField())
3143 return @[ NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute ];
3145 if (!m_object->isAccessibilityRenderObject())
3148 if (m_object->isTextControl())
3149 return textParamAttrs;
3151 if (is<AccessibilityTable>(*m_object) && downcast<AccessibilityTable>(*m_object).isExposableThroughAccessibility())
3152 return tableParamAttrs;
3154 if (m_object->isMenuRelated())
3157 if (m_object->isWebArea())
3158 return webAreaParamAttrs;
3163 #pragma clang diagnostic push
3164 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
3166 - (void)accessibilityPerformPressAction
3168 if (![self updateObjectBackingStore])
3171 if (m_object->isAttachment())
3172 [[self attachmentView] accessibilityPerformAction:NSAccessibilityPressAction];
3177 - (void)accessibilityPerformIncrementAction
3179 if (![self updateObjectBackingStore])
3182 if (m_object->isAttachment())
3183 [[self attachmentView] accessibilityPerformAction:NSAccessibilityIncrementAction];
3185 m_object->increment();
3188 - (void)accessibilityPerformDecrementAction
3190 if (![self updateObjectBackingStore])
3193 if (m_object->isAttachment())
3194 [[self attachmentView] accessibilityPerformAction:NSAccessibilityDecrementAction];
3196 m_object->decrement();
3199 #pragma clang diagnostic pop
3201 - (void)accessibilityPerformShowMenuAction
3203 if (m_object->roleValue() == ComboBoxRole)
3204 m_object->setIsExpanded(true);
3206 // This needs to be performed in an iteration of the run loop that did not start from an AX call.
3207 // If it's the same run loop iteration, the menu open notification won't be sent
3208 [self performSelector:@selector(accessibilityShowContextMenu) withObject:nil afterDelay:0.0];
3212 - (void)accessibilityShowContextMenu
3214 Page* page = m_object->page();
3218 IntRect rect = snappedIntRect(m_object->elementRect());
3219 FrameView* frameView = m_object->documentFrameView();
3221 // On WK2, we need to account for the scroll position.
3222 // On WK1, this isn't necessary, it's taken care of by the attachment views.
3223 if (frameView && !frameView->platformWidget()) {
3224 // Find the appropriate scroll view to use to convert the contents to the window.
3225 for (AccessibilityObject* parent = m_object->parentObject(); parent; parent = parent->parentObject()) {
3226 if (is<AccessibilityScrollView>(*parent)) {
3227 ScrollView* scrollView = downcast<AccessibilityScrollView>(*parent).scrollView();
3228 rect = scrollView->contentsToRootView(rect);
3234 page->contextMenuController().showContextMenuAt(&page->mainFrame(), rect.center());
3237 - (void)accessibilityScrollToVisible
3239 m_object->scrollToMakeVisible();
3242 - (void)accessibilityPerformAction:(NSString*)action
3244 if (![self updateObjectBackingStore])
3247 if ([action isEqualToString:NSAccessibilityPressAction])
3248 [self accessibilityPerformPressAction];
3250 else if ([action isEqualToString:NSAccessibilityShowMenuAction])
3251 [self accessibilityPerformShowMenuAction];
3253 else if ([action isEqualToString:NSAccessibilityIncrementAction])
3254 [self accessibilityPerformIncrementAction];
3256 else if ([action isEqualToString:NSAccessibilityDecrementAction])
3257 [self accessibilityPerformDecrementAction];
3259 else if ([action isEqualToString:NSAccessibilityScrollToVisibleAction])
3260 [self accessibilityScrollToVisible];
3263 - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attributeName
3265 // In case anything we do by changing values causes an alert or other modal
3266 // behaviors, we need to return now, so that VoiceOver doesn't hang indefinitely.
3267 dispatch_async(dispatch_get_main_queue(), ^{
3268 [self _accessibilitySetValue:value forAttribute:attributeName];
3272 - (void)_accessibilitySetValue:(id)value forAttribute:(NSString*)attributeName
3274 if (![self updateObjectBackingStore])
3277 id textMarkerRange = nil;
3278 NSNumber* number = nil;
3279 NSString* string = nil;
3280 NSRange range = {0, 0};
3281 NSArray* array = nil;
3283 // decode the parameter
3284 if (AXObjectIsTextMarkerRange(value))
3285 textMarkerRange = value;
3287 else if ([value isKindOfClass:[NSNumber self]])
3290 else if ([value isKindOfClass:[NSString self]])
3293 else if ([value isKindOfClass:[NSValue self]])
3294 range = [value rangeValue];
3296 else if ([value isKindOfClass:[NSArray self]])
3299 // handle the command
3300 if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"]) {
3301 ASSERT(textMarkerRange);
3302 m_object->setSelectedVisiblePositionRange([self visiblePositionRangeForTextMarkerRange:textMarkerRange]);
3303 } else if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute]) {
3306 bool focus = [number boolValue];
3308 // If focus is just set without making the view the first responder, then keyboard focus won't move to the right place.
3309 if (focus && m_object->isWebArea() && !m_object->document()->frame()->selection().isFocusedAndActive()) {
3310 FrameView* frameView = m_object->documentFrameView();
3311 Page* page = m_object->page();
3312 if (page && frameView) {
3313 ChromeClient& chromeClient = page->chrome().client();
3314 chromeClient.focus();
3315 if (frameView->platformWidget())
3316 chromeClient.makeFirstResponder(frameView->platformWidget());
3318 chromeClient.makeFirstResponder();
3322 m_object->setFocused(focus);
3323 } else if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
3324 if (number && m_object->canSetNumericValue())
3325 m_object->setValue([number floatValue]);
3327 m_object->setValue(string);
3328 } else if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute]) {
3331 m_object->setSelected([number boolValue]);
3332 } else if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {
3333 if (!array || m_object->roleValue() != ListBoxRole)
3335 AccessibilityObject::AccessibilityChildrenVector selectedChildren;
3336 convertToVector(array, selectedChildren);
3337 downcast<AccessibilityListBox>(*m_object).setSelectedChildren(selectedChildren);
3338 } else if (m_object->isTextControl()) {
3339 if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
3340 m_object->setSelectedText(string);
3341 } else if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
3342 m_object->setSelectedTextRange(PlainTextRange(range.location, range.length));
3343 } else if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute]) {
3344 m_object->makeRangeVisible(PlainTextRange(range.location, range.length));
3346 } else if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
3347 m_object->setIsExpanded([number boolValue]);
3348 else if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
3349 AccessibilityObject::AccessibilityChildrenVector selectedRows;
3350 convertToVector(array, selectedRows);
3351 if (m_object->isTree() || (is<AccessibilityTable>(*m_object) && downcast<AccessibilityTable>(*m_object).isExposableThroughAccessibility()))
3352 m_object->setSelectedRows(selectedRows);
3353 } else if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
3354 m_object->setARIAGrabbed([number boolValue]);
3355 else if (m_object->isWebArea() && [attributeName isEqualToString:NSAccessibilityCaretBrowsingEnabledAttribute])
3356 m_object->setCaretBrowsingEnabled([number boolValue]);
3359 // Used to set attributes synchronously on accessibility elements within tests.
3360 // For use with DumpRenderTree only.
3361 - (void)_accessibilitySetTestValue:(id)value forAttribute:(NSString*)attributeName
3363 [self _accessibilitySetValue:value forAttribute:attributeName];
3366 static RenderObject* rendererForView(NSView* view)
3368 if (![view conformsToProtocol:@protocol(WebCoreFrameView)])
3371 NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view;
3372 Frame* frame = [frameView _web_frame];
3376 Node* node = frame->document()->ownerElement();
3380 return node->renderer();
3383 - (id)_accessibilityParentForSubview:(NSView*)subview
3385 RenderObject* renderer = rendererForView(subview);
3389 AccessibilityObject* obj = renderer->document().axObjectCache()->getOrCreate(renderer);
3391 return obj->parentObjectUnignored()->wrapper();
3395 - (NSString*)accessibilityActionDescription:(NSString*)action
3397 // we have no custom actions
3398 return NSAccessibilityActionDescription(action);
3401 // The CFAttributedStringType representation of the text associated with this accessibility
3402 // object that is specified by the given range.
3403 - (NSAttributedString*)doAXAttributedStringForRange:(NSRange)range
3405 PlainTextRange textRange = PlainTextRange(range.location, range.length);
3406 VisiblePositionRange visiblePosRange = m_object->visiblePositionRangeForRange(textRange);
3407 return [self doAXAttributedStringForTextMarkerRange:[self textMarkerRangeFromVisiblePositions:visiblePosRange.start endPosition:visiblePosRange.end]];
3410 - (NSRange)_convertToNSRange:(Range*)range
3412 NSRange result = NSMakeRange(NSNotFound, 0);
3413 if (!range || !range->startContainer())
3416 Document* document = m_object->document();
3422 TextIterator::getLocationAndLengthFromRange(document->documentElement(), range, location, length);
3423 result.location = location;
3424 result.length = length;
3429 - (NSInteger)_indexForTextMarker:(id)marker
3434 VisibleSelection selection([self visiblePositionForTextMarker:marker]);
3435 return [self _convertToNSRange:selection.toNormalizedRange().get()].location;
3438 - (id)_textMarkerForIndex:(NSInteger)textIndex
3440 Document* document = m_object->document();
3444 PassRefPtr<Range> textRange = TextIterator::rangeFromLocationAndLength(document->documentElement(), textIndex, 0);
3445 if (!textRange || !textRange->boundaryPointsValid())
3448 VisiblePosition position(textRange->startPosition());
3449 return [self textMarkerForVisiblePosition:position];
3452 // The RTF representation of the text associated with this accessibility object that is
3453 // specified by the given range.
3454 - (NSData*)doAXRTFForRange:(NSRange)range
3456 NSAttributedString* attrString = [self doAXAttributedStringForRange:range];
3457 return [attrString RTFFromRange: NSMakeRange(0, [attrString length]) documentAttributes: nil];
3460 - (id)accessibilityAttributeValue:(NSString*)attribute forParameter:(id)parameter
3462 id textMarker = nil;
3463 id textMarkerRange = nil;
3464 NSNumber* number = nil;
3465 NSArray* array = nil;
3466 NSDictionary* dictionary = nil;
3467 RefPtr<AccessibilityObject> uiElement = nullptr;
3468 NSPoint point = NSZeroPoint;
3469 bool pointSet = false;
3470 NSRange range = {0, 0};
3471 bool rangeSet = false;
3472 NSRect rect = NSZeroRect;
3473 bool rectSet = false;
3475 // basic parameter validation
3476 if (!m_object || !attribute || !parameter)
3479 if (![self updateObjectBackingStore])
3482 // common parameter type check/casting. Nil checks in handlers catch wrong type case.
3483 // NOTE: This assumes nil is not a valid parameter, because it is indistinguishable from
3484 // a parameter of the wrong type.
3485 if (AXObjectIsTextMarker(parameter))
3486 textMarker = parameter;
3488 else if (AXObjectIsTextMarkerRange(parameter))
3489 textMarkerRange = parameter;
3491 else if ([parameter isKindOfClass:[WebAccessibilityObjectWrapper self]])
3492 uiElement = [(WebAccessibilityObjectWrapper*)parameter accessibilityObject];
3494 else if ([parameter isKindOfClass:[NSNumber self]])
3497 else if ([parameter isKindOfClass:[NSArray self]])
3500 else if ([parameter isKindOfClass:[NSDictionary self]])
3501 dictionary = parameter;
3503 else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSPoint)) == 0) {
3505 point = [(NSValue*)parameter pointValue];
3507 } else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSRange)) == 0) {
3509 range = [(NSValue*)parameter rangeValue];
3510 } else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSRect)) == 0) {
3512 rect = [(NSValue*)parameter rectValue];