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 NSAccessibilityPreventKeyboardDOMEventDispatchAttribute
468 #define NSAccessibilityPreventKeyboardDOMEventDispatchAttribute @"AXPreventKeyboardDOMEventDispatch"
471 #ifndef NSAccessibilityCaretBrowsingEnabledAttribute
472 #define NSAccessibilityCaretBrowsingEnabledAttribute @"AXCaretBrowsingEnabled"
475 @implementation WebAccessibilityObjectWrapper
477 - (void)unregisterUniqueIdForUIElement
479 wkUnregisterUniqueIdForElement(self);
484 // Send unregisterUniqueIdForUIElement unconditionally because if it is
485 // ever accidentally not done (via other bugs in our AX implementation) you
486 // end up with a crash like <rdar://problem/4273149>. It is safe and not
487 // expensive to send even if the object is not registered.
488 [self unregisterUniqueIdForUIElement];
494 ASSERT(m_object->isAttachment());
495 Widget* widget = m_object->widgetForAttachmentView();
498 return NSAccessibilityUnignoredDescendant(widget->platformWidget());
501 #pragma mark SystemInterface wrappers
503 static inline BOOL AXObjectIsTextMarker(id obj)
505 return obj != nil && CFGetTypeID(obj) == wkGetAXTextMarkerTypeID();
508 static inline BOOL AXObjectIsTextMarkerRange(id obj)
510 return obj != nil && CFGetTypeID(obj) == wkGetAXTextMarkerRangeTypeID();
513 static id AXTextMarkerRange(id startMarker, id endMarker)
515 ASSERT(startMarker != nil);
516 ASSERT(endMarker != nil);
517 ASSERT(CFGetTypeID(startMarker) == wkGetAXTextMarkerTypeID());
518 ASSERT(CFGetTypeID(endMarker) == wkGetAXTextMarkerTypeID());
519 return CFBridgingRelease(wkCreateAXTextMarkerRange((CFTypeRef)startMarker, (CFTypeRef)endMarker));
522 static id AXTextMarkerRangeStart(id range)
524 ASSERT(range != nil);
525 ASSERT(CFGetTypeID(range) == wkGetAXTextMarkerRangeTypeID());
526 return CFBridgingRelease(wkCopyAXTextMarkerRangeStart(range));
529 static id AXTextMarkerRangeEnd(id range)
531 ASSERT(range != nil);
532 ASSERT(CFGetTypeID(range) == wkGetAXTextMarkerRangeTypeID());
533 return CFBridgingRelease(wkCopyAXTextMarkerRangeEnd(range));
536 #pragma mark Other helpers
538 - (IntRect)screenToContents:(const IntRect&)rect
540 Document* document = m_object->document();
544 FrameView* frameView = document->view();
548 IntPoint startPoint = frameView->screenToContents(rect.minXMaxYCorner());
549 IntPoint endPoint = frameView->screenToContents(rect.maxXMinYCorner());
550 return IntRect(startPoint.x(), startPoint.y(), endPoint.x() - startPoint.x(), endPoint.y() - startPoint.y());
553 #pragma mark Search helpers
555 typedef HashMap<String, AccessibilitySearchKey> AccessibilitySearchKeyMap;
557 struct SearchKeyEntry {
559 AccessibilitySearchKey value;
562 static AccessibilitySearchKeyMap* createAccessibilitySearchKeyMap()
564 const SearchKeyEntry searchKeys[] = {
565 { NSAccessibilityAnyTypeSearchKey, AnyTypeSearchKey },
566 { NSAccessibilityBlockquoteSameLevelSearchKey, BlockquoteSameLevelSearchKey },
567 { NSAccessibilityBlockquoteSearchKey, BlockquoteSearchKey },
568 { NSAccessibilityBoldFontSearchKey, BoldFontSearchKey },
569 { NSAccessibilityButtonSearchKey, ButtonSearchKey },
570 { NSAccessibilityCheckBoxSearchKey, CheckBoxSearchKey },
571 { NSAccessibilityControlSearchKey, ControlSearchKey },
572 { NSAccessibilityDifferentTypeSearchKey, DifferentTypeSearchKey },
573 { NSAccessibilityFontChangeSearchKey, FontChangeSearchKey },
574 { NSAccessibilityFontColorChangeSearchKey, FontColorChangeSearchKey },
575 { NSAccessibilityFrameSearchKey, FrameSearchKey },
576 { NSAccessibilityGraphicSearchKey, GraphicSearchKey },
577 { NSAccessibilityHeadingLevel1SearchKey, HeadingLevel1SearchKey },
578 { NSAccessibilityHeadingLevel2SearchKey, HeadingLevel2SearchKey },
579 { NSAccessibilityHeadingLevel3SearchKey, HeadingLevel3SearchKey },
580 { NSAccessibilityHeadingLevel4SearchKey, HeadingLevel4SearchKey },
581 { NSAccessibilityHeadingLevel5SearchKey, HeadingLevel5SearchKey },
582 { NSAccessibilityHeadingLevel6SearchKey, HeadingLevel6SearchKey },
583 { NSAccessibilityHeadingSameLevelSearchKey, HeadingSameLevelSearchKey },
584 { NSAccessibilityHeadingSearchKey, HeadingSearchKey },
585 { NSAccessibilityHighlightedSearchKey, HighlightedSearchKey },
586 { NSAccessibilityItalicFontSearchKey, ItalicFontSearchKey },
587 { NSAccessibilityLandmarkSearchKey, LandmarkSearchKey },
588 { NSAccessibilityLinkSearchKey, LinkSearchKey },
589 { NSAccessibilityListSearchKey, ListSearchKey },
590 { NSAccessibilityLiveRegionSearchKey, LiveRegionSearchKey },
591 { NSAccessibilityMisspelledWordSearchKey, MisspelledWordSearchKey },
592 { NSAccessibilityOutlineSearchKey, OutlineSearchKey },
593 { NSAccessibilityPlainTextSearchKey, PlainTextSearchKey },
594 { NSAccessibilityRadioGroupSearchKey, RadioGroupSearchKey },
595 { NSAccessibilitySameTypeSearchKey, SameTypeSearchKey },
596 { NSAccessibilityStaticTextSearchKey, StaticTextSearchKey },
597 { NSAccessibilityStyleChangeSearchKey, StyleChangeSearchKey },
598 { NSAccessibilityTableSameLevelSearchKey, TableSameLevelSearchKey },
599 { NSAccessibilityTableSearchKey, TableSearchKey },
600 { NSAccessibilityTextFieldSearchKey, TextFieldSearchKey },
601 { NSAccessibilityUnderlineSearchKey, UnderlineSearchKey },
602 { NSAccessibilityUnvisitedLinkSearchKey, UnvisitedLinkSearchKey },
603 { NSAccessibilityVisitedLinkSearchKey, VisitedLinkSearchKey }
606 AccessibilitySearchKeyMap* searchKeyMap = new AccessibilitySearchKeyMap;
607 for (size_t i = 0; i < WTF_ARRAY_LENGTH(searchKeys); i++)
608 searchKeyMap->set(searchKeys[i].key, searchKeys[i].value);
613 static AccessibilitySearchKey accessibilitySearchKeyForString(const String& value)
616 return AnyTypeSearchKey;
618 static const AccessibilitySearchKeyMap* searchKeyMap = createAccessibilitySearchKeyMap();
620 AccessibilitySearchKey searchKey = searchKeyMap->get(value);
622 return searchKey ? searchKey : AnyTypeSearchKey;
625 static AccessibilitySearchCriteria accessibilitySearchCriteriaForSearchPredicateParameterizedAttribute(const NSDictionary *parameterizedAttribute)
627 NSString *directionParameter = [parameterizedAttribute objectForKey:@"AXDirection"];
628 NSNumber *immediateDescendantsOnlyParameter = [parameterizedAttribute objectForKey:NSAccessibilityImmediateDescendantsOnly];
629 NSNumber *resultsLimitParameter = [parameterizedAttribute objectForKey:@"AXResultsLimit"];
630 NSString *searchTextParameter = [parameterizedAttribute objectForKey:@"AXSearchText"];
631 WebAccessibilityObjectWrapper *startElementParameter = [parameterizedAttribute objectForKey:@"AXStartElement"];
632 NSNumber *visibleOnlyParameter = [parameterizedAttribute objectForKey:@"AXVisibleOnly"];
633 id searchKeyParameter = [parameterizedAttribute objectForKey:@"AXSearchKey"];
635 AccessibilitySearchDirection direction = SearchDirectionNext;
636 if ([directionParameter isKindOfClass:[NSString class]])
637 direction = [directionParameter isEqualToString:@"AXDirectionNext"] ? SearchDirectionNext : SearchDirectionPrevious;
639 bool immediateDescendantsOnly = false;
640 if ([immediateDescendantsOnlyParameter isKindOfClass:[NSNumber class]])
641 immediateDescendantsOnly = [immediateDescendantsOnlyParameter boolValue];
643 unsigned resultsLimit = 0;
644 if ([resultsLimitParameter isKindOfClass:[NSNumber class]])
645 resultsLimit = [resultsLimitParameter unsignedIntValue];
648 if ([searchTextParameter isKindOfClass:[NSString class]])
649 searchText = searchTextParameter;
651 AccessibilityObject *startElement = nullptr;
652 if ([startElementParameter isKindOfClass:[WebAccessibilityObjectWrapper class]])
653 startElement = [startElementParameter accessibilityObject];
655 bool visibleOnly = false;
656 if ([visibleOnlyParameter isKindOfClass:[NSNumber class]])
657 visibleOnly = [visibleOnlyParameter boolValue];
659 AccessibilitySearchCriteria criteria = AccessibilitySearchCriteria(startElement, direction, searchText, resultsLimit, visibleOnly, immediateDescendantsOnly);
661 if ([searchKeyParameter isKindOfClass:[NSString class]])
662 criteria.searchKeys.append(accessibilitySearchKeyForString(searchKeyParameter));
663 else if ([searchKeyParameter isKindOfClass:[NSArray class]]) {
664 size_t searchKeyCount = static_cast<size_t>([searchKeyParameter count]);
665 criteria.searchKeys.reserveInitialCapacity(searchKeyCount);
666 for (size_t i = 0; i < searchKeyCount; ++i) {
667 NSString *searchKey = [searchKeyParameter objectAtIndex:i];
668 if ([searchKey isKindOfClass:[NSString class]])
669 criteria.searchKeys.uncheckedAppend(accessibilitySearchKeyForString(searchKey));
676 #pragma mark Select text helpers
678 static AccessibilitySelectTextCriteria accessibilitySelectTextCriteriaForCriteriaParameterizedAttribute(const NSDictionary *parameterizedAttribute)
680 NSString *activityParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextActivity];
681 NSString *ambiguityResolutionParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextAmbiguityResolution];
682 NSString *replacementStringParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextReplacementString];
683 NSArray *searchStringsParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextSearchStrings];
685 AccessibilitySelectTextActivity activity = FindAndSelectActivity;
686 if ([activityParameter isKindOfClass:[NSString class]]) {
687 if ([activityParameter isEqualToString:NSAccessibilitySelectTextActivityFindAndReplace])
688 activity = FindAndReplaceActivity;
689 else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndCapitalize])
690 activity = FindAndCapitalize;
691 else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndLowercase])
692 activity = FindAndLowercase;
693 else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndUppercase])
694 activity = FindAndUppercase;
697 AccessibilitySelectTextAmbiguityResolution ambiguityResolution = ClosestToSelectionAmbiguityResolution;
698 if ([ambiguityResolutionParameter isKindOfClass:[NSString class]]) {
699 if ([ambiguityResolutionParameter isEqualToString:NSAccessibilitySelectTextAmbiguityResolutionClosestAfterSelection])
700 ambiguityResolution = ClosestAfterSelectionAmbiguityResolution;
701 else if ([ambiguityResolutionParameter isEqualToString:NSAccessibilitySelectTextAmbiguityResolutionClosestBeforeSelection])
702 ambiguityResolution = ClosestBeforeSelectionAmbiguityResolution;
705 String replacementString;
706 if ([replacementStringParameter isKindOfClass:[NSString class]])
707 replacementString = replacementStringParameter;
709 AccessibilitySelectTextCriteria criteria(activity, ambiguityResolution, replacementString);
711 if ([searchStringsParameter isKindOfClass:[NSArray class]]) {
712 size_t searchStringsCount = static_cast<size_t>([searchStringsParameter count]);
713 criteria.searchStrings.reserveInitialCapacity(searchStringsCount);
714 for (NSString *searchString in searchStringsParameter) {
715 if ([searchString isKindOfClass:[NSString class]])
716 criteria.searchStrings.uncheckedAppend(searchString);
723 #pragma mark Text Marker helpers
725 static id textMarkerForVisiblePosition(AXObjectCache* cache, const VisiblePosition& visiblePos)
729 TextMarkerData textMarkerData;
730 cache->textMarkerDataForVisiblePosition(textMarkerData, visiblePos);
731 if (!textMarkerData.axID)
734 return CFBridgingRelease(wkCreateAXTextMarker(&textMarkerData, sizeof(textMarkerData)));
737 - (id)textMarkerForVisiblePosition:(const VisiblePosition &)visiblePos
739 return textMarkerForVisiblePosition(m_object->axObjectCache(), visiblePos);
742 static VisiblePosition visiblePositionForTextMarker(AXObjectCache* cache, CFTypeRef textMarker)
747 return VisiblePosition();
748 TextMarkerData textMarkerData;
749 if (!wkGetBytesFromAXTextMarker(textMarker, &textMarkerData, sizeof(textMarkerData)))
750 return VisiblePosition();
752 return cache->visiblePositionForTextMarkerData(textMarkerData);
755 - (VisiblePosition)visiblePositionForTextMarker:(id)textMarker
757 return visiblePositionForTextMarker(m_object->axObjectCache(), textMarker);
760 static VisiblePosition visiblePositionForStartOfTextMarkerRange(AXObjectCache *cache, id textMarkerRange)
762 return visiblePositionForTextMarker(cache, AXTextMarkerRangeStart(textMarkerRange));
765 static VisiblePosition visiblePositionForEndOfTextMarkerRange(AXObjectCache *cache, id textMarkerRange)
767 return visiblePositionForTextMarker(cache, AXTextMarkerRangeEnd(textMarkerRange));
770 static id textMarkerRangeFromMarkers(id textMarker1, id textMarker2)
772 if (!textMarker1 || !textMarker2)
775 return AXTextMarkerRange(textMarker1, textMarker2);
778 // When modifying attributed strings, the range can come from a source which may provide faulty information (e.g. the spell checker).
779 // To protect against such cases the range should be validated before adding or removing attributes.
780 static BOOL AXAttributedStringRangeIsValid(NSAttributedString* attrString, NSRange range)
782 return (range.location < [attrString length] && NSMaxRange(range) <= [attrString length]);
785 static void AXAttributeStringSetFont(NSMutableAttributedString* attrString, NSString* attribute, NSFont* font, NSRange range)
787 if (!AXAttributedStringRangeIsValid(attrString, range))
791 NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
792 [font fontName] , NSAccessibilityFontNameKey,
793 [font familyName] , NSAccessibilityFontFamilyKey,
794 [font displayName] , NSAccessibilityVisibleNameKey,
795 [NSNumber numberWithFloat:[font pointSize]] , NSAccessibilityFontSizeKey,
798 [attrString addAttribute:attribute value:dict range:range];
800 [attrString removeAttribute:attribute range:range];
804 static CGColorRef CreateCGColorIfDifferent(NSColor* nsColor, CGColorRef existingColor)
806 // get color information assuming NSDeviceRGBColorSpace
807 NSColor* rgbColor = [nsColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
809 rgbColor = [NSColor blackColor];
810 CGFloat components[4];
811 [rgbColor getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]];
813 // create a new CGColorRef to return
814 CGColorSpaceRef cgColorSpace = CGColorSpaceCreateDeviceRGB();
815 CGColorRef cgColor = CGColorCreate(cgColorSpace, components);
816 CGColorSpaceRelease(cgColorSpace);
818 // check for match with existing color
819 if (existingColor && CGColorEqualToColor(cgColor, existingColor)) {
820 CGColorRelease(cgColor);
827 static void AXAttributeStringSetColor(NSMutableAttributedString* attrString, NSString* attribute, NSColor* color, NSRange range)
829 if (!AXAttributedStringRangeIsValid(attrString, range))
833 CGColorRef existingColor = (CGColorRef) [attrString attribute:attribute atIndex:range.location effectiveRange:nil];
834 CGColorRef cgColor = CreateCGColorIfDifferent(color, existingColor);
836 [attrString addAttribute:attribute value:(id)cgColor range:range];
837 CGColorRelease(cgColor);
840 [attrString removeAttribute:attribute range:range];
843 static void AXAttributeStringSetNumber(NSMutableAttributedString* attrString, NSString* attribute, NSNumber* number, NSRange range)
845 if (!AXAttributedStringRangeIsValid(attrString, range))
849 [attrString addAttribute:attribute value:number range:range];
851 [attrString removeAttribute:attribute range:range];
854 static void AXAttributeStringSetStyle(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
856 const RenderStyle& style = renderer->style();
858 // set basic font info
859 AXAttributeStringSetFont(attrString, NSAccessibilityFontTextAttribute, style.fontCascade().primaryFont().getNSFont(), range);
862 AXAttributeStringSetColor(attrString, NSAccessibilityForegroundColorTextAttribute, nsColor(style.visitedDependentColor(CSSPropertyColor)), range);
863 AXAttributeStringSetColor(attrString, NSAccessibilityBackgroundColorTextAttribute, nsColor(style.visitedDependentColor(CSSPropertyBackgroundColor)), range);
865 // set super/sub scripting
866 EVerticalAlign alignment = style.verticalAlign();
867 if (alignment == SUB)
868 AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:(-1)], range);
869 else if (alignment == SUPER)
870 AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:1], range);
872 [attrString removeAttribute:NSAccessibilitySuperscriptTextAttribute range:range];
875 if (style.textShadow())
876 AXAttributeStringSetNumber(attrString, NSAccessibilityShadowTextAttribute, [NSNumber numberWithBool:YES], range);
878 [attrString removeAttribute:NSAccessibilityShadowTextAttribute range:range];
880 // set underline and strikethrough
881 int decor = style.textDecorationsInEffect();
882 if ((decor & TextDecorationUnderline) == 0) {
883 [attrString removeAttribute:NSAccessibilityUnderlineTextAttribute range:range];
884 [attrString removeAttribute:NSAccessibilityUnderlineColorTextAttribute range:range];
887 if ((decor & TextDecorationLineThrough) == 0) {
888 [attrString removeAttribute:NSAccessibilityStrikethroughTextAttribute range:range];
889 [attrString removeAttribute:NSAccessibilityStrikethroughColorTextAttribute range:range];
892 if ((decor & (TextDecorationUnderline | TextDecorationLineThrough)) != 0) {
893 // FIXME: Should the underline style be reported here?
894 Color underlineColor, overlineColor, linethroughColor;
895 TextDecorationStyle underlineStyle, overlineStyle, linethroughStyle;
896 renderer->getTextDecorationColorsAndStyles(decor, underlineColor, overlineColor, linethroughColor, underlineStyle, overlineStyle, linethroughStyle);
898 if ((decor & TextDecorationUnderline) != 0) {
899 AXAttributeStringSetNumber(attrString, NSAccessibilityUnderlineTextAttribute, [NSNumber numberWithBool:YES], range);
900 AXAttributeStringSetColor(attrString, NSAccessibilityUnderlineColorTextAttribute, nsColor(underlineColor), range);
903 if ((decor & TextDecorationLineThrough) != 0) {
904 AXAttributeStringSetNumber(attrString, NSAccessibilityStrikethroughTextAttribute, [NSNumber numberWithBool:YES], range);
905 AXAttributeStringSetColor(attrString, NSAccessibilityStrikethroughColorTextAttribute, nsColor(linethroughColor), range);
909 // Indicate background highlighting.
910 for (Node* node = renderer->node(); node; node = node->parentNode()) {
911 if (node->hasTagName(markTag))
912 AXAttributeStringSetNumber(attrString, @"AXHighlight", [NSNumber numberWithBool:YES], range);
916 static void AXAttributeStringSetBlockquoteLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
918 if (!AXAttributedStringRangeIsValid(attrString, range))
921 AccessibilityObject* obj = renderer->document().axObjectCache()->getOrCreate(renderer);
922 int quoteLevel = obj->blockquoteLevel();
925 [attrString addAttribute:NSAccessibilityBlockQuoteLevelAttribute value:[NSNumber numberWithInt:quoteLevel] range:range];
927 [attrString removeAttribute:NSAccessibilityBlockQuoteLevelAttribute range:range];
930 static void AXAttributeStringSetSpelling(NSMutableAttributedString* attrString, Node* node, StringView text, NSRange range)
932 if (unifiedTextCheckerEnabled(node->document().frame())) {
933 // Check the spelling directly since document->markersForNode() does not store the misspelled marking when the cursor is in a word.
934 TextCheckerClient* checker = node->document().frame()->editor().textChecker();
936 // checkTextOfParagraph is the only spelling/grammar checker implemented in WK1 and WK2
937 Vector<TextCheckingResult> results;
938 checkTextOfParagraph(*checker, text, TextCheckingTypeSpelling, results);
940 size_t size = results.size();
941 NSNumber* trueValue = [NSNumber numberWithBool:YES];
942 for (unsigned i = 0; i < size; i++) {
943 const TextCheckingResult& result = results[i];
944 AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, trueValue, NSMakeRange(result.location + range.location, result.length));
946 AXAttributeStringSetNumber(attrString, NSAccessibilityMarkedMisspelledTextAttribute, trueValue, NSMakeRange(result.location + range.location, result.length));
952 for (unsigned currentPosition = 0; currentPosition < text.length(); ) {
953 int misspellingLocation = -1;
954 int misspellingLength = 0;
955 node->document().frame()->editor().textChecker()->checkSpellingOfString(text.substring(currentPosition), &misspellingLocation, &misspellingLength);
956 if (misspellingLocation == -1 || !misspellingLength)
959 NSRange spellRange = NSMakeRange(range.location + currentPosition + misspellingLocation, misspellingLength);
960 AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, [NSNumber numberWithBool:YES], spellRange);
962 AXAttributeStringSetNumber(attrString, NSAccessibilityMarkedMisspelledTextAttribute, [NSNumber numberWithBool:YES], spellRange);
965 currentPosition += misspellingLocation + misspellingLength;
969 static void AXAttributeStringSetexpandedTextValue(NSMutableAttributedString *attrString, RenderObject* renderer, NSRange range)
971 if (!renderer || !AXAttributedStringRangeIsValid(attrString, range))
973 AccessibilityObject* axObject = renderer->document().axObjectCache()->getOrCreate(renderer);
974 if (axObject->supportsExpandedTextValue())
975 [attrString addAttribute:NSAccessibilityExpandedTextValueAttribute value:axObject->expandedTextValue() range:range];
977 [attrString removeAttribute:NSAccessibilityExpandedTextValueAttribute range:range];
980 static void AXAttributeStringSetHeadingLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
985 if (!AXAttributedStringRangeIsValid(attrString, range))
988 // Sometimes there are objects between the text and the heading.
989 // In those cases the parent hierarchy should be queried to see if there is a heading level.
990 int parentHeadingLevel = 0;
991 AccessibilityObject* parentObject = renderer->document().axObjectCache()->getOrCreate(renderer->parent());
992 for (; parentObject; parentObject = parentObject->parentObject()) {
993 parentHeadingLevel = parentObject->headingLevel();
994 if (parentHeadingLevel)
998 if (parentHeadingLevel)
999 [attrString addAttribute:@"AXHeadingLevel" value:[NSNumber numberWithInt:parentHeadingLevel] range:range];
1001 [attrString removeAttribute:@"AXHeadingLevel" range:range];
1004 static void AXAttributeStringSetElement(NSMutableAttributedString* attrString, NSString* attribute, AccessibilityObject* object, NSRange range)
1006 if (!AXAttributedStringRangeIsValid(attrString, range))
1009 if (is<AccessibilityRenderObject>(object)) {
1010 // make a serializable AX object
1012 RenderObject* renderer = downcast<AccessibilityRenderObject>(*object).renderer();
1016 AXObjectCache* cache = renderer->document().axObjectCache();
1020 AXUIElementRef axElement = wkCreateAXUIElementRef(object->wrapper());
1022 [attrString addAttribute:attribute value:(id)axElement range:range];
1023 CFRelease(axElement);
1026 [attrString removeAttribute:attribute range:range];
1029 static void AXAttributedStringAppendText(NSMutableAttributedString* attrString, Node* node, StringView text)
1031 // skip invisible text
1032 RenderObject* renderer = node->renderer();
1036 // easier to calculate the range before appending the string
1037 NSRange attrStringRange = NSMakeRange([attrString length], text.length());
1039 // append the string from this node
1040 [[attrString mutableString] appendString:text.createNSStringWithoutCopying().get()];
1042 // add new attributes and remove irrelevant inherited ones
1043 // NOTE: color attributes are handled specially because -[NSMutableAttributedString addAttribute: value: range:] does not merge
1044 // identical colors. Workaround is to not replace an existing color attribute if it matches what we are adding. This also means
1045 // we cannot just pre-remove all inherited attributes on the appended string, so we have to remove the irrelevant ones individually.
1047 // remove inherited attachment from prior AXAttributedStringAppendReplaced
1048 [attrString removeAttribute:NSAccessibilityAttachmentTextAttribute range:attrStringRange];
1050 [attrString removeAttribute:NSAccessibilityMarkedMisspelledTextAttribute range:attrStringRange];
1052 [attrString removeAttribute:NSAccessibilityMisspelledTextAttribute range:attrStringRange];
1054 // set new attributes
1055 AXAttributeStringSetStyle(attrString, renderer, attrStringRange);
1056 AXAttributeStringSetHeadingLevel(attrString, renderer, attrStringRange);
1057 AXAttributeStringSetBlockquoteLevel(attrString, renderer, attrStringRange);
1058 AXAttributeStringSetexpandedTextValue(attrString, renderer, attrStringRange);
1059 AXAttributeStringSetElement(attrString, NSAccessibilityLinkTextAttribute, AccessibilityObject::anchorElementForNode(node), attrStringRange);
1061 // do spelling last because it tends to break up the range
1062 AXAttributeStringSetSpelling(attrString, node, text, attrStringRange);
1065 static NSString* nsStringForReplacedNode(Node* replacedNode)
1067 // we should always be given a rendered node and a replaced node, but be safe
1068 // replaced nodes are either attachments (widgets) or images
1069 if (!replacedNode || !isRendererReplacedElement(replacedNode->renderer()) || replacedNode->isTextNode()) {
1070 ASSERT_NOT_REACHED();
1074 // create an AX object, but skip it if it is not supposed to be seen
1075 RefPtr<AccessibilityObject> obj = replacedNode->renderer()->document().axObjectCache()->getOrCreate(replacedNode->renderer());
1076 if (obj->accessibilityIsIgnored())
1079 // use the attachmentCharacter to represent the replaced node
1080 const UniChar attachmentChar = NSAttachmentCharacter;
1081 return [NSString stringWithCharacters:&attachmentChar length:1];
1084 - (NSAttributedString*)doAXAttributedStringForTextMarkerRange:(id)textMarkerRange
1089 // extract the start and end VisiblePosition
1090 VisiblePosition startVisiblePosition = visiblePositionForStartOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);
1091 if (startVisiblePosition.isNull())
1094 VisiblePosition endVisiblePosition = visiblePositionForEndOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);
1095 if (endVisiblePosition.isNull())
1098 VisiblePositionRange visiblePositionRange(startVisiblePosition, endVisiblePosition);
1099 // iterate over the range to build the AX attributed string
1100 NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] init];
1101 TextIterator it(makeRange(startVisiblePosition, endVisiblePosition).get());
1102 while (!it.atEnd()) {
1103 // locate the node and starting offset for this range
1105 Node* node = it.range()->startContainer(exception);
1106 ASSERT(node == it.range()->endContainer(exception));
1107 int offset = it.range()->startOffset(exception);
1109 // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX)
1110 if (it.text().length()) {
1111 // Add the text of the list marker item if necessary.
1112 String listMarkerText = m_object->listMarkerTextForNodeAndPosition(node, VisiblePosition(it.range()->startPosition()));
1113 if (!listMarkerText.isEmpty())
1114 AXAttributedStringAppendText(attrString, node, listMarkerText);
1115 AXAttributedStringAppendText(attrString, node, it.text());
1117 Node* replacedNode = node->traverseToChildAt(offset);
1118 NSString *attachmentString = nsStringForReplacedNode(replacedNode);
1119 if (attachmentString) {
1120 NSRange attrStringRange = NSMakeRange([attrString length], [attachmentString length]);
1122 // append the placeholder string
1123 [[attrString mutableString] appendString:attachmentString];
1125 // remove all inherited attributes
1126 [attrString setAttributes:nil range:attrStringRange];
1128 // add the attachment attribute
1129 AccessibilityObject* obj = replacedNode->renderer()->document().axObjectCache()->getOrCreate(replacedNode->renderer());
1130 AXAttributeStringSetElement(attrString, NSAccessibilityAttachmentTextAttribute, obj, attrStringRange);
1136 return [attrString autorelease];
1139 static id textMarkerRangeFromVisiblePositions(AXObjectCache *cache, VisiblePosition startPosition, VisiblePosition endPosition)
1141 id startTextMarker = textMarkerForVisiblePosition(cache, startPosition);
1142 id endTextMarker = textMarkerForVisiblePosition(cache, endPosition);
1143 return textMarkerRangeFromMarkers(startTextMarker, endTextMarker);
1146 - (id)textMarkerRangeFromVisiblePositions:(VisiblePosition)startPosition endPosition:(VisiblePosition)endPosition
1148 return textMarkerRangeFromVisiblePositions(m_object->axObjectCache(), startPosition, endPosition);
1151 - (NSArray*)accessibilityActionNames
1153 if (![self updateObjectBackingStore])
1156 // All elements should get ShowMenu and ScrollToVisible.
1157 // But certain earlier VoiceOver versions do not support scroll to visible, and it confuses them to see it in the list.
1158 static NSArray *defaultElementActions = [[NSArray alloc] initWithObjects:NSAccessibilityShowMenuAction, NSAccessibilityScrollToVisibleAction, nil];
1160 // Action elements allow Press.
1161 // 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.
1162 static NSArray *actionElementActions = [[NSArray alloc] initWithObjects:NSAccessibilityPressAction, NSAccessibilityShowMenuAction, NSAccessibilityScrollToVisibleAction, nil];
1164 // Menu elements allow Press and Cancel.
1165 static NSArray *menuElementActions = [[actionElementActions arrayByAddingObject:NSAccessibilityCancelAction] retain];
1167 // Slider elements allow Increment/Decrement.
1168 static NSArray *sliderActions = [[defaultElementActions arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:NSAccessibilityIncrementAction, NSAccessibilityDecrementAction, nil]] retain];
1171 if (m_object->supportsPressAction())
1172 actions = actionElementActions;
1173 else if (m_object->isMenuRelated())
1174 actions = menuElementActions;
1175 else if (m_object->isSlider())
1176 actions = sliderActions;
1177 else if (m_object->isAttachment())
1178 actions = [[self attachmentView] accessibilityActionNames];
1180 actions = defaultElementActions;
1185 - (NSArray*)additionalAccessibilityAttributeNames
1190 NSMutableArray *additional = [NSMutableArray array];
1191 if (m_object->supportsARIAOwns())
1192 [additional addObject:NSAccessibilityOwnsAttribute];
1194 if (m_object->supportsARIAExpanded())
1195 [additional addObject:NSAccessibilityExpandedAttribute];
1197 if (m_object->isScrollbar())
1198 [additional addObject:NSAccessibilityOrientationAttribute];
1200 if (m_object->supportsARIADragging())
1201 [additional addObject:NSAccessibilityGrabbedAttribute];
1203 if (m_object->supportsARIADropping())
1204 [additional addObject:NSAccessibilityDropEffectsAttribute];
1206 if (is<AccessibilityTable>(*m_object) && downcast<AccessibilityTable>(*m_object).isExposableThroughAccessibility() && downcast<AccessibilityTable>(*m_object).supportsSelectedRows())
1207 [additional addObject:NSAccessibilitySelectedRowsAttribute];
1209 if (m_object->supportsARIALiveRegion()) {
1210 [additional addObject:NSAccessibilityARIALiveAttribute];
1211 [additional addObject:NSAccessibilityARIARelevantAttribute];
1214 if (m_object->supportsARIASetSize())
1215 [additional addObject:NSAccessibilityARIASetSizeAttribute];
1216 if (m_object->supportsARIAPosInSet())
1217 [additional addObject:NSAccessibilityARIAPosInSetAttribute];
1219 if (m_object->sortDirection() != SortDirectionNone)
1220 [additional addObject:NSAccessibilitySortDirectionAttribute];
1222 // If an object is a child of a live region, then add these
1223 if (m_object->isInsideARIALiveRegion())
1224 [additional addObject:NSAccessibilityARIAAtomicAttribute];
1225 // All objects should expose the ARIA busy attribute (ARIA 1.1 with ISSUE-538).
1226 [additional addObject:NSAccessibilityElementBusyAttribute];
1228 // Popup buttons on the Mac expose the value attribute.
1229 if (m_object->isPopUpButton()) {
1230 [additional addObject:NSAccessibilityValueAttribute];
1233 if (m_object->supportsRequiredAttribute()) {
1234 [additional addObject:NSAccessibilityRequiredAttribute];
1237 if (m_object->ariaHasPopup())
1238 [additional addObject:NSAccessibilityHasPopupAttribute];
1240 if (m_object->isMathRoot()) {
1241 // The index of a square root is always known, so there's no object associated with it.
1242 if (!m_object->isMathSquareRoot())
1243 [additional addObject:NSAccessibilityMathRootIndexAttribute];
1244 [additional addObject:NSAccessibilityMathRootRadicandAttribute];
1245 } else if (m_object->isMathFraction()) {
1246 [additional addObject:NSAccessibilityMathFractionNumeratorAttribute];
1247 [additional addObject:NSAccessibilityMathFractionDenominatorAttribute];
1248 [additional addObject:NSAccessibilityMathLineThicknessAttribute];
1249 } else if (m_object->isMathSubscriptSuperscript()) {
1250 [additional addObject:NSAccessibilityMathBaseAttribute];
1251 [additional addObject:NSAccessibilityMathSubscriptAttribute];
1252 [additional addObject:NSAccessibilityMathSuperscriptAttribute];
1253 } else if (m_object->isMathUnderOver()) {
1254 [additional addObject:NSAccessibilityMathBaseAttribute];
1255 [additional addObject:NSAccessibilityMathUnderAttribute];
1256 [additional addObject:NSAccessibilityMathOverAttribute];
1257 } else if (m_object->isMathFenced()) {
1258 [additional addObject:NSAccessibilityMathFencedOpenAttribute];
1259 [additional addObject:NSAccessibilityMathFencedCloseAttribute];
1260 } else if (m_object->isMathMultiscript()) {
1261 [additional addObject:NSAccessibilityMathBaseAttribute];
1262 [additional addObject:NSAccessibilityMathPrescriptsAttribute];
1263 [additional addObject:NSAccessibilityMathPostscriptsAttribute];
1266 if (m_object->supportsPath())
1267 [additional addObject:NSAccessibilityPathAttribute];
1269 if (m_object->supportsExpandedTextValue())
1270 [additional addObject:NSAccessibilityExpandedTextValueAttribute];
1275 - (NSArray*)accessibilityAttributeNames
1277 if (![self updateObjectBackingStore])
1280 if (m_object->isAttachment())
1281 return [[self attachmentView] accessibilityAttributeNames];
1283 static NSArray* attributes = nil;
1284 static NSArray* anchorAttrs = nil;
1285 static NSArray* webAreaAttrs = nil;
1286 static NSArray* textAttrs = nil;
1287 static NSArray* listAttrs = nil;
1288 static NSArray* listBoxAttrs = nil;
1289 static NSArray* rangeAttrs = nil;
1290 static NSArray* commonMenuAttrs = nil;
1291 static NSArray* menuAttrs = nil;
1292 static NSArray* menuBarAttrs = nil;
1293 static NSArray* menuItemAttrs = nil;
1294 static NSArray* menuButtonAttrs = nil;
1295 static NSArray* controlAttrs = nil;
1296 static NSArray* tableAttrs = nil;
1297 static NSArray* tableRowAttrs = nil;
1298 static NSArray* tableColAttrs = nil;
1299 static NSArray* tableCellAttrs = nil;
1300 static NSArray* groupAttrs = nil;
1301 static NSArray* inputImageAttrs = nil;
1302 static NSArray* passwordFieldAttrs = nil;
1303 static NSArray* tabListAttrs = nil;
1304 static NSArray* comboBoxAttrs = nil;
1305 static NSArray* outlineAttrs = nil;
1306 static NSArray* outlineRowAttrs = nil;
1307 static NSArray* buttonAttrs = nil;
1308 static NSArray* scrollViewAttrs = nil;
1309 static NSArray* incrementorAttrs = nil;
1310 NSMutableArray* tempArray;
1311 if (attributes == nil) {
1312 attributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1313 NSAccessibilitySubroleAttribute,
1314 NSAccessibilityRoleDescriptionAttribute,
1315 NSAccessibilityChildrenAttribute,
1316 NSAccessibilityHelpAttribute,
1317 NSAccessibilityParentAttribute,
1318 NSAccessibilityPositionAttribute,
1319 NSAccessibilitySizeAttribute,
1320 NSAccessibilityTitleAttribute,
1321 NSAccessibilityDescriptionAttribute,
1322 NSAccessibilityValueAttribute,
1323 NSAccessibilityFocusedAttribute,
1324 NSAccessibilityEnabledAttribute,
1325 NSAccessibilityWindowAttribute,
1326 @"AXSelectedTextMarkerRange",
1327 @"AXStartTextMarker",
1330 NSAccessibilityLinkedUIElementsAttribute,
1331 NSAccessibilitySelectedAttribute,
1332 NSAccessibilityBlockQuoteLevelAttribute,
1333 NSAccessibilityTopLevelUIElementAttribute,
1334 NSAccessibilityLanguageAttribute,
1335 NSAccessibilityDOMIdentifierAttribute,
1336 NSAccessibilityDOMClassListAttribute,
1339 if (commonMenuAttrs == nil) {
1340 commonMenuAttrs = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1341 NSAccessibilityRoleDescriptionAttribute,
1342 NSAccessibilityChildrenAttribute,
1343 NSAccessibilityParentAttribute,
1344 NSAccessibilityEnabledAttribute,
1345 NSAccessibilityPositionAttribute,
1346 NSAccessibilitySizeAttribute,
1349 if (anchorAttrs == nil) {
1350 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1351 [tempArray addObject:NSAccessibilityURLAttribute];
1352 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1353 anchorAttrs = [[NSArray alloc] initWithArray:tempArray];
1354 [tempArray release];
1356 if (webAreaAttrs == nil) {
1357 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1358 // WebAreas should not expose AXSubrole.
1359 [tempArray removeObject:NSAccessibilitySubroleAttribute];
1360 [tempArray addObject:@"AXLinkUIElements"];
1361 [tempArray addObject:@"AXLoaded"];
1362 [tempArray addObject:@"AXLayoutCount"];
1363 [tempArray addObject:NSAccessibilityLoadingProgressAttribute];
1364 [tempArray addObject:NSAccessibilityURLAttribute];
1365 [tempArray addObject:NSAccessibilityCaretBrowsingEnabledAttribute];
1366 [tempArray addObject:NSAccessibilityPreventKeyboardDOMEventDispatchAttribute];
1367 webAreaAttrs = [[NSArray alloc] initWithArray:tempArray];
1368 [tempArray release];
1370 if (textAttrs == nil) {
1371 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1372 [tempArray addObject:NSAccessibilityNumberOfCharactersAttribute];
1373 [tempArray addObject:NSAccessibilitySelectedTextAttribute];
1374 [tempArray addObject:NSAccessibilitySelectedTextRangeAttribute];
1375 [tempArray addObject:NSAccessibilityVisibleCharacterRangeAttribute];
1376 [tempArray addObject:NSAccessibilityInsertionPointLineNumberAttribute];
1377 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1378 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1379 [tempArray addObject:NSAccessibilityRequiredAttribute];
1380 [tempArray addObject:NSAccessibilityInvalidAttribute];
1381 [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1382 [tempArray addObject:NSAccessibilityValueAutofilledAttribute];
1383 textAttrs = [[NSArray alloc] initWithArray:tempArray];
1384 [tempArray release];
1386 if (listAttrs == nil) {
1387 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1388 [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1389 [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1390 [tempArray addObject:NSAccessibilityOrientationAttribute];
1391 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1392 listAttrs = [[NSArray alloc] initWithArray:tempArray];
1393 [tempArray release];
1395 if (listBoxAttrs == nil) {
1396 tempArray = [[NSMutableArray alloc] initWithArray:listAttrs];
1397 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1398 [tempArray addObject:NSAccessibilityRequiredAttribute];
1399 [tempArray addObject:NSAccessibilityInvalidAttribute];
1400 listBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1401 [tempArray release];
1403 if (rangeAttrs == nil) {
1404 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1405 [tempArray addObject:NSAccessibilityMinValueAttribute];
1406 [tempArray addObject:NSAccessibilityMaxValueAttribute];
1407 [tempArray addObject:NSAccessibilityOrientationAttribute];
1408 [tempArray addObject:NSAccessibilityValueDescriptionAttribute];
1409 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1410 rangeAttrs = [[NSArray alloc] initWithArray:tempArray];
1411 [tempArray release];
1413 if (menuBarAttrs == nil) {
1414 tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1415 [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1416 [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1417 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1418 menuBarAttrs = [[NSArray alloc] initWithArray:tempArray];
1419 [tempArray release];
1421 if (menuAttrs == nil) {
1422 tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1423 [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1424 [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1425 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1426 menuAttrs = [[NSArray alloc] initWithArray:tempArray];
1427 [tempArray release];
1429 if (menuItemAttrs == nil) {
1430 tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1431 [tempArray addObject:NSAccessibilityTitleAttribute];
1432 [tempArray addObject:NSAccessibilityDescriptionAttribute];
1433 [tempArray addObject:NSAccessibilityHelpAttribute];
1434 [tempArray addObject:NSAccessibilitySelectedAttribute];
1435 [tempArray addObject:NSAccessibilityValueAttribute];
1436 [tempArray addObject:(NSString*)kAXMenuItemCmdCharAttribute];
1437 [tempArray addObject:(NSString*)kAXMenuItemCmdVirtualKeyAttribute];
1438 [tempArray addObject:(NSString*)kAXMenuItemCmdGlyphAttribute];
1439 [tempArray addObject:(NSString*)kAXMenuItemCmdModifiersAttribute];
1440 [tempArray addObject:(NSString*)kAXMenuItemMarkCharAttribute];
1441 [tempArray addObject:(NSString*)kAXMenuItemPrimaryUIElementAttribute];
1442 [tempArray addObject:NSAccessibilityServesAsTitleForUIElementsAttribute];
1443 [tempArray addObject:NSAccessibilityFocusedAttribute];
1444 menuItemAttrs = [[NSArray alloc] initWithArray:tempArray];
1445 [tempArray release];
1447 if (menuButtonAttrs == nil) {
1448 menuButtonAttrs = [[NSArray alloc] initWithObjects:NSAccessibilityRoleAttribute,
1449 NSAccessibilityRoleDescriptionAttribute,
1450 NSAccessibilityParentAttribute,
1451 NSAccessibilityPositionAttribute,
1452 NSAccessibilitySizeAttribute,
1453 NSAccessibilityWindowAttribute,
1454 NSAccessibilityEnabledAttribute,
1455 NSAccessibilityFocusedAttribute,
1456 NSAccessibilityTitleAttribute,
1457 NSAccessibilityChildrenAttribute, nil];
1459 if (controlAttrs == nil) {
1460 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1461 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1462 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1463 [tempArray addObject:NSAccessibilityRequiredAttribute];
1464 [tempArray addObject:NSAccessibilityInvalidAttribute];
1465 controlAttrs = [[NSArray alloc] initWithArray:tempArray];
1466 [tempArray release];
1468 if (incrementorAttrs == nil) {
1469 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1470 [tempArray addObject:NSAccessibilityIncrementButtonAttribute];
1471 [tempArray addObject:NSAccessibilityDecrementButtonAttribute];
1472 [tempArray addObject:NSAccessibilityValueDescriptionAttribute];
1473 [tempArray addObject:NSAccessibilityMinValueAttribute];
1474 [tempArray addObject:NSAccessibilityMaxValueAttribute];
1475 incrementorAttrs = [[NSArray alloc] initWithArray:tempArray];
1476 [tempArray release];
1478 if (buttonAttrs == nil) {
1479 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1480 // Buttons should not expose AXValue.
1481 [tempArray removeObject:NSAccessibilityValueAttribute];
1482 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1483 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1484 buttonAttrs = [[NSArray alloc] initWithArray:tempArray];
1485 [tempArray release];
1487 if (comboBoxAttrs == nil) {
1488 tempArray = [[NSMutableArray alloc] initWithArray:controlAttrs];
1489 [tempArray addObject:NSAccessibilityExpandedAttribute];
1490 comboBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1491 [tempArray release];
1493 if (tableAttrs == nil) {
1494 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1495 [tempArray addObject:NSAccessibilityRowsAttribute];
1496 [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1497 [tempArray addObject:NSAccessibilityColumnsAttribute];
1498 [tempArray addObject:NSAccessibilityVisibleColumnsAttribute];
1499 [tempArray addObject:NSAccessibilityVisibleCellsAttribute];
1500 [tempArray addObject:NSAccessibilityColumnHeaderUIElementsAttribute];
1501 [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];
1502 [tempArray addObject:NSAccessibilityHeaderAttribute];
1503 [tempArray addObject:NSAccessibilityColumnCountAttribute];
1504 [tempArray addObject:NSAccessibilityRowCountAttribute];
1505 tableAttrs = [[NSArray alloc] initWithArray:tempArray];
1506 [tempArray release];
1508 if (tableRowAttrs == nil) {
1509 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1510 [tempArray addObject:NSAccessibilityIndexAttribute];
1511 tableRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1512 [tempArray release];
1514 if (tableColAttrs == nil) {
1515 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1516 [tempArray addObject:NSAccessibilityIndexAttribute];
1517 [tempArray addObject:NSAccessibilityHeaderAttribute];
1518 [tempArray addObject:NSAccessibilityRowsAttribute];
1519 [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1520 tableColAttrs = [[NSArray alloc] initWithArray:tempArray];
1521 [tempArray release];
1523 if (tableCellAttrs == nil) {
1524 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1525 [tempArray addObject:NSAccessibilityRowIndexRangeAttribute];
1526 [tempArray addObject:NSAccessibilityColumnIndexRangeAttribute];
1527 [tempArray addObject:NSAccessibilityColumnHeaderUIElementsAttribute];
1528 [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];
1529 tableCellAttrs = [[NSArray alloc] initWithArray:tempArray];
1530 [tempArray release];
1532 if (groupAttrs == nil) {
1533 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1534 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1535 groupAttrs = [[NSArray alloc] initWithArray:tempArray];
1536 [tempArray release];
1538 if (inputImageAttrs == nil) {
1539 tempArray = [[NSMutableArray alloc] initWithArray:buttonAttrs];
1540 [tempArray addObject:NSAccessibilityURLAttribute];
1541 inputImageAttrs = [[NSArray alloc] initWithArray:tempArray];
1542 [tempArray release];
1544 if (passwordFieldAttrs == nil) {
1545 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1546 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1547 [tempArray addObject:NSAccessibilityRequiredAttribute];
1548 [tempArray addObject:NSAccessibilityInvalidAttribute];
1549 [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1550 [tempArray addObject:NSAccessibilityValueAutofilledAttribute];
1551 passwordFieldAttrs = [[NSArray alloc] initWithArray:tempArray];
1552 [tempArray release];
1554 if (tabListAttrs == nil) {
1555 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1556 [tempArray addObject:NSAccessibilityTabsAttribute];
1557 [tempArray addObject:NSAccessibilityContentsAttribute];
1558 tabListAttrs = [[NSArray alloc] initWithArray:tempArray];
1559 [tempArray release];
1561 if (outlineAttrs == nil) {
1562 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1563 [tempArray addObject:NSAccessibilitySelectedRowsAttribute];
1564 [tempArray addObject:NSAccessibilityRowsAttribute];
1565 [tempArray addObject:NSAccessibilityColumnsAttribute];
1566 outlineAttrs = [[NSArray alloc] initWithArray:tempArray];
1567 [tempArray release];
1569 if (outlineRowAttrs == nil) {
1570 tempArray = [[NSMutableArray alloc] initWithArray:tableRowAttrs];
1571 [tempArray addObject:NSAccessibilityDisclosingAttribute];
1572 [tempArray addObject:NSAccessibilityDisclosedByRowAttribute];
1573 [tempArray addObject:NSAccessibilityDisclosureLevelAttribute];
1574 [tempArray addObject:NSAccessibilityDisclosedRowsAttribute];
1575 outlineRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1576 [tempArray release];
1578 if (scrollViewAttrs == nil) {
1579 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1580 [tempArray addObject:NSAccessibilityContentsAttribute];
1581 [tempArray addObject:NSAccessibilityHorizontalScrollBarAttribute];
1582 [tempArray addObject:NSAccessibilityVerticalScrollBarAttribute];
1583 scrollViewAttrs = [[NSArray alloc] initWithArray:tempArray];
1584 [tempArray release];
1587 NSArray *objectAttributes = attributes;
1589 if (m_object->isPasswordField())
1590 objectAttributes = passwordFieldAttrs;
1592 else if (m_object->isWebArea())
1593 objectAttributes = webAreaAttrs;
1595 else if (m_object->isTextControl())
1596 objectAttributes = textAttrs;
1598 else if (m_object->isLink() || m_object->isImage())
1599 objectAttributes = anchorAttrs;
1601 else if (is<AccessibilityTable>(*m_object) && downcast<AccessibilityTable>(*m_object).isExposableThroughAccessibility())
1602 objectAttributes = tableAttrs;
1603 else if (m_object->isTableColumn())
1604 objectAttributes = tableColAttrs;
1605 else if (m_object->isTableCell())
1606 objectAttributes = tableCellAttrs;
1607 else if (m_object->isTableRow()) {
1608 // An ARIA table row can be collapsed and expanded, so it needs the extra attributes.
1609 if (m_object->isARIATreeGridRow())
1610 objectAttributes = outlineRowAttrs;
1612 objectAttributes = tableRowAttrs;
1615 else if (m_object->isTree())
1616 objectAttributes = outlineAttrs;
1617 else if (m_object->isTreeItem())
1618 objectAttributes = outlineRowAttrs;
1620 else if (m_object->isListBox())
1621 objectAttributes = listBoxAttrs;
1622 else if (m_object->isList())
1623 objectAttributes = listAttrs;
1625 else if (m_object->isComboBox())
1626 objectAttributes = comboBoxAttrs;
1628 else if (m_object->isProgressIndicator() || m_object->isSlider())
1629 objectAttributes = rangeAttrs;
1631 // These are processed in order because an input image is a button, and a button is a control.
1632 else if (m_object->isInputImage())
1633 objectAttributes = inputImageAttrs;
1634 else if (m_object->isButton())
1635 objectAttributes = buttonAttrs;
1636 else if (m_object->isControl())
1637 objectAttributes = controlAttrs;
1639 else if (m_object->isGroup() || m_object->isListItem())
1640 objectAttributes = groupAttrs;
1641 else if (m_object->isTabList())
1642 objectAttributes = tabListAttrs;
1643 else if (m_object->isScrollView())
1644 objectAttributes = scrollViewAttrs;
1645 else if (m_object->isSpinButton())
1646 objectAttributes = incrementorAttrs;
1648 else if (m_object->isMenu())
1649 objectAttributes = menuAttrs;
1650 else if (m_object->isMenuBar())
1651 objectAttributes = menuBarAttrs;
1652 else if (m_object->isMenuButton())
1653 objectAttributes = menuButtonAttrs;
1654 else if (m_object->isMenuItem())
1655 objectAttributes = menuItemAttrs;
1657 NSArray *additionalAttributes = [self additionalAccessibilityAttributeNames];
1658 if ([additionalAttributes count])
1659 objectAttributes = [objectAttributes arrayByAddingObjectsFromArray:additionalAttributes];
1661 return objectAttributes;
1664 - (VisiblePositionRange)visiblePositionRangeForTextMarkerRange:(id)textMarkerRange
1666 if (!textMarkerRange)
1667 return VisiblePositionRange();
1668 AXObjectCache* cache = m_object->axObjectCache();
1669 return VisiblePositionRange(visiblePositionForStartOfTextMarkerRange(cache, textMarkerRange), visiblePositionForEndOfTextMarkerRange(cache, textMarkerRange));
1672 - (NSArray*)renderWidgetChildren
1674 Widget* widget = m_object->widget();
1677 #pragma clang diagnostic push
1678 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1679 return [(widget->platformWidget()) accessibilityAttributeValue: NSAccessibilityChildrenAttribute];
1680 #pragma clang diagnostic pop
1683 - (id)remoteAccessibilityParentObject
1688 Document* document = m_object->document();
1692 Frame* frame = document->frame();
1696 return frame->loader().client().accessibilityRemoteObject();
1699 static void convertToVector(NSArray* array, AccessibilityObject::AccessibilityChildrenVector& vector)
1701 unsigned length = [array count];
1702 vector.reserveInitialCapacity(length);
1703 for (unsigned i = 0; i < length; ++i) {
1704 AccessibilityObject* obj = [[array objectAtIndex:i] accessibilityObject];
1710 static NSMutableArray* convertToNSArray(const AccessibilityObject::AccessibilityChildrenVector& vector)
1712 NSMutableArray* array = [NSMutableArray arrayWithCapacity:vector.size()];
1713 for (const auto& child : vector) {
1714 WebAccessibilityObjectWrapper* wrapper = child->wrapper();
1717 // we want to return the attachment view instead of the object representing the attachment.
1718 // otherwise, we get palindrome errors in the AX hierarchy
1719 if (child->isAttachment() && [wrapper attachmentView])
1720 [array addObject:[wrapper attachmentView]];
1722 [array addObject:wrapper];
1728 static NSMutableArray *convertStringsToNSArray(const Vector<String>& vector)
1730 NSMutableArray *array = [NSMutableArray arrayWithCapacity:vector.size()];
1731 for (const auto& string : vector)
1732 [array addObject:string];
1736 - (id)textMarkerRangeForSelection
1738 VisibleSelection selection = m_object->selection();
1739 if (selection.isNone())
1741 return [self textMarkerRangeFromVisiblePositions:selection.visibleStart() endPosition:selection.visibleEnd()];
1744 - (CGPoint)convertPointToScreenSpace:(FloatPoint &)point
1746 FrameView* frameView = m_object->documentFrameView();
1748 // WebKit1 code path... platformWidget() exists.
1749 if (frameView && frameView->platformWidget()) {
1750 NSPoint nsPoint = (NSPoint)point;
1751 NSView* view = frameView->documentView();
1752 #pragma clang diagnostic push
1753 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1754 nsPoint = [[view window] convertBaseToScreen:[view convertPoint:nsPoint toView:nil]];
1755 #pragma clang diagnostic pop
1756 return CGPointMake(nsPoint.x, nsPoint.y);
1759 // Find the appropriate scroll view to use to convert the contents to the window.
1760 ScrollView* scrollView = nullptr;
1761 AccessibilityObject* parent = nullptr;
1762 for (parent = m_object->parentObject(); parent; parent = parent->parentObject()) {
1763 if (is<AccessibilityScrollView>(*parent)) {
1764 scrollView = downcast<AccessibilityScrollView>(*parent).scrollView();
1769 IntPoint intPoint = flooredIntPoint(point);
1771 intPoint = scrollView->contentsToRootView(intPoint);
1773 Page* page = m_object->page();
1775 // If we have an empty chrome client (like SVG) then we should use the page
1776 // of the scroll view parent to help us get to the screen rect.
1777 if (parent && page && page->chrome().client().isEmptyChromeClient())
1778 page = parent->page();
1781 IntRect rect = IntRect(intPoint, IntSize(0, 0));
1782 intPoint = page->chrome().rootViewToScreen(rect).location();
1789 static void WebTransformCGPathToNSBezierPath(void *info, const CGPathElement *element)
1791 NSBezierPath *bezierPath = (NSBezierPath *)info;
1792 switch (element->type) {
1793 case kCGPathElementMoveToPoint:
1794 [bezierPath moveToPoint:NSPointFromCGPoint(element->points[0])];
1796 case kCGPathElementAddLineToPoint:
1797 [bezierPath lineToPoint:NSPointFromCGPoint(element->points[0])];
1799 case kCGPathElementAddCurveToPoint:
1800 [bezierPath curveToPoint:NSPointFromCGPoint(element->points[0]) controlPoint1:NSPointFromCGPoint(element->points[1]) controlPoint2:NSPointFromCGPoint(element->points[2])];
1802 case kCGPathElementCloseSubpath:
1803 [bezierPath closePath];
1810 - (NSBezierPath *)bezierPathFromPath:(CGPathRef)path
1812 NSBezierPath *bezierPath = [NSBezierPath bezierPath];
1813 CGPathApply(path, bezierPath, WebTransformCGPathToNSBezierPath);
1817 - (NSBezierPath *)path
1819 Path path = m_object->elementPath();
1823 CGPathRef transformedPath = [self convertPathToScreenSpace:path];
1824 return [self bezierPathFromPath:transformedPath];
1827 - (NSValue *)position
1829 IntRect rect = snappedIntRect(m_object->elementRect());
1831 // The Cocoa accessibility API wants the lower-left corner.
1832 FloatPoint floatPoint = FloatPoint(rect.x(), rect.maxY());
1834 CGPoint cgPoint = [self convertPointToScreenSpace:floatPoint];
1836 return [NSValue valueWithPoint:NSMakePoint(cgPoint.x, cgPoint.y)];
1839 typedef HashMap<int, NSString*> AccessibilityRoleMap;
1841 static const AccessibilityRoleMap& createAccessibilityRoleMap()
1844 AccessibilityRole value;
1848 static const RoleEntry roles[] = {
1849 { UnknownRole, NSAccessibilityUnknownRole },
1850 { ButtonRole, NSAccessibilityButtonRole },
1851 { RadioButtonRole, NSAccessibilityRadioButtonRole },
1852 { CheckBoxRole, NSAccessibilityCheckBoxRole },
1853 { SliderRole, NSAccessibilitySliderRole },
1854 { TabGroupRole, NSAccessibilityTabGroupRole },
1855 { TextFieldRole, NSAccessibilityTextFieldRole },
1856 { StaticTextRole, NSAccessibilityStaticTextRole },
1857 { TextAreaRole, NSAccessibilityTextAreaRole },
1858 { ScrollAreaRole, NSAccessibilityScrollAreaRole },
1859 { PopUpButtonRole, NSAccessibilityPopUpButtonRole },
1860 { MenuButtonRole, NSAccessibilityMenuButtonRole },
1861 { TableRole, NSAccessibilityTableRole },
1862 { ApplicationRole, NSAccessibilityApplicationRole },
1863 { GroupRole, NSAccessibilityGroupRole },
1864 { RadioGroupRole, NSAccessibilityRadioGroupRole },
1865 { ListRole, NSAccessibilityListRole },
1866 { DirectoryRole, NSAccessibilityListRole },
1867 { ScrollBarRole, NSAccessibilityScrollBarRole },
1868 { ValueIndicatorRole, NSAccessibilityValueIndicatorRole },
1869 { ImageRole, NSAccessibilityImageRole },
1870 { MenuBarRole, NSAccessibilityMenuBarRole },
1871 { MenuRole, NSAccessibilityMenuRole },
1872 { MenuItemRole, NSAccessibilityMenuItemRole },
1873 { MenuItemCheckboxRole, NSAccessibilityMenuItemRole },
1874 { MenuItemRadioRole, NSAccessibilityMenuItemRole },
1875 { ColumnRole, NSAccessibilityColumnRole },
1876 { RowRole, NSAccessibilityRowRole },
1877 { ToolbarRole, NSAccessibilityToolbarRole },
1878 { BusyIndicatorRole, NSAccessibilityBusyIndicatorRole },
1879 { ProgressIndicatorRole, NSAccessibilityProgressIndicatorRole },
1880 { WindowRole, NSAccessibilityWindowRole },
1881 { DrawerRole, NSAccessibilityDrawerRole },
1882 { SystemWideRole, NSAccessibilitySystemWideRole },
1883 { OutlineRole, NSAccessibilityOutlineRole },
1884 { IncrementorRole, NSAccessibilityIncrementorRole },
1885 { BrowserRole, NSAccessibilityBrowserRole },
1886 { ComboBoxRole, NSAccessibilityComboBoxRole },
1887 { SplitGroupRole, NSAccessibilitySplitGroupRole },
1888 { SplitterRole, NSAccessibilitySplitterRole },
1889 { ColorWellRole, NSAccessibilityColorWellRole },
1890 { GrowAreaRole, NSAccessibilityGrowAreaRole },
1891 { SheetRole, NSAccessibilitySheetRole },
1892 { HelpTagRole, NSAccessibilityHelpTagRole },
1893 { MatteRole, NSAccessibilityMatteRole },
1894 { RulerRole, NSAccessibilityRulerRole },
1895 { RulerMarkerRole, NSAccessibilityRulerMarkerRole },
1896 { LinkRole, NSAccessibilityLinkRole },
1897 { DisclosureTriangleRole, NSAccessibilityDisclosureTriangleRole },
1898 { GridRole, NSAccessibilityGridRole },
1899 { WebCoreLinkRole, NSAccessibilityLinkRole },
1900 { ImageMapLinkRole, NSAccessibilityLinkRole },
1901 { ImageMapRole, @"AXImageMap" },
1902 { ListMarkerRole, @"AXListMarker" },
1903 { WebAreaRole, @"AXWebArea" },
1904 { HeadingRole, @"AXHeading" },
1905 { ListBoxRole, NSAccessibilityListRole },
1906 { ListBoxOptionRole, NSAccessibilityStaticTextRole },
1907 { CellRole, NSAccessibilityCellRole },
1908 { TableHeaderContainerRole, NSAccessibilityGroupRole },
1909 { RowHeaderRole, NSAccessibilityGroupRole },
1910 { DefinitionRole, NSAccessibilityGroupRole },
1911 { DescriptionListDetailRole, NSAccessibilityGroupRole },
1912 { DescriptionListTermRole, NSAccessibilityGroupRole },
1913 { DescriptionListRole, NSAccessibilityListRole },
1914 { SliderThumbRole, NSAccessibilityValueIndicatorRole },
1915 { LandmarkApplicationRole, NSAccessibilityGroupRole },
1916 { LandmarkBannerRole, NSAccessibilityGroupRole },
1917 { LandmarkComplementaryRole, NSAccessibilityGroupRole },
1918 { LandmarkContentInfoRole, NSAccessibilityGroupRole },
1919 { LandmarkMainRole, NSAccessibilityGroupRole },
1920 { LandmarkNavigationRole, NSAccessibilityGroupRole },
1921 { LandmarkSearchRole, NSAccessibilityGroupRole },
1922 { ApplicationAlertRole, NSAccessibilityGroupRole },
1923 { ApplicationAlertDialogRole, NSAccessibilityGroupRole },
1924 { ApplicationDialogRole, NSAccessibilityGroupRole },
1925 { ApplicationLogRole, NSAccessibilityGroupRole },
1926 { ApplicationMarqueeRole, NSAccessibilityGroupRole },
1927 { ApplicationStatusRole, NSAccessibilityGroupRole },
1928 { ApplicationTimerRole, NSAccessibilityGroupRole },
1929 { DocumentRole, NSAccessibilityGroupRole },
1930 { DocumentArticleRole, NSAccessibilityGroupRole },
1931 { DocumentMathRole, NSAccessibilityGroupRole },
1932 { DocumentNoteRole, NSAccessibilityGroupRole },
1933 { DocumentRegionRole, NSAccessibilityGroupRole },
1934 { UserInterfaceTooltipRole, NSAccessibilityGroupRole },
1935 { TabRole, NSAccessibilityRadioButtonRole },
1936 { TabListRole, NSAccessibilityTabGroupRole },
1937 { TabPanelRole, NSAccessibilityGroupRole },
1938 { TreeRole, NSAccessibilityOutlineRole },
1939 { TreeItemRole, NSAccessibilityRowRole },
1940 { ListItemRole, NSAccessibilityGroupRole },
1941 { ParagraphRole, NSAccessibilityGroupRole },
1942 { LabelRole, NSAccessibilityGroupRole },
1943 { DivRole, NSAccessibilityGroupRole },
1944 { FormRole, NSAccessibilityGroupRole },
1945 { SpinButtonRole, NSAccessibilityIncrementorRole },
1946 { FooterRole, NSAccessibilityGroupRole },
1947 { ToggleButtonRole, NSAccessibilityButtonRole },
1948 { CanvasRole, NSAccessibilityImageRole },
1949 { SVGRootRole, NSAccessibilityGroupRole },
1950 { LegendRole, NSAccessibilityGroupRole },
1951 { MathElementRole, NSAccessibilityGroupRole },
1952 { AudioRole, NSAccessibilityGroupRole },
1953 { VideoRole, NSAccessibilityGroupRole },
1954 { HorizontalRuleRole, NSAccessibilitySplitterRole },
1955 { BlockquoteRole, NSAccessibilityGroupRole },
1956 { SwitchRole, NSAccessibilityCheckBoxRole },
1957 { SearchFieldRole, NSAccessibilityTextFieldRole },
1959 AccessibilityRoleMap& roleMap = *new AccessibilityRoleMap;
1961 const unsigned numRoles = sizeof(roles) / sizeof(roles[0]);
1962 for (unsigned i = 0; i < numRoles; ++i)
1963 roleMap.set(roles[i].value, roles[i].string);
1967 static NSString* roleValueToNSString(AccessibilityRole value)
1970 static const AccessibilityRoleMap& roleMap = createAccessibilityRoleMap();
1971 return roleMap.get(value);
1976 #pragma clang diagnostic push
1977 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1978 if (m_object->isAttachment())
1979 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleAttribute];
1980 #pragma clang diagnostic pop
1981 AccessibilityRole role = m_object->roleValue();
1982 if (role == CanvasRole && m_object->canvasHasFallbackContent())
1984 NSString* string = roleValueToNSString(role);
1987 return NSAccessibilityUnknownRole;
1990 #pragma clang diagnostic push
1991 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1992 - (NSString*)subrole
1994 if (m_object->isPasswordField())
1995 return NSAccessibilitySecureTextFieldSubrole;
1996 if (m_object->isSearchField())
1997 return NSAccessibilitySearchFieldSubrole;
1999 if (m_object->isAttachment()) {
2000 NSView* attachView = [self attachmentView];
2001 if ([[attachView accessibilityAttributeNames] containsObject:NSAccessibilitySubroleAttribute]) {
2002 return [attachView accessibilityAttributeValue:NSAccessibilitySubroleAttribute];
2006 if (m_object->roleValue() == HorizontalRuleRole)
2007 return NSAccessibilityContentSeparatorSubrole;
2009 if (is<AccessibilitySpinButtonPart>(*m_object)) {
2010 if (downcast<AccessibilitySpinButtonPart>(*m_object).isIncrementor())
2011 return NSAccessibilityIncrementArrowSubrole;
2013 return NSAccessibilityDecrementArrowSubrole;
2016 if (m_object->isFileUploadButton())
2017 return @"AXFileUploadButton";
2019 if (m_object->isTreeItem())
2020 return NSAccessibilityOutlineRowSubrole;
2022 if (is<AccessibilityList>(*m_object)) {
2023 auto& listObject = downcast<AccessibilityList>(*m_object);
2024 if (listObject.isUnorderedList() || listObject.isOrderedList())
2025 return NSAccessibilityContentListSubrole;
2026 if (listObject.isDescriptionList()) {
2027 return NSAccessibilityDescriptionListSubrole;
2031 // ARIA content subroles.
2032 switch (m_object->roleValue()) {
2033 case LandmarkApplicationRole:
2034 return @"AXLandmarkApplication";
2035 case LandmarkBannerRole:
2036 return @"AXLandmarkBanner";
2037 case LandmarkComplementaryRole:
2038 return @"AXLandmarkComplementary";
2039 // Footer roles should appear as content info types.
2041 case LandmarkContentInfoRole:
2042 return @"AXLandmarkContentInfo";
2043 case LandmarkMainRole:
2044 return @"AXLandmarkMain";
2045 case LandmarkNavigationRole:
2046 return @"AXLandmarkNavigation";
2047 case LandmarkSearchRole:
2048 return @"AXLandmarkSearch";
2049 case ApplicationAlertRole:
2050 return @"AXApplicationAlert";
2051 case ApplicationAlertDialogRole:
2052 return @"AXApplicationAlertDialog";
2053 case ApplicationDialogRole:
2054 return @"AXApplicationDialog";
2055 case ApplicationLogRole:
2056 return @"AXApplicationLog";
2057 case ApplicationMarqueeRole:
2058 return @"AXApplicationMarquee";
2059 case ApplicationStatusRole:
2060 return @"AXApplicationStatus";
2061 case ApplicationTimerRole:
2062 return @"AXApplicationTimer";
2064 return @"AXDocument";
2065 case DocumentArticleRole:
2066 return @"AXDocumentArticle";
2067 case DocumentMathRole:
2068 return @"AXDocumentMath";
2069 case DocumentNoteRole:
2070 return @"AXDocumentNote";
2071 case DocumentRegionRole:
2072 return @"AXDocumentRegion";
2073 case UserInterfaceTooltipRole:
2074 return @"AXUserInterfaceTooltip";
2076 return @"AXTabPanel";
2077 case DefinitionRole:
2078 return @"AXDefinition";
2079 case DescriptionListTermRole:
2081 case DescriptionListDetailRole:
2082 return @"AXDescription";
2083 // Default doesn't return anything, so roles defined below can be chosen.
2088 if (m_object->roleValue() == MathElementRole) {
2089 if (m_object->isMathFraction())
2090 return @"AXMathFraction";
2091 if (m_object->isMathFenced())
2092 return @"AXMathFenced";
2093 if (m_object->isMathSubscriptSuperscript())
2094 return @"AXMathSubscriptSuperscript";
2095 if (m_object->isMathRow())
2096 return @"AXMathRow";
2097 if (m_object->isMathUnderOver())
2098 return @"AXMathUnderOver";
2099 if (m_object->isMathSquareRoot())
2100 return @"AXMathSquareRoot";
2101 if (m_object->isMathRoot())
2102 return @"AXMathRoot";
2103 if (m_object->isMathText())
2104 return @"AXMathText";
2105 if (m_object->isMathNumber())
2106 return @"AXMathNumber";
2107 if (m_object->isMathIdentifier())
2108 return @"AXMathIdentifier";
2109 if (m_object->isMathTable())
2110 return @"AXMathTable";
2111 if (m_object->isMathTableRow())
2112 return @"AXMathTableRow";
2113 if (m_object->isMathTableCell())
2114 return @"AXMathTableCell";
2115 if (m_object->isMathFenceOperator())
2116 return @"AXMathFenceOperator";
2117 if (m_object->isMathSeparatorOperator())
2118 return @"AXMathSeparatorOperator";
2119 if (m_object->isMathOperator())
2120 return @"AXMathOperator";
2121 if (m_object->isMathMultiscript())
2122 return @"AXMathMultiscript";
2125 if (m_object->roleValue() == VideoRole)
2127 if (m_object->roleValue() == AudioRole)
2130 if (m_object->isMediaTimeline())
2131 return NSAccessibilityTimelineSubrole;
2133 if (m_object->isSwitch())
2134 return NSAccessibilitySwitchSubrole;
2138 #pragma clang diagnostic pop
2140 - (NSString*)roleDescription
2145 #pragma clang diagnostic push
2146 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2147 // attachments have the AXImage role, but a different subrole
2148 if (m_object->isAttachment())
2149 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute];
2150 #pragma clang diagnostic pop
2152 NSString* axRole = [self role];
2154 if ([axRole isEqualToString:NSAccessibilityGroupRole]) {
2156 NSString *ariaLandmarkRoleDescription = [self ariaLandmarkRoleDescription];
2157 if (ariaLandmarkRoleDescription)
2158 return ariaLandmarkRoleDescription;
2160 switch (m_object->roleValue()) {
2162 return localizedMediaControlElementString("AudioElement");
2163 case DefinitionRole:
2164 return AXDefinitionText();
2165 case DescriptionListTermRole:
2166 return AXDescriptionListTermText();
2167 case DescriptionListDetailRole:
2168 return AXDescriptionListDetailText();
2170 return AXFooterRoleDescriptionText();
2172 return localizedMediaControlElementString("VideoElement");
2174 return NSAccessibilityRoleDescription(NSAccessibilityGroupRole, [self subrole]);
2178 if ([axRole isEqualToString:@"AXWebArea"])
2179 return AXWebAreaText();
2181 if ([axRole isEqualToString:@"AXLink"])
2182 return AXLinkText();
2184 if ([axRole isEqualToString:@"AXListMarker"])
2185 return AXListMarkerText();
2187 if ([axRole isEqualToString:@"AXImageMap"])
2188 return AXImageMapText();
2190 if ([axRole isEqualToString:@"AXHeading"])
2191 return AXHeadingText();
2193 if (m_object->isFileUploadButton())
2194 return AXFileUploadButtonText();
2196 // Only returning for DL (not UL or OL) because description changed with HTML5 from 'definition list' to
2197 // superset 'description list' and does not return the same values in AX API on some OS versions.
2198 if (is<AccessibilityList>(*m_object)) {
2199 if (downcast<AccessibilityList>(*m_object).isDescriptionList())
2200 return AXDescriptionListText();
2203 if (m_object->roleValue() == HorizontalRuleRole)
2204 return AXHorizontalRuleDescriptionText();
2206 // AppKit also returns AXTab for the role description for a tab item.
2207 if (m_object->isTabItem())
2208 return NSAccessibilityRoleDescription(@"AXTab", nil);
2210 // We should try the system default role description for all other roles.
2211 // If we get the same string back, then as a last resort, return unknown.
2212 NSString* defaultRoleDescription = NSAccessibilityRoleDescription(axRole, [self subrole]);
2214 // On earlier Mac versions (Lion), using a non-standard subrole would result in a role description
2215 // being returned that looked like AXRole:AXSubrole. To make all platforms have the same role descriptions
2216 // we should fallback on a role description ignoring the subrole in these cases.
2217 if ([defaultRoleDescription isEqualToString:[NSString stringWithFormat:@"%@:%@", axRole, [self subrole]]])
2218 defaultRoleDescription = NSAccessibilityRoleDescription(axRole, nil);
2220 if (![defaultRoleDescription isEqualToString:axRole])
2221 return defaultRoleDescription;
2223 return NSAccessibilityRoleDescription(NSAccessibilityUnknownRole, nil);
2226 - (NSString *)computedRoleString
2230 return m_object->computedRoleString();
2233 - (id)scrollViewParent
2235 if (!is<AccessibilityScrollView>(m_object))
2238 // If this scroll view provides it's parent object (because it's a sub-frame), then
2239 // we should not find the remoteAccessibilityParent.
2240 if (m_object->parentObject())
2243 ScrollView* scroll = downcast<AccessibilityScrollView>(*m_object).scrollView();
2247 if (scroll->platformWidget())
2248 return NSAccessibilityUnignoredAncestor(scroll->platformWidget());
2250 return [self remoteAccessibilityParentObject];
2253 // FIXME: split up this function in a better way.
2254 // suggestions: Use a hash table that maps attribute names to function calls,
2255 // or maybe pointers to member functions
2256 - (id)accessibilityAttributeValue:(NSString*)attributeName
2258 if (![self updateObjectBackingStore])
2261 if ([attributeName isEqualToString: NSAccessibilityRoleAttribute])
2264 if ([attributeName isEqualToString: NSAccessibilitySubroleAttribute])
2265 return [self subrole];
2267 if ([attributeName isEqualToString: NSAccessibilityRoleDescriptionAttribute])
2268 return [self roleDescription];
2270 // AXARIARole is only used by DumpRenderTree (so far).
2271 if ([attributeName isEqualToString:@"AXARIARole"])
2272 return [self computedRoleString];
2274 if ([attributeName isEqualToString: NSAccessibilityParentAttribute]) {
2276 // This will return the parent of the AXWebArea, if this is a web area.
2277 id scrollViewParent = [self scrollViewParent];
2278 if (scrollViewParent)
2279 return scrollViewParent;
2281 // Tree item (changed to AXRows) can only report the tree (AXOutline) as its parent.
2282 if (m_object->isTreeItem()) {
2283 AccessibilityObject* parent = m_object->parentObjectUnignored();
2285 if (parent->isTree())
2286 return parent->wrapper();
2287 parent = parent->parentObjectUnignored();
2291 AccessibilityObject* parent = m_object->parentObjectUnignored();
2295 // In WebKit1, the scroll view is provided by the system (the attachment view), so the parent
2296 // should be reported directly as such.
2297 if (m_object->isWebArea() && parent->isAttachment())
2298 return [parent->wrapper() attachmentView];
2300 return parent->wrapper();
2303 if ([attributeName isEqualToString: NSAccessibilityChildrenAttribute]) {
2304 if (m_object->children().isEmpty()) {
2305 NSArray* children = [self renderWidgetChildren];
2306 if (children != nil)
2310 // The tree's (AXOutline) children are supposed to be its rows and columns.
2311 // The ARIA spec doesn't have columns, so we just need rows.
2312 if (m_object->isTree())
2313 return [self accessibilityAttributeValue:NSAccessibilityRowsAttribute];
2315 // A tree item should only expose its content as its children (not its rows)
2316 if (m_object->isTreeItem()) {
2317 AccessibilityObject::AccessibilityChildrenVector contentCopy;
2318 m_object->ariaTreeItemContent(contentCopy);
2319 return convertToNSArray(contentCopy);
2322 return convertToNSArray(m_object->children());
2325 if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {
2326 if (m_object->isListBox()) {
2327 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2328 m_object->selectedChildren(selectedChildrenCopy);
2329 return convertToNSArray(selectedChildrenCopy);
2334 if ([attributeName isEqualToString: NSAccessibilityVisibleChildrenAttribute]) {
2335 if (m_object->isListBox()) {
2336 AccessibilityObject::AccessibilityChildrenVector visibleChildrenCopy;
2337 m_object->visibleChildren(visibleChildrenCopy);
2338 return convertToNSArray(visibleChildrenCopy);
2340 else if (m_object->isList())
2341 return [self accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
2347 if (m_object->isWebArea()) {
2348 if ([attributeName isEqualToString:@"AXLinkUIElements"]) {
2349 AccessibilityObject::AccessibilityChildrenVector links;
2350 downcast<AccessibilityRenderObject>(*m_object).getDocumentLinks(links);
2351 return convertToNSArray(links);
2353 if ([attributeName isEqualToString:@"AXLoaded"])
2354 return [NSNumber numberWithBool:m_object->isLoaded()];
2355 if ([attributeName isEqualToString:@"AXLayoutCount"])
2356 return [NSNumber numberWithInt:m_object->layoutCount()];
2357 if ([attributeName isEqualToString:NSAccessibilityLoadingProgressAttribute])
2358 return [NSNumber numberWithDouble:m_object->estimatedLoadingProgress()];
2361 if (m_object->isTextControl()) {
2362 if ([attributeName isEqualToString: NSAccessibilityNumberOfCharactersAttribute]) {
2363 int length = m_object->textLength();
2366 return [NSNumber numberWithUnsignedInt:length];
2368 if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
2369 String selectedText = m_object->selectedText();
2370 if (selectedText.isNull())
2372 return (NSString*)selectedText;
2374 if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
2375 PlainTextRange textRange = m_object->selectedTextRange();
2376 if (textRange.isNull())
2377 return [NSValue valueWithRange:NSMakeRange(0, 0)];
2378 return [NSValue valueWithRange:NSMakeRange(textRange.start, textRange.length)];
2380 // TODO: Get actual visible range. <rdar://problem/4712101>
2381 if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
2382 return m_object->isPasswordField() ? nil : [NSValue valueWithRange: NSMakeRange(0, m_object->textLength())];
2383 if ([attributeName isEqualToString: NSAccessibilityInsertionPointLineNumberAttribute]) {
2384 // if selectionEnd > 0, then there is selected text and this question should not be answered
2385 if (m_object->isPasswordField() || m_object->selectionEnd() > 0)
2388 AccessibilityObject* focusedObject = m_object->focusedUIElement();
2389 if (focusedObject != m_object)
2392 VisiblePosition focusedPosition = focusedObject->visiblePositionForIndex(focusedObject->selectionStart(), true);
2393 int lineNumber = m_object->lineForPosition(focusedPosition);
2397 return [NSNumber numberWithInt:lineNumber];
2401 if ([attributeName isEqualToString: NSAccessibilityURLAttribute]) {
2402 URL url = m_object->url();
2408 // Only native spin buttons have increment and decrement buttons.
2409 if (is<AccessibilitySpinButton>(*m_object)) {
2410 if ([attributeName isEqualToString:NSAccessibilityIncrementButtonAttribute])
2411 return downcast<AccessibilitySpinButton>(*m_object).incrementButton()->wrapper();
2412 if ([attributeName isEqualToString:NSAccessibilityDecrementButtonAttribute])
2413 return downcast<AccessibilitySpinButton>(*m_object).decrementButton()->wrapper();
2416 if ([attributeName isEqualToString: @"AXVisited"])
2417 return [NSNumber numberWithBool: m_object->isVisited()];
2419 if ([attributeName isEqualToString: NSAccessibilityTitleAttribute]) {
2420 if (m_object->isAttachment()) {
2421 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityTitleAttribute])
2422 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityTitleAttribute];
2425 // Meter elements should communicate their content via AXValueDescription.
2426 if (m_object->isMeter())
2427 return [NSString string];
2429 return [self baseAccessibilityTitle];
2432 if ([attributeName isEqualToString: NSAccessibilityDescriptionAttribute]) {
2433 if (m_object->isAttachment()) {
2434 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityDescriptionAttribute])
2435 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityDescriptionAttribute];
2437 return [self baseAccessibilityDescription];
2440 if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
2441 if (m_object->isAttachment()) {
2442 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityValueAttribute])
2443 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityValueAttribute];
2445 if (m_object->supportsRangeValue())
2446 return [NSNumber numberWithFloat:m_object->valueForRange()];
2447 if (m_object->roleValue() == SliderThumbRole)
2448 return [NSNumber numberWithFloat:m_object->parentObject()->valueForRange()];
2449 if (m_object->isHeading())
2450 return [NSNumber numberWithInt:m_object->headingLevel()];
2452 if (m_object->isCheckboxOrRadio() || m_object->isMenuItem() || m_object->isSwitch()) {
2453 switch (m_object->checkboxOrRadioValue()) {
2454 case ButtonStateOff:
2455 return [NSNumber numberWithInt:0];
2457 return [NSNumber numberWithInt:1];
2458 case ButtonStateMixed:
2459 return [NSNumber numberWithInt:2];
2463 // radio groups return the selected radio button as the AXValue
2464 if (m_object->isRadioGroup()) {
2465 AccessibilityObject* radioButton = m_object->selectedRadioButton();
2468 return radioButton->wrapper();
2471 if (m_object->isTabList()) {
2472 AccessibilityObject* tabItem = m_object->selectedTabItem();
2475 return tabItem->wrapper();
2478 if (m_object->isTabItem())
2479 return [NSNumber numberWithInt:m_object->isSelected()];
2481 if (m_object->isColorWell()) {
2483 m_object->colorValue(r, g, b);
2484 return [NSString stringWithFormat:@"rgb %7.5f %7.5f %7.5f 1", r / 255., g / 255., b / 255.];
2487 return m_object->stringValue();
2490 if ([attributeName isEqualToString:(NSString *)kAXMenuItemMarkCharAttribute]) {
2491 const unichar ch = 0x2713; // ✓ used on Mac for selected menu items.
2492 return (m_object->isChecked()) ? [NSString stringWithCharacters:&ch length:1] : nil;
2495 if ([attributeName isEqualToString: NSAccessibilityMinValueAttribute])
2496 return [NSNumber numberWithFloat:m_object->minValueForRange()];
2498 if ([attributeName isEqualToString: NSAccessibilityMaxValueAttribute])
2499 return [NSNumber numberWithFloat:m_object->maxValueForRange()];
2501 if ([attributeName isEqualToString: NSAccessibilityHelpAttribute])
2502 return [self baseAccessibilityHelpText];
2504 if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
2505 return [NSNumber numberWithBool: m_object->isFocused()];
2507 if ([attributeName isEqualToString: NSAccessibilityEnabledAttribute])
2508 return [NSNumber numberWithBool: m_object->isEnabled()];
2510 if ([attributeName isEqualToString: NSAccessibilitySizeAttribute]) {
2511 IntSize s = m_object->elementRect().pixelSnappedSize();
2512 return [NSValue valueWithSize: NSMakeSize(s.width(), s.height())];
2515 if ([attributeName isEqualToString: NSAccessibilityPositionAttribute])
2516 return [self position];
2517 if ([attributeName isEqualToString:NSAccessibilityPathAttribute])
2520 if ([attributeName isEqualToString: NSAccessibilityWindowAttribute] ||
2521 [attributeName isEqualToString: NSAccessibilityTopLevelUIElementAttribute]) {
2523 id remoteParent = [self remoteAccessibilityParentObject];
2525 return [remoteParent accessibilityAttributeValue:attributeName];
2527 FrameView* fv = m_object->documentFrameView();
2529 return [fv->platformWidget() window];
2533 if ([attributeName isEqualToString:NSAccessibilityAccessKeyAttribute]) {
2534 AtomicString accessKey = m_object->accessKey();
2535 if (accessKey.isNull())
2540 if ([attributeName isEqualToString:NSAccessibilityTabsAttribute]) {
2541 if (m_object->isTabList()) {
2542 AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2543 m_object->tabChildren(tabsChildren);
2544 return convertToNSArray(tabsChildren);
2548 if ([attributeName isEqualToString:NSAccessibilityContentsAttribute]) {
2549 // The contents of a tab list are all the children except the tabs.
2550 if (m_object->isTabList()) {
2551 const auto& children = m_object->children();
2552 AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2553 m_object->tabChildren(tabsChildren);
2555 AccessibilityObject::AccessibilityChildrenVector contents;
2556 unsigned childrenSize = children.size();
2557 for (unsigned k = 0; k < childrenSize; ++k) {
2558 if (tabsChildren.find(children[k]) == WTF::notFound)
2559 contents.append(children[k]);
2561 return convertToNSArray(contents);
2562 } else if (m_object->isScrollView()) {
2563 // A scrollView's contents are everything except the scroll bars.
2564 AccessibilityObject::AccessibilityChildrenVector contents;
2565 for (const auto& child : m_object->children()) {
2566 if (!child->isScrollbar())
2567 contents.append(child);
2569 return convertToNSArray(contents);
2573 if (is<AccessibilityTable>(*m_object) && downcast<AccessibilityTable>(*m_object).isExposableThroughAccessibility()) {
2574 auto& table = downcast<AccessibilityTable>(*m_object);
2575 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute])
2576 return convertToNSArray(table.rows());
2578 if ([attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
2579 AccessibilityObject::AccessibilityChildrenVector visibleRows;
2580 table.visibleRows(visibleRows);
2581 return convertToNSArray(visibleRows);
2584 // TODO: distinguish between visible and non-visible columns
2585 if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute] ||
2586 [attributeName isEqualToString:NSAccessibilityVisibleColumnsAttribute]) {
2587 return convertToNSArray(table.columns());
2590 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2591 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2592 m_object->selectedChildren(selectedChildrenCopy);
2593 return convertToNSArray(selectedChildrenCopy);
2596 // HTML tables don't support these
2597 if ([attributeName isEqualToString:NSAccessibilitySelectedColumnsAttribute] ||
2598 [attributeName isEqualToString:NSAccessibilitySelectedCellsAttribute])
2601 if ([attributeName isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute]) {
2602 AccessibilityObject::AccessibilityChildrenVector columnHeaders;
2603 table.columnHeaders(columnHeaders);
2604 return convertToNSArray(columnHeaders);
2607 if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2608 AccessibilityObject* headerContainer = table.headerContainer();
2609 if (headerContainer)
2610 return headerContainer->wrapper();
2614 if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
2615 AccessibilityObject::AccessibilityChildrenVector rowHeaders;
2616 table.rowHeaders(rowHeaders);
2617 return convertToNSArray(rowHeaders);
2620 if ([attributeName isEqualToString:NSAccessibilityVisibleCellsAttribute]) {
2621 AccessibilityObject::AccessibilityChildrenVector cells;
2623 return convertToNSArray(cells);
2626 if ([attributeName isEqualToString:NSAccessibilityColumnCountAttribute])
2627 return @(table.columnCount());
2629 if ([attributeName isEqualToString:NSAccessibilityRowCountAttribute])
2630 return @(table.rowCount());
2633 if (is<AccessibilityTableColumn>(*m_object)) {
2634 auto& column = downcast<AccessibilityTableColumn>(*m_object);
2635 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2636 return [NSNumber numberWithInt:column.columnIndex()];
2638 // rows attribute for a column is the list of all the elements in that column at each row
2639 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] ||
2640 [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
2641 return convertToNSArray(column.children());
2643 if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2644 AccessibilityObject* header = column.headerObject();
2647 return header->wrapper();
2651 if (is<AccessibilityTableCell>(*m_object)) {
2652 auto& cell = downcast<AccessibilityTableCell>(*m_object);
2653 if ([attributeName isEqualToString:NSAccessibilityRowIndexRangeAttribute]) {
2654 std::pair<unsigned, unsigned> rowRange;
2655 cell.rowIndexRange(rowRange);
2656 return [NSValue valueWithRange:NSMakeRange(rowRange.first, rowRange.second)];
2658 if ([attributeName isEqualToString:NSAccessibilityColumnIndexRangeAttribute]) {
2659 std::pair<unsigned, unsigned> columnRange;
2660 cell.columnIndexRange(columnRange);
2661 return [NSValue valueWithRange:NSMakeRange(columnRange.first, columnRange.second)];
2663 if ([attributeName isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute]) {
2664 AccessibilityObject::AccessibilityChildrenVector columnHeaders;
2665 cell.columnHeaders(columnHeaders);
2666 return convertToNSArray(columnHeaders);
2668 if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
2669 AccessibilityObject::AccessibilityChildrenVector rowHeaders;
2670 cell.rowHeaders(rowHeaders);
2671 return convertToNSArray(rowHeaders);
2675 if (m_object->isTree()) {
2676 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2677 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2678 m_object->selectedChildren(selectedChildrenCopy);
2679 return convertToNSArray(selectedChildrenCopy);
2681 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute]) {
2682 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2683 m_object->ariaTreeRows(rowsCopy);
2684 return convertToNSArray(rowsCopy);
2687 // TreeRoles do not support columns, but Mac AX expects to be able to ask about columns at the least.
2688 if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute])
2689 return [NSArray array];
2692 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute]) {
2693 if (m_object->isTreeItem()) {
2694 AccessibilityObject* parent = m_object->parentObject();
2695 for (; parent && !parent->isTree(); parent = parent->parentObject())
2701 // Find the index of this item by iterating the parents.
2702 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2703 parent->ariaTreeRows(rowsCopy);
2704 size_t count = rowsCopy.size();
2705 for (size_t k = 0; k < count; ++k)
2706 if (rowsCopy[k]->wrapper() == self)
2707 return [NSNumber numberWithUnsignedInt:k];
2711 if (is<AccessibilityTableRow>(*m_object)) {
2712 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2713 return [NSNumber numberWithInt:downcast<AccessibilityTableRow>(*m_object).rowIndex()];
2717 // The rows that are considered inside this row.
2718 if ([attributeName isEqualToString:NSAccessibilityDisclosedRowsAttribute]) {
2719 if (m_object->isTreeItem()) {
2720 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2721 m_object->ariaTreeItemDisclosedRows(rowsCopy);
2722 return convertToNSArray(rowsCopy);
2723 } else if (is<AccessibilityARIAGridRow>(*m_object)) {
2724 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2725 downcast<AccessibilityARIAGridRow>(*m_object).disclosedRows(rowsCopy);
2726 return convertToNSArray(rowsCopy);
2730 // The row that contains this row. It should be the same as the first parent that is a treeitem.
2731 if ([attributeName isEqualToString:NSAccessibilityDisclosedByRowAttribute]) {
2732 if (m_object->isTreeItem()) {
2733 AccessibilityObject* parent = m_object->parentObject();
2735 if (parent->isTreeItem())
2736 return parent->wrapper();
2737 // If the parent is the tree itself, then this value == nil.
2738 if (parent->isTree())
2740 parent = parent->parentObject();
2743 } else if (is<AccessibilityARIAGridRow>(*m_object)) {
2744 AccessibilityObject* row = downcast<AccessibilityARIAGridRow>(*m_object).disclosedByRow();
2747 return row->wrapper();
2751 if ([attributeName isEqualToString:NSAccessibilityDisclosureLevelAttribute]) {
2752 // Convert from 1-based level (from aria-level spec) to 0-based level (Mac)
2753 int level = m_object->hierarchicalLevel();
2756 return [NSNumber numberWithInt:level];
2758 if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
2759 return [NSNumber numberWithBool:m_object->isExpanded()];
2761 if ((m_object->isListBox() || m_object->isList()) && [attributeName isEqualToString:NSAccessibilityOrientationAttribute])
2762 return NSAccessibilityVerticalOrientationValue;
2764 if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
2765 return [self textMarkerRangeForSelection];
2767 if (m_object->renderer()) {
2768 if ([attributeName isEqualToString: @"AXStartTextMarker"])
2769 return [self textMarkerForVisiblePosition:startOfDocument(&m_object->renderer()->document())];
2770 if ([attributeName isEqualToString: @"AXEndTextMarker"])
2771 return [self textMarkerForVisiblePosition:endOfDocument(&m_object->renderer()->document())];
2774 if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute])
2775 return [NSNumber numberWithInt:m_object->blockquoteLevel()];
2776 if ([attributeName isEqualToString:@"AXTableLevel"])
2777 return [NSNumber numberWithInt:m_object->tableLevel()];
2779 if ([attributeName isEqualToString: NSAccessibilityLinkedUIElementsAttribute]) {
2780 AccessibilityObject::AccessibilityChildrenVector linkedUIElements;
2781 m_object->linkedUIElements(linkedUIElements);
2782 return convertToNSArray(linkedUIElements);
2785 if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
2786 return [NSNumber numberWithBool:m_object->isSelected()];
2788 if ([attributeName isEqualToString: NSAccessibilityServesAsTitleForUIElementsAttribute] && m_object->isMenuButton()) {
2789 AccessibilityObject* uiElement = downcast<AccessibilityRenderObject>(*m_object).menuForMenuButton();
2791 return [NSArray arrayWithObject:uiElement->wrapper()];
2794 if ([attributeName isEqualToString:NSAccessibilityTitleUIElementAttribute]) {
2795 if (!m_object->exposesTitleUIElement())
2798 AccessibilityObject* obj = m_object->titleUIElement();
2800 return obj->wrapper();
2804 if ([attributeName isEqualToString:NSAccessibilityValueDescriptionAttribute]) {
2805 if (m_object->isMeter())
2806 return [self baseAccessibilityTitle];
2808 return m_object->valueDescription();
2811 if ([attributeName isEqualToString:NSAccessibilityOrientationAttribute]) {
2812 AccessibilityOrientation elementOrientation = m_object->orientation();
2813 if (elementOrientation == AccessibilityOrientationVertical)
2814 return NSAccessibilityVerticalOrientationValue;
2815 if (elementOrientation == AccessibilityOrientationHorizontal)
2816 return NSAccessibilityHorizontalOrientationValue;
2820 if ([attributeName isEqualToString:NSAccessibilityHorizontalScrollBarAttribute]) {
2821 AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationHorizontal);
2823 return scrollBar->wrapper();
2826 if ([attributeName isEqualToString:NSAccessibilityVerticalScrollBarAttribute]) {
2827 AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationVertical);
2829 return scrollBar->wrapper();
2833 if ([attributeName isEqualToString:NSAccessibilitySortDirectionAttribute]) {
2834 switch (m_object->sortDirection()) {
2835 case SortDirectionAscending:
2836 return NSAccessibilityAscendingSortDirectionValue;
2837 case SortDirectionDescending:
2838 return NSAccessibilityDescendingSortDirectionValue;
2840 return NSAccessibilityUnknownSortDirectionValue;
2844 if ([attributeName isEqualToString:NSAccessibilityLanguageAttribute])
2845 return m_object->language();
2847 if ([attributeName isEqualToString:NSAccessibilityExpandedAttribute])
2848 return [NSNumber numberWithBool:m_object->isExpanded()];
2850 if ([attributeName isEqualToString:NSAccessibilityRequiredAttribute])
2851 return [NSNumber numberWithBool:m_object->isRequired()];
2853 if ([attributeName isEqualToString:NSAccessibilityInvalidAttribute])
2854 return m_object->invalidStatus();
2856 if ([attributeName isEqualToString:NSAccessibilityOwnsAttribute]) {
2857 AccessibilityObject::AccessibilityChildrenVector ariaOwns;
2858 m_object->ariaOwnsElements(ariaOwns);
2859 return convertToNSArray(ariaOwns);
2862 if ([attributeName isEqualToString:NSAccessibilityARIAPosInSetAttribute])
2863 return [NSNumber numberWithInt:m_object->ariaPosInSet()];
2864 if ([attributeName isEqualToString:NSAccessibilityARIASetSizeAttribute])
2865 return [NSNumber numberWithInt:m_object->ariaSetSize()];
2867 if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
2868 return [NSNumber numberWithBool:m_object->isARIAGrabbed()];
2870 if ([attributeName isEqualToString:NSAccessibilityDropEffectsAttribute]) {
2871 Vector<String> dropEffects;
2872 m_object->determineARIADropEffects(dropEffects);
2873 return convertStringsToNSArray(dropEffects);
2876 if ([attributeName isEqualToString:NSAccessibilityPlaceholderValueAttribute])
2877 return m_object->placeholderValue();
2879 if ([attributeName isEqualToString:NSAccessibilityValueAutofilledAttribute])
2880 return @(m_object->isValueAutofilled());
2882 if ([attributeName isEqualToString:NSAccessibilityHasPopupAttribute])
2883 return [NSNumber numberWithBool:m_object->ariaHasPopup()];
2885 // ARIA Live region attributes.
2886 if ([attributeName isEqualToString:NSAccessibilityARIALiveAttribute])
2887 return m_object->ariaLiveRegionStatus();
2888 if ([attributeName isEqualToString:NSAccessibilityARIARelevantAttribute])
2889 return m_object->ariaLiveRegionRelevant();
2890 if ([attributeName isEqualToString:NSAccessibilityARIAAtomicAttribute])
2891 return [NSNumber numberWithBool:m_object->ariaLiveRegionAtomic()];
2892 if ([attributeName isEqualToString:NSAccessibilityElementBusyAttribute])
2893 return [NSNumber numberWithBool:m_object->ariaLiveRegionBusy()];
2895 // MathML Attributes.
2896 if (m_object->isMathElement()) {
2897 if ([attributeName isEqualToString:NSAccessibilityMathRootIndexAttribute])
2898 return (m_object->mathRootIndexObject()) ? m_object->mathRootIndexObject()->wrapper() : 0;
2899 if ([attributeName isEqualToString:NSAccessibilityMathRootRadicandAttribute])
2900 return (m_object->mathRadicandObject()) ? m_object->mathRadicandObject()->wrapper() : 0;
2901 if ([attributeName isEqualToString:NSAccessibilityMathFractionNumeratorAttribute])
2902 return (m_object->mathNumeratorObject()) ? m_object->mathNumeratorObject()->wrapper() : 0;
2903 if ([attributeName isEqualToString:NSAccessibilityMathFractionDenominatorAttribute])
2904 return (m_object->mathDenominatorObject()) ? m_object->mathDenominatorObject()->wrapper() : 0;
2905 if ([attributeName isEqualToString:NSAccessibilityMathBaseAttribute])
2906 return (m_object->mathBaseObject()) ? m_object->mathBaseObject()->wrapper() : 0;
2907 if ([attributeName isEqualToString:NSAccessibilityMathSubscriptAttribute])
2908 return (m_object->mathSubscriptObject()) ? m_object->mathSubscriptObject()->wrapper() : 0;
2909 if ([attributeName isEqualToString:NSAccessibilityMathSuperscriptAttribute])
2910 return (m_object->mathSuperscriptObject()) ? m_object->mathSuperscriptObject()->wrapper() : 0;
2911 if ([attributeName isEqualToString:NSAccessibilityMathUnderAttribute])
2912 return (m_object->mathUnderObject()) ? m_object->mathUnderObject()->wrapper() : 0;
2913 if ([attributeName isEqualToString:NSAccessibilityMathOverAttribute])
2914 return (m_object->mathOverObject()) ? m_object->mathOverObject()->wrapper() : 0;
2915 if ([attributeName isEqualToString:NSAccessibilityMathFencedOpenAttribute])
2916 return m_object->mathFencedOpenString();
2917 if ([attributeName isEqualToString:NSAccessibilityMathFencedCloseAttribute])
2918 return m_object->mathFencedCloseString();
2919 if ([attributeName isEqualToString:NSAccessibilityMathLineThicknessAttribute])
2920 return [NSNumber numberWithInteger:m_object->mathLineThickness()];
2921 if ([attributeName isEqualToString:NSAccessibilityMathPostscriptsAttribute])
2922 return [self accessibilityMathPostscriptPairs];
2923 if ([attributeName isEqualToString:NSAccessibilityMathPrescriptsAttribute])
2924 return [self accessibilityMathPrescriptPairs];
2927 if ([attributeName isEqualToString:NSAccessibilityExpandedTextValueAttribute])
2928 return m_object->expandedTextValue();
2930 if ([attributeName isEqualToString:NSAccessibilityDOMIdentifierAttribute])
2931 return m_object->identifierAttribute();
2932 if ([attributeName isEqualToString:NSAccessibilityDOMClassListAttribute]) {
2933 Vector<String> classList;
2934 m_object->classList(classList);
2935 return convertStringsToNSArray(classList);
2938 // this is used only by DumpRenderTree for testing
2939 if ([attributeName isEqualToString:@"AXClickPoint"])
2940 return [NSValue valueWithPoint:m_object->clickPoint()];
2942 // This is used by DRT to verify CSS3 speech works.
2943 if ([attributeName isEqualToString:@"AXDRTSpeechAttribute"]) {
2944 ESpeak speakProperty = m_object->speakProperty();
2945 switch (speakProperty) {
2949 return @"spell-out";
2952 case SpeakLiteralPunctuation:
2953 return @"literal-punctuation";
2954 case SpeakNoPunctuation:
2955 return @"no-punctuation";
2962 // Used by DRT to find an accessible node by its element id.
2963 if ([attributeName isEqualToString:@"AXDRTElementIdAttribute"])
2964 return m_object->getAttribute(idAttr);
2966 if (m_object->isWebArea() && [attributeName isEqualToString:NSAccessibilityPreventKeyboardDOMEventDispatchAttribute])
2967 return [NSNumber numberWithBool:m_object->preventKeyboardDOMEventDispatch()];
2969 if (m_object->isWebArea() && [attributeName isEqualToString:NSAccessibilityCaretBrowsingEnabledAttribute])
2970 return [NSNumber numberWithBool:m_object->caretBrowsingEnabled()];
2975 - (NSString *)accessibilityPlatformMathSubscriptKey
2977 return NSAccessibilityMathSubscriptAttribute;
2980 - (NSString *)accessibilityPlatformMathSuperscriptKey
2982 return NSAccessibilityMathSuperscriptAttribute;
2985 - (id)accessibilityFocusedUIElement
2987 if (![self updateObjectBackingStore])
2990 RefPtr<AccessibilityObject> focusedObj = m_object->focusedUIElement();
2995 return focusedObj->wrapper();
2998 - (id)accessibilityHitTest:(NSPoint)point
3000 if (![self updateObjectBackingStore])
3003 m_object->updateChildrenIfNecessary();
3004 RefPtr<AccessibilityObject> axObject = m_object->accessibilityHitTest(IntPoint(point));
3006 return NSAccessibilityUnignoredAncestor(axObject->wrapper());
3007 return NSAccessibilityUnignoredAncestor(self);
3010 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName
3012 if (![self updateObjectBackingStore])
3015 if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
3018 if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
3019 return m_object->canSetFocusAttribute();
3021 if ([attributeName isEqualToString: NSAccessibilityValueAttribute])
3022 return m_object->canSetValueAttribute();
3024 if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
3025 return m_object->canSetSelectedAttribute();
3027 if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute])
3028 return m_object->canSetSelectedChildrenAttribute();
3030 if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
3031 return m_object->canSetExpandedAttribute();
3033 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute])
3036 if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute] ||
3037 [attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute] ||
3038 [attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
3039 return m_object->canSetTextRangeAttributes();
3041 if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
3044 if (m_object->isWebArea() && [attributeName isEqualToString:NSAccessibilityPreventKeyboardDOMEventDispatchAttribute])
3047 if (m_object->isWebArea() && [attributeName isEqualToString:NSAccessibilityCaretBrowsingEnabledAttribute])
3053 // accessibilityShouldUseUniqueId is an AppKit method we override so that
3054 // objects will be given a unique ID, and therefore allow AppKit to know when they
3055 // become obsolete (e.g. when the user navigates to a new web page, making this one
3056 // unrendered but not deallocated because it is in the back/forward cache).