Changeset 143066 in webkit
- Timestamp:
- Feb 15, 2013 4:17:50 PM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 2 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r143060 r143066 1 2013-02-15 Chris Fleizach <cfleizach@apple.com> 2 3 AX: Split WebAccessibilityObjectWrapper so code can be shared with iOS 4 https://bugs.webkit.org/show_bug.cgi?id=109849 5 6 Reviewed by David Kilzer. 7 8 Split up the WebAccessibilityObjectWrapper so that iOS can share more 9 code with MacOS. I imagine over time, more code will move into this base class, 10 but for now this will be a good start. 11 12 A base class called WebAccessibilityObjectWrapper now exists, and Mac has a subclass 13 of that. iOS will be able to do the same. 14 15 * WebCore.xcodeproj/project.pbxproj: 16 * accessibility/mac/AXObjectCacheMac.mm: 17 (WebCore::AXObjectCache::attachWrapper): 18 * accessibility/mac/WebAccessibilityObjectWrapper.h: 19 * accessibility/mac/WebAccessibilityObjectWrapper.mm: 20 (-[WebAccessibilityObjectWrapper detach]): 21 (-[WebAccessibilityObjectWrapper attachmentView]): 22 (-[WebAccessibilityObjectWrapper accessibilityObject]): 23 (-[WebAccessibilityObjectWrapper accessibilityPostedNotification:]): 24 (-[WebAccessibilityObjectWrapper titleTagShouldBeUsedInDescriptionField]): 25 (-[WebAccessibilityObjectWrapper accessibilityTitle]): 26 (-[WebAccessibilityObjectWrapper accessibilityDescription]): 27 (-[WebAccessibilityObjectWrapper accessibilityHelpText]): 28 * accessibility/mac/WebAccessibilityObjectWrapperMac.h: Added. 29 * accessibility/mac/WebAccessibilityObjectWrapperMac.m: Added. 30 (std): 31 (-[WebAccessibilityObjectWrapperMac detach]): 32 (-[WebAccessibilityObjectWrapperMac attachmentView]): 33 (CFAutoreleaseHelper): 34 (AXObjectIsTextMarker): 35 (AXObjectIsTextMarkerRange): 36 (AXTextMarkerRange): 37 (AXTextMarkerRangeStart): 38 (AXTextMarkerRangeEnd): 39 (SearchKeyEntry): 40 (createAccessibilitySearchKeyMap): 41 (accessibilitySearchKeyForString): 42 (textMarkerForVisiblePosition): 43 (-[WebAccessibilityObjectWrapperMac textMarkerForVisiblePosition:]): 44 (visiblePositionForTextMarker): 45 (-[WebAccessibilityObjectWrapperMac visiblePositionForTextMarker:]): 46 (visiblePositionForStartOfTextMarkerRange): 47 (visiblePositionForEndOfTextMarkerRange): 48 (textMarkerRangeFromMarkers): 49 (AXAttributedStringRangeIsValid): 50 (AXAttributeStringSetFont): 51 (CreateCGColorIfDifferent): 52 (AXAttributeStringSetColor): 53 (AXAttributeStringSetNumber): 54 (AXAttributeStringSetStyle): 55 (AXAttributeStringSetBlockquoteLevel): 56 (AXAttributeStringSetSpelling): 57 (AXAttributeStringSetHeadingLevel): 58 (AXAttributeStringSetElement): 59 (AXAttributedStringAppendText): 60 (nsStringForReplacedNode): 61 (-[WebAccessibilityObjectWrapperMac doAXAttributedStringForTextMarkerRange:]): 62 (textMarkerRangeFromVisiblePositions): 63 (-[WebAccessibilityObjectWrapperMac textMarkerRangeFromVisiblePositions:endPosition:]): 64 (-[WebAccessibilityObjectWrapperMac accessibilityActionNames]): 65 (-[WebAccessibilityObjectWrapperMac additionalAccessibilityAttributeNames]): 66 (-[WebAccessibilityObjectWrapperMac accessibilityAttributeNames]): 67 (-[WebAccessibilityObjectWrapperMac visiblePositionRangeForTextMarkerRange:]): 68 (-[WebAccessibilityObjectWrapperMac renderWidgetChildren]): 69 (-[WebAccessibilityObjectWrapperMac remoteAccessibilityParentObject]): 70 (convertToVector): 71 (convertToNSArray): 72 (-[WebAccessibilityObjectWrapperMac textMarkerRangeForSelection]): 73 (-[WebAccessibilityObjectWrapperMac position]): 74 (createAccessibilityRoleMap): 75 (roleValueToNSString): 76 (-[WebAccessibilityObjectWrapperMac role]): 77 (-[WebAccessibilityObjectWrapperMac subrole]): 78 (-[WebAccessibilityObjectWrapperMac roleDescription]): 79 (-[WebAccessibilityObjectWrapperMac scrollViewParent]): 80 (-[WebAccessibilityObjectWrapperMac titleTagShouldBeUsedInDescriptionField]): 81 (-[WebAccessibilityObjectWrapperMac accessibilityTitle]): 82 (-[WebAccessibilityObjectWrapperMac accessibilityDescription]): 83 (-[WebAccessibilityObjectWrapperMac accessibilityHelpText]): 84 (-[WebAccessibilityObjectWrapperMac accessibilityAttributeValue:]): 85 (-[WebAccessibilityObjectWrapperMac accessibilityFocusedUIElement]): 86 (-[WebAccessibilityObjectWrapperMac accessibilityHitTest:]): 87 (-[WebAccessibilityObjectWrapperMac accessibilityIsAttributeSettable:]): 88 (-[WebAccessibilityObjectWrapperMac accessibilityIsIgnored]): 89 (-[WebAccessibilityObjectWrapperMac accessibilityParameterizedAttributeNames]): 90 (-[WebAccessibilityObjectWrapperMac accessibilityPerformPressAction]): 91 (-[WebAccessibilityObjectWrapperMac accessibilityPerformIncrementAction]): 92 (-[WebAccessibilityObjectWrapperMac accessibilityPerformDecrementAction]): 93 (-[WebAccessibilityObjectWrapperMac accessibilityPerformShowMenuAction]): 94 (-[WebAccessibilityObjectWrapperMac accessibilityShowContextMenu]): 95 (-[WebAccessibilityObjectWrapperMac accessibilityPerformAction:]): 96 (-[WebAccessibilityObjectWrapperMac accessibilitySetValue:forAttribute:]): 97 (rendererForView): 98 (-[WebAccessibilityObjectWrapperMac _accessibilityParentForSubview:]): 99 (-[WebAccessibilityObjectWrapperMac accessibilityActionDescription:]): 100 (-[WebAccessibilityObjectWrapperMac doAXAttributedStringForRange:]): 101 (-[WebAccessibilityObjectWrapperMac _convertToNSRange:]): 102 (-[WebAccessibilityObjectWrapperMac _indexForTextMarker:]): 103 (-[WebAccessibilityObjectWrapperMac _textMarkerForIndex:]): 104 (-[WebAccessibilityObjectWrapperMac doAXRTFForRange:]): 105 (-[WebAccessibilityObjectWrapperMac accessibilityAttributeValue:forParameter:]): 106 (-[WebAccessibilityObjectWrapperMac accessibilitySupportsOverriddenAttributes]): 107 (-[WebAccessibilityObjectWrapperMac accessibilityShouldUseUniqueId]): 108 (-[WebAccessibilityObjectWrapperMac accessibilityIndexOfChild:]): 109 (-[WebAccessibilityObjectWrapperMac accessibilityArrayAttributeCount:]): 110 (-[WebAccessibilityObjectWrapperMac accessibilityArrayAttributeValues:index:maxCount:]): 111 ([WebAccessibilityObjectWrapperMac accessibilitySetShouldRepostNotifications:]): 112 (-[WebAccessibilityObjectWrapperMac accessibilityPostedNotification:]): 113 1 114 2013-02-15 Elliott Sprehn <esprehn@chromium.org> 2 115 -
trunk/Source/WebCore/accessibility/mac/AXObjectCacheMac.mm
r142895 r143066 31 31 #import "AccessibilityObject.h" 32 32 #import "RenderObject.h" 33 #import "WebAccessibilityObjectWrapper .h"33 #import "WebAccessibilityObjectWrapperMac.h" 34 34 #import "WebCoreSystemInterface.h" 35 35 … … 52 52 void AXObjectCache::attachWrapper(AccessibilityObject* obj) 53 53 { 54 RetainPtr<WebAccessibilityObjectWrapper> wrapper(AdoptNS, [[WebAccessibilityObjectWrapper alloc] initWithAccessibilityObject:obj]);54 RetainPtr<WebAccessibilityObjectWrapper> wrapper(AdoptNS, [[WebAccessibilityObjectWrapperMac alloc] initWithAccessibilityObject:obj]); 55 55 obj->setWrapper(wrapper.get()); 56 56 } -
trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapper.h
r102378 r143066 42 42 - (void)detach; 43 43 - (WebCore::AccessibilityObject*)accessibilityObject; 44 + (void)accessibilitySetShouldRepostNotifications:(BOOL)repost;44 - (BOOL)updateObjectBackingStore; 45 45 46 - (id)attachmentView; 46 47 // Used to inform an element when a notification is posted for it. Used by DRT. 47 48 - (void)accessibilityPostedNotification:(NSString *)notificationName; 48 49 - (NSView*)attachmentView;50 49 51 50 @end -
trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapper.mm
r142895 r143066 78 78 using namespace std; 79 79 80 // Cell Tables81 #ifndef NSAccessibilitySelectedCellsAttribute82 #define NSAccessibilitySelectedCellsAttribute @"AXSelectedCells"83 #endif84 85 #ifndef NSAccessibilityVisibleCellsAttribute86 #define NSAccessibilityVisibleCellsAttribute @"AXVisibleCells"87 #endif88 89 #ifndef NSAccessibilityRowHeaderUIElementsAttribute90 #define NSAccessibilityRowHeaderUIElementsAttribute @"AXRowHeaderUIElements"91 #endif92 93 #ifndef NSAccessibilityRowIndexRangeAttribute94 #define NSAccessibilityRowIndexRangeAttribute @"AXRowIndexRange"95 #endif96 97 #ifndef NSAccessibilityColumnIndexRangeAttribute98 #define NSAccessibilityColumnIndexRangeAttribute @"AXColumnIndexRange"99 #endif100 101 #ifndef NSAccessibilityCellForColumnAndRowParameterizedAttribute102 #define NSAccessibilityCellForColumnAndRowParameterizedAttribute @"AXCellForColumnAndRow"103 #endif104 105 #ifndef NSAccessibilityCellRole106 #define NSAccessibilityCellRole @"AXCell"107 #endif108 109 // Lists110 #ifndef NSAccessibilityContentListSubrole111 #define NSAccessibilityContentListSubrole @"AXContentList"112 #endif113 114 #ifndef NSAccessibilityDescriptionListSubrole115 #define NSAccessibilityDescriptionListSubrole @"AXDescriptionList"116 #endif117 118 // Miscellaneous119 #ifndef NSAccessibilityBlockQuoteLevelAttribute120 #define NSAccessibilityBlockQuoteLevelAttribute @"AXBlockQuoteLevel"121 #endif122 123 #ifndef NSAccessibilityAccessKeyAttribute124 #define NSAccessibilityAccessKeyAttribute @"AXAccessKey"125 #endif126 127 #ifndef NSAccessibilityLanguageAttribute128 #define NSAccessibilityLanguageAttribute @"AXLanguage"129 #endif130 131 #ifndef NSAccessibilityRequiredAttribute132 #define NSAccessibilityRequiredAttribute @"AXRequired"133 #endif134 135 #ifndef NSAccessibilityInvalidAttribute136 #define NSAccessibilityInvalidAttribute @"AXInvalid"137 #endif138 139 #ifndef NSAccessibilityOwnsAttribute140 #define NSAccessibilityOwnsAttribute @"AXOwns"141 #endif142 143 #ifndef NSAccessibilityGrabbedAttribute144 #define NSAccessibilityGrabbedAttribute @"AXGrabbed"145 #endif146 147 #ifndef NSAccessibilityDropEffectsAttribute148 #define NSAccessibilityDropEffectsAttribute @"AXDropEffects"149 #endif150 151 #ifndef NSAccessibilityARIALiveAttribute152 #define NSAccessibilityARIALiveAttribute @"AXARIALive"153 #endif154 155 #ifndef NSAccessibilityARIAAtomicAttribute156 #define NSAccessibilityARIAAtomicAttribute @"AXARIAAtomic"157 #endif158 159 #ifndef NSAccessibilityARIARelevantAttribute160 #define NSAccessibilityARIARelevantAttribute @"AXARIARelevant"161 #endif162 163 #ifndef NSAccessibilityARIABusyAttribute164 #define NSAccessibilityARIABusyAttribute @"AXARIABusy"165 #endif166 167 #ifndef NSAccessibilityLoadingProgressAttribute168 #define NSAccessibilityLoadingProgressAttribute @"AXLoadingProgress"169 #endif170 171 #ifndef NSAccessibilityHasPopupAttribute172 #define NSAccessibilityHasPopupAttribute @"AXHasPopup"173 #endif174 175 #ifndef NSAccessibilityPlaceholderValueAttribute176 #define NSAccessibilityPlaceholderValueAttribute @"AXPlaceholderValue"177 #endif178 179 // Search180 #ifndef NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute181 #define NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute @"AXUIElementsForSearchPredicate"182 #endif183 184 // Search Keys185 #ifndef NSAccessibilityAnyTypeSearchKey186 #define NSAccessibilityAnyTypeSearchKey @"AXAnyTypeSearchKey"187 #endif188 189 #ifndef NSAccessibilityBlockquoteSameLevelSearchKey190 #define NSAccessibilityBlockquoteSameLevelSearchKey @"AXBlockquoteSameLevelSearchKey"191 #endif192 193 #ifndef NSAccessibilityBlockquoteSearchKey194 #define NSAccessibilityBlockquoteSearchKey @"AXBlockquoteSearchKey"195 #endif196 197 #ifndef NSAccessibilityBoldFontSearchKey198 #define NSAccessibilityBoldFontSearchKey @"AXBoldFontSearchKey"199 #endif200 201 #ifndef NSAccessibilityButtonSearchKey202 #define NSAccessibilityButtonSearchKey @"AXButtonSearchKey"203 #endif204 205 #ifndef NSAccessibilityCheckBoxSearchKey206 #define NSAccessibilityCheckBoxSearchKey @"AXCheckBoxSearchKey"207 #endif208 209 #ifndef NSAccessibilityControlSearchKey210 #define NSAccessibilityControlSearchKey @"AXControlSearchKey"211 #endif212 213 #ifndef NSAccessibilityDifferentTypeSearchKey214 #define NSAccessibilityDifferentTypeSearchKey @"AXDifferentTypeSearchKey"215 #endif216 217 #ifndef NSAccessibilityFontChangeSearchKey218 #define NSAccessibilityFontChangeSearchKey @"AXFontChangeSearchKey"219 #endif220 221 #ifndef NSAccessibilityFontColorChangeSearchKey222 #define NSAccessibilityFontColorChangeSearchKey @"AXFontColorChangeSearchKey"223 #endif224 225 #ifndef NSAccessibilityFrameSearchKey226 #define NSAccessibilityFrameSearchKey @"AXFrameSearchKey"227 #endif228 229 #ifndef NSAccessibilityGraphicSearchKey230 #define NSAccessibilityGraphicSearchKey @"AXGraphicSearchKey"231 #endif232 233 #ifndef NSAccessibilityHeadingLevel1SearchKey234 #define NSAccessibilityHeadingLevel1SearchKey @"AXHeadingLevel1SearchKey"235 #endif236 237 #ifndef NSAccessibilityHeadingLevel2SearchKey238 #define NSAccessibilityHeadingLevel2SearchKey @"AXHeadingLevel2SearchKey"239 #endif240 241 #ifndef NSAccessibilityHeadingLevel3SearchKey242 #define NSAccessibilityHeadingLevel3SearchKey @"AXHeadingLevel3SearchKey"243 #endif244 245 #ifndef NSAccessibilityHeadingLevel4SearchKey246 #define NSAccessibilityHeadingLevel4SearchKey @"AXHeadingLevel4SearchKey"247 #endif248 249 #ifndef NSAccessibilityHeadingLevel5SearchKey250 #define NSAccessibilityHeadingLevel5SearchKey @"AXHeadingLevel5SearchKey"251 #endif252 253 #ifndef NSAccessibilityHeadingLevel6SearchKey254 #define NSAccessibilityHeadingLevel6SearchKey @"AXHeadingLevel6SearchKey"255 #endif256 257 #ifndef NSAccessibilityHeadingSameLevelSearchKey258 #define NSAccessibilityHeadingSameLevelSearchKey @"AXHeadingSameLevelSearchKey"259 #endif260 261 #ifndef NSAccessibilityHeadingSearchKey262 #define NSAccessibilityHeadingSearchKey @"AXHeadingSearchKey"263 #endif264 265 #ifndef NSAccessibilityHighlightedSearchKey266 #define NSAccessibilityHighlightedSearchKey @"AXHighlightedSearchKey"267 #endif268 269 #ifndef NSAccessibilityItalicFontSearchKey270 #define NSAccessibilityItalicFontSearchKey @"AXItalicFontSearchKey"271 #endif272 273 #ifndef NSAccessibilityLandmarkSearchKey274 #define NSAccessibilityLandmarkSearchKey @"AXLandmarkSearchKey"275 #endif276 277 #ifndef NSAccessibilityLinkSearchKey278 #define NSAccessibilityLinkSearchKey @"AXLinkSearchKey"279 #endif280 281 #ifndef NSAccessibilityListSearchKey282 #define NSAccessibilityListSearchKey @"AXListSearchKey"283 #endif284 285 #ifndef NSAccessibilityLiveRegionSearchKey286 #define NSAccessibilityLiveRegionSearchKey @"AXLiveRegionSearchKey"287 #endif288 289 #ifndef NSAccessibilityMisspelledWordSearchKey290 #define NSAccessibilityMisspelledWordSearchKey @"AXMisspelledWordSearchKey"291 #endif292 293 #ifndef NSAccessibilityPlainTextSearchKey294 #define NSAccessibilityPlainTextSearchKey @"AXPlainTextSearchKey"295 #endif296 297 #ifndef NSAccessibilityRadioGroupSearchKey298 #define NSAccessibilityRadioGroupSearchKey @"AXRadioGroupSearchKey"299 #endif300 301 #ifndef NSAccessibilitySameTypeSearchKey302 #define NSAccessibilitySameTypeSearchKey @"AXSameTypeSearchKey"303 #endif304 305 #ifndef NSAccessibilityStaticTextSearchKey306 #define NSAccessibilityStaticTextSearchKey @"AXStaticTextSearchKey"307 #endif308 309 #ifndef NSAccessibilityStyleChangeSearchKey310 #define NSAccessibilityStyleChangeSearchKey @"AXStyleChangeSearchKey"311 #endif312 313 #ifndef NSAccessibilityTableSameLevelSearchKey314 #define NSAccessibilityTableSameLevelSearchKey @"AXTableSameLevelSearchKey"315 #endif316 317 #ifndef NSAccessibilityTableSearchKey318 #define NSAccessibilityTableSearchKey @"AXTableSearchKey"319 #endif320 321 #ifndef NSAccessibilityTextFieldSearchKey322 #define NSAccessibilityTextFieldSearchKey @"AXTextFieldSearchKey"323 #endif324 325 #ifndef NSAccessibilityUnderlineSearchKey326 #define NSAccessibilityUnderlineSearchKey @"AXUnderlineSearchKey"327 #endif328 329 #ifndef NSAccessibilityUnvisitedLinkSearchKey330 #define NSAccessibilityUnvisitedLinkSearchKey @"AXUnvisitedLinkSearchKey"331 #endif332 333 #ifndef NSAccessibilityVisitedLinkSearchKey334 #define NSAccessibilityVisitedLinkSearchKey @"AXVisitedLinkSearchKey"335 #endif336 337 #define NSAccessibilityTextMarkerIsValidParameterizedAttribute @"AXTextMarkerIsValid"338 #define NSAccessibilityIndexForTextMarkerParameterizedAttribute @"AXIndexForTextMarker"339 #define NSAccessibilityTextMarkerForIndexParameterizedAttribute @"AXTextMarkerForIndex"340 341 // Math attributes342 #define NSAccessibilityMathRootRadicandAttribute @"AXMathRootRadicand"343 #define NSAccessibilityMathRootIndexAttribute @"AXMathRootIndex"344 #define NSAccessibilityMathFractionDenominatorAttribute @"AXMathFractionDenominator"345 #define NSAccessibilityMathFractionNumeratorAttribute @"AXMathFractionNumerator"346 #define NSAccessibilityMathBaseAttribute @"AXMathBase"347 #define NSAccessibilityMathSubscriptAttribute @"AXMathSubscript"348 #define NSAccessibilityMathSuperscriptAttribute @"AXMathSuperscript"349 #define NSAccessibilityMathUnderAttribute @"AXMathUnder"350 #define NSAccessibilityMathOverAttribute @"AXMathOver"351 #define NSAccessibilityMathFencedOpenAttribute @"AXMathFencedOpen"352 #define NSAccessibilityMathFencedCloseAttribute @"AXMathFencedClose"353 354 @interface NSObject (WebKitAccessibilityArrayCategory)355 356 - (NSUInteger)accessibilityIndexOfChild:(id)child;357 - (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute;358 - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount;359 360 @end361 362 80 @implementation WebAccessibilityObjectWrapper 363 81 … … 371 89 } 372 90 373 - (void)unregisterUniqueIdForUIElement374 {375 wkUnregisterUniqueIdForElement(self);376 }377 378 91 - (void)detach 379 92 { 380 // Send unregisterUniqueIdForUIElement unconditionally because if it is381 // ever accidentally not done (via other bugs in our AX implementation) you382 // end up with a crash like <rdar://problem/4273149>. It is safe and not383 // expensive to send even if the object is not registered.384 [self unregisterUniqueIdForUIElement];385 93 m_object = 0; 386 94 } … … 402 110 } 403 111 112 - (id)attachmentView 113 { 114 return nil; 115 } 116 404 117 - (AccessibilityObject*)accessibilityObject 405 118 { 406 119 return m_object; 407 }408 409 - (NSView*)attachmentView410 {411 ASSERT(m_object->isAttachment());412 Widget* widget = m_object->widgetForAttachmentView();413 if (!widget)414 return nil;415 return NSAccessibilityUnignoredDescendant(widget->platformWidget());416 }417 418 #pragma mark SystemInterface wrappers419 420 static inline id CFAutoreleaseHelper(CFTypeRef obj)421 {422 if (obj)423 CFMakeCollectable(obj);424 [(id)obj autorelease];425 return (id)obj;426 }427 428 static inline BOOL AXObjectIsTextMarker(id obj)429 {430 return obj != nil && CFGetTypeID(obj) == wkGetAXTextMarkerTypeID();431 }432 433 static inline BOOL AXObjectIsTextMarkerRange(id obj)434 {435 return obj != nil && CFGetTypeID(obj) == wkGetAXTextMarkerRangeTypeID();436 }437 438 static id AXTextMarkerRange(id startMarker, id endMarker)439 {440 ASSERT(startMarker != nil);441 ASSERT(endMarker != nil);442 ASSERT(CFGetTypeID(startMarker) == wkGetAXTextMarkerTypeID());443 ASSERT(CFGetTypeID(endMarker) == wkGetAXTextMarkerTypeID());444 return CFAutoreleaseHelper(wkCreateAXTextMarkerRange((CFTypeRef)startMarker, (CFTypeRef)endMarker));445 }446 447 static id AXTextMarkerRangeStart(id range)448 {449 ASSERT(range != nil);450 ASSERT(CFGetTypeID(range) == wkGetAXTextMarkerRangeTypeID());451 return CFAutoreleaseHelper(wkCopyAXTextMarkerRangeStart(range));452 }453 454 static id AXTextMarkerRangeEnd(id range)455 {456 ASSERT(range != nil);457 ASSERT(CFGetTypeID(range) == wkGetAXTextMarkerRangeTypeID());458 return CFAutoreleaseHelper(wkCopyAXTextMarkerRangeEnd(range));459 }460 461 #pragma mark Search helpers462 463 typedef HashMap<String, AccessibilitySearchKey> AccessibilitySearchKeyMap;464 465 struct SearchKeyEntry {466 String key;467 AccessibilitySearchKey value;468 };469 470 static AccessibilitySearchKeyMap* createAccessibilitySearchKeyMap()471 {472 const SearchKeyEntry searchKeys[] = {473 { NSAccessibilityAnyTypeSearchKey, AnyTypeSearchKey },474 { NSAccessibilityBlockquoteSameLevelSearchKey, BlockquoteSameLevelSearchKey },475 { NSAccessibilityBlockquoteSearchKey, BlockquoteSearchKey },476 { NSAccessibilityBoldFontSearchKey, BoldFontSearchKey },477 { NSAccessibilityButtonSearchKey, ButtonSearchKey },478 { NSAccessibilityCheckBoxSearchKey, CheckBoxSearchKey },479 { NSAccessibilityControlSearchKey, ControlSearchKey },480 { NSAccessibilityDifferentTypeSearchKey, DifferentTypeSearchKey },481 { NSAccessibilityFontChangeSearchKey, FontChangeSearchKey },482 { NSAccessibilityFontColorChangeSearchKey, FontColorChangeSearchKey },483 { NSAccessibilityFrameSearchKey, FrameSearchKey },484 { NSAccessibilityGraphicSearchKey, GraphicSearchKey },485 { NSAccessibilityHeadingLevel1SearchKey, HeadingLevel1SearchKey },486 { NSAccessibilityHeadingLevel2SearchKey, HeadingLevel2SearchKey },487 { NSAccessibilityHeadingLevel3SearchKey, HeadingLevel3SearchKey },488 { NSAccessibilityHeadingLevel4SearchKey, HeadingLevel4SearchKey },489 { NSAccessibilityHeadingLevel5SearchKey, HeadingLevel5SearchKey },490 { NSAccessibilityHeadingLevel6SearchKey, HeadingLevel6SearchKey },491 { NSAccessibilityHeadingSameLevelSearchKey, HeadingSameLevelSearchKey },492 { NSAccessibilityHeadingSearchKey, HeadingSearchKey },493 { NSAccessibilityHighlightedSearchKey, HighlightedSearchKey },494 { NSAccessibilityItalicFontSearchKey, ItalicFontSearchKey },495 { NSAccessibilityLandmarkSearchKey, LandmarkSearchKey },496 { NSAccessibilityLinkSearchKey, LinkSearchKey },497 { NSAccessibilityListSearchKey, ListSearchKey },498 { NSAccessibilityLiveRegionSearchKey, LiveRegionSearchKey },499 { NSAccessibilityMisspelledWordSearchKey, MisspelledWordSearchKey },500 { NSAccessibilityPlainTextSearchKey, PlainTextSearchKey },501 { NSAccessibilityRadioGroupSearchKey, RadioGroupSearchKey },502 { NSAccessibilitySameTypeSearchKey, SameTypeSearchKey },503 { NSAccessibilityStaticTextSearchKey, StaticTextSearchKey },504 { NSAccessibilityStyleChangeSearchKey, StyleChangeSearchKey },505 { NSAccessibilityTableSameLevelSearchKey, TableSameLevelSearchKey },506 { NSAccessibilityTableSearchKey, TableSearchKey },507 { NSAccessibilityTextFieldSearchKey, TextFieldSearchKey },508 { NSAccessibilityUnderlineSearchKey, UnderlineSearchKey },509 { NSAccessibilityUnvisitedLinkSearchKey, UnvisitedLinkSearchKey },510 { NSAccessibilityVisitedLinkSearchKey, VisitedLinkSearchKey }511 };512 513 AccessibilitySearchKeyMap* searchKeyMap = new AccessibilitySearchKeyMap;514 for (size_t i = 0; i < WTF_ARRAY_LENGTH(searchKeys); i++)515 searchKeyMap->set(searchKeys[i].key, searchKeys[i].value);516 517 return searchKeyMap;518 }519 520 static AccessibilitySearchKey accessibilitySearchKeyForString(const String& value)521 {522 if (value.isEmpty())523 return AnyTypeSearchKey;524 525 static const AccessibilitySearchKeyMap* searchKeyMap = createAccessibilitySearchKeyMap();526 527 AccessibilitySearchKey searchKey = searchKeyMap->get(value);528 529 return searchKey ? searchKey : AnyTypeSearchKey;530 }531 532 #pragma mark Text Marker helpers533 534 static id textMarkerForVisiblePosition(AXObjectCache* cache, const VisiblePosition& visiblePos)535 {536 ASSERT(cache);537 538 TextMarkerData textMarkerData;539 cache->textMarkerDataForVisiblePosition(textMarkerData, visiblePos);540 if (!textMarkerData.axID)541 return nil;542 543 return CFAutoreleaseHelper(wkCreateAXTextMarker(&textMarkerData, sizeof(textMarkerData)));544 }545 546 - (id)textMarkerForVisiblePosition:(const VisiblePosition &)visiblePos547 {548 return textMarkerForVisiblePosition(m_object->axObjectCache(), visiblePos);549 }550 551 static VisiblePosition visiblePositionForTextMarker(AXObjectCache* cache, CFTypeRef textMarker)552 {553 ASSERT(cache);554 555 if (!textMarker)556 return VisiblePosition();557 TextMarkerData textMarkerData;558 if (!wkGetBytesFromAXTextMarker(textMarker, &textMarkerData, sizeof(textMarkerData)))559 return VisiblePosition();560 561 return cache->visiblePositionForTextMarkerData(textMarkerData);562 }563 564 - (VisiblePosition)visiblePositionForTextMarker:(id)textMarker565 {566 return visiblePositionForTextMarker(m_object->axObjectCache(), textMarker);567 }568 569 static VisiblePosition visiblePositionForStartOfTextMarkerRange(AXObjectCache *cache, id textMarkerRange)570 {571 return visiblePositionForTextMarker(cache, AXTextMarkerRangeStart(textMarkerRange));572 }573 574 static VisiblePosition visiblePositionForEndOfTextMarkerRange(AXObjectCache *cache, id textMarkerRange)575 {576 return visiblePositionForTextMarker(cache, AXTextMarkerRangeEnd(textMarkerRange));577 }578 579 static id textMarkerRangeFromMarkers(id textMarker1, id textMarker2)580 {581 if (!textMarker1 || !textMarker2)582 return nil;583 584 return AXTextMarkerRange(textMarker1, textMarker2);585 }586 587 // When modifying attributed strings, the range can come from a source which may provide faulty information (e.g. the spell checker).588 // To protect against such cases the range should be validated before adding or removing attributes.589 static BOOL AXAttributedStringRangeIsValid(NSAttributedString* attrString, NSRange range)590 {591 return (range.location < [attrString length] && NSMaxRange(range) <= [attrString length]);592 }593 594 static void AXAttributeStringSetFont(NSMutableAttributedString* attrString, NSString* attribute, NSFont* font, NSRange range)595 {596 if (!AXAttributedStringRangeIsValid(attrString, range))597 return;598 599 if (font) {600 NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:601 [font fontName] , NSAccessibilityFontNameKey,602 [font familyName] , NSAccessibilityFontFamilyKey,603 [font displayName] , NSAccessibilityVisibleNameKey,604 [NSNumber numberWithFloat:[font pointSize]] , NSAccessibilityFontSizeKey,605 nil];606 607 [attrString addAttribute:attribute value:dict range:range];608 } else609 [attrString removeAttribute:attribute range:range];610 611 }612 613 static CGColorRef CreateCGColorIfDifferent(NSColor* nsColor, CGColorRef existingColor)614 {615 // get color information assuming NSDeviceRGBColorSpace616 NSColor* rgbColor = [nsColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];617 if (rgbColor == nil)618 rgbColor = [NSColor blackColor];619 CGFloat components[4];620 [rgbColor getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]];621 622 // create a new CGColorRef to return623 CGColorSpaceRef cgColorSpace = CGColorSpaceCreateDeviceRGB();624 CGColorRef cgColor = CGColorCreate(cgColorSpace, components);625 CGColorSpaceRelease(cgColorSpace);626 627 // check for match with existing color628 if (existingColor && CGColorEqualToColor(cgColor, existingColor)) {629 CGColorRelease(cgColor);630 cgColor = 0;631 }632 633 return cgColor;634 }635 636 static void AXAttributeStringSetColor(NSMutableAttributedString* attrString, NSString* attribute, NSColor* color, NSRange range)637 {638 if (!AXAttributedStringRangeIsValid(attrString, range))639 return;640 641 if (color) {642 CGColorRef existingColor = (CGColorRef) [attrString attribute:attribute atIndex:range.location effectiveRange:nil];643 CGColorRef cgColor = CreateCGColorIfDifferent(color, existingColor);644 if (cgColor) {645 [attrString addAttribute:attribute value:(id)cgColor range:range];646 CGColorRelease(cgColor);647 }648 } else649 [attrString removeAttribute:attribute range:range];650 }651 652 static void AXAttributeStringSetNumber(NSMutableAttributedString* attrString, NSString* attribute, NSNumber* number, NSRange range)653 {654 if (!AXAttributedStringRangeIsValid(attrString, range))655 return;656 657 if (number)658 [attrString addAttribute:attribute value:number range:range];659 else660 [attrString removeAttribute:attribute range:range];661 }662 663 static void AXAttributeStringSetStyle(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)664 {665 RenderStyle* style = renderer->style();666 667 // set basic font info668 AXAttributeStringSetFont(attrString, NSAccessibilityFontTextAttribute, style->font().primaryFont()->getNSFont(), range);669 670 // set basic colors671 AXAttributeStringSetColor(attrString, NSAccessibilityForegroundColorTextAttribute, nsColor(style->visitedDependentColor(CSSPropertyColor)), range);672 AXAttributeStringSetColor(attrString, NSAccessibilityBackgroundColorTextAttribute, nsColor(style->visitedDependentColor(CSSPropertyBackgroundColor)), range);673 674 // set super/sub scripting675 EVerticalAlign alignment = style->verticalAlign();676 if (alignment == SUB)677 AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:(-1)], range);678 else if (alignment == SUPER)679 AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:1], range);680 else681 [attrString removeAttribute:NSAccessibilitySuperscriptTextAttribute range:range];682 683 // set shadow684 if (style->textShadow())685 AXAttributeStringSetNumber(attrString, NSAccessibilityShadowTextAttribute, [NSNumber numberWithBool:YES], range);686 else687 [attrString removeAttribute:NSAccessibilityShadowTextAttribute range:range];688 689 // set underline and strikethrough690 int decor = style->textDecorationsInEffect();691 if ((decor & UNDERLINE) == 0) {692 [attrString removeAttribute:NSAccessibilityUnderlineTextAttribute range:range];693 [attrString removeAttribute:NSAccessibilityUnderlineColorTextAttribute range:range];694 }695 696 if ((decor & LINE_THROUGH) == 0) {697 [attrString removeAttribute:NSAccessibilityStrikethroughTextAttribute range:range];698 [attrString removeAttribute:NSAccessibilityStrikethroughColorTextAttribute range:range];699 }700 701 if ((decor & (UNDERLINE | LINE_THROUGH)) != 0) {702 // find colors using quirk mode approach (strict mode would use current703 // color for all but the root line box, which would use getTextDecorationColors)704 Color underline, overline, linethrough;705 renderer->getTextDecorationColors(decor, underline, overline, linethrough);706 707 if ((decor & UNDERLINE) != 0) {708 AXAttributeStringSetNumber(attrString, NSAccessibilityUnderlineTextAttribute, [NSNumber numberWithBool:YES], range);709 AXAttributeStringSetColor(attrString, NSAccessibilityUnderlineColorTextAttribute, nsColor(underline), range);710 }711 712 if ((decor & LINE_THROUGH) != 0) {713 AXAttributeStringSetNumber(attrString, NSAccessibilityStrikethroughTextAttribute, [NSNumber numberWithBool:YES], range);714 AXAttributeStringSetColor(attrString, NSAccessibilityStrikethroughColorTextAttribute, nsColor(linethrough), range);715 }716 }717 718 // Indicate background highlighting.719 for (Node* node = renderer->node(); node; node = node->parentNode()) {720 if (node->hasTagName(markTag))721 AXAttributeStringSetNumber(attrString, @"AXHighlight", [NSNumber numberWithBool:YES], range);722 }723 }724 725 static void AXAttributeStringSetBlockquoteLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)726 {727 if (!AXAttributedStringRangeIsValid(attrString, range))728 return;729 730 AccessibilityObject* obj = renderer->document()->axObjectCache()->getOrCreate(renderer);731 int quoteLevel = obj->blockquoteLevel();732 733 if (quoteLevel)734 [attrString addAttribute:NSAccessibilityBlockQuoteLevelAttribute value:[NSNumber numberWithInt:quoteLevel] range:range];735 else736 [attrString removeAttribute:NSAccessibilityBlockQuoteLevelAttribute range:range];737 }738 739 static void AXAttributeStringSetSpelling(NSMutableAttributedString* attrString, Node* node, const UChar* chars, int charLength, NSRange range)740 {741 if (unifiedTextCheckerEnabled(node->document()->frame())) {742 // Check the spelling directly since document->markersForNode() does not store the misspelled marking when the cursor is in a word.743 TextCheckerClient* checker = node->document()->frame()->editor()->textChecker();744 745 // checkTextOfParagraph is the only spelling/grammar checker implemented in WK1 and WK2746 Vector<TextCheckingResult> results;747 checkTextOfParagraph(checker, chars, charLength, TextCheckingTypeSpelling, results);748 749 size_t size = results.size();750 NSNumber* trueValue = [NSNumber numberWithBool:YES];751 for (unsigned i = 0; i < size; i++) {752 const TextCheckingResult& result = results[i];753 AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, trueValue, NSMakeRange(result.location + range.location, result.length));754 }755 return;756 }757 758 int currentPosition = 0;759 while (charLength > 0) {760 const UChar* charData = chars + currentPosition;761 TextCheckerClient* checker = node->document()->frame()->editor()->textChecker();762 763 int misspellingLocation = -1;764 int misspellingLength = 0;765 checker->checkSpellingOfString(charData, charLength, &misspellingLocation, &misspellingLength);766 if (misspellingLocation == -1 || !misspellingLength)767 break;768 769 NSRange spellRange = NSMakeRange(range.location + currentPosition + misspellingLocation, misspellingLength);770 AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, [NSNumber numberWithBool:YES], spellRange);771 charLength -= (misspellingLocation + misspellingLength);772 currentPosition += (misspellingLocation + misspellingLength);773 }774 }775 776 static void AXAttributeStringSetHeadingLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)777 {778 if (!renderer)779 return;780 781 if (!AXAttributedStringRangeIsValid(attrString, range))782 return;783 784 // Sometimes there are objects between the text and the heading.785 // In those cases the parent hierarchy should be queried to see if there is a heading level.786 int parentHeadingLevel = 0;787 AccessibilityObject* parentObject = renderer->document()->axObjectCache()->getOrCreate(renderer->parent());788 for (; parentObject; parentObject = parentObject->parentObject()) {789 parentHeadingLevel = parentObject->headingLevel();790 if (parentHeadingLevel)791 break;792 }793 794 if (parentHeadingLevel)795 [attrString addAttribute:@"AXHeadingLevel" value:[NSNumber numberWithInt:parentHeadingLevel] range:range];796 else797 [attrString removeAttribute:@"AXHeadingLevel" range:range];798 }799 800 static void AXAttributeStringSetElement(NSMutableAttributedString* attrString, NSString* attribute, AccessibilityObject* object, NSRange range)801 {802 if (!AXAttributedStringRangeIsValid(attrString, range))803 return;804 805 if (object && object->isAccessibilityRenderObject()) {806 // make a serializable AX object807 808 RenderObject* renderer = static_cast<AccessibilityRenderObject*>(object)->renderer();809 if (!renderer)810 return;811 812 Document* doc = renderer->document();813 if (!doc)814 return;815 816 AXObjectCache* cache = doc->axObjectCache();817 if (!cache)818 return;819 820 AXUIElementRef axElement = wkCreateAXUIElementRef(object->wrapper());821 if (axElement) {822 [attrString addAttribute:attribute value:(id)axElement range:range];823 CFRelease(axElement);824 }825 } else826 [attrString removeAttribute:attribute range:range];827 }828 829 static void AXAttributedStringAppendText(NSMutableAttributedString* attrString, Node* node, const UChar* chars, int length)830 {831 // skip invisible text832 if (!node->renderer())833 return;834 835 // easier to calculate the range before appending the string836 NSRange attrStringRange = NSMakeRange([attrString length], length);837 838 // append the string from this node839 [[attrString mutableString] appendString:[NSString stringWithCharacters:chars length:length]];840 841 // add new attributes and remove irrelevant inherited ones842 // NOTE: color attributes are handled specially because -[NSMutableAttributedString addAttribute: value: range:] does not merge843 // identical colors. Workaround is to not replace an existing color attribute if it matches what we are adding. This also means844 // we cannot just pre-remove all inherited attributes on the appended string, so we have to remove the irrelevant ones individually.845 846 // remove inherited attachment from prior AXAttributedStringAppendReplaced847 [attrString removeAttribute:NSAccessibilityAttachmentTextAttribute range:attrStringRange];848 [attrString removeAttribute:NSAccessibilityMisspelledTextAttribute range:attrStringRange];849 850 // set new attributes851 AXAttributeStringSetStyle(attrString, node->renderer(), attrStringRange);852 AXAttributeStringSetHeadingLevel(attrString, node->renderer(), attrStringRange);853 AXAttributeStringSetBlockquoteLevel(attrString, node->renderer(), attrStringRange);854 AXAttributeStringSetElement(attrString, NSAccessibilityLinkTextAttribute, AccessibilityObject::anchorElementForNode(node), attrStringRange);855 856 // do spelling last because it tends to break up the range857 AXAttributeStringSetSpelling(attrString, node, chars, length, attrStringRange);858 }859 860 static NSString* nsStringForReplacedNode(Node* replacedNode)861 {862 // we should always be given a rendered node and a replaced node, but be safe863 // replaced nodes are either attachments (widgets) or images864 if (!replacedNode || !replacedNode->renderer() || !replacedNode->renderer()->isReplaced() || replacedNode->isTextNode()) {865 ASSERT_NOT_REACHED();866 return nil;867 }868 869 // create an AX object, but skip it if it is not supposed to be seen870 RefPtr<AccessibilityObject> obj = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer());871 if (obj->accessibilityIsIgnored())872 return nil;873 874 // use the attachmentCharacter to represent the replaced node875 const UniChar attachmentChar = NSAttachmentCharacter;876 return [NSString stringWithCharacters:&attachmentChar length:1];877 }878 879 - (NSAttributedString*)doAXAttributedStringForTextMarkerRange:(id)textMarkerRange880 {881 if (!m_object)882 return nil;883 884 // extract the start and end VisiblePosition885 VisiblePosition startVisiblePosition = visiblePositionForStartOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);886 if (startVisiblePosition.isNull())887 return nil;888 889 VisiblePosition endVisiblePosition = visiblePositionForEndOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);890 if (endVisiblePosition.isNull())891 return nil;892 893 VisiblePositionRange visiblePositionRange(startVisiblePosition, endVisiblePosition);894 // iterate over the range to build the AX attributed string895 NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] init];896 TextIterator it(makeRange(startVisiblePosition, endVisiblePosition).get());897 while (!it.atEnd()) {898 // locate the node and starting offset for this range899 int exception = 0;900 Node* node = it.range()->startContainer(exception);901 ASSERT(node == it.range()->endContainer(exception));902 int offset = it.range()->startOffset(exception);903 904 // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX)905 if (it.length() != 0) {906 // Add the text of the list marker item if necessary.907 String listMarkerText = m_object->listMarkerTextForNodeAndPosition(node, VisiblePosition(it.range()->startPosition()));908 if (!listMarkerText.isEmpty())909 AXAttributedStringAppendText(attrString, node, listMarkerText.characters(), listMarkerText.length());910 911 AXAttributedStringAppendText(attrString, node, it.characters(), it.length());912 } else {913 Node* replacedNode = node->childNode(offset);914 NSString *attachmentString = nsStringForReplacedNode(replacedNode);915 if (attachmentString) {916 NSRange attrStringRange = NSMakeRange([attrString length], [attachmentString length]);917 918 // append the placeholder string919 [[attrString mutableString] appendString:attachmentString];920 921 // remove all inherited attributes922 [attrString setAttributes:nil range:attrStringRange];923 924 // add the attachment attribute925 AccessibilityObject* obj = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer());926 AXAttributeStringSetElement(attrString, NSAccessibilityAttachmentTextAttribute, obj, attrStringRange);927 }928 }929 it.advance();930 }931 932 return [attrString autorelease];933 }934 935 static id textMarkerRangeFromVisiblePositions(AXObjectCache *cache, VisiblePosition startPosition, VisiblePosition endPosition)936 {937 id startTextMarker = textMarkerForVisiblePosition(cache, startPosition);938 id endTextMarker = textMarkerForVisiblePosition(cache, endPosition);939 return textMarkerRangeFromMarkers(startTextMarker, endTextMarker);940 }941 942 - (id)textMarkerRangeFromVisiblePositions:(VisiblePosition)startPosition endPosition:(VisiblePosition)endPosition943 {944 return textMarkerRangeFromVisiblePositions(m_object->axObjectCache(), startPosition, endPosition);945 }946 947 - (NSArray*)accessibilityActionNames948 {949 if (![self updateObjectBackingStore])950 return nil;951 952 static NSArray* actionElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityPressAction, NSAccessibilityShowMenuAction, nil];953 static NSArray* defaultElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityShowMenuAction, nil];954 static NSArray* menuElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityCancelAction, NSAccessibilityPressAction, nil];955 static NSArray* sliderActions = [[NSArray alloc] initWithObjects: NSAccessibilityIncrementAction, NSAccessibilityDecrementAction, nil];956 957 NSArray *actions;958 if (m_object->actionElement() || m_object->isButton())959 actions = actionElementActions;960 else if (m_object->isMenuRelated())961 actions = menuElementActions;962 else if (m_object->isSlider())963 actions = sliderActions;964 else if (m_object->isAttachment())965 actions = [[self attachmentView] accessibilityActionNames];966 else967 actions = defaultElementActions;968 969 return actions;970 }971 972 - (NSArray*)additionalAccessibilityAttributeNames973 {974 if (!m_object)975 return nil;976 977 NSMutableArray *additional = [NSMutableArray array];978 if (m_object->supportsARIAOwns())979 [additional addObject:NSAccessibilityOwnsAttribute];980 981 if (m_object->supportsARIAExpanded())982 [additional addObject:NSAccessibilityExpandedAttribute];983 984 if (m_object->isScrollbar())985 [additional addObject:NSAccessibilityOrientationAttribute];986 987 if (m_object->supportsARIADragging())988 [additional addObject:NSAccessibilityGrabbedAttribute];989 990 if (m_object->supportsARIADropping())991 [additional addObject:NSAccessibilityDropEffectsAttribute];992 993 if (m_object->isAccessibilityTable() && static_cast<AccessibilityTable*>(m_object)->supportsSelectedRows())994 [additional addObject:NSAccessibilitySelectedRowsAttribute];995 996 if (m_object->supportsARIALiveRegion()) {997 [additional addObject:NSAccessibilityARIALiveAttribute];998 [additional addObject:NSAccessibilityARIARelevantAttribute];999 }1000 1001 if (m_object->sortDirection() != SortDirectionNone)1002 [additional addObject:NSAccessibilitySortDirectionAttribute];1003 1004 // If an object is a child of a live region, then add these1005 if (m_object->isInsideARIALiveRegion())1006 [additional addObject:NSAccessibilityARIAAtomicAttribute];1007 // All objects should expose the ARIA busy attribute (ARIA 1.1 with ISSUE-538).1008 [additional addObject:NSAccessibilityARIABusyAttribute];1009 1010 // Popup buttons on the Mac expose the value attribute.1011 if (m_object->isPopUpButton())1012 [additional addObject:NSAccessibilityValueAttribute];1013 1014 if (m_object->ariaHasPopup())1015 [additional addObject:NSAccessibilityHasPopupAttribute];1016 1017 if (m_object->isMathRoot()) {1018 // The index of a square root is always known, so there's no object associated with it.1019 if (!m_object->isMathSquareRoot())1020 [additional addObject:NSAccessibilityMathRootIndexAttribute];1021 [additional addObject:NSAccessibilityMathRootRadicandAttribute];1022 } else if (m_object->isMathFraction()) {1023 [additional addObject:NSAccessibilityMathFractionNumeratorAttribute];1024 [additional addObject:NSAccessibilityMathFractionDenominatorAttribute];1025 } else if (m_object->isMathSubscriptSuperscript()) {1026 [additional addObject:NSAccessibilityMathBaseAttribute];1027 [additional addObject:NSAccessibilityMathSubscriptAttribute];1028 [additional addObject:NSAccessibilityMathSuperscriptAttribute];1029 } else if (m_object->isMathUnderOver()) {1030 [additional addObject:NSAccessibilityMathBaseAttribute];1031 [additional addObject:NSAccessibilityMathUnderAttribute];1032 [additional addObject:NSAccessibilityMathOverAttribute];1033 } else if (m_object->isMathFenced()) {1034 [additional addObject:NSAccessibilityMathFencedOpenAttribute];1035 [additional addObject:NSAccessibilityMathFencedCloseAttribute];1036 }1037 1038 return additional;1039 }1040 1041 - (NSArray*)accessibilityAttributeNames1042 {1043 if (![self updateObjectBackingStore])1044 return nil;1045 1046 if (m_object->isAttachment())1047 return [[self attachmentView] accessibilityAttributeNames];1048 1049 static NSArray* attributes = nil;1050 static NSArray* anchorAttrs = nil;1051 static NSArray* webAreaAttrs = nil;1052 static NSArray* textAttrs = nil;1053 static NSArray* listAttrs = nil;1054 static NSArray* listBoxAttrs = nil;1055 static NSArray* rangeAttrs = nil;1056 static NSArray* commonMenuAttrs = nil;1057 static NSArray* menuAttrs = nil;1058 static NSArray* menuBarAttrs = nil;1059 static NSArray* menuItemAttrs = nil;1060 static NSArray* menuButtonAttrs = nil;1061 static NSArray* controlAttrs = nil;1062 static NSArray* tableAttrs = nil;1063 static NSArray* tableRowAttrs = nil;1064 static NSArray* tableColAttrs = nil;1065 static NSArray* tableCellAttrs = nil;1066 static NSArray* groupAttrs = nil;1067 static NSArray* inputImageAttrs = nil;1068 static NSArray* passwordFieldAttrs = nil;1069 static NSArray* tabListAttrs = nil;1070 static NSArray* comboBoxAttrs = nil;1071 static NSArray* outlineAttrs = nil;1072 static NSArray* outlineRowAttrs = nil;1073 static NSArray* buttonAttrs = nil;1074 static NSArray* scrollViewAttrs = nil;1075 static NSArray* incrementorAttrs = nil;1076 NSMutableArray* tempArray;1077 if (attributes == nil) {1078 attributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,1079 NSAccessibilitySubroleAttribute,1080 NSAccessibilityRoleDescriptionAttribute,1081 NSAccessibilityChildrenAttribute,1082 NSAccessibilityHelpAttribute,1083 NSAccessibilityParentAttribute,1084 NSAccessibilityPositionAttribute,1085 NSAccessibilitySizeAttribute,1086 NSAccessibilityTitleAttribute,1087 NSAccessibilityDescriptionAttribute,1088 NSAccessibilityValueAttribute,1089 NSAccessibilityFocusedAttribute,1090 NSAccessibilityEnabledAttribute,1091 NSAccessibilityWindowAttribute,1092 @"AXSelectedTextMarkerRange",1093 @"AXStartTextMarker",1094 @"AXEndTextMarker",1095 @"AXVisited",1096 NSAccessibilityLinkedUIElementsAttribute,1097 NSAccessibilitySelectedAttribute,1098 NSAccessibilityBlockQuoteLevelAttribute,1099 NSAccessibilityTopLevelUIElementAttribute,1100 nil];1101 }1102 if (commonMenuAttrs == nil) {1103 commonMenuAttrs = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,1104 NSAccessibilityRoleDescriptionAttribute,1105 NSAccessibilityChildrenAttribute,1106 NSAccessibilityParentAttribute,1107 NSAccessibilityEnabledAttribute,1108 NSAccessibilityPositionAttribute,1109 NSAccessibilitySizeAttribute,1110 nil];1111 }1112 if (anchorAttrs == nil) {1113 tempArray = [[NSMutableArray alloc] initWithArray:attributes];1114 [tempArray addObject:NSAccessibilityURLAttribute];1115 [tempArray addObject:NSAccessibilityAccessKeyAttribute];1116 anchorAttrs = [[NSArray alloc] initWithArray:tempArray];1117 [tempArray release];1118 }1119 if (webAreaAttrs == nil) {1120 tempArray = [[NSMutableArray alloc] initWithArray:attributes];1121 [tempArray addObject:@"AXLinkUIElements"];1122 [tempArray addObject:@"AXLoaded"];1123 [tempArray addObject:@"AXLayoutCount"];1124 [tempArray addObject:NSAccessibilityLoadingProgressAttribute];1125 [tempArray addObject:NSAccessibilityURLAttribute];1126 webAreaAttrs = [[NSArray alloc] initWithArray:tempArray];1127 [tempArray release];1128 }1129 if (textAttrs == nil) {1130 tempArray = [[NSMutableArray alloc] initWithArray:attributes];1131 [tempArray addObject:NSAccessibilityNumberOfCharactersAttribute];1132 [tempArray addObject:NSAccessibilitySelectedTextAttribute];1133 [tempArray addObject:NSAccessibilitySelectedTextRangeAttribute];1134 [tempArray addObject:NSAccessibilityVisibleCharacterRangeAttribute];1135 [tempArray addObject:NSAccessibilityInsertionPointLineNumberAttribute];1136 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];1137 [tempArray addObject:NSAccessibilityAccessKeyAttribute];1138 [tempArray addObject:NSAccessibilityRequiredAttribute];1139 [tempArray addObject:NSAccessibilityInvalidAttribute];1140 [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];1141 textAttrs = [[NSArray alloc] initWithArray:tempArray];1142 [tempArray release];1143 }1144 if (listAttrs == nil) {1145 tempArray = [[NSMutableArray alloc] initWithArray:attributes];1146 [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];1147 [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];1148 [tempArray addObject:NSAccessibilityOrientationAttribute];1149 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];1150 listAttrs = [[NSArray alloc] initWithArray:tempArray];1151 [tempArray release];1152 }1153 if (listBoxAttrs == nil) {1154 tempArray = [[NSMutableArray alloc] initWithArray:listAttrs];1155 [tempArray addObject:NSAccessibilityAccessKeyAttribute];1156 [tempArray addObject:NSAccessibilityRequiredAttribute];1157 [tempArray addObject:NSAccessibilityInvalidAttribute];1158 listBoxAttrs = [[NSArray alloc] initWithArray:tempArray];1159 [tempArray release];1160 }1161 if (rangeAttrs == nil) {1162 tempArray = [[NSMutableArray alloc] initWithArray:attributes];1163 [tempArray addObject:NSAccessibilityMinValueAttribute];1164 [tempArray addObject:NSAccessibilityMaxValueAttribute];1165 [tempArray addObject:NSAccessibilityOrientationAttribute];1166 [tempArray addObject:NSAccessibilityValueDescriptionAttribute];1167 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];1168 rangeAttrs = [[NSArray alloc] initWithArray:tempArray];1169 [tempArray release];1170 }1171 if (menuBarAttrs == nil) {1172 tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];1173 [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];1174 [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];1175 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];1176 menuBarAttrs = [[NSArray alloc] initWithArray:tempArray];1177 [tempArray release];1178 }1179 if (menuAttrs == nil) {1180 tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];1181 [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];1182 [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];1183 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];1184 menuAttrs = [[NSArray alloc] initWithArray:tempArray];1185 [tempArray release];1186 }1187 if (menuItemAttrs == nil) {1188 tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];1189 [tempArray addObject:NSAccessibilityTitleAttribute];1190 [tempArray addObject:NSAccessibilityHelpAttribute];1191 [tempArray addObject:NSAccessibilitySelectedAttribute];1192 [tempArray addObject:(NSString*)kAXMenuItemCmdCharAttribute];1193 [tempArray addObject:(NSString*)kAXMenuItemCmdVirtualKeyAttribute];1194 [tempArray addObject:(NSString*)kAXMenuItemCmdGlyphAttribute];1195 [tempArray addObject:(NSString*)kAXMenuItemCmdModifiersAttribute];1196 [tempArray addObject:(NSString*)kAXMenuItemMarkCharAttribute];1197 [tempArray addObject:(NSString*)kAXMenuItemPrimaryUIElementAttribute];1198 [tempArray addObject:NSAccessibilityServesAsTitleForUIElementsAttribute];1199 menuItemAttrs = [[NSArray alloc] initWithArray:tempArray];1200 [tempArray release];1201 }1202 if (menuButtonAttrs == nil) {1203 menuButtonAttrs = [[NSArray alloc] initWithObjects:NSAccessibilityRoleAttribute,1204 NSAccessibilityRoleDescriptionAttribute,1205 NSAccessibilityParentAttribute,1206 NSAccessibilityPositionAttribute,1207 NSAccessibilitySizeAttribute,1208 NSAccessibilityWindowAttribute,1209 NSAccessibilityEnabledAttribute,1210 NSAccessibilityFocusedAttribute,1211 NSAccessibilityTitleAttribute,1212 NSAccessibilityChildrenAttribute, nil];1213 }1214 if (controlAttrs == nil) {1215 tempArray = [[NSMutableArray alloc] initWithArray:attributes];1216 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];1217 [tempArray addObject:NSAccessibilityAccessKeyAttribute];1218 [tempArray addObject:NSAccessibilityRequiredAttribute];1219 [tempArray addObject:NSAccessibilityInvalidAttribute];1220 controlAttrs = [[NSArray alloc] initWithArray:tempArray];1221 [tempArray release];1222 }1223 if (incrementorAttrs == nil) {1224 tempArray = [[NSMutableArray alloc] initWithArray:attributes];1225 [tempArray addObject:NSAccessibilityIncrementButtonAttribute];1226 [tempArray addObject:NSAccessibilityDecrementButtonAttribute];1227 incrementorAttrs = [[NSArray alloc] initWithArray:tempArray];1228 [tempArray release];1229 }1230 if (buttonAttrs == nil) {1231 tempArray = [[NSMutableArray alloc] initWithArray:attributes];1232 // Buttons should not expose AXValue.1233 [tempArray removeObject:NSAccessibilityValueAttribute];1234 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];1235 [tempArray addObject:NSAccessibilityAccessKeyAttribute];1236 buttonAttrs = [[NSArray alloc] initWithArray:tempArray];1237 [tempArray release];1238 }1239 if (comboBoxAttrs == nil) {1240 tempArray = [[NSMutableArray alloc] initWithArray:controlAttrs];1241 [tempArray addObject:NSAccessibilityExpandedAttribute];1242 comboBoxAttrs = [[NSArray alloc] initWithArray:tempArray];1243 [tempArray release];1244 }1245 if (tableAttrs == nil) {1246 tempArray = [[NSMutableArray alloc] initWithArray:attributes];1247 [tempArray addObject:NSAccessibilityRowsAttribute];1248 [tempArray addObject:NSAccessibilityVisibleRowsAttribute];1249 [tempArray addObject:NSAccessibilityColumnsAttribute];1250 [tempArray addObject:NSAccessibilityVisibleColumnsAttribute];1251 [tempArray addObject:NSAccessibilityVisibleCellsAttribute];1252 [tempArray addObject:(NSString *)kAXColumnHeaderUIElementsAttribute];1253 [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];1254 [tempArray addObject:NSAccessibilityHeaderAttribute];1255 tableAttrs = [[NSArray alloc] initWithArray:tempArray];1256 [tempArray release];1257 }1258 if (tableRowAttrs == nil) {1259 tempArray = [[NSMutableArray alloc] initWithArray:attributes];1260 [tempArray addObject:NSAccessibilityIndexAttribute];1261 tableRowAttrs = [[NSArray alloc] initWithArray:tempArray];1262 [tempArray release];1263 }1264 if (tableColAttrs == nil) {1265 tempArray = [[NSMutableArray alloc] initWithArray:attributes];1266 [tempArray addObject:NSAccessibilityIndexAttribute];1267 [tempArray addObject:NSAccessibilityHeaderAttribute];1268 [tempArray addObject:NSAccessibilityRowsAttribute];1269 [tempArray addObject:NSAccessibilityVisibleRowsAttribute];1270 tableColAttrs = [[NSArray alloc] initWithArray:tempArray];1271 [tempArray release];1272 }1273 if (tableCellAttrs == nil) {1274 tempArray = [[NSMutableArray alloc] initWithArray:attributes];1275 [tempArray addObject:NSAccessibilityRowIndexRangeAttribute];1276 [tempArray addObject:NSAccessibilityColumnIndexRangeAttribute];1277 tableCellAttrs = [[NSArray alloc] initWithArray:tempArray];1278 [tempArray release];1279 }1280 if (groupAttrs == nil) {1281 tempArray = [[NSMutableArray alloc] initWithArray:attributes];1282 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];1283 groupAttrs = [[NSArray alloc] initWithArray:tempArray];1284 [tempArray release];1285 }1286 if (inputImageAttrs == nil) {1287 tempArray = [[NSMutableArray alloc] initWithArray:buttonAttrs];1288 [tempArray addObject:NSAccessibilityURLAttribute];1289 inputImageAttrs = [[NSArray alloc] initWithArray:tempArray];1290 [tempArray release];1291 }1292 if (passwordFieldAttrs == nil) {1293 tempArray = [[NSMutableArray alloc] initWithArray:attributes];1294 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];1295 [tempArray addObject:NSAccessibilityRequiredAttribute];1296 [tempArray addObject:NSAccessibilityInvalidAttribute];1297 [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];1298 passwordFieldAttrs = [[NSArray alloc] initWithArray:tempArray];1299 [tempArray release];1300 }1301 if (tabListAttrs == nil) {1302 tempArray = [[NSMutableArray alloc] initWithArray:attributes];1303 [tempArray addObject:NSAccessibilityTabsAttribute];1304 [tempArray addObject:NSAccessibilityContentsAttribute];1305 tabListAttrs = [[NSArray alloc] initWithArray:tempArray];1306 [tempArray release];1307 }1308 if (outlineAttrs == nil) {1309 tempArray = [[NSMutableArray alloc] initWithArray:attributes];1310 [tempArray addObject:NSAccessibilitySelectedRowsAttribute];1311 [tempArray addObject:NSAccessibilityRowsAttribute];1312 [tempArray addObject:NSAccessibilityColumnsAttribute];1313 outlineAttrs = [[NSArray alloc] initWithArray:tempArray];1314 [tempArray release];1315 }1316 if (outlineRowAttrs == nil) {1317 tempArray = [[NSMutableArray alloc] initWithArray:tableRowAttrs];1318 [tempArray addObject:NSAccessibilityDisclosingAttribute];1319 [tempArray addObject:NSAccessibilityDisclosedByRowAttribute];1320 [tempArray addObject:NSAccessibilityDisclosureLevelAttribute];1321 [tempArray addObject:NSAccessibilityDisclosedRowsAttribute];1322 outlineRowAttrs = [[NSArray alloc] initWithArray:tempArray];1323 [tempArray release];1324 }1325 if (scrollViewAttrs == nil) {1326 tempArray = [[NSMutableArray alloc] initWithArray:attributes];1327 [tempArray addObject:NSAccessibilityContentsAttribute];1328 [tempArray addObject:NSAccessibilityHorizontalScrollBarAttribute];1329 [tempArray addObject:NSAccessibilityVerticalScrollBarAttribute];1330 scrollViewAttrs = [[NSArray alloc] initWithArray:tempArray];1331 [tempArray release];1332 }1333 1334 NSArray *objectAttributes = attributes;1335 1336 if (m_object->isPasswordField())1337 objectAttributes = passwordFieldAttrs;1338 1339 else if (m_object->isWebArea())1340 objectAttributes = webAreaAttrs;1341 1342 else if (m_object->isTextControl())1343 objectAttributes = textAttrs;1344 1345 else if (m_object->isAnchor() || m_object->isImage() || m_object->isLink())1346 objectAttributes = anchorAttrs;1347 1348 else if (m_object->isAccessibilityTable())1349 objectAttributes = tableAttrs;1350 else if (m_object->isTableColumn())1351 objectAttributes = tableColAttrs;1352 else if (m_object->isTableCell())1353 objectAttributes = tableCellAttrs;1354 else if (m_object->isTableRow()) {1355 // An ARIA table row can be collapsed and expanded, so it needs the extra attributes.1356 if (m_object->isARIATreeGridRow())1357 objectAttributes = outlineRowAttrs;1358 else1359 objectAttributes = tableRowAttrs;1360 }1361 1362 else if (m_object->isTree())1363 objectAttributes = outlineAttrs;1364 else if (m_object->isTreeItem())1365 objectAttributes = outlineRowAttrs;1366 1367 else if (m_object->isListBox())1368 objectAttributes = listBoxAttrs;1369 else if (m_object->isList())1370 objectAttributes = listAttrs;1371 1372 else if (m_object->isComboBox())1373 objectAttributes = comboBoxAttrs;1374 1375 else if (m_object->isProgressIndicator() || m_object->isSlider())1376 objectAttributes = rangeAttrs;1377 1378 // These are processed in order because an input image is a button, and a button is a control.1379 else if (m_object->isInputImage())1380 objectAttributes = inputImageAttrs;1381 else if (m_object->isButton())1382 objectAttributes = buttonAttrs;1383 else if (m_object->isControl())1384 objectAttributes = controlAttrs;1385 1386 else if (m_object->isGroup() || m_object->isListItem())1387 objectAttributes = groupAttrs;1388 else if (m_object->isTabList())1389 objectAttributes = tabListAttrs;1390 else if (m_object->isScrollView())1391 objectAttributes = scrollViewAttrs;1392 else if (m_object->isSpinButton())1393 objectAttributes = incrementorAttrs;1394 1395 else if (m_object->isMenu())1396 objectAttributes = menuAttrs;1397 else if (m_object->isMenuBar())1398 objectAttributes = menuBarAttrs;1399 else if (m_object->isMenuButton())1400 objectAttributes = menuButtonAttrs;1401 else if (m_object->isMenuItem())1402 objectAttributes = menuItemAttrs;1403 1404 NSArray *additionalAttributes = [self additionalAccessibilityAttributeNames];1405 if ([additionalAttributes count])1406 objectAttributes = [objectAttributes arrayByAddingObjectsFromArray:additionalAttributes];1407 1408 return objectAttributes;1409 }1410 1411 - (VisiblePositionRange)visiblePositionRangeForTextMarkerRange:(id)textMarkerRange1412 {1413 if (!textMarkerRange)1414 return VisiblePositionRange();1415 AXObjectCache* cache = m_object->axObjectCache();1416 return VisiblePositionRange(visiblePositionForStartOfTextMarkerRange(cache, textMarkerRange), visiblePositionForEndOfTextMarkerRange(cache, textMarkerRange));1417 }1418 1419 - (NSArray*)renderWidgetChildren1420 {1421 Widget* widget = m_object->widget();1422 if (!widget)1423 return nil;1424 return [(widget->platformWidget()) accessibilityAttributeValue: NSAccessibilityChildrenAttribute];1425 }1426 1427 - (id)remoteAccessibilityParentObject1428 {1429 if (!m_object)1430 return nil;1431 1432 Document* document = m_object->document();1433 if (!document)1434 return nil;1435 1436 Frame* frame = document->frame();1437 if (!frame)1438 return nil;1439 1440 return frame->loader()->client()->accessibilityRemoteObject();1441 }1442 1443 static void convertToVector(NSArray* array, AccessibilityObject::AccessibilityChildrenVector& vector)1444 {1445 unsigned length = [array count];1446 vector.reserveInitialCapacity(length);1447 for (unsigned i = 0; i < length; ++i) {1448 AccessibilityObject* obj = [[array objectAtIndex:i] accessibilityObject];1449 if (obj)1450 vector.append(obj);1451 }1452 }1453 1454 static NSMutableArray* convertToNSArray(const AccessibilityObject::AccessibilityChildrenVector& vector)1455 {1456 unsigned length = vector.size();1457 NSMutableArray* array = [NSMutableArray arrayWithCapacity: length];1458 for (unsigned i = 0; i < length; ++i) {1459 WebAccessibilityObjectWrapper* wrapper = vector[i]->wrapper();1460 ASSERT(wrapper);1461 if (wrapper) {1462 // we want to return the attachment view instead of the object representing the attachment.1463 // otherwise, we get palindrome errors in the AX hierarchy1464 if (vector[i]->isAttachment() && [wrapper attachmentView])1465 [array addObject:[wrapper attachmentView]];1466 else1467 [array addObject:wrapper];1468 }1469 }1470 return array;1471 }1472 1473 - (id)textMarkerRangeForSelection1474 {1475 VisibleSelection selection = m_object->selection();1476 if (selection.isNone())1477 return nil;1478 return [self textMarkerRangeFromVisiblePositions:selection.visibleStart() endPosition:selection.visibleEnd()];1479 }1480 1481 - (NSValue *)position1482 {1483 IntRect rect = pixelSnappedIntRect(m_object->elementRect());1484 NSPoint point;1485 1486 FrameView* frameView = m_object->documentFrameView();1487 1488 // WebKit1 code path... platformWidget() exists.1489 if (frameView && frameView->platformWidget()) {1490 1491 // The Cocoa accessibility API wants the lower-left corner.1492 point = NSMakePoint(rect.x(), rect.maxY());1493 1494 if (frameView) {1495 NSView* view = frameView->documentView();1496 point = [[view window] convertBaseToScreen:[view convertPoint: point toView:nil]];1497 }1498 } else {1499 1500 // Find the appropriate scroll view to use to convert the contents to the window.1501 ScrollView* scrollView = 0;1502 AccessibilityObject* parent = 0;1503 for (parent = m_object->parentObject(); parent; parent = parent->parentObject()) {1504 if (parent->isAccessibilityScrollView()) {1505 scrollView = toAccessibilityScrollView(parent)->scrollView();1506 break;1507 }1508 }1509 1510 if (scrollView)1511 rect = scrollView->contentsToRootView(rect);1512 1513 Page* page = m_object->page();1514 1515 // If we have an empty chrome client (like SVG) then we should use the page1516 // of the scroll view parent to help us get to the screen rect.1517 if (parent && page && page->chrome()->client()->isEmptyChromeClient())1518 page = parent->page();1519 1520 if (page)1521 point = page->chrome()->rootViewToScreen(rect).location();1522 else1523 point = rect.location();1524 }1525 1526 return [NSValue valueWithPoint:point];1527 }1528 1529 typedef HashMap<int, NSString*> AccessibilityRoleMap;1530 1531 static const AccessibilityRoleMap& createAccessibilityRoleMap()1532 {1533 struct RoleEntry {1534 AccessibilityRole value;1535 NSString* string;1536 };1537 1538 static const RoleEntry roles[] = {1539 { UnknownRole, NSAccessibilityUnknownRole },1540 { ButtonRole, NSAccessibilityButtonRole },1541 { RadioButtonRole, NSAccessibilityRadioButtonRole },1542 { CheckBoxRole, NSAccessibilityCheckBoxRole },1543 { SliderRole, NSAccessibilitySliderRole },1544 { TabGroupRole, NSAccessibilityTabGroupRole },1545 { TextFieldRole, NSAccessibilityTextFieldRole },1546 { StaticTextRole, NSAccessibilityStaticTextRole },1547 { TextAreaRole, NSAccessibilityTextAreaRole },1548 { ScrollAreaRole, NSAccessibilityScrollAreaRole },1549 { PopUpButtonRole, NSAccessibilityPopUpButtonRole },1550 { MenuButtonRole, NSAccessibilityMenuButtonRole },1551 { TableRole, NSAccessibilityTableRole },1552 { ApplicationRole, NSAccessibilityApplicationRole },1553 { GroupRole, NSAccessibilityGroupRole },1554 { RadioGroupRole, NSAccessibilityRadioGroupRole },1555 { ListRole, NSAccessibilityListRole },1556 { DirectoryRole, NSAccessibilityListRole },1557 { ScrollBarRole, NSAccessibilityScrollBarRole },1558 { ValueIndicatorRole, NSAccessibilityValueIndicatorRole },1559 { ImageRole, NSAccessibilityImageRole },1560 { MenuBarRole, NSAccessibilityMenuBarRole },1561 { MenuRole, NSAccessibilityMenuRole },1562 { MenuItemRole, NSAccessibilityMenuItemRole },1563 { ColumnRole, NSAccessibilityColumnRole },1564 { RowRole, NSAccessibilityRowRole },1565 { ToolbarRole, NSAccessibilityToolbarRole },1566 { BusyIndicatorRole, NSAccessibilityBusyIndicatorRole },1567 { ProgressIndicatorRole, NSAccessibilityProgressIndicatorRole },1568 { WindowRole, NSAccessibilityWindowRole },1569 { DrawerRole, NSAccessibilityDrawerRole },1570 { SystemWideRole, NSAccessibilitySystemWideRole },1571 { OutlineRole, NSAccessibilityOutlineRole },1572 { IncrementorRole, NSAccessibilityIncrementorRole },1573 { BrowserRole, NSAccessibilityBrowserRole },1574 { ComboBoxRole, NSAccessibilityComboBoxRole },1575 { SplitGroupRole, NSAccessibilitySplitGroupRole },1576 { SplitterRole, NSAccessibilitySplitterRole },1577 { ColorWellRole, NSAccessibilityColorWellRole },1578 { GrowAreaRole, NSAccessibilityGrowAreaRole },1579 { SheetRole, NSAccessibilitySheetRole },1580 { HelpTagRole, NSAccessibilityHelpTagRole },1581 { MatteRole, NSAccessibilityMatteRole },1582 { RulerRole, NSAccessibilityRulerRole },1583 { RulerMarkerRole, NSAccessibilityRulerMarkerRole },1584 { LinkRole, NSAccessibilityLinkRole },1585 { DisclosureTriangleRole, NSAccessibilityDisclosureTriangleRole },1586 { GridRole, NSAccessibilityGridRole },1587 { WebCoreLinkRole, NSAccessibilityLinkRole },1588 { ImageMapLinkRole, NSAccessibilityLinkRole },1589 { ImageMapRole, @"AXImageMap" },1590 { ListMarkerRole, @"AXListMarker" },1591 { WebAreaRole, @"AXWebArea" },1592 { SeamlessWebAreaRole, NSAccessibilityGroupRole },1593 { HeadingRole, @"AXHeading" },1594 { ListBoxRole, NSAccessibilityListRole },1595 { ListBoxOptionRole, NSAccessibilityStaticTextRole },1596 { CellRole, NSAccessibilityCellRole },1597 { TableHeaderContainerRole, NSAccessibilityGroupRole },1598 { RowHeaderRole, NSAccessibilityGroupRole },1599 { DefinitionRole, NSAccessibilityGroupRole },1600 { DescriptionListDetailRole, NSAccessibilityGroupRole },1601 { DescriptionListTermRole, NSAccessibilityGroupRole },1602 { SliderThumbRole, NSAccessibilityValueIndicatorRole },1603 { LandmarkApplicationRole, NSAccessibilityGroupRole },1604 { LandmarkBannerRole, NSAccessibilityGroupRole },1605 { LandmarkComplementaryRole, NSAccessibilityGroupRole },1606 { LandmarkContentInfoRole, NSAccessibilityGroupRole },1607 { LandmarkMainRole, NSAccessibilityGroupRole },1608 { LandmarkNavigationRole, NSAccessibilityGroupRole },1609 { LandmarkSearchRole, NSAccessibilityGroupRole },1610 { ApplicationAlertRole, NSAccessibilityGroupRole },1611 { ApplicationAlertDialogRole, NSAccessibilityGroupRole },1612 { ApplicationDialogRole, NSAccessibilityGroupRole },1613 { ApplicationLogRole, NSAccessibilityGroupRole },1614 { ApplicationMarqueeRole, NSAccessibilityGroupRole },1615 { ApplicationStatusRole, NSAccessibilityGroupRole },1616 { ApplicationTimerRole, NSAccessibilityGroupRole },1617 { DocumentRole, NSAccessibilityGroupRole },1618 { DocumentArticleRole, NSAccessibilityGroupRole },1619 { DocumentMathRole, NSAccessibilityGroupRole },1620 { DocumentNoteRole, NSAccessibilityGroupRole },1621 { DocumentRegionRole, NSAccessibilityGroupRole },1622 { UserInterfaceTooltipRole, NSAccessibilityGroupRole },1623 { TabRole, NSAccessibilityRadioButtonRole },1624 { TabListRole, NSAccessibilityTabGroupRole },1625 { TabPanelRole, NSAccessibilityGroupRole },1626 { TreeRole, NSAccessibilityOutlineRole },1627 { TreeItemRole, NSAccessibilityRowRole },1628 { ListItemRole, NSAccessibilityGroupRole },1629 { ParagraphRole, NSAccessibilityGroupRole },1630 { LabelRole, NSAccessibilityGroupRole },1631 { DivRole, NSAccessibilityGroupRole },1632 { FormRole, NSAccessibilityGroupRole },1633 { SpinButtonRole, NSAccessibilityIncrementorRole },1634 { FooterRole, NSAccessibilityGroupRole },1635 { ToggleButtonRole, NSAccessibilityButtonRole },1636 { CanvasRole, NSAccessibilityImageRole },1637 { SVGRootRole, NSAccessibilityGroupRole },1638 { LegendRole, NSAccessibilityGroupRole },1639 { MathElementRole, NSAccessibilityGroupRole }1640 };1641 AccessibilityRoleMap& roleMap = *new AccessibilityRoleMap;1642 1643 const unsigned numRoles = sizeof(roles) / sizeof(roles[0]);1644 for (unsigned i = 0; i < numRoles; ++i)1645 roleMap.set(roles[i].value, roles[i].string);1646 return roleMap;1647 }1648 1649 static NSString* roleValueToNSString(AccessibilityRole value)1650 {1651 ASSERT(value);1652 static const AccessibilityRoleMap& roleMap = createAccessibilityRoleMap();1653 return roleMap.get(value);1654 }1655 1656 - (NSString*)role1657 {1658 if (m_object->isAttachment())1659 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleAttribute];1660 AccessibilityRole role = m_object->roleValue();1661 if (role == CanvasRole && m_object->canvasHasFallbackContent())1662 role = GroupRole;1663 NSString* string = roleValueToNSString(role);1664 if (string != nil)1665 return string;1666 return NSAccessibilityUnknownRole;1667 }1668 1669 - (NSString*)subrole1670 {1671 if (m_object->isPasswordField())1672 return NSAccessibilitySecureTextFieldSubrole;1673 if (m_object->isSearchField())1674 return NSAccessibilitySearchFieldSubrole;1675 1676 if (m_object->isAttachment()) {1677 NSView* attachView = [self attachmentView];1678 if ([[attachView accessibilityAttributeNames] containsObject:NSAccessibilitySubroleAttribute]) {1679 return [attachView accessibilityAttributeValue:NSAccessibilitySubroleAttribute];1680 }1681 }1682 1683 if (m_object->isSpinButtonPart()) {1684 if (toAccessibilitySpinButtonPart(m_object)->isIncrementor())1685 return NSAccessibilityIncrementArrowSubrole;1686 1687 return NSAccessibilityDecrementArrowSubrole;1688 }1689 1690 if (m_object->isFileUploadButton())1691 return @"AXFileUploadButton";1692 1693 if (m_object->isTreeItem())1694 return NSAccessibilityOutlineRowSubrole;1695 1696 if (m_object->isList()) {1697 AccessibilityList* listObject = static_cast<AccessibilityList*>(m_object);1698 if (listObject->isUnorderedList() || listObject->isOrderedList())1699 return NSAccessibilityContentListSubrole;1700 if (listObject->isDescriptionList())1701 return NSAccessibilityDescriptionListSubrole;1702 }1703 1704 // ARIA content subroles.1705 switch (m_object->roleValue()) {1706 case LandmarkApplicationRole:1707 return @"AXLandmarkApplication";1708 case LandmarkBannerRole:1709 return @"AXLandmarkBanner";1710 case LandmarkComplementaryRole:1711 return @"AXLandmarkComplementary";1712 // Footer roles should appear as content info types.1713 case FooterRole:1714 case LandmarkContentInfoRole:1715 return @"AXLandmarkContentInfo";1716 case LandmarkMainRole:1717 return @"AXLandmarkMain";1718 case LandmarkNavigationRole:1719 return @"AXLandmarkNavigation";1720 case LandmarkSearchRole:1721 return @"AXLandmarkSearch";1722 case ApplicationAlertRole:1723 return @"AXApplicationAlert";1724 case ApplicationAlertDialogRole:1725 return @"AXApplicationAlertDialog";1726 case ApplicationDialogRole:1727 return @"AXApplicationDialog";1728 case ApplicationLogRole:1729 return @"AXApplicationLog";1730 case ApplicationMarqueeRole:1731 return @"AXApplicationMarquee";1732 case ApplicationStatusRole:1733 return @"AXApplicationStatus";1734 case ApplicationTimerRole:1735 return @"AXApplicationTimer";1736 case DocumentRole:1737 return @"AXDocument";1738 case DocumentArticleRole:1739 return @"AXDocumentArticle";1740 case DocumentMathRole:1741 return @"AXDocumentMath";1742 case DocumentNoteRole:1743 return @"AXDocumentNote";1744 case DocumentRegionRole:1745 return @"AXDocumentRegion";1746 case UserInterfaceTooltipRole:1747 return @"AXUserInterfaceTooltip";1748 case TabPanelRole:1749 return @"AXTabPanel";1750 case DefinitionRole:1751 return @"AXDefinition";1752 case DescriptionListTermRole:1753 return @"AXTerm";1754 case DescriptionListDetailRole:1755 return @"AXDescription";1756 // Default doesn't return anything, so roles defined below can be chosen.1757 default:1758 break;1759 }1760 1761 if (m_object->roleValue() == MathElementRole) {1762 if (m_object->isMathFraction())1763 return @"AXMathFraction";1764 if (m_object->isMathFenced())1765 return @"AXMathFenced";1766 if (m_object->isMathSubscriptSuperscript())1767 return @"AXMathSubscriptSuperscript";1768 if (m_object->isMathRow())1769 return @"AXMathRow";1770 if (m_object->isMathUnderOver())1771 return @"AXMathUnderOver";1772 if (m_object->isMathSquareRoot())1773 return @"AXMathSquareRoot";1774 if (m_object->isMathRoot())1775 return @"AXMathRoot";1776 if (m_object->isMathText())1777 return @"AXMathText";1778 if (m_object->isMathNumber())1779 return @"AXMathNumber";1780 if (m_object->isMathIdentifier())1781 return @"AXMathIdentifier";1782 if (m_object->isMathTable())1783 return @"AXMathTable";1784 if (m_object->isMathTableRow())1785 return @"AXMathTableRow";1786 if (m_object->isMathTableCell())1787 return @"AXMathTableCell";1788 if (m_object->isMathFenceOperator())1789 return @"AXMathFenceOperator";1790 if (m_object->isMathSeparatorOperator())1791 return @"AXMathSeparatorOperator";1792 if (m_object->isMathOperator())1793 return @"AXMathOperator";1794 }1795 1796 if (m_object->isMediaTimeline())1797 return NSAccessibilityTimelineSubrole;1798 1799 return nil;1800 }1801 1802 - (NSString*)roleDescription1803 {1804 if (!m_object)1805 return nil;1806 1807 // attachments have the AXImage role, but a different subrole1808 if (m_object->isAttachment())1809 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute];1810 1811 NSString* axRole = [self role];1812 1813 if ([axRole isEqualToString:NSAccessibilityGroupRole]) {1814 switch (m_object->roleValue()) {1815 default:1816 return NSAccessibilityRoleDescription(NSAccessibilityGroupRole, [self subrole]);1817 case LandmarkApplicationRole:1818 return AXARIAContentGroupText(@"ARIALandmarkApplication");1819 case LandmarkBannerRole:1820 return AXARIAContentGroupText(@"ARIALandmarkBanner");1821 case LandmarkComplementaryRole:1822 return AXARIAContentGroupText(@"ARIALandmarkComplementary");1823 case LandmarkContentInfoRole:1824 return AXARIAContentGroupText(@"ARIALandmarkContentInfo");1825 case LandmarkMainRole:1826 return AXARIAContentGroupText(@"ARIALandmarkMain");1827 case LandmarkNavigationRole:1828 return AXARIAContentGroupText(@"ARIALandmarkNavigation");1829 case LandmarkSearchRole:1830 return AXARIAContentGroupText(@"ARIALandmarkSearch");1831 case ApplicationAlertRole:1832 return AXARIAContentGroupText(@"ARIAApplicationAlert");1833 case ApplicationAlertDialogRole:1834 return AXARIAContentGroupText(@"ARIAApplicationAlertDialog");1835 case ApplicationDialogRole:1836 return AXARIAContentGroupText(@"ARIAApplicationDialog");1837 case ApplicationLogRole:1838 return AXARIAContentGroupText(@"ARIAApplicationLog");1839 case ApplicationMarqueeRole:1840 return AXARIAContentGroupText(@"ARIAApplicationMarquee");1841 case ApplicationStatusRole:1842 return AXARIAContentGroupText(@"ARIAApplicationStatus");1843 case ApplicationTimerRole:1844 return AXARIAContentGroupText(@"ARIAApplicationTimer");1845 case DocumentRole:1846 return AXARIAContentGroupText(@"ARIADocument");1847 case DocumentArticleRole:1848 return AXARIAContentGroupText(@"ARIADocumentArticle");1849 case DocumentMathRole:1850 return AXARIAContentGroupText(@"ARIADocumentMath");1851 case DocumentNoteRole:1852 return AXARIAContentGroupText(@"ARIADocumentNote");1853 case DocumentRegionRole:1854 return AXARIAContentGroupText(@"ARIADocumentRegion");1855 case UserInterfaceTooltipRole:1856 return AXARIAContentGroupText(@"ARIAUserInterfaceTooltip");1857 case TabPanelRole:1858 return AXARIAContentGroupText(@"ARIATabPanel");1859 case DefinitionRole:1860 return AXDefinitionText();1861 case DescriptionListTermRole:1862 return AXDescriptionListTermText();1863 case DescriptionListDetailRole:1864 return AXDescriptionListDetailText();1865 case FooterRole:1866 return AXFooterRoleDescriptionText();1867 }1868 }1869 1870 if ([axRole isEqualToString:@"AXWebArea"])1871 return AXWebAreaText();1872 1873 if ([axRole isEqualToString:@"AXLink"])1874 return AXLinkText();1875 1876 if ([axRole isEqualToString:@"AXListMarker"])1877 return AXListMarkerText();1878 1879 if ([axRole isEqualToString:@"AXImageMap"])1880 return AXImageMapText();1881 1882 if ([axRole isEqualToString:@"AXHeading"])1883 return AXHeadingText();1884 1885 if (m_object->isFileUploadButton())1886 return AXFileUploadButtonText();1887 1888 // AppKit also returns AXTab for the role description for a tab item.1889 if (m_object->isTabItem())1890 return NSAccessibilityRoleDescription(@"AXTab", nil);1891 1892 // We should try the system default role description for all other roles.1893 // If we get the same string back, then as a last resort, return unknown.1894 NSString* defaultRoleDescription = NSAccessibilityRoleDescription(axRole, [self subrole]);1895 1896 // On earlier Mac versions (Lion), using a non-standard subrole would result in a role description1897 // being returned that looked like AXRole:AXSubrole. To make all platforms have the same role descriptions1898 // we should fallback on a role description ignoring the subrole in these cases.1899 if ([defaultRoleDescription isEqualToString:[NSString stringWithFormat:@"%@:%@", axRole, [self subrole]]])1900 defaultRoleDescription = NSAccessibilityRoleDescription(axRole, nil);1901 1902 if (![defaultRoleDescription isEqualToString:axRole])1903 return defaultRoleDescription;1904 1905 return NSAccessibilityRoleDescription(NSAccessibilityUnknownRole, nil);1906 }1907 1908 - (id)scrollViewParent1909 {1910 if (!m_object || !m_object->isAccessibilityScrollView())1911 return nil;1912 1913 // If this scroll view provides it's parent object (because it's a sub-frame), then1914 // we should not find the remoteAccessibilityParent.1915 if (m_object->parentObject())1916 return nil;1917 1918 AccessibilityScrollView* scrollView = toAccessibilityScrollView(m_object);1919 ScrollView* scroll = scrollView->scrollView();1920 if (!scroll)1921 return nil;1922 1923 if (scroll->platformWidget())1924 return NSAccessibilityUnignoredAncestor(scroll->platformWidget());1925 1926 return [self remoteAccessibilityParentObject];1927 120 } 1928 121 … … 2034 227 } 2035 228 2036 // FIXME: split up this function in a better way.2037 // suggestions: Use a hash table that maps attribute names to function calls,2038 // or maybe pointers to member functions2039 - (id)accessibilityAttributeValue:(NSString*)attributeName2040 {2041 if (![self updateObjectBackingStore])2042 return nil;2043 2044 if ([attributeName isEqualToString: NSAccessibilityRoleAttribute])2045 return [self role];2046 2047 if ([attributeName isEqualToString: NSAccessibilitySubroleAttribute])2048 return [self subrole];2049 2050 if ([attributeName isEqualToString: NSAccessibilityRoleDescriptionAttribute])2051 return [self roleDescription];2052 2053 if ([attributeName isEqualToString: NSAccessibilityParentAttribute]) {2054 2055 // This will return the parent of the AXWebArea, if this is a web area.2056 id scrollViewParent = [self scrollViewParent];2057 if (scrollViewParent)2058 return scrollViewParent;2059 2060 // Tree item (changed to AXRows) can only report the tree (AXOutline) as its parent.2061 if (m_object->isTreeItem()) {2062 AccessibilityObject* parent = m_object->parentObjectUnignored();2063 while (parent) {2064 if (parent->isTree())2065 return parent->wrapper();2066 parent = parent->parentObjectUnignored();2067 }2068 }2069 2070 AccessibilityObject* parent = m_object->parentObjectUnignored();2071 if (!parent)2072 return nil;2073 2074 // In WebKit1, the scroll view is provided by the system (the attachment view), so the parent2075 // should be reported directly as such.2076 if (m_object->isWebArea() && parent->isAttachment())2077 return [parent->wrapper() attachmentView];2078 2079 return parent->wrapper();2080 }2081 2082 if ([attributeName isEqualToString: NSAccessibilityChildrenAttribute]) {2083 if (m_object->children().isEmpty()) {2084 NSArray* children = [self renderWidgetChildren];2085 if (children != nil)2086 return children;2087 }2088 2089 // The tree's (AXOutline) children are supposed to be its rows and columns.2090 // The ARIA spec doesn't have columns, so we just need rows.2091 if (m_object->isTree())2092 return [self accessibilityAttributeValue:NSAccessibilityRowsAttribute];2093 2094 // A tree item should only expose its content as its children (not its rows)2095 if (m_object->isTreeItem()) {2096 AccessibilityObject::AccessibilityChildrenVector contentCopy;2097 m_object->ariaTreeItemContent(contentCopy);2098 return convertToNSArray(contentCopy);2099 }2100 2101 return convertToNSArray(m_object->children());2102 }2103 2104 if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {2105 if (m_object->isListBox()) {2106 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;2107 m_object->selectedChildren(selectedChildrenCopy);2108 return convertToNSArray(selectedChildrenCopy);2109 }2110 return nil;2111 }2112 2113 if ([attributeName isEqualToString: NSAccessibilityVisibleChildrenAttribute]) {2114 if (m_object->isListBox()) {2115 AccessibilityObject::AccessibilityChildrenVector visibleChildrenCopy;2116 m_object->visibleChildren(visibleChildrenCopy);2117 return convertToNSArray(visibleChildrenCopy);2118 }2119 else if (m_object->isList())2120 return [self accessibilityAttributeValue:NSAccessibilityChildrenAttribute];2121 2122 return nil;2123 }2124 2125 2126 if (m_object->isWebArea()) {2127 if ([attributeName isEqualToString:@"AXLinkUIElements"]) {2128 AccessibilityObject::AccessibilityChildrenVector links;2129 static_cast<AccessibilityRenderObject*>(m_object)->getDocumentLinks(links);2130 return convertToNSArray(links);2131 }2132 if ([attributeName isEqualToString:@"AXLoaded"])2133 return [NSNumber numberWithBool:m_object->isLoaded()];2134 if ([attributeName isEqualToString:@"AXLayoutCount"])2135 return [NSNumber numberWithInt:m_object->layoutCount()];2136 if ([attributeName isEqualToString:NSAccessibilityLoadingProgressAttribute])2137 return [NSNumber numberWithDouble:m_object->estimatedLoadingProgress()];2138 }2139 2140 if (m_object->isTextControl()) {2141 if ([attributeName isEqualToString: NSAccessibilityNumberOfCharactersAttribute]) {2142 int length = m_object->textLength();2143 if (length < 0)2144 return nil;2145 return [NSNumber numberWithUnsignedInt:length];2146 }2147 if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {2148 String selectedText = m_object->selectedText();2149 if (selectedText.isNull())2150 return nil;2151 return (NSString*)selectedText;2152 }2153 if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {2154 PlainTextRange textRange = m_object->selectedTextRange();2155 if (textRange.isNull())2156 return [NSValue valueWithRange:NSMakeRange(0, 0)];2157 return [NSValue valueWithRange:NSMakeRange(textRange.start, textRange.length)];2158 }2159 // TODO: Get actual visible range. <rdar://problem/4712101>2160 if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])2161 return m_object->isPasswordField() ? nil : [NSValue valueWithRange: NSMakeRange(0, m_object->textLength())];2162 if ([attributeName isEqualToString: NSAccessibilityInsertionPointLineNumberAttribute]) {2163 // if selectionEnd > 0, then there is selected text and this question should not be answered2164 if (m_object->isPasswordField() || m_object->selectionEnd() > 0)2165 return nil;2166 2167 AccessibilityObject* focusedObject = m_object->focusedUIElement();2168 if (focusedObject != m_object)2169 return nil;2170 2171 VisiblePosition focusedPosition = focusedObject->visiblePositionForIndex(focusedObject->selectionStart(), true);2172 int lineNumber = m_object->lineForPosition(focusedPosition);2173 if (lineNumber < 0)2174 return nil;2175 2176 return [NSNumber numberWithInt:lineNumber];2177 }2178 }2179 2180 if ([attributeName isEqualToString: NSAccessibilityURLAttribute]) {2181 KURL url = m_object->url();2182 if (url.isNull())2183 return nil;2184 return (NSURL*)url;2185 }2186 2187 if (m_object->isSpinButton()) {2188 if ([attributeName isEqualToString:NSAccessibilityIncrementButtonAttribute])2189 return toAccessibilitySpinButton(m_object)->incrementButton()->wrapper();2190 if ([attributeName isEqualToString:NSAccessibilityDecrementButtonAttribute])2191 return toAccessibilitySpinButton(m_object)->decrementButton()->wrapper();2192 }2193 2194 if ([attributeName isEqualToString: @"AXVisited"])2195 return [NSNumber numberWithBool: m_object->isVisited()];2196 2197 if ([attributeName isEqualToString: NSAccessibilityTitleAttribute]) {2198 if (m_object->isAttachment()) {2199 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityTitleAttribute])2200 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityTitleAttribute];2201 }2202 2203 return [self accessibilityTitle];2204 }2205 2206 if ([attributeName isEqualToString: NSAccessibilityDescriptionAttribute]) {2207 if (m_object->isAttachment()) {2208 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityDescriptionAttribute])2209 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityDescriptionAttribute];2210 }2211 return [self accessibilityDescription];2212 }2213 2214 if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {2215 if (m_object->isAttachment()) {2216 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityValueAttribute])2217 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityValueAttribute];2218 }2219 if (m_object->supportsRangeValue())2220 return [NSNumber numberWithFloat:m_object->valueForRange()];2221 if (m_object->roleValue() == SliderThumbRole)2222 return [NSNumber numberWithFloat:m_object->parentObject()->valueForRange()];2223 if (m_object->isHeading())2224 return [NSNumber numberWithInt:m_object->headingLevel()];2225 2226 if (m_object->isCheckboxOrRadio()) {2227 switch (m_object->checkboxOrRadioValue()) {2228 case ButtonStateOff:2229 return [NSNumber numberWithInt:0];2230 case ButtonStateOn:2231 return [NSNumber numberWithInt:1];2232 case ButtonStateMixed:2233 return [NSNumber numberWithInt:2];2234 }2235 }2236 2237 // radio groups return the selected radio button as the AXValue2238 if (m_object->isRadioGroup()) {2239 AccessibilityObject* radioButton = m_object->selectedRadioButton();2240 if (!radioButton)2241 return nil;2242 return radioButton->wrapper();2243 }2244 2245 if (m_object->isTabList()) {2246 AccessibilityObject* tabItem = m_object->selectedTabItem();2247 if (!tabItem)2248 return nil;2249 return tabItem->wrapper();2250 }2251 2252 if (m_object->isTabItem())2253 return [NSNumber numberWithInt:m_object->isSelected()];2254 2255 if (m_object->isColorWell()) {2256 int r, g, b;2257 m_object->colorValue(r, g, b);2258 return [NSString stringWithFormat:@"rgb %7.5f %7.5f %7.5f 1", r / 255., g / 255., b / 255.];2259 }2260 2261 return m_object->stringValue();2262 }2263 2264 if ([attributeName isEqualToString: NSAccessibilityMinValueAttribute])2265 return [NSNumber numberWithFloat:m_object->minValueForRange()];2266 2267 if ([attributeName isEqualToString: NSAccessibilityMaxValueAttribute])2268 return [NSNumber numberWithFloat:m_object->maxValueForRange()];2269 2270 if ([attributeName isEqualToString: NSAccessibilityHelpAttribute])2271 return [self accessibilityHelpText];2272 2273 if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])2274 return [NSNumber numberWithBool: m_object->isFocused()];2275 2276 if ([attributeName isEqualToString: NSAccessibilityEnabledAttribute])2277 return [NSNumber numberWithBool: m_object->isEnabled()];2278 2279 if ([attributeName isEqualToString: NSAccessibilitySizeAttribute]) {2280 IntSize s = m_object->pixelSnappedSize();2281 return [NSValue valueWithSize: NSMakeSize(s.width(), s.height())];2282 }2283 2284 if ([attributeName isEqualToString: NSAccessibilityPositionAttribute])2285 return [self position];2286 2287 if ([attributeName isEqualToString: NSAccessibilityWindowAttribute] ||2288 [attributeName isEqualToString: NSAccessibilityTopLevelUIElementAttribute]) {2289 2290 id remoteParent = [self remoteAccessibilityParentObject];2291 if (remoteParent)2292 return [remoteParent accessibilityAttributeValue:attributeName];2293 2294 FrameView* fv = m_object->documentFrameView();2295 if (fv)2296 return [fv->platformWidget() window];2297 return nil;2298 }2299 2300 if ([attributeName isEqualToString:NSAccessibilityAccessKeyAttribute]) {2301 AtomicString accessKey = m_object->accessKey();2302 if (accessKey.isNull())2303 return nil;2304 return accessKey;2305 }2306 2307 if ([attributeName isEqualToString:NSAccessibilityTabsAttribute]) {2308 if (m_object->isTabList()) {2309 AccessibilityObject::AccessibilityChildrenVector tabsChildren;2310 m_object->tabChildren(tabsChildren);2311 return convertToNSArray(tabsChildren);2312 }2313 }2314 2315 if ([attributeName isEqualToString:NSAccessibilityContentsAttribute]) {2316 // The contents of a tab list are all the children except the tabs.2317 if (m_object->isTabList()) {2318 AccessibilityObject::AccessibilityChildrenVector children = m_object->children();2319 AccessibilityObject::AccessibilityChildrenVector tabsChildren;2320 m_object->tabChildren(tabsChildren);2321 2322 AccessibilityObject::AccessibilityChildrenVector contents;2323 unsigned childrenSize = children.size();2324 for (unsigned k = 0; k < childrenSize; ++k) {2325 if (tabsChildren.find(children[k]) == WTF::notFound)2326 contents.append(children[k]);2327 }2328 return convertToNSArray(contents);2329 } else if (m_object->isScrollView()) {2330 AccessibilityObject::AccessibilityChildrenVector children = m_object->children();2331 2332 // A scrollView's contents are everything except the scroll bars.2333 AccessibilityObject::AccessibilityChildrenVector contents;2334 unsigned childrenSize = children.size();2335 for (unsigned k = 0; k < childrenSize; ++k) {2336 if (!children[k]->isScrollbar())2337 contents.append(children[k]);2338 }2339 return convertToNSArray(contents);2340 }2341 }2342 2343 if (m_object->isAccessibilityTable()) {2344 // TODO: distinguish between visible and non-visible rows2345 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] ||2346 [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {2347 return convertToNSArray(static_cast<AccessibilityTable*>(m_object)->rows());2348 }2349 // TODO: distinguish between visible and non-visible columns2350 if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute] ||2351 [attributeName isEqualToString:NSAccessibilityVisibleColumnsAttribute]) {2352 return convertToNSArray(static_cast<AccessibilityTable*>(m_object)->columns());2353 }2354 2355 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {2356 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;2357 m_object->selectedChildren(selectedChildrenCopy);2358 return convertToNSArray(selectedChildrenCopy);2359 }2360 2361 // HTML tables don't support these2362 if ([attributeName isEqualToString:NSAccessibilitySelectedColumnsAttribute] ||2363 [attributeName isEqualToString:NSAccessibilitySelectedCellsAttribute])2364 return nil;2365 2366 if ([attributeName isEqualToString:(NSString *)kAXColumnHeaderUIElementsAttribute]) {2367 AccessibilityObject::AccessibilityChildrenVector columnHeaders;2368 static_cast<AccessibilityTable*>(m_object)->columnHeaders(columnHeaders);2369 return convertToNSArray(columnHeaders);2370 }2371 2372 if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {2373 AccessibilityObject* headerContainer = static_cast<AccessibilityTable*>(m_object)->headerContainer();2374 if (headerContainer)2375 return headerContainer->wrapper();2376 return nil;2377 }2378 2379 if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {2380 AccessibilityObject::AccessibilityChildrenVector rowHeaders;2381 static_cast<AccessibilityTable*>(m_object)->rowHeaders(rowHeaders);2382 return convertToNSArray(rowHeaders);2383 }2384 2385 if ([attributeName isEqualToString:NSAccessibilityVisibleCellsAttribute]) {2386 AccessibilityObject::AccessibilityChildrenVector cells;2387 static_cast<AccessibilityTable*>(m_object)->cells(cells);2388 return convertToNSArray(cells);2389 }2390 }2391 2392 if (m_object->isTableColumn()) {2393 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])2394 return [NSNumber numberWithInt:static_cast<AccessibilityTableColumn*>(m_object)->columnIndex()];2395 2396 // rows attribute for a column is the list of all the elements in that column at each row2397 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] ||2398 [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {2399 return convertToNSArray(static_cast<AccessibilityTableColumn*>(m_object)->children());2400 }2401 if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {2402 AccessibilityObject* header = static_cast<AccessibilityTableColumn*>(m_object)->headerObject();2403 if (!header)2404 return nil;2405 return header->wrapper();2406 }2407 }2408 2409 if (m_object->isTableCell()) {2410 if ([attributeName isEqualToString:NSAccessibilityRowIndexRangeAttribute]) {2411 pair<int, int> rowRange;2412 static_cast<AccessibilityTableCell*>(m_object)->rowIndexRange(rowRange);2413 return [NSValue valueWithRange:NSMakeRange(rowRange.first, rowRange.second)];2414 }2415 if ([attributeName isEqualToString:NSAccessibilityColumnIndexRangeAttribute]) {2416 pair<int, int> columnRange;2417 static_cast<AccessibilityTableCell*>(m_object)->columnIndexRange(columnRange);2418 return [NSValue valueWithRange:NSMakeRange(columnRange.first, columnRange.second)];2419 }2420 }2421 2422 if (m_object->isTree()) {2423 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {2424 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;2425 m_object->selectedChildren(selectedChildrenCopy);2426 return convertToNSArray(selectedChildrenCopy);2427 }2428 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute]) {2429 AccessibilityObject::AccessibilityChildrenVector rowsCopy;2430 m_object->ariaTreeRows(rowsCopy);2431 return convertToNSArray(rowsCopy);2432 }2433 2434 // TreeRoles do not support columns, but Mac AX expects to be able to ask about columns at the least.2435 if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute])2436 return [NSArray array];2437 }2438 2439 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute]) {2440 if (m_object->isTreeItem()) {2441 AccessibilityObject* parent = m_object->parentObject();2442 for (; parent && !parent->isTree(); parent = parent->parentObject())2443 { }2444 2445 if (!parent)2446 return nil;2447 2448 // Find the index of this item by iterating the parents.2449 AccessibilityObject::AccessibilityChildrenVector rowsCopy;2450 parent->ariaTreeRows(rowsCopy);2451 size_t count = rowsCopy.size();2452 for (size_t k = 0; k < count; ++k)2453 if (rowsCopy[k]->wrapper() == self)2454 return [NSNumber numberWithUnsignedInt:k];2455 2456 return nil;2457 }2458 if (m_object->isTableRow()) {2459 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])2460 return [NSNumber numberWithInt:static_cast<AccessibilityTableRow*>(m_object)->rowIndex()];2461 }2462 }2463 2464 // The rows that are considered inside this row.2465 if ([attributeName isEqualToString:NSAccessibilityDisclosedRowsAttribute]) {2466 if (m_object->isTreeItem()) {2467 AccessibilityObject::AccessibilityChildrenVector rowsCopy;2468 m_object->ariaTreeItemDisclosedRows(rowsCopy);2469 return convertToNSArray(rowsCopy);2470 } else if (m_object->isARIATreeGridRow()) {2471 AccessibilityObject::AccessibilityChildrenVector rowsCopy;2472 static_cast<AccessibilityARIAGridRow*>(m_object)->disclosedRows(rowsCopy);2473 return convertToNSArray(rowsCopy);2474 }2475 }2476 2477 // The row that contains this row. It should be the same as the first parent that is a treeitem.2478 if ([attributeName isEqualToString:NSAccessibilityDisclosedByRowAttribute]) {2479 if (m_object->isTreeItem()) {2480 AccessibilityObject* parent = m_object->parentObject();2481 while (parent) {2482 if (parent->isTreeItem())2483 return parent->wrapper();2484 // If the parent is the tree itself, then this value == nil.2485 if (parent->isTree())2486 return nil;2487 parent = parent->parentObject();2488 }2489 return nil;2490 } else if (m_object->isARIATreeGridRow()) {2491 AccessibilityObject* row = static_cast<AccessibilityARIAGridRow*>(m_object)->disclosedByRow();2492 if (!row)2493 return nil;2494 return row->wrapper();2495 }2496 }2497 2498 if ([attributeName isEqualToString:NSAccessibilityDisclosureLevelAttribute]) {2499 // Convert from 1-based level (from aria-level spec) to 0-based level (Mac)2500 int level = m_object->hierarchicalLevel();2501 if (level > 0)2502 level -= 1;2503 return [NSNumber numberWithInt:level];2504 }2505 if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])2506 return [NSNumber numberWithBool:m_object->isExpanded()];2507 2508 if ((m_object->isListBox() || m_object->isList()) && [attributeName isEqualToString:NSAccessibilityOrientationAttribute])2509 return NSAccessibilityVerticalOrientationValue;2510 2511 if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])2512 return [self textMarkerRangeForSelection];2513 2514 if (m_object->renderer()) {2515 if ([attributeName isEqualToString: @"AXStartTextMarker"])2516 return [self textMarkerForVisiblePosition:startOfDocument(m_object->renderer()->document())];2517 if ([attributeName isEqualToString: @"AXEndTextMarker"])2518 return [self textMarkerForVisiblePosition:endOfDocument(m_object->renderer()->document())];2519 }2520 2521 if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute])2522 return [NSNumber numberWithInt:m_object->blockquoteLevel()];2523 if ([attributeName isEqualToString:@"AXTableLevel"])2524 return [NSNumber numberWithInt:m_object->tableLevel()];2525 2526 if ([attributeName isEqualToString: NSAccessibilityLinkedUIElementsAttribute]) {2527 AccessibilityObject::AccessibilityChildrenVector linkedUIElements;2528 m_object->linkedUIElements(linkedUIElements);2529 if (linkedUIElements.size() == 0)2530 return nil;2531 return convertToNSArray(linkedUIElements);2532 }2533 2534 if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])2535 return [NSNumber numberWithBool:m_object->isSelected()];2536 2537 if ([attributeName isEqualToString: NSAccessibilityServesAsTitleForUIElementsAttribute] && m_object->isMenuButton()) {2538 AccessibilityObject* uiElement = static_cast<AccessibilityRenderObject*>(m_object)->menuForMenuButton();2539 if (uiElement)2540 return [NSArray arrayWithObject:uiElement->wrapper()];2541 }2542 2543 if ([attributeName isEqualToString:NSAccessibilityTitleUIElementAttribute]) {2544 if (!m_object->exposesTitleUIElement())2545 return nil;2546 2547 AccessibilityObject* obj = m_object->titleUIElement();2548 if (obj)2549 return obj->wrapper();2550 return nil;2551 }2552 2553 if ([attributeName isEqualToString:NSAccessibilityValueDescriptionAttribute])2554 return m_object->valueDescription();2555 2556 if ([attributeName isEqualToString:NSAccessibilityOrientationAttribute]) {2557 AccessibilityOrientation elementOrientation = m_object->orientation();2558 if (elementOrientation == AccessibilityOrientationVertical)2559 return NSAccessibilityVerticalOrientationValue;2560 if (elementOrientation == AccessibilityOrientationHorizontal)2561 return NSAccessibilityHorizontalOrientationValue;2562 return nil;2563 }2564 2565 if ([attributeName isEqualToString:NSAccessibilityHorizontalScrollBarAttribute]) {2566 AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationHorizontal);2567 if (scrollBar)2568 return scrollBar->wrapper();2569 return nil;2570 }2571 if ([attributeName isEqualToString:NSAccessibilityVerticalScrollBarAttribute]) {2572 AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationVertical);2573 if (scrollBar)2574 return scrollBar->wrapper();2575 return nil;2576 }2577 2578 if ([attributeName isEqualToString:NSAccessibilitySortDirectionAttribute]) {2579 switch (m_object->sortDirection()) {2580 case SortDirectionAscending:2581 return NSAccessibilityAscendingSortDirectionValue;2582 case SortDirectionDescending:2583 return NSAccessibilityDescendingSortDirectionValue;2584 default:2585 return NSAccessibilityUnknownSortDirectionValue;2586 }2587 }2588 2589 if ([attributeName isEqualToString:NSAccessibilityLanguageAttribute])2590 return m_object->language();2591 2592 if ([attributeName isEqualToString:NSAccessibilityExpandedAttribute])2593 return [NSNumber numberWithBool:m_object->isExpanded()];2594 2595 if ([attributeName isEqualToString:NSAccessibilityRequiredAttribute])2596 return [NSNumber numberWithBool:m_object->isRequired()];2597 2598 if ([attributeName isEqualToString:NSAccessibilityInvalidAttribute])2599 return m_object->invalidStatus();2600 2601 if ([attributeName isEqualToString:NSAccessibilityOwnsAttribute]) {2602 AccessibilityObject::AccessibilityChildrenVector ariaOwns;2603 m_object->ariaOwnsElements(ariaOwns);2604 return convertToNSArray(ariaOwns);2605 }2606 2607 if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])2608 return [NSNumber numberWithBool:m_object->isARIAGrabbed()];2609 2610 if ([attributeName isEqualToString:NSAccessibilityDropEffectsAttribute]) {2611 Vector<String> dropEffects;2612 m_object->determineARIADropEffects(dropEffects);2613 size_t length = dropEffects.size();2614 2615 NSMutableArray* dropEffectsArray = [NSMutableArray arrayWithCapacity:length];2616 for (size_t i = 0; i < length; ++i)2617 [dropEffectsArray addObject:dropEffects[i]];2618 return dropEffectsArray;2619 }2620 2621 if ([attributeName isEqualToString:NSAccessibilityPlaceholderValueAttribute])2622 return m_object->placeholderValue();2623 2624 if ([attributeName isEqualToString:NSAccessibilityHasPopupAttribute])2625 return [NSNumber numberWithBool:m_object->ariaHasPopup()];2626 2627 // ARIA Live region attributes.2628 if ([attributeName isEqualToString:NSAccessibilityARIALiveAttribute])2629 return m_object->ariaLiveRegionStatus();2630 if ([attributeName isEqualToString:NSAccessibilityARIARelevantAttribute])2631 return m_object->ariaLiveRegionRelevant();2632 if ([attributeName isEqualToString:NSAccessibilityARIAAtomicAttribute])2633 return [NSNumber numberWithBool:m_object->ariaLiveRegionAtomic()];2634 if ([attributeName isEqualToString:NSAccessibilityARIABusyAttribute])2635 return [NSNumber numberWithBool:m_object->ariaLiveRegionBusy()];2636 2637 // MathML Attributes.2638 if (m_object->isMathElement()) {2639 if ([attributeName isEqualToString:NSAccessibilityMathRootIndexAttribute])2640 return (m_object->mathRootIndexObject()) ? m_object->mathRootIndexObject()->wrapper() : 0;2641 if ([attributeName isEqualToString:NSAccessibilityMathRootRadicandAttribute])2642 return (m_object->mathRadicandObject()) ? m_object->mathRadicandObject()->wrapper() : 0;2643 if ([attributeName isEqualToString:NSAccessibilityMathFractionNumeratorAttribute])2644 return (m_object->mathNumeratorObject()) ? m_object->mathNumeratorObject()->wrapper() : 0;2645 if ([attributeName isEqualToString:NSAccessibilityMathFractionDenominatorAttribute])2646 return (m_object->mathDenominatorObject()) ? m_object->mathDenominatorObject()->wrapper() : 0;2647 if ([attributeName isEqualToString:NSAccessibilityMathBaseAttribute])2648 return (m_object->mathBaseObject()) ? m_object->mathBaseObject()->wrapper() : 0;2649 if ([attributeName isEqualToString:NSAccessibilityMathSubscriptAttribute])2650 return (m_object->mathSubscriptObject()) ? m_object->mathSubscriptObject()->wrapper() : 0;2651 if ([attributeName isEqualToString:NSAccessibilityMathSuperscriptAttribute])2652 return (m_object->mathSuperscriptObject()) ? m_object->mathSuperscriptObject()->wrapper() : 0;2653 if ([attributeName isEqualToString:NSAccessibilityMathUnderAttribute])2654 return (m_object->mathUnderObject()) ? m_object->mathUnderObject()->wrapper() : 0;2655 if ([attributeName isEqualToString:NSAccessibilityMathOverAttribute])2656 return (m_object->mathOverObject()) ? m_object->mathOverObject()->wrapper() : 0;2657 if ([attributeName isEqualToString:NSAccessibilityMathFencedOpenAttribute])2658 return m_object->mathFencedOpenString();2659 if ([attributeName isEqualToString:NSAccessibilityMathFencedCloseAttribute])2660 return m_object->mathFencedCloseString();2661 }2662 2663 // this is used only by DumpRenderTree for testing2664 if ([attributeName isEqualToString:@"AXClickPoint"])2665 return [NSValue valueWithPoint:m_object->clickPoint()];2666 2667 // This is used by DRT to verify CSS3 speech works.2668 if ([attributeName isEqualToString:@"AXDRTSpeechAttribute"]) {2669 ESpeak speakProperty = m_object->speakProperty();2670 switch (speakProperty) {2671 case SpeakNone:2672 return @"none";2673 case SpeakSpellOut:2674 return @"spell-out";2675 case SpeakDigits:2676 return @"digits";2677 case SpeakLiteralPunctuation:2678 return @"literal-punctuation";2679 case SpeakNoPunctuation:2680 return @"no-punctuation";2681 default:2682 case SpeakNormal:2683 return @"normal";2684 }2685 }2686 2687 // Used by DRT to find an accessible node by its element id.2688 if ([attributeName isEqualToString:@"AXDRTElementIdAttribute"])2689 return m_object->getAttribute(idAttr);2690 2691 return nil;2692 }2693 2694 - (id)accessibilityFocusedUIElement2695 {2696 if (![self updateObjectBackingStore])2697 return nil;2698 2699 RefPtr<AccessibilityObject> focusedObj = m_object->focusedUIElement();2700 2701 if (!focusedObj)2702 return nil;2703 2704 return focusedObj->wrapper();2705 }2706 2707 - (id)accessibilityHitTest:(NSPoint)point2708 {2709 if (![self updateObjectBackingStore])2710 return nil;2711 2712 m_object->updateChildrenIfNecessary();2713 RefPtr<AccessibilityObject> axObject = m_object->accessibilityHitTest(IntPoint(point));2714 if (axObject)2715 return NSAccessibilityUnignoredAncestor(axObject->wrapper());2716 return NSAccessibilityUnignoredAncestor(self);2717 }2718 2719 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName2720 {2721 if (![self updateObjectBackingStore])2722 return nil;2723 2724 if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])2725 return YES;2726 2727 if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])2728 return m_object->canSetFocusAttribute();2729 2730 if ([attributeName isEqualToString: NSAccessibilityValueAttribute])2731 return m_object->canSetValueAttribute();2732 2733 if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])2734 return m_object->canSetSelectedAttribute();2735 2736 if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute])2737 return m_object->canSetSelectedChildrenAttribute();2738 2739 if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])2740 return m_object->canSetExpandedAttribute();2741 2742 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute])2743 return YES;2744 2745 if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute] ||2746 [attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute] ||2747 [attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])2748 return m_object->canSetTextRangeAttributes();2749 2750 if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])2751 return YES;2752 2753 return NO;2754 }2755 2756 // accessibilityShouldUseUniqueId is an AppKit method we override so that2757 // objects will be given a unique ID, and therefore allow AppKit to know when they2758 // become obsolete (e.g. when the user navigates to a new web page, making this one2759 // unrendered but not deallocated because it is in the back/forward cache).2760 // It is important to call NSAccessibilityUnregisterUniqueIdForUIElement in the2761 // appropriate place (e.g. dealloc) to remove these non-retained references from2762 // AppKit's id mapping tables. We do this in detach by calling unregisterUniqueIdForUIElement.2763 //2764 // Registering an object is also required for observing notifications. Only registered objects can be observed.2765 - (BOOL)accessibilityIsIgnored2766 {2767 if (![self updateObjectBackingStore])2768 return YES;2769 2770 if (m_object->isAttachment())2771 return [[self attachmentView] accessibilityIsIgnored];2772 return m_object->accessibilityIsIgnored();2773 }2774 2775 - (NSArray* )accessibilityParameterizedAttributeNames2776 {2777 if (![self updateObjectBackingStore])2778 return nil;2779 2780 if (m_object->isAttachment())2781 return nil;2782 2783 static NSArray* paramAttrs = nil;2784 static NSArray* textParamAttrs = nil;2785 static NSArray* tableParamAttrs = nil;2786 static NSArray* webAreaParamAttrs = nil;2787 if (paramAttrs == nil) {2788 paramAttrs = [[NSArray alloc] initWithObjects:2789 @"AXUIElementForTextMarker",2790 @"AXTextMarkerRangeForUIElement",2791 @"AXLineForTextMarker",2792 @"AXTextMarkerRangeForLine",2793 @"AXStringForTextMarkerRange",2794 @"AXTextMarkerForPosition",2795 @"AXBoundsForTextMarkerRange",2796 @"AXAttributedStringForTextMarkerRange",2797 @"AXTextMarkerRangeForUnorderedTextMarkers",2798 @"AXNextTextMarkerForTextMarker",2799 @"AXPreviousTextMarkerForTextMarker",2800 @"AXLeftWordTextMarkerRangeForTextMarker",2801 @"AXRightWordTextMarkerRangeForTextMarker",2802 @"AXLeftLineTextMarkerRangeForTextMarker",2803 @"AXRightLineTextMarkerRangeForTextMarker",2804 @"AXSentenceTextMarkerRangeForTextMarker",2805 @"AXParagraphTextMarkerRangeForTextMarker",2806 @"AXNextWordEndTextMarkerForTextMarker",2807 @"AXPreviousWordStartTextMarkerForTextMarker",2808 @"AXNextLineEndTextMarkerForTextMarker",2809 @"AXPreviousLineStartTextMarkerForTextMarker",2810 @"AXNextSentenceEndTextMarkerForTextMarker",2811 @"AXPreviousSentenceStartTextMarkerForTextMarker",2812 @"AXNextParagraphEndTextMarkerForTextMarker",2813 @"AXPreviousParagraphStartTextMarkerForTextMarker",2814 @"AXStyleTextMarkerRangeForTextMarker",2815 @"AXLengthForTextMarkerRange",2816 NSAccessibilityBoundsForRangeParameterizedAttribute,2817 NSAccessibilityStringForRangeParameterizedAttribute,2818 NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute,2819 nil];2820 }2821 2822 if (textParamAttrs == nil) {2823 NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];2824 [tempArray addObject:(NSString*)kAXLineForIndexParameterizedAttribute];2825 [tempArray addObject:(NSString*)kAXRangeForLineParameterizedAttribute];2826 [tempArray addObject:(NSString*)kAXStringForRangeParameterizedAttribute];2827 [tempArray addObject:(NSString*)kAXRangeForPositionParameterizedAttribute];2828 [tempArray addObject:(NSString*)kAXRangeForIndexParameterizedAttribute];2829 [tempArray addObject:(NSString*)kAXBoundsForRangeParameterizedAttribute];2830 [tempArray addObject:(NSString*)kAXRTFForRangeParameterizedAttribute];2831 [tempArray addObject:(NSString*)kAXAttributedStringForRangeParameterizedAttribute];2832 [tempArray addObject:(NSString*)kAXStyleRangeForIndexParameterizedAttribute];2833 textParamAttrs = [[NSArray alloc] initWithArray:tempArray];2834 [tempArray release];2835 }2836 if (tableParamAttrs == nil) {2837 NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];2838 [tempArray addObject:NSAccessibilityCellForColumnAndRowParameterizedAttribute];2839 tableParamAttrs = [[NSArray alloc] initWithArray:tempArray];2840 [tempArray release];2841 }2842 if (!webAreaParamAttrs) {2843 NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];2844 [tempArray addObject:NSAccessibilityTextMarkerForIndexParameterizedAttribute];2845 [tempArray addObject:NSAccessibilityTextMarkerIsValidParameterizedAttribute];2846 [tempArray addObject:NSAccessibilityIndexForTextMarkerParameterizedAttribute];2847 webAreaParamAttrs = [[NSArray alloc] initWithArray:tempArray];2848 [tempArray release];2849 }2850 2851 if (m_object->isPasswordField())2852 return [NSArray array];2853 2854 if (!m_object->isAccessibilityRenderObject())2855 return paramAttrs;2856 2857 if (m_object->isTextControl())2858 return textParamAttrs;2859 2860 if (m_object->isAccessibilityTable())2861 return tableParamAttrs;2862 2863 if (m_object->isMenuRelated())2864 return nil;2865 2866 if (m_object->isWebArea())2867 return webAreaParamAttrs;2868 2869 return paramAttrs;2870 }2871 2872 - (void)accessibilityPerformPressAction2873 {2874 if (![self updateObjectBackingStore])2875 return;2876 2877 if (m_object->isAttachment())2878 [[self attachmentView] accessibilityPerformAction:NSAccessibilityPressAction];2879 else2880 m_object->press();2881 }2882 2883 - (void)accessibilityPerformIncrementAction2884 {2885 if (![self updateObjectBackingStore])2886 return;2887 2888 if (m_object->isAttachment())2889 [[self attachmentView] accessibilityPerformAction:NSAccessibilityIncrementAction];2890 else2891 m_object->increment();2892 }2893 2894 - (void)accessibilityPerformDecrementAction2895 {2896 if (![self updateObjectBackingStore])2897 return;2898 2899 if (m_object->isAttachment())2900 [[self attachmentView] accessibilityPerformAction:NSAccessibilityDecrementAction];2901 else2902 m_object->decrement();2903 }2904 2905 - (void)accessibilityPerformShowMenuAction2906 {2907 if (m_object->roleValue() == ComboBoxRole)2908 m_object->setIsExpanded(true);2909 else {2910 // This needs to be performed in an iteration of the run loop that did not start from an AX call.2911 // If it's the same run loop iteration, the menu open notification won't be sent2912 [self performSelector:@selector(accessibilityShowContextMenu) withObject:nil afterDelay:0.0];2913 }2914 }2915 2916 - (void)accessibilityShowContextMenu2917 {2918 Page* page = m_object->page();2919 if (!page)2920 return;2921 2922 IntRect rect = pixelSnappedIntRect(m_object->elementRect());2923 FrameView* frameView = m_object->documentFrameView();2924 2925 // On WK2, we need to account for the scroll position.2926 // On WK1, this isn't necessary, it's taken care of by the attachment views.2927 if (frameView && !frameView->platformWidget()) {2928 // Find the appropriate scroll view to use to convert the contents to the window.2929 for (AccessibilityObject* parent = m_object->parentObject(); parent; parent = parent->parentObject()) {2930 if (parent->isAccessibilityScrollView()) {2931 ScrollView* scrollView = toAccessibilityScrollView(parent)->scrollView();2932 rect = scrollView->contentsToRootView(rect);2933 break;2934 }2935 }2936 }2937 2938 page->contextMenuController()->showContextMenuAt(page->mainFrame(), rect.center());2939 }2940 2941 - (void)accessibilityPerformAction:(NSString*)action2942 {2943 if (![self updateObjectBackingStore])2944 return;2945 2946 if ([action isEqualToString:NSAccessibilityPressAction])2947 [self accessibilityPerformPressAction];2948 2949 else if ([action isEqualToString:NSAccessibilityShowMenuAction])2950 [self accessibilityPerformShowMenuAction];2951 2952 else if ([action isEqualToString:NSAccessibilityIncrementAction])2953 [self accessibilityPerformIncrementAction];2954 2955 else if ([action isEqualToString:NSAccessibilityDecrementAction])2956 [self accessibilityPerformDecrementAction];2957 }2958 2959 - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attributeName2960 {2961 if (![self updateObjectBackingStore])2962 return;2963 2964 id textMarkerRange = nil;2965 NSNumber* number = nil;2966 NSString* string = nil;2967 NSRange range = {0, 0};2968 NSArray* array = nil;2969 2970 // decode the parameter2971 if (AXObjectIsTextMarkerRange(value))2972 textMarkerRange = value;2973 2974 else if ([value isKindOfClass:[NSNumber self]])2975 number = value;2976 2977 else if ([value isKindOfClass:[NSString self]])2978 string = value;2979 2980 else if ([value isKindOfClass:[NSValue self]])2981 range = [value rangeValue];2982 2983 else if ([value isKindOfClass:[NSArray self]])2984 array = value;2985 2986 // handle the command2987 if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"]) {2988 ASSERT(textMarkerRange);2989 m_object->setSelectedVisiblePositionRange([self visiblePositionRangeForTextMarkerRange:textMarkerRange]);2990 } else if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute]) {2991 ASSERT(number);2992 m_object->setFocused([number intValue] != 0);2993 } else if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {2994 if (number && m_object->canSetNumericValue())2995 m_object->setValue([number floatValue]);2996 else if (string)2997 m_object->setValue(string);2998 } else if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute]) {2999 if (!number)3000 return;3001 m_object->setSelected([number boolValue]);3002 } else if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {3003 if (!array || m_object->roleValue() != ListBoxRole)3004 return;3005 AccessibilityObject::AccessibilityChildrenVector selectedChildren;3006 convertToVector(array, selectedChildren);3007 static_cast<AccessibilityListBox*>(m_object)->setSelectedChildren(selectedChildren);3008 } else if (m_object->isTextControl()) {3009 if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {3010 m_object->setSelectedText(string);3011 } else if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {3012 m_object->setSelectedTextRange(PlainTextRange(range.location, range.length));3013 } else if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute]) {3014 m_object->makeRangeVisible(PlainTextRange(range.location, range.length));3015 }3016 } else if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])3017 m_object->setIsExpanded([number boolValue]);3018 else if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {3019 AccessibilityObject::AccessibilityChildrenVector selectedRows;3020 convertToVector(array, selectedRows);3021 if (m_object->isTree() || m_object->isAccessibilityTable())3022 m_object->setSelectedRows(selectedRows);3023 } else if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])3024 m_object->setARIAGrabbed([number boolValue]);3025 }3026 3027 static RenderObject* rendererForView(NSView* view)3028 {3029 if (![view conformsToProtocol:@protocol(WebCoreFrameView)])3030 return 0;3031 3032 NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view;3033 Frame* frame = [frameView _web_frame];3034 if (!frame)3035 return 0;3036 3037 Node* node = frame->document()->ownerElement();3038 if (!node)3039 return 0;3040 3041 return node->renderer();3042 }3043 3044 - (id)_accessibilityParentForSubview:(NSView*)subview3045 {3046 RenderObject* renderer = rendererForView(subview);3047 if (!renderer)3048 return nil;3049 3050 AccessibilityObject* obj = renderer->document()->axObjectCache()->getOrCreate(renderer);3051 if (obj)3052 return obj->parentObjectUnignored()->wrapper();3053 return nil;3054 }3055 3056 - (NSString*)accessibilityActionDescription:(NSString*)action3057 {3058 // we have no custom actions3059 return NSAccessibilityActionDescription(action);3060 }3061 3062 // The CFAttributedStringType representation of the text associated with this accessibility3063 // object that is specified by the given range.3064 - (NSAttributedString*)doAXAttributedStringForRange:(NSRange)range3065 {3066 PlainTextRange textRange = PlainTextRange(range.location, range.length);3067 VisiblePositionRange visiblePosRange = m_object->visiblePositionRangeForRange(textRange);3068 return [self doAXAttributedStringForTextMarkerRange:[self textMarkerRangeFromVisiblePositions:visiblePosRange.start endPosition:visiblePosRange.end]];3069 }3070 3071 - (NSRange)_convertToNSRange:(Range*)range3072 {3073 NSRange result = NSMakeRange(NSNotFound, 0);3074 if (!range || !range->startContainer())3075 return result;3076 3077 Document* document = m_object->document();3078 if (!document)3079 return result;3080 3081 size_t location;3082 size_t length;3083 TextIterator::getLocationAndLengthFromRange(document->documentElement(), range, location, length);3084 result.location = location;3085 result.length = length;3086 3087 return result;3088 }3089 3090 - (NSInteger)_indexForTextMarker:(id)marker3091 {3092 if (!marker)3093 return NSNotFound;3094 3095 VisibleSelection selection([self visiblePositionForTextMarker:marker]);3096 return [self _convertToNSRange:selection.toNormalizedRange().get()].location;3097 }3098 3099 - (id)_textMarkerForIndex:(NSInteger)textIndex3100 {3101 Document* document = m_object->document();3102 if (!document)3103 return nil;3104 3105 PassRefPtr<Range> textRange = TextIterator::rangeFromLocationAndLength(document->documentElement(), textIndex, 0);3106 if (!textRange || !textRange->boundaryPointsValid())3107 return nil;3108 3109 VisiblePosition position(textRange->startPosition());3110 return [self textMarkerForVisiblePosition:position];3111 }3112 3113 // The RTF representation of the text associated with this accessibility object that is3114 // specified by the given range.3115 - (NSData*)doAXRTFForRange:(NSRange)range3116 {3117 NSAttributedString* attrString = [self doAXAttributedStringForRange:range];3118 return [attrString RTFFromRange: NSMakeRange(0, [attrString length]) documentAttributes: nil];3119 }3120 3121 - (id)accessibilityAttributeValue:(NSString*)attribute forParameter:(id)parameter3122 {3123 id textMarker = nil;3124 id textMarkerRange = nil;3125 NSNumber* number = nil;3126 NSArray* array = nil;3127 NSDictionary* dictionary = nil;3128 RefPtr<AccessibilityObject> uiElement = 0;3129 NSPoint point = NSZeroPoint;3130 bool pointSet = false;3131 NSRange range = {0, 0};3132 bool rangeSet = false;3133 3134 // basic parameter validation3135 if (!m_object || !attribute || !parameter)3136 return nil;3137 3138 if (![self updateObjectBackingStore])3139 return nil;3140 3141 // common parameter type check/casting. Nil checks in handlers catch wrong type case.3142 // NOTE: This assumes nil is not a valid parameter, because it is indistinguishable from3143 // a parameter of the wrong type.3144 if (AXObjectIsTextMarker(parameter))3145 textMarker = parameter;3146 3147 else if (AXObjectIsTextMarkerRange(parameter))3148 textMarkerRange = parameter;3149 3150 else if ([parameter isKindOfClass:[WebAccessibilityObjectWrapper self]])3151 uiElement = [(WebAccessibilityObjectWrapper*)parameter accessibilityObject];3152 3153 else if ([parameter isKindOfClass:[NSNumber self]])3154 number = parameter;3155 3156 else if ([parameter isKindOfClass:[NSArray self]])3157 array = parameter;3158 3159 else if ([parameter isKindOfClass:[NSDictionary self]])3160 dictionary = parameter;3161 3162 else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSPoint)) == 0) {3163 pointSet = true;3164 point = [(NSValue*)parameter pointValue];3165 3166 } else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSRange)) == 0) {3167 rangeSet = true;3168 range = [(NSValue*)parameter rangeValue];3169 } else {3170 // Attribute type is not supported. Allow super to handle.3171 return [super accessibilityAttributeValue:attribute forParameter:parameter];3172 }3173 3174 // dispatch3175 if ([attribute isEqualToString:NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute]) {3176 AccessibilityObject* startObject = 0;3177 if ([[dictionary objectForKey:@"AXStartElement"] isKindOfClass:[WebAccessibilityObjectWrapper self]])3178 startObject = [(WebAccessibilityObjectWrapper*)[dictionary objectForKey:@"AXStartElement"] accessibilityObject];3179 3180 AccessibilitySearchDirection searchDirection = SearchDirectionNext;3181 if ([[dictionary objectForKey:@"AXDirection"] isKindOfClass:[NSString self]])3182 searchDirection = ([(NSString*)[dictionary objectForKey:@"AXDirection"] isEqualToString:@"AXDirectionNext"]) ? SearchDirectionNext : SearchDirectionPrevious;3183 3184 AccessibilitySearchKey searchKey = AnyTypeSearchKey;3185 if ([[dictionary objectForKey:@"AXSearchKey"] isKindOfClass:[NSString self]])3186 searchKey = accessibilitySearchKeyForString((CFStringRef)[dictionary objectForKey:@"AXSearchKey"]);3187 3188 String searchText;3189 if ([[dictionary objectForKey:@"AXSearchText"] isKindOfClass:[NSString self]])3190 searchText = (CFStringRef)[dictionary objectForKey:@"AXSearchText"];3191 3192 unsigned resultsLimit = 0;3193 if ([[dictionary objectForKey:@"AXResultsLimit"] isKindOfClass:[NSNumber self]])3194 resultsLimit = [(NSNumber*)[dictionary objectForKey:@"AXResultsLimit"] unsignedIntValue];3195 3196 AccessibilitySearchCriteria criteria = {startObject, searchDirection, searchKey, &searchText, resultsLimit};3197 3198 AccessibilityObject::AccessibilityChildrenVector results;3199 m_object->findMatchingObjects(&criteria, results);3200 3201 return convertToNSArray(results);3202 }3203 3204 if ([attribute isEqualToString:NSAccessibilityTextMarkerIsValidParameterizedAttribute]) {3205 VisiblePosition pos = [self visiblePositionForTextMarker:textMarker];3206 return [NSNumber numberWithBool:!pos.isNull()];3207 }3208 if ([attribute isEqualToString:NSAccessibilityIndexForTextMarkerParameterizedAttribute]) {3209 return [NSNumber numberWithInteger:[self _indexForTextMarker:textMarker]];3210 }3211 if ([attribute isEqualToString:NSAccessibilityTextMarkerForIndexParameterizedAttribute]) {3212 return [self _textMarkerForIndex:[number integerValue]];3213 }3214 3215 if ([attribute isEqualToString:@"AXUIElementForTextMarker"]) {3216 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];3217 AccessibilityObject* axObject = m_object->accessibilityObjectForPosition(visiblePos);3218 if (!axObject)3219 return nil;3220 return axObject->wrapper();3221 }3222 3223 if ([attribute isEqualToString:@"AXTextMarkerRangeForUIElement"]) {3224 VisiblePositionRange vpRange = uiElement.get()->visiblePositionRange();3225 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];3226 }3227 3228 if ([attribute isEqualToString:@"AXLineForTextMarker"]) {3229 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];3230 return [NSNumber numberWithUnsignedInt:m_object->lineForPosition(visiblePos)];3231 }3232 3233 if ([attribute isEqualToString:@"AXTextMarkerRangeForLine"]) {3234 VisiblePositionRange vpRange = m_object->visiblePositionRangeForLine([number intValue]);3235 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];3236 }3237 3238 if ([attribute isEqualToString:@"AXStringForTextMarkerRange"]) {3239 VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];3240 return m_object->stringForVisiblePositionRange(visiblePosRange);3241 }3242 3243 if ([attribute isEqualToString:@"AXTextMarkerForPosition"]) {3244 IntPoint webCorePoint = IntPoint(point);3245 return pointSet ? [self textMarkerForVisiblePosition:m_object->visiblePositionForPoint(webCorePoint)] : nil;3246 }3247 3248 if ([attribute isEqualToString:@"AXBoundsForTextMarkerRange"]) {3249 VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];3250 NSRect rect = m_object->boundsForVisiblePositionRange(visiblePosRange);3251 return [NSValue valueWithRect:rect];3252 }3253 3254 if ([attribute isEqualToString:NSAccessibilityBoundsForRangeParameterizedAttribute]) {3255 VisiblePosition start = m_object->visiblePositionForIndex(range.location);3256 VisiblePosition end = m_object->visiblePositionForIndex(range.location+range.length);3257 if (start.isNull() || end.isNull())3258 return nil;3259 NSRect rect = m_object->boundsForVisiblePositionRange(VisiblePositionRange(start, end));3260 return [NSValue valueWithRect:rect];3261 }3262 3263 if ([attribute isEqualToString:NSAccessibilityStringForRangeParameterizedAttribute]) {3264 VisiblePosition start = m_object->visiblePositionForIndex(range.location);3265 VisiblePosition end = m_object->visiblePositionForIndex(range.location+range.length);3266 if (start.isNull() || end.isNull())3267 return nil;3268 return m_object->stringForVisiblePositionRange(VisiblePositionRange(start, end));3269 }3270 3271 if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"])3272 return [self doAXAttributedStringForTextMarkerRange:textMarkerRange];3273 3274 if ([attribute isEqualToString:@"AXTextMarkerRangeForUnorderedTextMarkers"]) {3275 if ([array count] < 2)3276 return nil;3277 3278 id textMarker1 = [array objectAtIndex:0];3279 id textMarker2 = [array objectAtIndex:1];3280 if (!AXObjectIsTextMarker(textMarker1) || !AXObjectIsTextMarker(textMarker2))3281 return nil;3282 3283 VisiblePosition visiblePos1 = [self visiblePositionForTextMarker:(textMarker1)];3284 VisiblePosition visiblePos2 = [self visiblePositionForTextMarker:(textMarker2)];3285 VisiblePositionRange vpRange = m_object->visiblePositionRangeForUnorderedPositions(visiblePos1, visiblePos2);3286 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];3287 }3288 3289 if ([attribute isEqualToString:@"AXNextTextMarkerForTextMarker"]) {3290 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];3291 return [self textMarkerForVisiblePosition:m_object->nextVisiblePosition(visiblePos)];3292 }3293 3294 if ([attribute isEqualToString:@"AXPreviousTextMarkerForTextMarker"]) {3295 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];3296 return [self textMarkerForVisiblePosition:m_object->previousVisiblePosition(visiblePos)];3297 }3298 3299 if ([attribute isEqualToString:@"AXLeftWordTextMarkerRangeForTextMarker"]) {3300 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];3301 VisiblePositionRange vpRange = m_object->positionOfLeftWord(visiblePos);3302 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];3303 }3304 3305 if ([attribute isEqualToString:@"AXRightWordTextMarkerRangeForTextMarker"]) {3306 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];3307 VisiblePositionRange vpRange = m_object->positionOfRightWord(visiblePos);3308 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];3309 }3310 3311 if ([attribute isEqualToString:@"AXLeftLineTextMarkerRangeForTextMarker"]) {3312 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];3313 VisiblePositionRange vpRange = m_object->leftLineVisiblePositionRange(visiblePos);3314 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];3315 }3316 3317 if ([attribute isEqualToString:@"AXRightLineTextMarkerRangeForTextMarker"]) {3318 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];3319 VisiblePositionRange vpRange = m_object->rightLineVisiblePositionRange(visiblePos);3320 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];3321 }3322 3323 if ([attribute isEqualToString:@"AXSentenceTextMarkerRangeForTextMarker"]) {3324 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];3325 VisiblePositionRange vpRange = m_object->sentenceForPosition(visiblePos);3326 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];3327 }3328 3329 if ([attribute isEqualToString:@"AXParagraphTextMarkerRangeForTextMarker"]) {3330 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];3331 VisiblePositionRange vpRange = m_object->paragraphForPosition(visiblePos);3332 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];3333 }3334 3335 if ([attribute isEqualToString:@"AXNextWordEndTextMarkerForTextMarker"]) {3336 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];3337 return [self textMarkerForVisiblePosition:m_object->nextWordEnd(visiblePos)];3338 }3339 3340 if ([attribute isEqualToString:@"AXPreviousWordStartTextMarkerForTextMarker"]) {3341 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];3342 return [self textMarkerForVisiblePosition:m_object->previousWordStart(visiblePos)];3343 }3344 3345 if ([attribute isEqualToString:@"AXNextLineEndTextMarkerForTextMarker"]) {3346 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];3347 return [self textMarkerForVisiblePosition:m_object->nextLineEndPosition(visiblePos)];3348 }3349 3350 if ([attribute isEqualToString:@"AXPreviousLineStartTextMarkerForTextMarker"]) {3351 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];3352 return [self textMarkerForVisiblePosition:m_object->previousLineStartPosition(visiblePos)];3353 }3354 3355 if ([attribute isEqualToString:@"AXNextSentenceEndTextMarkerForTextMarker"]) {3356 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];3357 return [self textMarkerForVisiblePosition:m_object->nextSentenceEndPosition(visiblePos)];3358 }3359 3360 if ([attribute isEqualToString:@"AXPreviousSentenceStartTextMarkerForTextMarker"]) {3361 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];3362 return [self textMarkerForVisiblePosition:m_object->previousSentenceStartPosition(visiblePos)];3363 }3364 3365 if ([attribute isEqualToString:@"AXNextParagraphEndTextMarkerForTextMarker"]) {3366 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];3367 return [self textMarkerForVisiblePosition:m_object->nextParagraphEndPosition(visiblePos)];3368 }3369 3370 if ([attribute isEqualToString:@"AXPreviousParagraphStartTextMarkerForTextMarker"]) {3371 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];3372 return [self textMarkerForVisiblePosition:m_object->previousParagraphStartPosition(visiblePos)];3373 }3374 3375 if ([attribute isEqualToString:@"AXStyleTextMarkerRangeForTextMarker"]) {3376 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];3377 VisiblePositionRange vpRange = m_object->styleRangeForPosition(visiblePos);3378 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];3379 }3380 3381 if ([attribute isEqualToString:@"AXLengthForTextMarkerRange"]) {3382 VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];3383 int length = m_object->lengthForVisiblePositionRange(visiblePosRange);3384 if (length < 0)3385 return nil;3386 return [NSNumber numberWithInt:length];3387 }3388 3389 // Used only by DumpRenderTree (so far).3390 if ([attribute isEqualToString:@"AXStartTextMarkerForTextMarkerRange"]) {3391 VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];3392 return [self textMarkerForVisiblePosition:visiblePosRange.start];3393 }3394 3395 if ([attribute isEqualToString:@"AXEndTextMarkerForTextMarkerRange"]) {3396 VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];3397 return [self textMarkerForVisiblePosition:visiblePosRange.end];3398 }3399 3400 if (m_object->isAccessibilityTable()) {3401 if ([attribute isEqualToString:NSAccessibilityCellForColumnAndRowParameterizedAttribute]) {3402 if (array == nil || [array count] != 2)3403 return nil;3404 AccessibilityTableCell* cell = static_cast<AccessibilityTable*>(m_object)->cellForColumnAndRow([[array objectAtIndex:0] unsignedIntValue], [[array objectAtIndex:1] unsignedIntValue]);3405 if (!cell)3406 return nil;3407 3408 return cell->wrapper();3409 }3410 }3411 3412 if (m_object->isTextControl()) {3413 if ([attribute isEqualToString: (NSString *)kAXLineForIndexParameterizedAttribute]) {3414 int lineNumber = m_object->doAXLineForIndex([number intValue]);3415 if (lineNumber < 0)3416 return nil;3417 return [NSNumber numberWithUnsignedInt:lineNumber];3418 }3419 3420 if ([attribute isEqualToString: (NSString *)kAXRangeForLineParameterizedAttribute]) {3421 PlainTextRange textRange = m_object->doAXRangeForLine([number intValue]);3422 return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];3423 }3424 3425 if ([attribute isEqualToString: (NSString*)kAXStringForRangeParameterizedAttribute]) {3426 PlainTextRange plainTextRange = PlainTextRange(range.location, range.length);3427 return rangeSet ? (id)(m_object->doAXStringForRange(plainTextRange)) : nil;3428 }3429 3430 if ([attribute isEqualToString: (NSString*)kAXRangeForPositionParameterizedAttribute]) {3431 if (!pointSet)3432 return nil;3433 IntPoint webCorePoint = IntPoint(point);3434 PlainTextRange textRange = m_object->doAXRangeForPosition(webCorePoint);3435 return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];3436 }3437 3438 if ([attribute isEqualToString: (NSString*)kAXRangeForIndexParameterizedAttribute]) {3439 PlainTextRange textRange = m_object->doAXRangeForIndex([number intValue]);3440 return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];3441 }3442 3443 if ([attribute isEqualToString: (NSString*)kAXBoundsForRangeParameterizedAttribute]) {3444 if (!rangeSet)3445 return nil;3446 PlainTextRange plainTextRange = PlainTextRange(range.location, range.length);3447 NSRect rect = m_object->doAXBoundsForRange(plainTextRange);3448 return [NSValue valueWithRect:rect];3449 }3450 3451 if ([attribute isEqualToString: (NSString*)kAXRTFForRangeParameterizedAttribute])3452 return rangeSet ? [self doAXRTFForRange:range] : nil;3453 3454 if ([attribute isEqualToString: (NSString*)kAXAttributedStringForRangeParameterizedAttribute])3455 return rangeSet ? [self doAXAttributedStringForRange:range] : nil;3456 3457 if ([attribute isEqualToString: (NSString*)kAXStyleRangeForIndexParameterizedAttribute]) {3458 PlainTextRange textRange = m_object->doAXStyleRangeForIndex([number intValue]);3459 return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];3460 }3461 }3462 3463 // There are some parameters that super handles that are not explicitly returned by the list of the element's attributes.3464 // In that case it must be passed to super.3465 return [super accessibilityAttributeValue:attribute forParameter:parameter];3466 }3467 3468 - (BOOL)accessibilitySupportsOverriddenAttributes3469 {3470 return YES;3471 }3472 3473 - (BOOL)accessibilityShouldUseUniqueId3474 {3475 // All AX object wrappers should use unique ID's because it's faster within AppKit to look them up.3476 return YES;3477 }3478 3479 // API that AppKit uses for faster access3480 - (NSUInteger)accessibilityIndexOfChild:(id)child3481 {3482 if (![self updateObjectBackingStore])3483 return NSNotFound;3484 3485 // Tree objects return their rows as their children. We can use the original method3486 // here, because we won't gain any speed up.3487 if (m_object->isTree())3488 return [super accessibilityIndexOfChild:child];3489 3490 const AccessibilityObject::AccessibilityChildrenVector& children = m_object->children();3491 3492 if (children.isEmpty())3493 return [[self renderWidgetChildren] indexOfObject:child];3494 3495 unsigned count = children.size();3496 for (unsigned k = 0; k < count; ++k) {3497 WebAccessibilityObjectWrapper* wrapper = children[k]->wrapper();3498 if (wrapper == child || (children[k]->isAttachment() && [wrapper attachmentView] == child))3499 return k;3500 }3501 3502 return NSNotFound;3503 }3504 3505 - (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute3506 {3507 if (![self updateObjectBackingStore])3508 return 0;3509 3510 if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {3511 // Tree items object returns a different set of children than those that are in children()3512 // because an AXOutline (the mac role is becomes) has some odd stipulations.3513 if (m_object->isTree() || m_object->isTreeItem())3514 return [[self accessibilityAttributeValue:NSAccessibilityChildrenAttribute] count];3515 3516 const AccessibilityObject::AccessibilityChildrenVector& children = m_object->children();3517 if (children.isEmpty())3518 return [[self renderWidgetChildren] count];3519 3520 return children.size();3521 }3522 3523 return [super accessibilityArrayAttributeCount:attribute];3524 }3525 3526 - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount3527 {3528 if (![self updateObjectBackingStore])3529 return nil;3530 3531 if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {3532 if (m_object->children().isEmpty()) {3533 NSArray *children = [self renderWidgetChildren];3534 if (!children)3535 return nil;3536 3537 NSUInteger childCount = [children count];3538 if (index >= childCount)3539 return nil;3540 3541 NSUInteger arrayLength = min(childCount - index, maxCount);3542 return [children subarrayWithRange:NSMakeRange(index, arrayLength)];3543 } else if (m_object->isTree()) {3544 // Tree objects return their rows as their children. We can use the original method in this case.3545 return [super accessibilityArrayAttributeValues:attribute index:index maxCount:maxCount];3546 }3547 3548 const AccessibilityObject::AccessibilityChildrenVector& children = m_object->children();3549 unsigned childCount = children.size();3550 if (index >= childCount)3551 return nil;3552 3553 unsigned available = min(childCount - index, maxCount);3554 3555 NSMutableArray *subarray = [NSMutableArray arrayWithCapacity:available];3556 for (unsigned added = 0; added < available; ++index, ++added) {3557 WebAccessibilityObjectWrapper* wrapper = children[index]->wrapper();3558 if (wrapper) {3559 // The attachment view should be returned, otherwise AX palindrome errors occur.3560 if (children[index]->isAttachment() && [wrapper attachmentView])3561 [subarray addObject:[wrapper attachmentView]];3562 else3563 [subarray addObject:wrapper];3564 }3565 }3566 3567 return subarray;3568 }3569 3570 return [super accessibilityArrayAttributeValues:attribute index:index maxCount:maxCount];3571 }3572 3573 229 // This is set by DRT when it wants to listen for notifications. 3574 230 static BOOL accessibilityShouldRepostNotifications;
Note: See TracChangeset
for help on using the changeset viewer.