2 * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #import "WebAccessibilityObjectWrapper.h"
32 #if HAVE(ACCESSIBILITY)
34 #import "AXObjectCache.h"
35 #import "AccessibilityARIAGridRow.h"
36 #import "AccessibilityList.h"
37 #import "AccessibilityListBox.h"
38 #import "AccessibilityRenderObject.h"
39 #import "AccessibilityScrollView.h"
40 #import "AccessibilitySpinButton.h"
41 #import "AccessibilityTable.h"
42 #import "AccessibilityTableCell.h"
43 #import "AccessibilityTableColumn.h"
44 #import "AccessibilityTableRow.h"
46 #import "ChromeClient.h"
48 #import "ContextMenuController.h"
51 #import "FrameLoaderClient.h"
52 #import "FrameSelection.h"
53 #import "HTMLAnchorElement.h"
54 #import "HTMLAreaElement.h"
55 #import "HTMLFrameOwnerElement.h"
56 #import "HTMLImageElement.h"
57 #import "HTMLInputElement.h"
59 #import "HTMLTextAreaElement.h"
60 #import "LocalizedStrings.h"
62 #import "RenderTextControl.h"
63 #import "RenderView.h"
64 #import "RenderWidget.h"
65 #import "ScrollView.h"
66 #import "SimpleFontData.h"
67 #import "TextCheckerClient.h"
68 #import "TextCheckingHelper.h"
69 #import "TextIterator.h"
70 #import "WebCoreFrameView.h"
71 #import "WebCoreObjCExtras.h"
72 #import "WebCoreSystemInterface.h"
73 #import "htmlediting.h"
74 #import "visible_units.h"
76 using namespace WebCore;
77 using namespace HTMLNames;
81 #ifndef NSAccessibilitySelectedCellsAttribute
82 #define NSAccessibilitySelectedCellsAttribute @"AXSelectedCells"
85 #ifndef NSAccessibilityVisibleCellsAttribute
86 #define NSAccessibilityVisibleCellsAttribute @"AXVisibleCells"
89 #ifndef NSAccessibilityRowHeaderUIElementsAttribute
90 #define NSAccessibilityRowHeaderUIElementsAttribute @"AXRowHeaderUIElements"
93 #ifndef NSAccessibilityRowIndexRangeAttribute
94 #define NSAccessibilityRowIndexRangeAttribute @"AXRowIndexRange"
97 #ifndef NSAccessibilityColumnIndexRangeAttribute
98 #define NSAccessibilityColumnIndexRangeAttribute @"AXColumnIndexRange"
101 #ifndef NSAccessibilityCellForColumnAndRowParameterizedAttribute
102 #define NSAccessibilityCellForColumnAndRowParameterizedAttribute @"AXCellForColumnAndRow"
105 #ifndef NSAccessibilityCellRole
106 #define NSAccessibilityCellRole @"AXCell"
110 #ifndef NSAccessibilityContentListSubrole
111 #define NSAccessibilityContentListSubrole @"AXContentList"
114 #ifndef NSAccessibilityDefinitionListSubrole
115 #define NSAccessibilityDefinitionListSubrole @"AXDefinitionList"
119 #ifndef NSAccessibilityBlockQuoteLevelAttribute
120 #define NSAccessibilityBlockQuoteLevelAttribute @"AXBlockQuoteLevel"
123 #ifndef NSAccessibilityAccessKeyAttribute
124 #define NSAccessibilityAccessKeyAttribute @"AXAccessKey"
127 #ifndef NSAccessibilityLanguageAttribute
128 #define NSAccessibilityLanguageAttribute @"AXLanguage"
131 #ifndef NSAccessibilityRequiredAttribute
132 #define NSAccessibilityRequiredAttribute @"AXRequired"
135 #ifndef NSAccessibilityInvalidAttribute
136 #define NSAccessibilityInvalidAttribute @"AXInvalid"
139 #ifndef NSAccessibilityOwnsAttribute
140 #define NSAccessibilityOwnsAttribute @"AXOwns"
143 #ifndef NSAccessibilityGrabbedAttribute
144 #define NSAccessibilityGrabbedAttribute @"AXGrabbed"
147 #ifndef NSAccessibilityDropEffectsAttribute
148 #define NSAccessibilityDropEffectsAttribute @"AXDropEffects"
151 #ifndef NSAccessibilityARIALiveAttribute
152 #define NSAccessibilityARIALiveAttribute @"AXARIALive"
155 #ifndef NSAccessibilityARIAAtomicAttribute
156 #define NSAccessibilityARIAAtomicAttribute @"AXARIAAtomic"
159 #ifndef NSAccessibilityARIARelevantAttribute
160 #define NSAccessibilityARIARelevantAttribute @"AXARIARelevant"
163 #ifndef NSAccessibilityARIABusyAttribute
164 #define NSAccessibilityARIABusyAttribute @"AXARIABusy"
167 #ifndef NSAccessibilityLoadingProgressAttribute
168 #define NSAccessibilityLoadingProgressAttribute @"AXLoadingProgress"
171 #ifndef NSAccessibilityHasPopupAttribute
172 #define NSAccessibilityHasPopupAttribute @"AXHasPopup"
175 #ifndef NSAccessibilityPlaceholderValueAttribute
176 #define NSAccessibilityPlaceholderValueAttribute @"AXPlaceholderValue"
180 #ifndef NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute
181 #define NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute @"AXUIElementsForSearchPredicate"
185 #ifndef NSAccessibilityAnyTypeSearchKey
186 #define NSAccessibilityAnyTypeSearchKey @"AXAnyTypeSearchKey"
189 #ifndef NSAccessibilityBlockquoteSameLevelSearchKey
190 #define NSAccessibilityBlockquoteSameLevelSearchKey @"AXBlockquoteSameLevelSearchKey"
193 #ifndef NSAccessibilityBlockquoteSearchKey
194 #define NSAccessibilityBlockquoteSearchKey @"AXBlockquoteSearchKey"
197 #ifndef NSAccessibilityBoldFontSearchKey
198 #define NSAccessibilityBoldFontSearchKey @"AXBoldFontSearchKey"
201 #ifndef NSAccessibilityButtonSearchKey
202 #define NSAccessibilityButtonSearchKey @"AXButtonSearchKey"
205 #ifndef NSAccessibilityCheckBoxSearchKey
206 #define NSAccessibilityCheckBoxSearchKey @"AXCheckBoxSearchKey"
209 #ifndef NSAccessibilityControlSearchKey
210 #define NSAccessibilityControlSearchKey @"AXControlSearchKey"
213 #ifndef NSAccessibilityDifferentTypeSearchKey
214 #define NSAccessibilityDifferentTypeSearchKey @"AXDifferentTypeSearchKey"
217 #ifndef NSAccessibilityFontChangeSearchKey
218 #define NSAccessibilityFontChangeSearchKey @"AXFontChangeSearchKey"
221 #ifndef NSAccessibilityFontColorChangeSearchKey
222 #define NSAccessibilityFontColorChangeSearchKey @"AXFontColorChangeSearchKey"
225 #ifndef NSAccessibilityFrameSearchKey
226 #define NSAccessibilityFrameSearchKey @"AXFrameSearchKey"
229 #ifndef NSAccessibilityGraphicSearchKey
230 #define NSAccessibilityGraphicSearchKey @"AXGraphicSearchKey"
233 #ifndef NSAccessibilityHeadingLevel1SearchKey
234 #define NSAccessibilityHeadingLevel1SearchKey @"AXHeadingLevel1SearchKey"
237 #ifndef NSAccessibilityHeadingLevel2SearchKey
238 #define NSAccessibilityHeadingLevel2SearchKey @"AXHeadingLevel2SearchKey"
241 #ifndef NSAccessibilityHeadingLevel3SearchKey
242 #define NSAccessibilityHeadingLevel3SearchKey @"AXHeadingLevel3SearchKey"
245 #ifndef NSAccessibilityHeadingLevel4SearchKey
246 #define NSAccessibilityHeadingLevel4SearchKey @"AXHeadingLevel4SearchKey"
249 #ifndef NSAccessibilityHeadingLevel5SearchKey
250 #define NSAccessibilityHeadingLevel5SearchKey @"AXHeadingLevel5SearchKey"
253 #ifndef NSAccessibilityHeadingLevel6SearchKey
254 #define NSAccessibilityHeadingLevel6SearchKey @"AXHeadingLevel6SearchKey"
257 #ifndef NSAccessibilityHeadingSameLevelSearchKey
258 #define NSAccessibilityHeadingSameLevelSearchKey @"AXHeadingSameLevelSearchKey"
261 #ifndef NSAccessibilityHeadingSearchKey
262 #define NSAccessibilityHeadingSearchKey @"AXHeadingSearchKey"
265 #ifndef NSAccessibilityHighlightedSearchKey
266 #define NSAccessibilityHighlightedSearchKey @"AXHighlightedSearchKey"
269 #ifndef NSAccessibilityItalicFontSearchKey
270 #define NSAccessibilityItalicFontSearchKey @"AXItalicFontSearchKey"
273 #ifndef NSAccessibilityLandmarkSearchKey
274 #define NSAccessibilityLandmarkSearchKey @"AXLandmarkSearchKey"
277 #ifndef NSAccessibilityLinkSearchKey
278 #define NSAccessibilityLinkSearchKey @"AXLinkSearchKey"
281 #ifndef NSAccessibilityListSearchKey
282 #define NSAccessibilityListSearchKey @"AXListSearchKey"
285 #ifndef NSAccessibilityLiveRegionSearchKey
286 #define NSAccessibilityLiveRegionSearchKey @"AXLiveRegionSearchKey"
289 #ifndef NSAccessibilityMisspelledWordSearchKey
290 #define NSAccessibilityMisspelledWordSearchKey @"AXMisspelledWordSearchKey"
293 #ifndef NSAccessibilityPlainTextSearchKey
294 #define NSAccessibilityPlainTextSearchKey @"AXPlainTextSearchKey"
297 #ifndef NSAccessibilityRadioGroupSearchKey
298 #define NSAccessibilityRadioGroupSearchKey @"AXRadioGroupSearchKey"
301 #ifndef NSAccessibilitySameTypeSearchKey
302 #define NSAccessibilitySameTypeSearchKey @"AXSameTypeSearchKey"
305 #ifndef NSAccessibilityStaticTextSearchKey
306 #define NSAccessibilityStaticTextSearchKey @"AXStaticTextSearchKey"
309 #ifndef NSAccessibilityStyleChangeSearchKey
310 #define NSAccessibilityStyleChangeSearchKey @"AXStyleChangeSearchKey"
313 #ifndef NSAccessibilityTableSameLevelSearchKey
314 #define NSAccessibilityTableSameLevelSearchKey @"AXTableSameLevelSearchKey"
317 #ifndef NSAccessibilityTableSearchKey
318 #define NSAccessibilityTableSearchKey @"AXTableSearchKey"
321 #ifndef NSAccessibilityTextFieldSearchKey
322 #define NSAccessibilityTextFieldSearchKey @"AXTextFieldSearchKey"
325 #ifndef NSAccessibilityUnderlineSearchKey
326 #define NSAccessibilityUnderlineSearchKey @"AXUnderlineSearchKey"
329 #ifndef NSAccessibilityUnvisitedLinkSearchKey
330 #define NSAccessibilityUnvisitedLinkSearchKey @"AXUnvisitedLinkSearchKey"
333 #ifndef NSAccessibilityVisitedLinkSearchKey
334 #define NSAccessibilityVisitedLinkSearchKey @"AXVisitedLinkSearchKey"
337 #define NSAccessibilityTextMarkerIsValidParameterizedAttribute @"AXTextMarkerIsValid"
338 #define NSAccessibilityIndexForTextMarkerParameterizedAttribute @"AXIndexForTextMarker"
339 #define NSAccessibilityTextMarkerForIndexParameterizedAttribute @"AXTextMarkerForIndex"
342 #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"
354 @interface NSObject (WebKitAccessibilityArrayCategory)
356 - (NSUInteger)accessibilityIndexOfChild:(id)child;
357 - (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute;
358 - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount;
362 @implementation WebAccessibilityObjectWrapper
364 - (id)initWithAccessibilityObject:(AccessibilityObject*)axObject
366 if (!(self = [super init]))
373 - (void)unregisterUniqueIdForUIElement
375 wkUnregisterUniqueIdForElement(self);
380 // Send unregisterUniqueIdForUIElement unconditionally because if it is
381 // ever accidentally not done (via other bugs in our AX implementation) you
382 // end up with a crash like <rdar://problem/4273149>. It is safe and not
383 // expensive to send even if the object is not registered.
384 [self unregisterUniqueIdForUIElement];
388 - (BOOL)updateObjectBackingStore
390 // Calling updateBackingStore() can invalidate this element so self must be retained.
391 // If it does become invalidated, m_object will be nil.
392 [[self retain] autorelease];
397 m_object->updateBackingStore();
404 - (AccessibilityObject*)accessibilityObject
409 - (NSView*)attachmentView
411 ASSERT(m_object->isAttachment());
412 Widget* widget = m_object->widgetForAttachmentView();
415 return NSAccessibilityUnignoredDescendant(widget->platformWidget());
418 #pragma mark SystemInterface wrappers
420 static inline id CFAutoreleaseHelper(CFTypeRef obj)
423 CFMakeCollectable(obj);
424 [(id)obj autorelease];
428 static inline BOOL AXObjectIsTextMarker(id obj)
430 return obj != nil && CFGetTypeID(obj) == wkGetAXTextMarkerTypeID();
433 static inline BOOL AXObjectIsTextMarkerRange(id obj)
435 return obj != nil && CFGetTypeID(obj) == wkGetAXTextMarkerRangeTypeID();
438 static id AXTextMarkerRange(id startMarker, id endMarker)
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));
447 static id AXTextMarkerRangeStart(id range)
449 ASSERT(range != nil);
450 ASSERT(CFGetTypeID(range) == wkGetAXTextMarkerRangeTypeID());
451 return CFAutoreleaseHelper(wkCopyAXTextMarkerRangeStart(range));
454 static id AXTextMarkerRangeEnd(id range)
456 ASSERT(range != nil);
457 ASSERT(CFGetTypeID(range) == wkGetAXTextMarkerRangeTypeID());
458 return CFAutoreleaseHelper(wkCopyAXTextMarkerRangeEnd(range));
461 #pragma mark Search helpers
463 typedef HashMap<String, AccessibilitySearchKey> AccessibilitySearchKeyMap;
465 struct SearchKeyEntry {
467 AccessibilitySearchKey value;
470 static AccessibilitySearchKeyMap* createAccessibilitySearchKeyMap()
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 }
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);
520 static AccessibilitySearchKey accessibilitySearchKeyForString(const String& value)
523 return AnyTypeSearchKey;
525 static const AccessibilitySearchKeyMap* searchKeyMap = createAccessibilitySearchKeyMap();
527 AccessibilitySearchKey searchKey = searchKeyMap->get(value);
529 return searchKey ? searchKey : AnyTypeSearchKey;
532 #pragma mark Text Marker helpers
534 static id textMarkerForVisiblePosition(AXObjectCache* cache, const VisiblePosition& visiblePos)
538 TextMarkerData textMarkerData;
539 cache->textMarkerDataForVisiblePosition(textMarkerData, visiblePos);
540 if (!textMarkerData.axID)
543 return CFAutoreleaseHelper(wkCreateAXTextMarker(&textMarkerData, sizeof(textMarkerData)));
546 - (id)textMarkerForVisiblePosition:(const VisiblePosition &)visiblePos
548 return textMarkerForVisiblePosition(m_object->axObjectCache(), visiblePos);
551 static VisiblePosition visiblePositionForTextMarker(AXObjectCache* cache, CFTypeRef textMarker)
556 return VisiblePosition();
557 TextMarkerData textMarkerData;
558 if (!wkGetBytesFromAXTextMarker(textMarker, &textMarkerData, sizeof(textMarkerData)))
559 return VisiblePosition();
561 return cache->visiblePositionForTextMarkerData(textMarkerData);
564 - (VisiblePosition)visiblePositionForTextMarker:(id)textMarker
566 return visiblePositionForTextMarker(m_object->axObjectCache(), textMarker);
569 static VisiblePosition visiblePositionForStartOfTextMarkerRange(AXObjectCache *cache, id textMarkerRange)
571 return visiblePositionForTextMarker(cache, AXTextMarkerRangeStart(textMarkerRange));
574 static VisiblePosition visiblePositionForEndOfTextMarkerRange(AXObjectCache *cache, id textMarkerRange)
576 return visiblePositionForTextMarker(cache, AXTextMarkerRangeEnd(textMarkerRange));
579 static id textMarkerRangeFromMarkers(id textMarker1, id textMarker2)
581 if (!textMarker1 || !textMarker2)
584 return AXTextMarkerRange(textMarker1, textMarker2);
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)
591 return (range.location < [attrString length] && NSMaxRange(range) <= [attrString length]);
594 static void AXAttributeStringSetFont(NSMutableAttributedString* attrString, NSString* attribute, NSFont* font, NSRange range)
596 if (!AXAttributedStringRangeIsValid(attrString, range))
600 NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
601 [font fontName] , NSAccessibilityFontNameKey,
602 [font familyName] , NSAccessibilityFontFamilyKey,
603 [font displayName] , NSAccessibilityVisibleNameKey,
604 [NSNumber numberWithFloat:[font pointSize]] , NSAccessibilityFontSizeKey,
607 [attrString addAttribute:attribute value:dict range:range];
609 [attrString removeAttribute:attribute range:range];
613 static CGColorRef CreateCGColorIfDifferent(NSColor* nsColor, CGColorRef existingColor)
615 // get color information assuming NSDeviceRGBColorSpace
616 NSColor* rgbColor = [nsColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
618 rgbColor = [NSColor blackColor];
619 CGFloat components[4];
620 [rgbColor getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]];
622 // create a new CGColorRef to return
623 CGColorSpaceRef cgColorSpace = CGColorSpaceCreateDeviceRGB();
624 CGColorRef cgColor = CGColorCreate(cgColorSpace, components);
625 CGColorSpaceRelease(cgColorSpace);
627 // check for match with existing color
628 if (existingColor && CGColorEqualToColor(cgColor, existingColor)) {
629 CGColorRelease(cgColor);
636 static void AXAttributeStringSetColor(NSMutableAttributedString* attrString, NSString* attribute, NSColor* color, NSRange range)
638 if (!AXAttributedStringRangeIsValid(attrString, range))
642 CGColorRef existingColor = (CGColorRef) [attrString attribute:attribute atIndex:range.location effectiveRange:nil];
643 CGColorRef cgColor = CreateCGColorIfDifferent(color, existingColor);
645 [attrString addAttribute:attribute value:(id)cgColor range:range];
646 CGColorRelease(cgColor);
649 [attrString removeAttribute:attribute range:range];
652 static void AXAttributeStringSetNumber(NSMutableAttributedString* attrString, NSString* attribute, NSNumber* number, NSRange range)
654 if (!AXAttributedStringRangeIsValid(attrString, range))
658 [attrString addAttribute:attribute value:number range:range];
660 [attrString removeAttribute:attribute range:range];
663 static void AXAttributeStringSetStyle(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
665 RenderStyle* style = renderer->style();
667 // set basic font info
668 AXAttributeStringSetFont(attrString, NSAccessibilityFontTextAttribute, style->font().primaryFont()->getNSFont(), range);
671 AXAttributeStringSetColor(attrString, NSAccessibilityForegroundColorTextAttribute, nsColor(style->visitedDependentColor(CSSPropertyColor)), range);
672 AXAttributeStringSetColor(attrString, NSAccessibilityBackgroundColorTextAttribute, nsColor(style->visitedDependentColor(CSSPropertyBackgroundColor)), range);
674 // set super/sub scripting
675 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);
681 [attrString removeAttribute:NSAccessibilitySuperscriptTextAttribute range:range];
684 if (style->textShadow())
685 AXAttributeStringSetNumber(attrString, NSAccessibilityShadowTextAttribute, [NSNumber numberWithBool:YES], range);
687 [attrString removeAttribute:NSAccessibilityShadowTextAttribute range:range];
689 // set underline and strikethrough
690 int decor = style->textDecorationsInEffect();
691 if ((decor & UNDERLINE) == 0) {
692 [attrString removeAttribute:NSAccessibilityUnderlineTextAttribute range:range];
693 [attrString removeAttribute:NSAccessibilityUnderlineColorTextAttribute range:range];
696 if ((decor & LINE_THROUGH) == 0) {
697 [attrString removeAttribute:NSAccessibilityStrikethroughTextAttribute range:range];
698 [attrString removeAttribute:NSAccessibilityStrikethroughColorTextAttribute range:range];
701 if ((decor & (UNDERLINE | LINE_THROUGH)) != 0) {
702 // find colors using quirk mode approach (strict mode would use current
703 // color for all but the root line box, which would use getTextDecorationColors)
704 Color underline, overline, linethrough;
705 renderer->getTextDecorationColors(decor, underline, overline, linethrough);
707 if ((decor & UNDERLINE) != 0) {
708 AXAttributeStringSetNumber(attrString, NSAccessibilityUnderlineTextAttribute, [NSNumber numberWithBool:YES], range);
709 AXAttributeStringSetColor(attrString, NSAccessibilityUnderlineColorTextAttribute, nsColor(underline), range);
712 if ((decor & LINE_THROUGH) != 0) {
713 AXAttributeStringSetNumber(attrString, NSAccessibilityStrikethroughTextAttribute, [NSNumber numberWithBool:YES], range);
714 AXAttributeStringSetColor(attrString, NSAccessibilityStrikethroughColorTextAttribute, nsColor(linethrough), range);
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);
725 static void AXAttributeStringSetBlockquoteLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
727 if (!AXAttributedStringRangeIsValid(attrString, range))
730 AccessibilityObject* obj = renderer->document()->axObjectCache()->getOrCreate(renderer);
731 int quoteLevel = obj->blockquoteLevel();
734 [attrString addAttribute:NSAccessibilityBlockQuoteLevelAttribute value:[NSNumber numberWithInt:quoteLevel] range:range];
736 [attrString removeAttribute:NSAccessibilityBlockQuoteLevelAttribute range:range];
739 static void AXAttributeStringSetSpelling(NSMutableAttributedString* attrString, Node* node, const UChar* chars, int charLength, NSRange range)
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();
745 // checkTextOfParagraph is the only spelling/grammar checker implemented in WK1 and WK2
746 Vector<TextCheckingResult> results;
747 checkTextOfParagraph(checker, chars, charLength, TextCheckingTypeSpelling, results);
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));
758 int currentPosition = 0;
759 while (charLength > 0) {
760 const UChar* charData = chars + currentPosition;
761 TextCheckerClient* checker = node->document()->frame()->editor()->textChecker();
763 int misspellingLocation = -1;
764 int misspellingLength = 0;
765 checker->checkSpellingOfString(charData, charLength, &misspellingLocation, &misspellingLength);
766 if (misspellingLocation == -1 || !misspellingLength)
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);
776 static void AXAttributeStringSetHeadingLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
781 if (!AXAttributedStringRangeIsValid(attrString, range))
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)
794 if (parentHeadingLevel)
795 [attrString addAttribute:@"AXHeadingLevel" value:[NSNumber numberWithInt:parentHeadingLevel] range:range];
797 [attrString removeAttribute:@"AXHeadingLevel" range:range];
800 static void AXAttributeStringSetElement(NSMutableAttributedString* attrString, NSString* attribute, AccessibilityObject* object, NSRange range)
802 if (!AXAttributedStringRangeIsValid(attrString, range))
805 if (object && object->isAccessibilityRenderObject()) {
806 // make a serializable AX object
808 RenderObject* renderer = static_cast<AccessibilityRenderObject*>(object)->renderer();
812 Document* doc = renderer->document();
816 AXObjectCache* cache = doc->axObjectCache();
820 AXUIElementRef axElement = wkCreateAXUIElementRef(object->wrapper());
822 [attrString addAttribute:attribute value:(id)axElement range:range];
823 CFRelease(axElement);
826 [attrString removeAttribute:attribute range:range];
829 static void AXAttributedStringAppendText(NSMutableAttributedString* attrString, Node* node, const UChar* chars, int length)
831 // skip invisible text
832 if (!node->renderer())
835 // easier to calculate the range before appending the string
836 NSRange attrStringRange = NSMakeRange([attrString length], length);
838 // append the string from this node
839 [[attrString mutableString] appendString:[NSString stringWithCharacters:chars length:length]];
841 // add new attributes and remove irrelevant inherited ones
842 // NOTE: color attributes are handled specially because -[NSMutableAttributedString addAttribute: value: range:] does not merge
843 // identical colors. Workaround is to not replace an existing color attribute if it matches what we are adding. This also means
844 // we cannot just pre-remove all inherited attributes on the appended string, so we have to remove the irrelevant ones individually.
846 // remove inherited attachment from prior AXAttributedStringAppendReplaced
847 [attrString removeAttribute:NSAccessibilityAttachmentTextAttribute range:attrStringRange];
848 [attrString removeAttribute:NSAccessibilityMisspelledTextAttribute range:attrStringRange];
850 // set new attributes
851 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);
856 // do spelling last because it tends to break up the range
857 AXAttributeStringSetSpelling(attrString, node, chars, length, attrStringRange);
860 static NSString* nsStringForReplacedNode(Node* replacedNode)
862 // we should always be given a rendered node and a replaced node, but be safe
863 // replaced nodes are either attachments (widgets) or images
864 if (!replacedNode || !replacedNode->renderer() || !replacedNode->renderer()->isReplaced() || replacedNode->isTextNode()) {
865 ASSERT_NOT_REACHED();
869 // create an AX object, but skip it if it is not supposed to be seen
870 RefPtr<AccessibilityObject> obj = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer());
871 if (obj->accessibilityIsIgnored())
874 // use the attachmentCharacter to represent the replaced node
875 const UniChar attachmentChar = NSAttachmentCharacter;
876 return [NSString stringWithCharacters:&attachmentChar length:1];
879 - (NSAttributedString*)doAXAttributedStringForTextMarkerRange:(id)textMarkerRange
884 // extract the start and end VisiblePosition
885 VisiblePosition startVisiblePosition = visiblePositionForStartOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);
886 if (startVisiblePosition.isNull())
889 VisiblePosition endVisiblePosition = visiblePositionForEndOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);
890 if (endVisiblePosition.isNull())
893 VisiblePositionRange visiblePositionRange(startVisiblePosition, endVisiblePosition);
894 // iterate over the range to build the AX attributed string
895 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 range
900 Node* node = it.range()->startContainer(exception);
901 ASSERT(node == it.range()->endContainer(exception));
902 int offset = it.range()->startOffset(exception);
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());
911 AXAttributedStringAppendText(attrString, node, it.characters(), it.length());
913 Node* replacedNode = node->childNode(offset);
914 NSString *attachmentString = nsStringForReplacedNode(replacedNode);
915 if (attachmentString) {
916 NSRange attrStringRange = NSMakeRange([attrString length], [attachmentString length]);
918 // append the placeholder string
919 [[attrString mutableString] appendString:attachmentString];
921 // remove all inherited attributes
922 [attrString setAttributes:nil range:attrStringRange];
924 // add the attachment attribute
925 AccessibilityObject* obj = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer());
926 AXAttributeStringSetElement(attrString, NSAccessibilityAttachmentTextAttribute, obj, attrStringRange);
932 return [attrString autorelease];
935 static id textMarkerRangeFromVisiblePositions(AXObjectCache *cache, VisiblePosition startPosition, VisiblePosition endPosition)
937 id startTextMarker = textMarkerForVisiblePosition(cache, startPosition);
938 id endTextMarker = textMarkerForVisiblePosition(cache, endPosition);
939 return textMarkerRangeFromMarkers(startTextMarker, endTextMarker);
942 - (id)textMarkerRangeFromVisiblePositions:(VisiblePosition)startPosition endPosition:(VisiblePosition)endPosition
944 return textMarkerRangeFromVisiblePositions(m_object->axObjectCache(), startPosition, endPosition);
947 - (NSArray*)accessibilityActionNames
949 if (![self updateObjectBackingStore])
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];
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];
967 actions = defaultElementActions;
972 - (NSArray*)additionalAccessibilityAttributeNames
977 NSMutableArray *additional = [NSMutableArray array];
978 if (m_object->supportsARIAOwns())
979 [additional addObject:NSAccessibilityOwnsAttribute];
981 if (m_object->supportsARIAExpanded())
982 [additional addObject:NSAccessibilityExpandedAttribute];
984 if (m_object->isScrollbar())
985 [additional addObject:NSAccessibilityOrientationAttribute];
987 if (m_object->supportsARIADragging())
988 [additional addObject:NSAccessibilityGrabbedAttribute];
990 if (m_object->supportsARIADropping())
991 [additional addObject:NSAccessibilityDropEffectsAttribute];
993 if (m_object->isAccessibilityTable() && static_cast<AccessibilityTable*>(m_object)->supportsSelectedRows())
994 [additional addObject:NSAccessibilitySelectedRowsAttribute];
996 if (m_object->supportsARIALiveRegion()) {
997 [additional addObject:NSAccessibilityARIALiveAttribute];
998 [additional addObject:NSAccessibilityARIARelevantAttribute];
1001 if (m_object->sortDirection() != SortDirectionNone)
1002 [additional addObject:NSAccessibilitySortDirectionAttribute];
1004 // If an object is a child of a live region, then add these
1005 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];
1010 // Popup buttons on the Mac expose the value attribute.
1011 if (m_object->isPopUpButton())
1012 [additional addObject:NSAccessibilityValueAttribute];
1014 if (m_object->ariaHasPopup())
1015 [additional addObject:NSAccessibilityHasPopupAttribute];
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];
1041 - (NSArray*)accessibilityAttributeNames
1043 if (![self updateObjectBackingStore])
1046 if (m_object->isAttachment())
1047 return [[self attachmentView] accessibilityAttributeNames];
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",
1096 NSAccessibilityLinkedUIElementsAttribute,
1097 NSAccessibilitySelectedAttribute,
1098 NSAccessibilityBlockQuoteLevelAttribute,
1099 NSAccessibilityTopLevelUIElementAttribute,
1102 if (commonMenuAttrs == nil) {
1103 commonMenuAttrs = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1104 NSAccessibilityRoleDescriptionAttribute,
1105 NSAccessibilityChildrenAttribute,
1106 NSAccessibilityParentAttribute,
1107 NSAccessibilityEnabledAttribute,
1108 NSAccessibilityPositionAttribute,
1109 NSAccessibilitySizeAttribute,
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];
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];
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];
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];
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];
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];
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];
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];
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];
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];
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];
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];
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];
1239 if (comboBoxAttrs == nil) {
1240 tempArray = [[NSMutableArray alloc] initWithArray:controlAttrs];
1241 [tempArray addObject:NSAccessibilityExpandedAttribute];
1242 comboBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1243 [tempArray release];
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];
1258 if (tableRowAttrs == nil) {
1259 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1260 [tempArray addObject:NSAccessibilityIndexAttribute];
1261 tableRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1262 [tempArray release];
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];
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];
1280 if (groupAttrs == nil) {
1281 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1282 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1283 groupAttrs = [[NSArray alloc] initWithArray:tempArray];
1284 [tempArray release];
1286 if (inputImageAttrs == nil) {
1287 tempArray = [[NSMutableArray alloc] initWithArray:buttonAttrs];
1288 [tempArray addObject:NSAccessibilityURLAttribute];
1289 inputImageAttrs = [[NSArray alloc] initWithArray:tempArray];
1290 [tempArray release];
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];
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];
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];
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];
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];
1334 NSArray *objectAttributes = attributes;
1336 if (m_object->isPasswordField())
1337 objectAttributes = passwordFieldAttrs;
1339 else if (m_object->isWebArea())
1340 objectAttributes = webAreaAttrs;
1342 else if (m_object->isTextControl())
1343 objectAttributes = textAttrs;
1345 else if (m_object->isAnchor() || m_object->isImage() || m_object->isLink())
1346 objectAttributes = anchorAttrs;
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;
1359 objectAttributes = tableRowAttrs;
1362 else if (m_object->isTree())
1363 objectAttributes = outlineAttrs;
1364 else if (m_object->isTreeItem())
1365 objectAttributes = outlineRowAttrs;
1367 else if (m_object->isListBox())
1368 objectAttributes = listBoxAttrs;
1369 else if (m_object->isList())
1370 objectAttributes = listAttrs;
1372 else if (m_object->isComboBox())
1373 objectAttributes = comboBoxAttrs;
1375 else if (m_object->isProgressIndicator() || m_object->isSlider())
1376 objectAttributes = rangeAttrs;
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;
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;
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;
1404 NSArray *additionalAttributes = [self additionalAccessibilityAttributeNames];
1405 if ([additionalAttributes count])
1406 objectAttributes = [objectAttributes arrayByAddingObjectsFromArray:additionalAttributes];
1408 return objectAttributes;
1411 - (VisiblePositionRange)visiblePositionRangeForTextMarkerRange:(id)textMarkerRange
1413 if (!textMarkerRange)
1414 return VisiblePositionRange();
1415 AXObjectCache* cache = m_object->axObjectCache();
1416 return VisiblePositionRange(visiblePositionForStartOfTextMarkerRange(cache, textMarkerRange), visiblePositionForEndOfTextMarkerRange(cache, textMarkerRange));
1419 - (NSArray*)renderWidgetChildren
1421 Widget* widget = m_object->widget();
1424 return [(widget->platformWidget()) accessibilityAttributeValue: NSAccessibilityChildrenAttribute];
1427 - (id)remoteAccessibilityParentObject
1432 Document* document = m_object->document();
1436 Frame* frame = document->frame();
1440 return frame->loader()->client()->accessibilityRemoteObject();
1443 static void convertToVector(NSArray* array, AccessibilityObject::AccessibilityChildrenVector& vector)
1445 unsigned length = [array count];
1446 vector.reserveInitialCapacity(length);
1447 for (unsigned i = 0; i < length; ++i) {
1448 AccessibilityObject* obj = [[array objectAtIndex:i] accessibilityObject];
1454 static NSMutableArray* convertToNSArray(const AccessibilityObject::AccessibilityChildrenVector& vector)
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();
1462 // we want to return the attachment view instead of the object representing the attachment.
1463 // otherwise, we get palindrome errors in the AX hierarchy
1464 if (vector[i]->isAttachment() && [wrapper attachmentView])
1465 [array addObject:[wrapper attachmentView]];
1467 [array addObject:wrapper];
1473 - (id)textMarkerRangeForSelection
1475 VisibleSelection selection = m_object->selection();
1476 if (selection.isNone())
1478 return [self textMarkerRangeFromVisiblePositions:selection.visibleStart() endPosition:selection.visibleEnd()];
1481 - (NSValue *)position
1483 IntRect rect = pixelSnappedIntRect(m_object->elementRect());
1486 FrameView* frameView = m_object->documentFrameView();
1488 // WebKit1 code path... platformWidget() exists.
1489 if (frameView && frameView->platformWidget()) {
1491 // The Cocoa accessibility API wants the lower-left corner.
1492 point = NSMakePoint(rect.x(), rect.maxY());
1495 NSView* view = frameView->documentView();
1496 point = [[view window] convertBaseToScreen:[view convertPoint: point toView:nil]];
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();
1511 rect = scrollView->contentsToRootView(rect);
1513 Page* page = m_object->page();
1515 // If we have an empty chrome client (like SVG) then we should use the page
1516 // 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();
1521 point = page->chrome()->rootViewToScreen(rect).location();
1523 point = rect.location();
1526 return [NSValue valueWithPoint:point];
1529 typedef HashMap<int, NSString*> AccessibilityRoleMap;
1531 static const AccessibilityRoleMap& createAccessibilityRoleMap()
1534 AccessibilityRole value;
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 #if ACCESSIBILITY_TABLES
1597 { CellRole, NSAccessibilityCellRole },
1599 { CellRole, NSAccessibilityGroupRole },
1601 { TableHeaderContainerRole, NSAccessibilityGroupRole },
1602 { RowHeaderRole, NSAccessibilityGroupRole },
1603 { DefinitionListDefinitionRole, NSAccessibilityGroupRole },
1604 { DefinitionListTermRole, NSAccessibilityGroupRole },
1605 { SliderThumbRole, NSAccessibilityValueIndicatorRole },
1606 { LandmarkApplicationRole, NSAccessibilityGroupRole },
1607 { LandmarkBannerRole, NSAccessibilityGroupRole },
1608 { LandmarkComplementaryRole, NSAccessibilityGroupRole },
1609 { LandmarkContentInfoRole, NSAccessibilityGroupRole },
1610 { LandmarkMainRole, NSAccessibilityGroupRole },
1611 { LandmarkNavigationRole, NSAccessibilityGroupRole },
1612 { LandmarkSearchRole, NSAccessibilityGroupRole },
1613 { ApplicationAlertRole, NSAccessibilityGroupRole },
1614 { ApplicationAlertDialogRole, NSAccessibilityGroupRole },
1615 { ApplicationDialogRole, NSAccessibilityGroupRole },
1616 { ApplicationLogRole, NSAccessibilityGroupRole },
1617 { ApplicationMarqueeRole, NSAccessibilityGroupRole },
1618 { ApplicationStatusRole, NSAccessibilityGroupRole },
1619 { ApplicationTimerRole, NSAccessibilityGroupRole },
1620 { DocumentRole, NSAccessibilityGroupRole },
1621 { DocumentArticleRole, NSAccessibilityGroupRole },
1622 { DocumentMathRole, NSAccessibilityGroupRole },
1623 { DocumentNoteRole, NSAccessibilityGroupRole },
1624 { DocumentRegionRole, NSAccessibilityGroupRole },
1625 { UserInterfaceTooltipRole, NSAccessibilityGroupRole },
1626 { TabRole, NSAccessibilityRadioButtonRole },
1627 { TabListRole, NSAccessibilityTabGroupRole },
1628 { TabPanelRole, NSAccessibilityGroupRole },
1629 { TreeRole, NSAccessibilityOutlineRole },
1630 { TreeItemRole, NSAccessibilityRowRole },
1631 { ListItemRole, NSAccessibilityGroupRole },
1632 { ParagraphRole, NSAccessibilityGroupRole },
1633 { LabelRole, NSAccessibilityGroupRole },
1634 { DivRole, NSAccessibilityGroupRole },
1635 { FormRole, NSAccessibilityGroupRole },
1636 { SpinButtonRole, NSAccessibilityIncrementorRole },
1637 { FooterRole, NSAccessibilityGroupRole },
1638 { ToggleButtonRole, NSAccessibilityButtonRole },
1639 { CanvasRole, NSAccessibilityImageRole },
1640 { SVGRootRole, NSAccessibilityGroupRole },
1641 { LegendRole, NSAccessibilityGroupRole },
1642 { MathElementRole, NSAccessibilityGroupRole }
1644 AccessibilityRoleMap& roleMap = *new AccessibilityRoleMap;
1646 const unsigned numRoles = sizeof(roles) / sizeof(roles[0]);
1647 for (unsigned i = 0; i < numRoles; ++i)
1648 roleMap.set(roles[i].value, roles[i].string);
1652 static NSString* roleValueToNSString(AccessibilityRole value)
1655 static const AccessibilityRoleMap& roleMap = createAccessibilityRoleMap();
1656 return roleMap.get(value);
1661 if (m_object->isAttachment())
1662 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleAttribute];
1663 AccessibilityRole role = m_object->roleValue();
1664 if (role == CanvasRole && m_object->canvasHasFallbackContent())
1666 NSString* string = roleValueToNSString(role);
1669 return NSAccessibilityUnknownRole;
1672 - (NSString*)subrole
1674 if (m_object->isPasswordField())
1675 return NSAccessibilitySecureTextFieldSubrole;
1676 if (m_object->isSearchField())
1677 return NSAccessibilitySearchFieldSubrole;
1679 if (m_object->isAttachment()) {
1680 NSView* attachView = [self attachmentView];
1681 if ([[attachView accessibilityAttributeNames] containsObject:NSAccessibilitySubroleAttribute]) {
1682 return [attachView accessibilityAttributeValue:NSAccessibilitySubroleAttribute];
1686 if (m_object->isSpinButtonPart()) {
1687 if (toAccessibilitySpinButtonPart(m_object)->isIncrementor())
1688 return NSAccessibilityIncrementArrowSubrole;
1690 return NSAccessibilityDecrementArrowSubrole;
1693 if (m_object->isFileUploadButton())
1694 return @"AXFileUploadButton";
1696 if (m_object->isTreeItem())
1697 return NSAccessibilityOutlineRowSubrole;
1699 if (m_object->isList()) {
1700 AccessibilityList* listObject = static_cast<AccessibilityList*>(m_object);
1701 if (listObject->isUnorderedList() || listObject->isOrderedList())
1702 return NSAccessibilityContentListSubrole;
1703 if (listObject->isDefinitionList())
1704 return NSAccessibilityDefinitionListSubrole;
1707 // ARIA content subroles.
1708 switch (m_object->roleValue()) {
1709 case LandmarkApplicationRole:
1710 return @"AXLandmarkApplication";
1711 case LandmarkBannerRole:
1712 return @"AXLandmarkBanner";
1713 case LandmarkComplementaryRole:
1714 return @"AXLandmarkComplementary";
1715 // Footer roles should appear as content info types.
1717 case LandmarkContentInfoRole:
1718 return @"AXLandmarkContentInfo";
1719 case LandmarkMainRole:
1720 return @"AXLandmarkMain";
1721 case LandmarkNavigationRole:
1722 return @"AXLandmarkNavigation";
1723 case LandmarkSearchRole:
1724 return @"AXLandmarkSearch";
1725 case ApplicationAlertRole:
1726 return @"AXApplicationAlert";
1727 case ApplicationAlertDialogRole:
1728 return @"AXApplicationAlertDialog";
1729 case ApplicationDialogRole:
1730 return @"AXApplicationDialog";
1731 case ApplicationLogRole:
1732 return @"AXApplicationLog";
1733 case ApplicationMarqueeRole:
1734 return @"AXApplicationMarquee";
1735 case ApplicationStatusRole:
1736 return @"AXApplicationStatus";
1737 case ApplicationTimerRole:
1738 return @"AXApplicationTimer";
1740 return @"AXDocument";
1741 case DocumentArticleRole:
1742 return @"AXDocumentArticle";
1743 case DocumentMathRole:
1744 return @"AXDocumentMath";
1745 case DocumentNoteRole:
1746 return @"AXDocumentNote";
1747 case DocumentRegionRole:
1748 return @"AXDocumentRegion";
1749 case UserInterfaceTooltipRole:
1750 return @"AXUserInterfaceTooltip";
1752 return @"AXTabPanel";
1753 case DefinitionListTermRole:
1755 case DefinitionListDefinitionRole:
1756 return @"AXDefinition";
1757 // Default doesn't return anything, so roles defined below can be chosen.
1762 if (m_object->roleValue() == MathElementRole) {
1763 if (m_object->isMathFraction())
1764 return @"AXMathFraction";
1765 if (m_object->isMathFenced())
1766 return @"AXMathFenced";
1767 if (m_object->isMathSubscriptSuperscript())
1768 return @"AXMathSubscriptSuperscript";
1769 if (m_object->isMathRow())
1770 return @"AXMathRow";
1771 if (m_object->isMathUnderOver())
1772 return @"AXMathUnderOver";
1773 if (m_object->isMathSquareRoot())
1774 return @"AXMathSquareRoot";
1775 if (m_object->isMathRoot())
1776 return @"AXMathRoot";
1777 if (m_object->isMathText())
1778 return @"AXMathText";
1779 if (m_object->isMathNumber())
1780 return @"AXMathNumber";
1781 if (m_object->isMathIdentifier())
1782 return @"AXMathIdentifier";
1783 if (m_object->isMathTable())
1784 return @"AXMathTable";
1785 if (m_object->isMathTableRow())
1786 return @"AXMathTableRow";
1787 if (m_object->isMathTableCell())
1788 return @"AXMathTableCell";
1789 if (m_object->isMathFenceOperator())
1790 return @"AXMathFenceOperator";
1791 if (m_object->isMathSeparatorOperator())
1792 return @"AXMathSeparatorOperator";
1793 if (m_object->isMathOperator())
1794 return @"AXMathOperator";
1797 if (m_object->isMediaTimeline())
1798 return NSAccessibilityTimelineSubrole;
1803 - (NSString*)roleDescription
1808 // attachments have the AXImage role, but a different subrole
1809 if (m_object->isAttachment())
1810 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute];
1812 NSString* axRole = [self role];
1814 if ([axRole isEqualToString:NSAccessibilityGroupRole]) {
1815 switch (m_object->roleValue()) {
1817 return NSAccessibilityRoleDescription(NSAccessibilityGroupRole, [self subrole]);
1818 case LandmarkApplicationRole:
1819 return AXARIAContentGroupText(@"ARIALandmarkApplication");
1820 case LandmarkBannerRole:
1821 return AXARIAContentGroupText(@"ARIALandmarkBanner");
1822 case LandmarkComplementaryRole:
1823 return AXARIAContentGroupText(@"ARIALandmarkComplementary");
1824 case LandmarkContentInfoRole:
1825 return AXARIAContentGroupText(@"ARIALandmarkContentInfo");
1826 case LandmarkMainRole:
1827 return AXARIAContentGroupText(@"ARIALandmarkMain");
1828 case LandmarkNavigationRole:
1829 return AXARIAContentGroupText(@"ARIALandmarkNavigation");
1830 case LandmarkSearchRole:
1831 return AXARIAContentGroupText(@"ARIALandmarkSearch");
1832 case ApplicationAlertRole:
1833 return AXARIAContentGroupText(@"ARIAApplicationAlert");
1834 case ApplicationAlertDialogRole:
1835 return AXARIAContentGroupText(@"ARIAApplicationAlertDialog");
1836 case ApplicationDialogRole:
1837 return AXARIAContentGroupText(@"ARIAApplicationDialog");
1838 case ApplicationLogRole:
1839 return AXARIAContentGroupText(@"ARIAApplicationLog");
1840 case ApplicationMarqueeRole:
1841 return AXARIAContentGroupText(@"ARIAApplicationMarquee");
1842 case ApplicationStatusRole:
1843 return AXARIAContentGroupText(@"ARIAApplicationStatus");
1844 case ApplicationTimerRole:
1845 return AXARIAContentGroupText(@"ARIAApplicationTimer");
1847 return AXARIAContentGroupText(@"ARIADocument");
1848 case DocumentArticleRole:
1849 return AXARIAContentGroupText(@"ARIADocumentArticle");
1850 case DocumentMathRole:
1851 return AXARIAContentGroupText(@"ARIADocumentMath");
1852 case DocumentNoteRole:
1853 return AXARIAContentGroupText(@"ARIADocumentNote");
1854 case DocumentRegionRole:
1855 return AXARIAContentGroupText(@"ARIADocumentRegion");
1856 case UserInterfaceTooltipRole:
1857 return AXARIAContentGroupText(@"ARIAUserInterfaceTooltip");
1859 return AXARIAContentGroupText(@"ARIATabPanel");
1860 case DefinitionListTermRole:
1861 return AXDefinitionListTermText();
1862 case DefinitionListDefinitionRole:
1863 return AXDefinitionListDefinitionText();
1865 return AXFooterRoleDescriptionText();
1869 if ([axRole isEqualToString:@"AXWebArea"])
1870 return AXWebAreaText();
1872 if ([axRole isEqualToString:@"AXLink"])
1873 return AXLinkText();
1875 if ([axRole isEqualToString:@"AXListMarker"])
1876 return AXListMarkerText();
1878 if ([axRole isEqualToString:@"AXImageMap"])
1879 return AXImageMapText();
1881 if ([axRole isEqualToString:@"AXHeading"])
1882 return AXHeadingText();
1884 if (m_object->isFileUploadButton())
1885 return AXFileUploadButtonText();
1887 // AppKit also returns AXTab for the role description for a tab item.
1888 if (m_object->isTabItem())
1889 return NSAccessibilityRoleDescription(@"AXTab", nil);
1891 // We should try the system default role description for all other roles.
1892 // If we get the same string back, then as a last resort, return unknown.
1893 NSString* defaultRoleDescription = NSAccessibilityRoleDescription(axRole, [self subrole]);
1894 if (![defaultRoleDescription isEqualToString:axRole])
1895 return defaultRoleDescription;
1897 return NSAccessibilityRoleDescription(NSAccessibilityUnknownRole, nil);
1900 - (id)scrollViewParent
1902 if (!m_object || !m_object->isAccessibilityScrollView())
1905 // If this scroll view provides it's parent object (because it's a sub-frame), then
1906 // we should not find the remoteAccessibilityParent.
1907 if (m_object->parentObject())
1910 AccessibilityScrollView* scrollView = toAccessibilityScrollView(m_object);
1911 ScrollView* scroll = scrollView->scrollView();
1915 if (scroll->platformWidget())
1916 return NSAccessibilityUnignoredAncestor(scroll->platformWidget());
1918 return [self remoteAccessibilityParentObject];
1921 // FIXME: Different kinds of elements are putting the title tag to use in different
1922 // AX fields. This should be rectified, but in the initial patch I want to achieve
1923 // parity with existing behavior.
1924 - (BOOL)titleTagShouldBeUsedInDescriptionField
1926 return (m_object->isLink() && !m_object->isImageMapLink()) || m_object->isImage();
1929 // This should be the "visible" text that's actually on the screen if possible.
1930 // If there's alternative text, that can override the title.
1931 - (NSString *)accessibilityTitle
1933 // Static text objects should not have a title. Its content is communicated in its AXValue.
1934 if (m_object->roleValue() == StaticTextRole)
1935 return [NSString string];
1937 // A file upload button presents a challenge because it has button text and a value, but the
1938 // API doesn't support this paradigm.
1939 // The compromise is to return the button type in the role description and the value of the file path in the title
1940 if (m_object->isFileUploadButton())
1941 return m_object->stringValue();
1943 Vector<AccessibilityText> textOrder;
1944 m_object->accessibilityText(textOrder);
1946 unsigned length = textOrder.size();
1947 for (unsigned k = 0; k < length; k++) {
1948 const AccessibilityText& text = textOrder[k];
1950 // If we have alternative text, then we should not expose a title.
1951 if (text.textSource == AlternativeText)
1954 // Once we encounter visible text, or the text from our children that should be used foremost.
1955 if (text.textSource == VisibleText || text.textSource == ChildrenText)
1958 // If there's an element that labels this object and it's not exposed, then we should use
1959 // that text as our title.
1960 if (text.textSource == LabelByElementText && !m_object->exposesTitleUIElement())
1963 // FIXME: The title tag is used in certain cases for the title. This usage should
1964 // probably be in the description field since it's not "visible".
1965 if (text.textSource == TitleTagText && ![self titleTagShouldBeUsedInDescriptionField])
1969 return [NSString string];
1972 - (NSString *)accessibilityDescription
1974 // Static text objects should not have a description. Its content is communicated in its AXValue.
1975 // One exception is the media control labels that have a value and a description. Those are set programatically.
1976 if (m_object->roleValue() == StaticTextRole && !m_object->isMediaControlLabel())
1977 return [NSString string];
1979 Vector<AccessibilityText> textOrder;
1980 m_object->accessibilityText(textOrder);
1982 unsigned length = textOrder.size();
1983 for (unsigned k = 0; k < length; k++) {
1984 const AccessibilityText& text = textOrder[k];
1986 if (text.textSource == AlternativeText)
1989 if (text.textSource == TitleTagText && [self titleTagShouldBeUsedInDescriptionField])
1993 return [NSString string];
1996 - (NSString *)accessibilityHelpText
1998 Vector<AccessibilityText> textOrder;
1999 m_object->accessibilityText(textOrder);
2001 unsigned length = textOrder.size();
2002 bool descriptiveTextAvailable = false;
2003 for (unsigned k = 0; k < length; k++) {
2004 const AccessibilityText& text = textOrder[k];
2006 if (text.textSource == HelpText || text.textSource == SummaryText)
2009 // If an element does NOT have other descriptive text the title tag should be used as its descriptive text.
2010 // But, if those ARE available, then the title tag should be used for help text instead.
2011 switch (text.textSource) {
2012 case AlternativeText:
2015 case LabelByElementText:
2016 descriptiveTextAvailable = true;
2021 if (text.textSource == TitleTagText && descriptiveTextAvailable)
2025 return [NSString string];
2028 // FIXME: split up this function in a better way.
2029 // suggestions: Use a hash table that maps attribute names to function calls,
2030 // or maybe pointers to member functions
2031 - (id)accessibilityAttributeValue:(NSString*)attributeName
2033 if (![self updateObjectBackingStore])
2036 if ([attributeName isEqualToString: NSAccessibilityRoleAttribute])
2039 if ([attributeName isEqualToString: NSAccessibilitySubroleAttribute])
2040 return [self subrole];
2042 if ([attributeName isEqualToString: NSAccessibilityRoleDescriptionAttribute])
2043 return [self roleDescription];
2045 if ([attributeName isEqualToString: NSAccessibilityParentAttribute]) {
2047 // This will return the parent of the AXWebArea, if this is a web area.
2048 id scrollViewParent = [self scrollViewParent];
2049 if (scrollViewParent)
2050 return scrollViewParent;
2052 // Tree item (changed to AXRows) can only report the tree (AXOutline) as its parent.
2053 if (m_object->isTreeItem()) {
2054 AccessibilityObject* parent = m_object->parentObjectUnignored();
2056 if (parent->isTree())
2057 return parent->wrapper();
2058 parent = parent->parentObjectUnignored();
2062 AccessibilityObject* parent = m_object->parentObjectUnignored();
2066 // In WebKit1, the scroll view is provided by the system (the attachment view), so the parent
2067 // should be reported directly as such.
2068 if (m_object->isWebArea() && parent->isAttachment())
2069 return [parent->wrapper() attachmentView];
2071 return parent->wrapper();
2074 if ([attributeName isEqualToString: NSAccessibilityChildrenAttribute]) {
2075 if (m_object->children().isEmpty()) {
2076 NSArray* children = [self renderWidgetChildren];
2077 if (children != nil)
2081 // The tree's (AXOutline) children are supposed to be its rows and columns.
2082 // The ARIA spec doesn't have columns, so we just need rows.
2083 if (m_object->isTree())
2084 return [self accessibilityAttributeValue:NSAccessibilityRowsAttribute];
2086 // A tree item should only expose its content as its children (not its rows)
2087 if (m_object->isTreeItem()) {
2088 AccessibilityObject::AccessibilityChildrenVector contentCopy;
2089 m_object->ariaTreeItemContent(contentCopy);
2090 return convertToNSArray(contentCopy);
2093 return convertToNSArray(m_object->children());
2096 if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {
2097 if (m_object->isListBox()) {
2098 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2099 m_object->selectedChildren(selectedChildrenCopy);
2100 return convertToNSArray(selectedChildrenCopy);
2105 if ([attributeName isEqualToString: NSAccessibilityVisibleChildrenAttribute]) {
2106 if (m_object->isListBox()) {
2107 AccessibilityObject::AccessibilityChildrenVector visibleChildrenCopy;
2108 m_object->visibleChildren(visibleChildrenCopy);
2109 return convertToNSArray(visibleChildrenCopy);
2111 else if (m_object->isList())
2112 return [self accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
2118 if (m_object->isWebArea()) {
2119 if ([attributeName isEqualToString:@"AXLinkUIElements"]) {
2120 AccessibilityObject::AccessibilityChildrenVector links;
2121 static_cast<AccessibilityRenderObject*>(m_object)->getDocumentLinks(links);
2122 return convertToNSArray(links);
2124 if ([attributeName isEqualToString:@"AXLoaded"])
2125 return [NSNumber numberWithBool:m_object->isLoaded()];
2126 if ([attributeName isEqualToString:@"AXLayoutCount"])
2127 return [NSNumber numberWithInt:m_object->layoutCount()];
2128 if ([attributeName isEqualToString:NSAccessibilityLoadingProgressAttribute])
2129 return [NSNumber numberWithDouble:m_object->estimatedLoadingProgress()];
2132 if (m_object->isTextControl()) {
2133 if ([attributeName isEqualToString: NSAccessibilityNumberOfCharactersAttribute]) {
2134 int length = m_object->textLength();
2137 return [NSNumber numberWithUnsignedInt:length];
2139 if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
2140 String selectedText = m_object->selectedText();
2141 if (selectedText.isNull())
2143 return (NSString*)selectedText;
2145 if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
2146 PlainTextRange textRange = m_object->selectedTextRange();
2147 if (textRange.isNull())
2148 return [NSValue valueWithRange:NSMakeRange(0, 0)];
2149 return [NSValue valueWithRange:NSMakeRange(textRange.start, textRange.length)];
2151 // TODO: Get actual visible range. <rdar://problem/4712101>
2152 if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
2153 return m_object->isPasswordField() ? nil : [NSValue valueWithRange: NSMakeRange(0, m_object->textLength())];
2154 if ([attributeName isEqualToString: NSAccessibilityInsertionPointLineNumberAttribute]) {
2155 // if selectionEnd > 0, then there is selected text and this question should not be answered
2156 if (m_object->isPasswordField() || m_object->selectionEnd() > 0)
2159 AccessibilityObject* focusedObject = m_object->focusedUIElement();
2160 if (focusedObject != m_object)
2163 VisiblePosition focusedPosition = focusedObject->visiblePositionForIndex(focusedObject->selectionStart(), true);
2164 int lineNumber = m_object->lineForPosition(focusedPosition);
2168 return [NSNumber numberWithInt:lineNumber];
2172 if ([attributeName isEqualToString: NSAccessibilityURLAttribute]) {
2173 KURL url = m_object->url();
2179 if (m_object->isSpinButton()) {
2180 if ([attributeName isEqualToString:NSAccessibilityIncrementButtonAttribute])
2181 return toAccessibilitySpinButton(m_object)->incrementButton()->wrapper();
2182 if ([attributeName isEqualToString:NSAccessibilityDecrementButtonAttribute])
2183 return toAccessibilitySpinButton(m_object)->decrementButton()->wrapper();
2186 if ([attributeName isEqualToString: @"AXVisited"])
2187 return [NSNumber numberWithBool: m_object->isVisited()];
2189 if ([attributeName isEqualToString: NSAccessibilityTitleAttribute]) {
2190 if (m_object->isAttachment()) {
2191 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityTitleAttribute])
2192 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityTitleAttribute];
2195 return [self accessibilityTitle];
2198 if ([attributeName isEqualToString: NSAccessibilityDescriptionAttribute]) {
2199 if (m_object->isAttachment()) {
2200 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityDescriptionAttribute])
2201 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityDescriptionAttribute];
2203 return [self accessibilityDescription];
2206 if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
2207 if (m_object->isAttachment()) {
2208 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityValueAttribute])
2209 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityValueAttribute];
2211 if (m_object->supportsRangeValue())
2212 return [NSNumber numberWithFloat:m_object->valueForRange()];
2213 if (m_object->roleValue() == SliderThumbRole)
2214 return [NSNumber numberWithFloat:m_object->parentObject()->valueForRange()];
2215 if (m_object->isHeading())
2216 return [NSNumber numberWithInt:m_object->headingLevel()];
2218 if (m_object->isCheckboxOrRadio()) {
2219 switch (m_object->checkboxOrRadioValue()) {
2220 case ButtonStateOff:
2221 return [NSNumber numberWithInt:0];
2223 return [NSNumber numberWithInt:1];
2224 case ButtonStateMixed:
2225 return [NSNumber numberWithInt:2];
2229 // radio groups return the selected radio button as the AXValue
2230 if (m_object->isRadioGroup()) {
2231 AccessibilityObject* radioButton = m_object->selectedRadioButton();
2234 return radioButton->wrapper();
2237 if (m_object->isTabList()) {
2238 AccessibilityObject* tabItem = m_object->selectedTabItem();
2241 return tabItem->wrapper();
2244 if (m_object->isTabItem())
2245 return [NSNumber numberWithInt:m_object->isSelected()];
2247 return m_object->stringValue();
2250 if ([attributeName isEqualToString: NSAccessibilityMinValueAttribute])
2251 return [NSNumber numberWithFloat:m_object->minValueForRange()];
2253 if ([attributeName isEqualToString: NSAccessibilityMaxValueAttribute])
2254 return [NSNumber numberWithFloat:m_object->maxValueForRange()];
2256 if ([attributeName isEqualToString: NSAccessibilityHelpAttribute])
2257 return [self accessibilityHelpText];
2259 if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
2260 return [NSNumber numberWithBool: m_object->isFocused()];
2262 if ([attributeName isEqualToString: NSAccessibilityEnabledAttribute])
2263 return [NSNumber numberWithBool: m_object->isEnabled()];
2265 if ([attributeName isEqualToString: NSAccessibilitySizeAttribute]) {
2266 IntSize s = m_object->pixelSnappedSize();
2267 return [NSValue valueWithSize: NSMakeSize(s.width(), s.height())];
2270 if ([attributeName isEqualToString: NSAccessibilityPositionAttribute])
2271 return [self position];
2273 if ([attributeName isEqualToString: NSAccessibilityWindowAttribute] ||
2274 [attributeName isEqualToString: NSAccessibilityTopLevelUIElementAttribute]) {
2276 id remoteParent = [self remoteAccessibilityParentObject];
2278 return [remoteParent accessibilityAttributeValue:attributeName];
2280 FrameView* fv = m_object->documentFrameView();
2282 return [fv->platformWidget() window];
2286 if ([attributeName isEqualToString:NSAccessibilityAccessKeyAttribute]) {
2287 AtomicString accessKey = m_object->accessKey();
2288 if (accessKey.isNull())
2293 if ([attributeName isEqualToString:NSAccessibilityTabsAttribute]) {
2294 if (m_object->isTabList()) {
2295 AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2296 m_object->tabChildren(tabsChildren);
2297 return convertToNSArray(tabsChildren);
2301 if ([attributeName isEqualToString:NSAccessibilityContentsAttribute]) {
2302 // The contents of a tab list are all the children except the tabs.
2303 if (m_object->isTabList()) {
2304 AccessibilityObject::AccessibilityChildrenVector children = m_object->children();
2305 AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2306 m_object->tabChildren(tabsChildren);
2308 AccessibilityObject::AccessibilityChildrenVector contents;
2309 unsigned childrenSize = children.size();
2310 for (unsigned k = 0; k < childrenSize; ++k) {
2311 if (tabsChildren.find(children[k]) == WTF::notFound)
2312 contents.append(children[k]);
2314 return convertToNSArray(contents);
2315 } else if (m_object->isScrollView()) {
2316 AccessibilityObject::AccessibilityChildrenVector children = m_object->children();
2318 // A scrollView's contents are everything except the scroll bars.
2319 AccessibilityObject::AccessibilityChildrenVector contents;
2320 unsigned childrenSize = children.size();
2321 for (unsigned k = 0; k < childrenSize; ++k) {
2322 if (!children[k]->isScrollbar())
2323 contents.append(children[k]);
2325 return convertToNSArray(contents);
2329 if (m_object->isAccessibilityTable()) {
2330 // TODO: distinguish between visible and non-visible rows
2331 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] ||
2332 [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
2333 return convertToNSArray(static_cast<AccessibilityTable*>(m_object)->rows());
2335 // TODO: distinguish between visible and non-visible columns
2336 if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute] ||
2337 [attributeName isEqualToString:NSAccessibilityVisibleColumnsAttribute]) {
2338 return convertToNSArray(static_cast<AccessibilityTable*>(m_object)->columns());
2341 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2342 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2343 m_object->selectedChildren(selectedChildrenCopy);
2344 return convertToNSArray(selectedChildrenCopy);
2347 // HTML tables don't support these
2348 if ([attributeName isEqualToString:NSAccessibilitySelectedColumnsAttribute] ||
2349 [attributeName isEqualToString:NSAccessibilitySelectedCellsAttribute])
2352 if ([attributeName isEqualToString:(NSString *)kAXColumnHeaderUIElementsAttribute]) {
2353 AccessibilityObject::AccessibilityChildrenVector columnHeaders;
2354 static_cast<AccessibilityTable*>(m_object)->columnHeaders(columnHeaders);
2355 return convertToNSArray(columnHeaders);
2358 if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2359 AccessibilityObject* headerContainer = static_cast<AccessibilityTable*>(m_object)->headerContainer();
2360 if (headerContainer)
2361 return headerContainer->wrapper();
2365 if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
2366 AccessibilityObject::AccessibilityChildrenVector rowHeaders;
2367 static_cast<AccessibilityTable*>(m_object)->rowHeaders(rowHeaders);
2368 return convertToNSArray(rowHeaders);
2371 if ([attributeName isEqualToString:NSAccessibilityVisibleCellsAttribute]) {
2372 AccessibilityObject::AccessibilityChildrenVector cells;
2373 static_cast<AccessibilityTable*>(m_object)->cells(cells);
2374 return convertToNSArray(cells);
2378 if (m_object->isTableColumn()) {
2379 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2380 return [NSNumber numberWithInt:static_cast<AccessibilityTableColumn*>(m_object)->columnIndex()];
2382 // rows attribute for a column is the list of all the elements in that column at each row
2383 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] ||
2384 [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
2385 return convertToNSArray(static_cast<AccessibilityTableColumn*>(m_object)->children());
2387 if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2388 AccessibilityObject* header = static_cast<AccessibilityTableColumn*>(m_object)->headerObject();
2391 return header->wrapper();
2395 if (m_object->isTableCell()) {
2396 if ([attributeName isEqualToString:NSAccessibilityRowIndexRangeAttribute]) {
2397 pair<int, int> rowRange;
2398 static_cast<AccessibilityTableCell*>(m_object)->rowIndexRange(rowRange);
2399 return [NSValue valueWithRange:NSMakeRange(rowRange.first, rowRange.second)];
2401 if ([attributeName isEqualToString:NSAccessibilityColumnIndexRangeAttribute]) {
2402 pair<int, int> columnRange;
2403 static_cast<AccessibilityTableCell*>(m_object)->columnIndexRange(columnRange);
2404 return [NSValue valueWithRange:NSMakeRange(columnRange.first, columnRange.second)];
2408 if (m_object->isTree()) {
2409 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2410 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2411 m_object->selectedChildren(selectedChildrenCopy);
2412 return convertToNSArray(selectedChildrenCopy);
2414 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute]) {
2415 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2416 m_object->ariaTreeRows(rowsCopy);
2417 return convertToNSArray(rowsCopy);
2420 // TreeRoles do not support columns, but Mac AX expects to be able to ask about columns at the least.
2421 if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute])
2422 return [NSArray array];
2425 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute]) {
2426 if (m_object->isTreeItem()) {
2427 AccessibilityObject* parent = m_object->parentObject();
2428 for (; parent && !parent->isTree(); parent = parent->parentObject())
2434 // Find the index of this item by iterating the parents.
2435 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2436 parent->ariaTreeRows(rowsCopy);
2437 size_t count = rowsCopy.size();
2438 for (size_t k = 0; k < count; ++k)
2439 if (rowsCopy[k]->wrapper() == self)
2440 return [NSNumber numberWithUnsignedInt:k];
2444 if (m_object->isTableRow()) {
2445 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2446 return [NSNumber numberWithInt:static_cast<AccessibilityTableRow*>(m_object)->rowIndex()];
2450 // The rows that are considered inside this row.
2451 if ([attributeName isEqualToString:NSAccessibilityDisclosedRowsAttribute]) {
2452 if (m_object->isTreeItem()) {
2453 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2454 m_object->ariaTreeItemDisclosedRows(rowsCopy);
2455 return convertToNSArray(rowsCopy);
2456 } else if (m_object->isARIATreeGridRow()) {
2457 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2458 static_cast<AccessibilityARIAGridRow*>(m_object)->disclosedRows(rowsCopy);
2459 return convertToNSArray(rowsCopy);
2463 // The row that contains this row. It should be the same as the first parent that is a treeitem.
2464 if ([attributeName isEqualToString:NSAccessibilityDisclosedByRowAttribute]) {
2465 if (m_object->isTreeItem()) {
2466 AccessibilityObject* parent = m_object->parentObject();
2468 if (parent->isTreeItem())
2469 return parent->wrapper();
2470 // If the parent is the tree itself, then this value == nil.
2471 if (parent->isTree())
2473 parent = parent->parentObject();
2476 } else if (m_object->isARIATreeGridRow()) {
2477 AccessibilityObject* row = static_cast<AccessibilityARIAGridRow*>(m_object)->disclosedByRow();
2480 return row->wrapper();
2484 if ([attributeName isEqualToString:NSAccessibilityDisclosureLevelAttribute]) {
2485 // Convert from 1-based level (from aria-level spec) to 0-based level (Mac)
2486 int level = m_object->hierarchicalLevel();
2489 return [NSNumber numberWithInt:level];
2491 if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
2492 return [NSNumber numberWithBool:m_object->isExpanded()];
2494 if ((m_object->isListBox() || m_object->isList()) && [attributeName isEqualToString:NSAccessibilityOrientationAttribute])
2495 return NSAccessibilityVerticalOrientationValue;
2497 if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
2498 return [self textMarkerRangeForSelection];
2500 if (m_object->renderer()) {
2501 if ([attributeName isEqualToString: @"AXStartTextMarker"])
2502 return [self textMarkerForVisiblePosition:startOfDocument(m_object->renderer()->document())];
2503 if ([attributeName isEqualToString: @"AXEndTextMarker"])
2504 return [self textMarkerForVisiblePosition:endOfDocument(m_object->renderer()->document())];
2507 if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute])
2508 return [NSNumber numberWithInt:m_object->blockquoteLevel()];
2509 if ([attributeName isEqualToString:@"AXTableLevel"])
2510 return [NSNumber numberWithInt:m_object->tableLevel()];
2512 if ([attributeName isEqualToString: NSAccessibilityLinkedUIElementsAttribute]) {
2513 AccessibilityObject::AccessibilityChildrenVector linkedUIElements;
2514 m_object->linkedUIElements(linkedUIElements);
2515 if (linkedUIElements.size() == 0)
2517 return convertToNSArray(linkedUIElements);
2520 if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
2521 return [NSNumber numberWithBool:m_object->isSelected()];
2523 if ([attributeName isEqualToString: NSAccessibilityServesAsTitleForUIElementsAttribute] && m_object->isMenuButton()) {
2524 AccessibilityObject* uiElement = static_cast<AccessibilityRenderObject*>(m_object)->menuForMenuButton();
2526 return [NSArray arrayWithObject:uiElement->wrapper()];
2529 if ([attributeName isEqualToString:NSAccessibilityTitleUIElementAttribute]) {
2530 if (!m_object->exposesTitleUIElement())
2533 AccessibilityObject* obj = m_object->titleUIElement();
2535 return obj->wrapper();
2539 if ([attributeName isEqualToString:NSAccessibilityValueDescriptionAttribute])
2540 return m_object->valueDescription();
2542 if ([attributeName isEqualToString:NSAccessibilityOrientationAttribute]) {
2543 AccessibilityOrientation elementOrientation = m_object->orientation();
2544 if (elementOrientation == AccessibilityOrientationVertical)
2545 return NSAccessibilityVerticalOrientationValue;
2546 if (elementOrientation == AccessibilityOrientationHorizontal)
2547 return NSAccessibilityHorizontalOrientationValue;
2551 if ([attributeName isEqualToString:NSAccessibilityHorizontalScrollBarAttribute]) {
2552 AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationHorizontal);
2554 return scrollBar->wrapper();
2557 if ([attributeName isEqualToString:NSAccessibilityVerticalScrollBarAttribute]) {
2558 AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationVertical);
2560 return scrollBar->wrapper();
2564 if ([attributeName isEqualToString:NSAccessibilitySortDirectionAttribute]) {
2565 switch (m_object->sortDirection()) {
2566 case SortDirectionAscending:
2567 return NSAccessibilityAscendingSortDirectionValue;
2568 case SortDirectionDescending:
2569 return NSAccessibilityDescendingSortDirectionValue;
2571 return NSAccessibilityUnknownSortDirectionValue;
2575 if ([attributeName isEqualToString:NSAccessibilityLanguageAttribute])
2576 return m_object->language();
2578 if ([attributeName isEqualToString:NSAccessibilityExpandedAttribute])
2579 return [NSNumber numberWithBool:m_object->isExpanded()];
2581 if ([attributeName isEqualToString:NSAccessibilityRequiredAttribute])
2582 return [NSNumber numberWithBool:m_object->isRequired()];
2584 if ([attributeName isEqualToString:NSAccessibilityInvalidAttribute])
2585 return m_object->invalidStatus();
2587 if ([attributeName isEqualToString:NSAccessibilityOwnsAttribute]) {
2588 AccessibilityObject::AccessibilityChildrenVector ariaOwns;
2589 m_object->ariaOwnsElements(ariaOwns);
2590 return convertToNSArray(ariaOwns);
2593 if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
2594 return [NSNumber numberWithBool:m_object->isARIAGrabbed()];
2596 if ([attributeName isEqualToString:NSAccessibilityDropEffectsAttribute]) {
2597 Vector<String> dropEffects;
2598 m_object->determineARIADropEffects(dropEffects);
2599 size_t length = dropEffects.size();
2601 NSMutableArray* dropEffectsArray = [NSMutableArray arrayWithCapacity:length];
2602 for (size_t i = 0; i < length; ++i)
2603 [dropEffectsArray addObject:dropEffects[i]];
2604 return dropEffectsArray;
2607 if ([attributeName isEqualToString:NSAccessibilityPlaceholderValueAttribute])
2608 return m_object->placeholderValue();
2610 if ([attributeName isEqualToString:NSAccessibilityHasPopupAttribute])
2611 return [NSNumber numberWithBool:m_object->ariaHasPopup()];
2613 // ARIA Live region attributes.
2614 if ([attributeName isEqualToString:NSAccessibilityARIALiveAttribute])
2615 return m_object->ariaLiveRegionStatus();
2616 if ([attributeName isEqualToString:NSAccessibilityARIARelevantAttribute])
2617 return m_object->ariaLiveRegionRelevant();
2618 if ([attributeName isEqualToString:NSAccessibilityARIAAtomicAttribute])
2619 return [NSNumber numberWithBool:m_object->ariaLiveRegionAtomic()];
2620 if ([attributeName isEqualToString:NSAccessibilityARIABusyAttribute])
2621 return [NSNumber numberWithBool:m_object->ariaLiveRegionBusy()];
2623 // MathML Attributes.
2624 if (m_object->isMathElement()) {
2625 if ([attributeName isEqualToString:NSAccessibilityMathRootIndexAttribute])
2626 return (m_object->mathRootIndexObject()) ? m_object->mathRootIndexObject()->wrapper() : 0;
2627 if ([attributeName isEqualToString:NSAccessibilityMathRootRadicandAttribute])
2628 return (m_object->mathRadicandObject()) ? m_object->mathRadicandObject()->wrapper() : 0;
2629 if ([attributeName isEqualToString:NSAccessibilityMathFractionNumeratorAttribute])
2630 return (m_object->mathNumeratorObject()) ? m_object->mathNumeratorObject()->wrapper() : 0;
2631 if ([attributeName isEqualToString:NSAccessibilityMathFractionDenominatorAttribute])
2632 return (m_object->mathDenominatorObject()) ? m_object->mathDenominatorObject()->wrapper() : 0;
2633 if ([attributeName isEqualToString:NSAccessibilityMathBaseAttribute])
2634 return (m_object->mathBaseObject()) ? m_object->mathBaseObject()->wrapper() : 0;
2635 if ([attributeName isEqualToString:NSAccessibilityMathSubscriptAttribute])
2636 return (m_object->mathSubscriptObject()) ? m_object->mathSubscriptObject()->wrapper() : 0;
2637 if ([attributeName isEqualToString:NSAccessibilityMathSuperscriptAttribute])
2638 return (m_object->mathSuperscriptObject()) ? m_object->mathSuperscriptObject()->wrapper() : 0;
2639 if ([attributeName isEqualToString:NSAccessibilityMathUnderAttribute])
2640 return (m_object->mathUnderObject()) ? m_object->mathUnderObject()->wrapper() : 0;
2641 if ([attributeName isEqualToString:NSAccessibilityMathOverAttribute])
2642 return (m_object->mathOverObject()) ? m_object->mathOverObject()->wrapper() : 0;
2643 if ([attributeName isEqualToString:NSAccessibilityMathFencedOpenAttribute])
2644 return m_object->mathFencedOpenString();
2645 if ([attributeName isEqualToString:NSAccessibilityMathFencedCloseAttribute])
2646 return m_object->mathFencedCloseString();
2649 // this is used only by DumpRenderTree for testing
2650 if ([attributeName isEqualToString:@"AXClickPoint"])
2651 return [NSValue valueWithPoint:m_object->clickPoint()];
2653 // This is used by DRT to verify CSS3 speech works.
2654 if ([attributeName isEqualToString:@"AXDRTSpeechAttribute"]) {
2655 ESpeak speakProperty = m_object->speakProperty();
2656 switch (speakProperty) {
2660 return @"spell-out";
2663 case SpeakLiteralPunctuation:
2664 return @"literal-punctuation";
2665 case SpeakNoPunctuation:
2666 return @"no-punctuation";
2673 // Used by DRT to find an accessible node by its element id.
2674 if ([attributeName isEqualToString:@"AXDRTElementIdAttribute"])
2675 return m_object->getAttribute(idAttr);
2680 - (id)accessibilityFocusedUIElement
2682 if (![self updateObjectBackingStore])
2685 RefPtr<AccessibilityObject> focusedObj = m_object->focusedUIElement();
2690 return focusedObj->wrapper();
2693 - (id)accessibilityHitTest:(NSPoint)point
2695 if (![self updateObjectBackingStore])
2698 m_object->updateChildrenIfNecessary();
2699 RefPtr<AccessibilityObject> axObject = m_object->accessibilityHitTest(IntPoint(point));
2701 return NSAccessibilityUnignoredAncestor(axObject->wrapper());
2702 return NSAccessibilityUnignoredAncestor(self);
2705 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName
2707 if (![self updateObjectBackingStore])
2710 if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
2713 if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
2714 return m_object->canSetFocusAttribute();
2716 if ([attributeName isEqualToString: NSAccessibilityValueAttribute])
2717 return m_object->canSetValueAttribute();
2719 if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
2720 return m_object->canSetSelectedAttribute();
2722 if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute])
2723 return m_object->canSetSelectedChildrenAttribute();
2725 if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
2726 return m_object->canSetExpandedAttribute();
2728 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute])
2731 if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute] ||
2732 [attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute] ||
2733 [attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
2734 return m_object->canSetTextRangeAttributes();
2736 if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
2742 // accessibilityShouldUseUniqueId is an AppKit method we override so that
2743 // objects will be given a unique ID, and therefore allow AppKit to know when they
2744 // become obsolete (e.g. when the user navigates to a new web page, making this one
2745 // unrendered but not deallocated because it is in the back/forward cache).
2746 // It is important to call NSAccessibilityUnregisterUniqueIdForUIElement in the
2747 // appropriate place (e.g. dealloc) to remove these non-retained references from
2748 // AppKit's id mapping tables. We do this in detach by calling unregisterUniqueIdForUIElement.
2750 // Registering an object is also required for observing notifications. Only registered objects can be observed.
2751 - (BOOL)accessibilityIsIgnored
2753 if (![self updateObjectBackingStore])
2756 if (m_object->isAttachment())
2757 return [[self attachmentView] accessibilityIsIgnored];
2758 return m_object->accessibilityIsIgnored();
2761 - (NSArray* )accessibilityParameterizedAttributeNames
2763 if (![self updateObjectBackingStore])
2766 if (m_object->isAttachment())
2769 static NSArray* paramAttrs = nil;
2770 static NSArray* textParamAttrs = nil;
2771 static NSArray* tableParamAttrs = nil;
2772 static NSArray* webAreaParamAttrs = nil;
2773 if (paramAttrs == nil) {
2774 paramAttrs = [[NSArray alloc] initWithObjects:
2775 @"AXUIElementForTextMarker",
2776 @"AXTextMarkerRangeForUIElement",
2777 @"AXLineForTextMarker",
2778 @"AXTextMarkerRangeForLine",
2779 @"AXStringForTextMarkerRange",
2780 @"AXTextMarkerForPosition",
2781 @"AXBoundsForTextMarkerRange",
2782 @"AXAttributedStringForTextMarkerRange",
2783 @"AXTextMarkerRangeForUnorderedTextMarkers",
2784 @"AXNextTextMarkerForTextMarker",
2785 @"AXPreviousTextMarkerForTextMarker",
2786 @"AXLeftWordTextMarkerRangeForTextMarker",
2787 @"AXRightWordTextMarkerRangeForTextMarker",
2788 @"AXLeftLineTextMarkerRangeForTextMarker",
2789 @"AXRightLineTextMarkerRangeForTextMarker",
2790 @"AXSentenceTextMarkerRangeForTextMarker",
2791 @"AXParagraphTextMarkerRangeForTextMarker",
2792 @"AXNextWordEndTextMarkerForTextMarker",
2793 @"AXPreviousWordStartTextMarkerForTextMarker",
2794 @"AXNextLineEndTextMarkerForTextMarker",
2795 @"AXPreviousLineStartTextMarkerForTextMarker",
2796 @"AXNextSentenceEndTextMarkerForTextMarker",
2797 @"AXPreviousSentenceStartTextMarkerForTextMarker",
2798 @"AXNextParagraphEndTextMarkerForTextMarker",
2799 @"AXPreviousParagraphStartTextMarkerForTextMarker",
2800 @"AXStyleTextMarkerRangeForTextMarker",
2801 @"AXLengthForTextMarkerRange",
2802 NSAccessibilityBoundsForRangeParameterizedAttribute,
2803 NSAccessibilityStringForRangeParameterizedAttribute,
2804 NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute,
2808 if (textParamAttrs == nil) {
2809 NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
2810 [tempArray addObject:(NSString*)kAXLineForIndexParameterizedAttribute];
2811 [tempArray addObject:(NSString*)kAXRangeForLineParameterizedAttribute];
2812 [tempArray addObject:(NSString*)kAXStringForRangeParameterizedAttribute];
2813 [tempArray addObject:(NSString*)kAXRangeForPositionParameterizedAttribute];
2814 [tempArray addObject:(NSString*)kAXRangeForIndexParameterizedAttribute];
2815 [tempArray addObject:(NSString*)kAXBoundsForRangeParameterizedAttribute];
2816 [tempArray addObject:(NSString*)kAXRTFForRangeParameterizedAttribute];
2817 [tempArray addObject:(NSString*)kAXAttributedStringForRangeParameterizedAttribute];
2818 [tempArray addObject:(NSString*)kAXStyleRangeForIndexParameterizedAttribute];
2819 textParamAttrs = [[NSArray alloc] initWithArray:tempArray];
2820 [tempArray release];
2822 if (tableParamAttrs == nil) {
2823 NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
2824 [tempArray addObject:NSAccessibilityCellForColumnAndRowParameterizedAttribute];
2825 tableParamAttrs = [[NSArray alloc] initWithArray:tempArray];
2826 [tempArray release];
2828 if (!webAreaParamAttrs) {
2829 NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
2830 [tempArray addObject:NSAccessibilityTextMarkerForIndexParameterizedAttribute];
2831 [tempArray addObject:NSAccessibilityTextMarkerIsValidParameterizedAttribute];
2832 [tempArray addObject:NSAccessibilityIndexForTextMarkerParameterizedAttribute];
2833 webAreaParamAttrs = [[NSArray alloc] initWithArray:tempArray];
2834 [tempArray release];
2837 if (m_object->isPasswordField())
2838 return [NSArray array];
2840 if (!m_object->isAccessibilityRenderObject())
2843 if (m_object->isTextControl())
2844 return textParamAttrs;
2846 if (m_object->isAccessibilityTable())
2847 return tableParamAttrs;
2849 if (m_object->isMenuRelated())
2852 if (m_object->isWebArea())
2853 return webAreaParamAttrs;
2858 - (void)accessibilityPerformPressAction
2860 if (![self updateObjectBackingStore])
2863 if (m_object->isAttachment())
2864 [[self attachmentView] accessibilityPerformAction:NSAccessibilityPressAction];
2869 - (void)accessibilityPerformIncrementAction
2871 if (![self updateObjectBackingStore])
2874 if (m_object->isAttachment())
2875 [[self attachmentView] accessibilityPerformAction:NSAccessibilityIncrementAction];
2877 m_object->increment();
2880 - (void)accessibilityPerformDecrementAction
2882 if (![self updateObjectBackingStore])
2885 if (m_object->isAttachment())
2886 [[self attachmentView] accessibilityPerformAction:NSAccessibilityDecrementAction];
2888 m_object->decrement();
2891 - (void)accessibilityPerformShowMenuAction
2893 if (m_object->roleValue() == ComboBoxRole)
2894 m_object->setIsExpanded(true);
2896 // This needs to be performed in an iteration of the run loop that did not start from an AX call.
2897 // If it's the same run loop iteration, the menu open notification won't be sent
2898 [self performSelector:@selector(accessibilityShowContextMenu) withObject:nil afterDelay:0.0];
2902 - (void)accessibilityShowContextMenu
2904 Page* page = m_object->page();
2908 IntRect rect = pixelSnappedIntRect(m_object->elementRect());
2909 FrameView* frameView = m_object->documentFrameView();
2911 // On WK2, we need to account for the scroll position.
2912 // On WK1, this isn't necessary, it's taken care of by the attachment views.
2913 if (frameView && !frameView->platformWidget()) {
2914 // Find the appropriate scroll view to use to convert the contents to the window.
2915 for (AccessibilityObject* parent = m_object->parentObject(); parent; parent = parent->parentObject()) {
2916 if (parent->isAccessibilityScrollView()) {
2917 ScrollView* scrollView = toAccessibilityScrollView(parent)->scrollView();
2918 rect = scrollView->contentsToRootView(rect);
2924 page->contextMenuController()->showContextMenuAt(page->mainFrame(), rect.center());
2927 - (void)accessibilityPerformAction:(NSString*)action
2929 if (![self updateObjectBackingStore])
2932 if ([action isEqualToString:NSAccessibilityPressAction])
2933 [self accessibilityPerformPressAction];
2935 else if ([action isEqualToString:NSAccessibilityShowMenuAction])
2936 [self accessibilityPerformShowMenuAction];
2938 else if ([action isEqualToString:NSAccessibilityIncrementAction])
2939 [self accessibilityPerformIncrementAction];
2941 else if ([action isEqualToString:NSAccessibilityDecrementAction])
2942 [self accessibilityPerformDecrementAction];
2945 - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attributeName
2947 if (![self updateObjectBackingStore])
2950 id textMarkerRange = nil;
2951 NSNumber* number = nil;
2952 NSString* string = nil;
2953 NSRange range = {0, 0};
2954 NSArray* array = nil;
2956 // decode the parameter
2957 if (AXObjectIsTextMarkerRange(value))
2958 textMarkerRange = value;
2960 else if ([value isKindOfClass:[NSNumber self]])
2963 else if ([value isKindOfClass:[NSString self]])
2966 else if ([value isKindOfClass:[NSValue self]])
2967 range = [value rangeValue];
2969 else if ([value isKindOfClass:[NSArray self]])
2972 // handle the command
2973 if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"]) {
2974 ASSERT(textMarkerRange);
2975 m_object->setSelectedVisiblePositionRange([self visiblePositionRangeForTextMarkerRange:textMarkerRange]);
2976 } else if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute]) {
2978 m_object->setFocused([number intValue] != 0);
2979 } else if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
2980 if (number && m_object->canSetNumericValue())
2981 m_object->setValue([number floatValue]);
2983 m_object->setValue(string);
2984 } else if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute]) {
2987 m_object->setSelected([number boolValue]);
2988 } else if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {
2989 if (!array || m_object->roleValue() != ListBoxRole)
2991 AccessibilityObject::AccessibilityChildrenVector selectedChildren;
2992 convertToVector(array, selectedChildren);
2993 static_cast<AccessibilityListBox*>(m_object)->setSelectedChildren(selectedChildren);
2994 } else if (m_object->isTextControl()) {
2995 if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
2996 m_object->setSelectedText(string);
2997 } else if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
2998 m_object->setSelectedTextRange(PlainTextRange(range.location, range.length));
2999 } else if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute]) {
3000 m_object->makeRangeVisible(PlainTextRange(range.location, range.length));
3002 } else if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
3003 m_object->setIsExpanded([number boolValue]);
3004 else if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
3005 AccessibilityObject::AccessibilityChildrenVector selectedRows;
3006 convertToVector(array, selectedRows);
3007 if (m_object->isTree() || m_object->isAccessibilityTable())
3008 m_object->setSelectedRows(selectedRows);
3009 } else if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
3010 m_object->setARIAGrabbed([number boolValue]);
3013 static RenderObject* rendererForView(NSView* view)
3015 if (![view conformsToProtocol:@protocol(WebCoreFrameView)])
3018 NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view;
3019 Frame* frame = [frameView _web_frame];
3023 Node* node = frame->document()->ownerElement();
3027 return node->renderer();
3030 - (id)_accessibilityParentForSubview:(NSView*)subview
3032 RenderObject* renderer = rendererForView(subview);
3036 AccessibilityObject* obj = renderer->document()->axObjectCache()->getOrCreate(renderer);
3038 return obj->parentObjectUnignored()->wrapper();
3042 - (NSString*)accessibilityActionDescription:(NSString*)action
3044 // we have no custom actions
3045 return NSAccessibilityActionDescription(action);
3048 // The CFAttributedStringType representation of the text associated with this accessibility
3049 // object that is specified by the given range.
3050 - (NSAttributedString*)doAXAttributedStringForRange:(NSRange)range
3052 PlainTextRange textRange = PlainTextRange(range.location, range.length);
3053 VisiblePositionRange visiblePosRange = m_object->visiblePositionRangeForRange(textRange);
3054 return [self doAXAttributedStringForTextMarkerRange:[self textMarkerRangeFromVisiblePositions:visiblePosRange.start endPosition:visiblePosRange.end]];
3057 - (NSRange)_convertToNSRange:(Range*)range
3059 NSRange result = NSMakeRange(NSNotFound, 0);
3060 if (!range || !range->startContainer())
3063 Document* document = m_object->document();
3069 TextIterator::getLocationAndLengthFromRange(document->documentElement(), range, location, length);
3070 result.location = location;
3071 result.length = length;
3076 - (NSInteger)_indexForTextMarker:(id)marker
3081 VisibleSelection selection([self visiblePositionForTextMarker:marker]);
3082 return [self _convertToNSRange:selection.toNormalizedRange().get()].location;
3085 - (id)_textMarkerForIndex:(NSInteger)textIndex
3087 Document* document = m_object->document();
3091 PassRefPtr<Range> textRange = TextIterator::rangeFromLocationAndLength(document->documentElement(), textIndex, 0);
3092 if (!textRange || !textRange->boundaryPointsValid())
3095 VisiblePosition position(textRange->startPosition());
3096 return [self textMarkerForVisiblePosition:position];
3099 // The RTF representation of the text associated with this accessibility object that is
3100 // specified by the given range.
3101 - (NSData*)doAXRTFForRange:(NSRange)range
3103 NSAttributedString* attrString = [self doAXAttributedStringForRange:range];
3104 return [attrString RTFFromRange: NSMakeRange(0, [attrString length]) documentAttributes: nil];
3107 - (id)accessibilityAttributeValue:(NSString*)attribute forParameter:(id)parameter
3109 id textMarker = nil;
3110 id textMarkerRange = nil;
3111 NSNumber* number = nil;
3112 NSArray* array = nil;
3113 NSDictionary* dictionary = nil;
3114 RefPtr<AccessibilityObject> uiElement = 0;
3115 NSPoint point = NSZeroPoint;
3116 bool pointSet = false;
3117 NSRange range = {0, 0};
3118 bool rangeSet = false;
3120 // basic parameter validation
3121 if (!m_object || !attribute || !parameter)
3124 if (![self updateObjectBackingStore])
3127 // common parameter type check/casting. Nil checks in handlers catch wrong type case.
3128 // NOTE: This assumes nil is not a valid parameter, because it is indistinguishable from
3129 // a parameter of the wrong type.
3130 if (AXObjectIsTextMarker(parameter))
3131 textMarker = parameter;
3133 else if (AXObjectIsTextMarkerRange(parameter))
3134 textMarkerRange = parameter;
3136 else if ([parameter isKindOfClass:[WebAccessibilityObjectWrapper self]])
3137 uiElement = [(WebAccessibilityObjectWrapper*)parameter accessibilityObject];
3139 else if ([parameter isKindOfClass:[NSNumber self]])
3142 else if ([parameter isKindOfClass:[NSArray self]])
3145 else if ([parameter isKindOfClass:[NSDictionary self]])
3146 dictionary = parameter;
3148 else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSPoint)) == 0) {
3150 point = [(NSValue*)parameter pointValue];
3152 } else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSRange)) == 0) {
3154 range = [(NSValue*)parameter rangeValue];
3156 // Attribute type is not supported. Allow super to handle.
3157 return [super accessibilityAttributeValue:attribute forParameter:parameter];
3161 if ([attribute isEqualToString:NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute]) {
3162 AccessibilityObject* startObject = 0;
3163 if ([[dictionary objectForKey:@"AXStartElement"] isKindOfClass:[WebAccessibilityObjectWrapper self]])
3164 startObject = [(WebAccessibilityObjectWrapper*)[dictionary objectForKey:@"AXStartElement"] accessibilityObject];
3166 AccessibilitySearchDirection searchDirection = SearchDirectionNext;
3167 if ([[dictionary objectForKey:@"AXDirection"] isKindOfClass:[NSString self]])
3168 searchDirection = ([(NSString*)[dictionary objectForKey:@"AXDirection"] isEqualToString:@"AXDirectionNext"]) ? SearchDirectionNext : SearchDirectionPrevious;
3170 AccessibilitySearchKey searchKey = AnyTypeSearchKey;
3171 if ([[dictionary objectForKey:@"AXSearchKey"] isKindOfClass:[NSString self]])
3172 searchKey = accessibilitySearchKeyForString((CFStringRef)[dictionary objectForKey:@"AXSearchKey"]);
3175 if ([[dictionary objectForKey:@"AXSearchText"] isKindOfClass:[NSString self]])
3176 searchText = (CFStringRef)[dictionary objectForKey:@"AXSearchText"];
3178 unsigned resultsLimit = 0;
3179 if ([[dictionary objectForKey:@"AXResultsLimit"] isKindOfClass:[NSNumber self]])
3180 resultsLimit = [(NSNumber*)[dictionary objectForKey:@"AXResultsLimit"] unsignedIntValue];
3182 AccessibilitySearchCriteria criteria = {startObject, searchDirection, searchKey, &searchText, resultsLimit};
3184 AccessibilityObject::AccessibilityChildrenVector results;
3185 m_object->findMatchingObjects(&criteria, results);
3187 return convertToNSArray(results);
3190 if ([attribute isEqualToString:NSAccessibilityTextMarkerIsValidParameterizedAttribute]) {
3191 VisiblePosition pos = [self visiblePositionForTextMarker:textMarker];
3192 return [NSNumber numberWithBool:!pos.isNull()];
3194 if ([attribute isEqualToString:NSAccessibilityIndexForTextMarkerParameterizedAttribute]) {
3195 return [NSNumber numberWithInteger:[self _indexForTextMarker:textMarker]];
3197 if ([attribute isEqualToString:NSAccessibilityTextMarkerForIndexParameterizedAttribute]) {
3198 return [self _textMarkerForIndex:[number integerValue]];
3201 if ([attribute isEqualToString:@"AXUIElementForTextMarker"]) {
3202 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3203 AccessibilityObject* axObject = m_object->accessibilityObjectForPosition(visiblePos);
3206 return axObject->wrapper();
3209 if ([attribute isEqualToString:@"AXTextMarkerRangeForUIElement"]) {
3210 VisiblePositionRange vpRange = uiElement.get()->visiblePositionRange();
3211 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3214 if ([attribute isEqualToString:@"AXLineForTextMarker"]) {
3215 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3216 return [NSNumber numberWithUnsignedInt:m_object->lineForPosition(visiblePos)];
3219 if ([attribute isEqualToString:@"AXTextMarkerRangeForLine"]) {
3220 VisiblePositionRange vpRange = m_object->visiblePositionRangeForLine([number intValue]);
3221 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3224 if ([attribute isEqualToString:@"AXStringForTextMarkerRange"]) {
3225 VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
3226 return m_object->stringForVisiblePositionRange(visiblePosRange);
3229 if ([attribute isEqualToString:@"AXTextMarkerForPosition"]) {
3230 IntPoint webCorePoint = IntPoint(point);
3231 return pointSet ? [self textMarkerForVisiblePosition:m_object->visiblePositionForPoint(webCorePoint)] : nil;
3234 if ([attribute isEqualToString:@"AXBoundsForTextMarkerRange"]) {
3235 VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
3236 NSRect rect = m_object->boundsForVisiblePositionRange(visiblePosRange);
3237 return [NSValue valueWithRect:rect];
3240 if ([attribute isEqualToString:NSAccessibilityBoundsForRangeParameterizedAttribute]) {
3241 VisiblePosition start = m_object->visiblePositionForIndex(range.location);
3242 VisiblePosition end = m_object->visiblePositionForIndex(range.location+range.length);
3243 if (start.isNull() || end.isNull())
3245 NSRect rect = m_object->boundsForVisiblePositionRange(VisiblePositionRange(start, end));
3246 return [NSValue valueWithRect:rect];
3249 if ([attribute isEqualToString:NSAccessibilityStringForRangeParameterizedAttribute]) {
3250 VisiblePosition start = m_object->visiblePositionForIndex(range.location);
3251 VisiblePosition end = m_object->visiblePositionForIndex(range.location+range.length);
3252 if (start.isNull() || end.isNull())
3254 return m_object->stringForVisiblePositionRange(VisiblePositionRange(start, end));
3257 if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"])
3258 return [self doAXAttributedStringForTextMarkerRange:textMarkerRange];
3260 if ([attribute isEqualToString:@"AXTextMarkerRangeForUnorderedTextMarkers"]) {
3261 if ([array count] < 2)
3264 id textMarker1 = [array objectAtIndex:0];
3265 id textMarker2 = [array objectAtIndex:1];
3266 if (!AXObjectIsTextMarker(textMarker1) || !AXObjectIsTextMarker(textMarker2))
3269 VisiblePosition visiblePos1 = [self visiblePositionForTextMarker:(textMarker1)];
3270 VisiblePosition visiblePos2 = [self visiblePositionForTextMarker:(textMarker2)];
3271 VisiblePositionRange vpRange = m_object->visiblePositionRangeForUnorderedPositions(visiblePos1, visiblePos2);
3272 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3275 if ([attribute isEqualToString:@"AXNextTextMarkerForTextMarker"]) {
3276 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3277 return [self textMarkerForVisiblePosition:m_object->nextVisiblePosition(visiblePos)];
3280 if ([attribute isEqualToString:@"AXPreviousTextMarkerForTextMarker"]) {
3281 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3282 return [self textMarkerForVisiblePosition:m_object->previousVisiblePosition(visiblePos)];
3285 if ([attribute isEqualToString:@"AXLeftWordTextMarkerRangeForTextMarker"]) {
3286 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3287 VisiblePositionRange vpRange = m_object->positionOfLeftWord(visiblePos);
3288 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3291 if ([attribute isEqualToString:@"AXRightWordTextMarkerRangeForTextMarker"]) {
3292 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3293 VisiblePositionRange vpRange = m_object->positionOfRightWord(visiblePos);
3294 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3297 if ([attribute isEqualToString:@"AXLeftLineTextMarkerRangeForTextMarker"]) {
3298 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3299 VisiblePositionRange vpRange = m_object->leftLineVisiblePositionRange(visiblePos);
3300 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3303 if ([attribute isEqualToString:@"AXRightLineTextMarkerRangeForTextMarker"]) {
3304 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3305 VisiblePositionRange vpRange = m_object->rightLineVisiblePositionRange(visiblePos);
3306 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3309 if ([attribute isEqualToString:@"AXSentenceTextMarkerRangeForTextMarker"]) {
3310 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3311 VisiblePositionRange vpRange = m_object->sentenceForPosition(visiblePos);
3312 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3315 if ([attribute isEqualToString:@"AXParagraphTextMarkerRangeForTextMarker"]) {
3316 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3317 VisiblePositionRange vpRange = m_object->paragraphForPosition(visiblePos);
3318 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3321 if ([attribute isEqualToString:@"AXNextWordEndTextMarkerForTextMarker"]) {
3322 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3323 return [self textMarkerForVisiblePosition:m_object->nextWordEnd(visiblePos)];
3326 if ([attribute isEqualToString:@"AXPreviousWordStartTextMarkerForTextMarker"]) {
3327 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3328 return [self textMarkerForVisiblePosition:m_object->previousWordStart(visiblePos)];
3331 if ([attribute isEqualToString:@"AXNextLineEndTextMarkerForTextMarker"]) {
3332 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3333 return [self textMarkerForVisiblePosition:m_object->nextLineEndPosition(visiblePos)];
3336 if ([attribute isEqualToString:@"AXPreviousLineStartTextMarkerForTextMarker"]) {
3337 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3338 return [self textMarkerForVisiblePosition:m_object->previousLineStartPosition(visiblePos)];
3341 if ([attribute isEqualToString:@"AXNextSentenceEndTextMarkerForTextMarker"]) {
3342 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3343 return [self textMarkerForVisiblePosition:m_object->nextSentenceEndPosition(visiblePos)];
3346 if ([attribute isEqualToString:@"AXPreviousSentenceStartTextMarkerForTextMarker"]) {
3347 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3348 return [self textMarkerForVisiblePosition:m_object->previousSentenceStartPosition(visiblePos)];
3351 if ([attribute isEqualToString:@"AXNextParagraphEndTextMarkerForTextMarker"]) {
3352 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3353 return [self textMarkerForVisiblePosition:m_object->nextParagraphEndPosition(visiblePos)];
3356 if ([attribute isEqualToString:@"AXPreviousParagraphStartTextMarkerForTextMarker"]) {
3357 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3358 return [self textMarkerForVisiblePosition:m_object->previousParagraphStartPosition(visiblePos)];
3361 if ([attribute isEqualToString:@"AXStyleTextMarkerRangeForTextMarker"]) {
3362 VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3363 VisiblePositionRange vpRange = m_object->styleRangeForPosition(visiblePos);
3364 return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3367 if ([attribute isEqualToString:@"AXLengthForTextMarkerRange"]) {
3368 VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
3369 int length = m_object->lengthForVisiblePositionRange(visiblePosRange);
3372 return [NSNumber numberWithInt:length];
3375 // Used only by DumpRenderTree (so far).
3376 if ([attribute isEqualToString:@"AXStartTextMarkerForTextMarkerRange"]) {
3377 VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
3378 return [self textMarkerForVisiblePosition:visiblePosRange.start];
3381 if ([attribute isEqualToString:@"AXEndTextMarkerForTextMarkerRange"]) {
3382 VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
3383 return [self textMarkerForVisiblePosition:visiblePosRange.end];
3386 if (m_object->isAccessibilityTable()) {
3387 if ([attribute isEqualToString:NSAccessibilityCellForColumnAndRowParameterizedAttribute]) {
3388 if (array == nil || [array count] != 2)
3390 AccessibilityTableCell* cell = static_cast<AccessibilityTable*>(m_object)->cellForColumnAndRow([[array objectAtIndex:0] unsignedIntValue], [[array objectAtIndex:1] unsignedIntValue]);
3394 return cell->wrapper();
3398 if (m_object->isTextControl()) {
3399 if ([attribute isEqualToString: (NSString *)kAXLineForIndexParameterizedAttribute]) {
3400 int lineNumber = m_object->doAXLineForIndex([number intValue]);
3403 return [NSNumber numberWithUnsignedInt:lineNumber];
3406 if ([attribute isEqualToString: (NSString *)kAXRangeForLineParameterizedAttribute]) {
3407 PlainTextRange textRange = m_object->doAXRangeForLine([number intValue]);
3408 return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];
3411 if ([attribute isEqualToString: (NSString*)kAXStringForRangeParameterizedAttribute]) {
3412 PlainTextRange plainTextRange = PlainTextRange(range.location, range.length);
3413 return rangeSet ? (id)(m_object->doAXStringForRange(plainTextRange)) : nil;
3416 if ([attribute isEqualToString: (NSString*)kAXRangeForPositionParameterizedAttribute]) {
3419 IntPoint webCorePoint = IntPoint(point);
3420 PlainTextRange textRange = m_object->doAXRangeForPosition(webCorePoint);
3421 return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];
3424 if ([attribute isEqualToString: (NSString*)kAXRangeForIndexParameterizedAttribute]) {
3425 PlainTextRange textRange = m_object->doAXRangeForIndex([number intValue]);
3426 return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];
3429 if ([attribute isEqualToString: (NSString*)kAXBoundsForRangeParameterizedAttribute]) {
3432 PlainTextRange plainTextRange = PlainTextRange(range.location, range.length);
3433 NSRect rect = m_object->doAXBoundsForRange(plainTextRange);
3434 return [NSValue valueWithRect:rect];
3437 if ([attribute isEqualToString: (NSString*)kAXRTFForRangeParameterizedAttribute])
3438 return rangeSet ? [self doAXRTFForRange:range] : nil;
3440 if ([attribute isEqualToString: (NSString*)kAXAttributedStringForRangeParameterizedAttribute])
3441 return rangeSet ? [self doAXAttributedStringForRange:range] : nil;
3443 if ([attribute isEqualToString: (NSString*)kAXStyleRangeForIndexParameterizedAttribute]) {
3444 PlainTextRange textRange = m_object->doAXStyleRangeForIndex([number intValue]);
3445 return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];
3449 // There are some parameters that super handles that are not explicitly returned by the list of the element's attributes.
3450 // In that case it must be passed to super.
3451 return [super accessibilityAttributeValue:attribute forParameter:parameter];
3454 - (BOOL)accessibilitySupportsOverriddenAttributes
3459 - (BOOL)accessibilityShouldUseUniqueId
3461 // All AX object wrappers should use unique ID's because it's faster within AppKit to look them up.
3465 // API that AppKit uses for faster access
3466 - (NSUInteger)accessibilityIndexOfChild:(id)child
3468 if (![self updateObjectBackingStore])
3471 // Tree objects return their rows as their children. We can use the original method
3472 // here, because we won't gain any speed up.
3473 if (m_object->isTree())
3474 return [super accessibilityIndexOfChild:child];
3476 const AccessibilityObject::AccessibilityChildrenVector& children = m_object->children();
3478 if (children.isEmpty())
3479 return [[self renderWidgetChildren] indexOfObject:child];
3481 unsigned count = children.size();
3482 for (unsigned k = 0; k < count; ++k) {
3483 WebAccessibilityObjectWrapper* wrapper = children[k]->wrapper();
3484 if (wrapper == child || (children[k]->isAttachment() && [wrapper attachmentView] == child))
3491 - (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute
3493 if (![self updateObjectBackingStore])
3496 if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
3497 // Tree items object returns a different set of children than those that are in children()
3498 // because an AXOutline (the mac role is becomes) has some odd stipulations.
3499 if (m_object->isTree() || m_object->isTreeItem())
3500 return [[self accessibilityAttributeValue:NSAccessibilityChildrenAttribute] count];
3502 const AccessibilityObject::AccessibilityChildrenVector& children = m_object->children();
3503 if (children.isEmpty())
3504 return [[self renderWidgetChildren] count];
3506 return children.size();
3509 return [super accessibilityArrayAttributeCount:attribute];
3512 - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount
3514 if (![self updateObjectBackingStore])
3517 if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
3518 if (m_object->children().isEmpty()) {
3519 NSArray *children = [self renderWidgetChildren];
3523 NSUInteger childCount = [children count];
3524 if (index >= childCount)
3527 NSUInteger arrayLength = min(childCount - index, maxCount);
3528 return [children subarrayWithRange:NSMakeRange(index, arrayLength)];
3529 } else if (m_object->isTree()) {
3530 // Tree objects return their rows as their children. We can use the original method in this case.
3531 return [super accessibilityArrayAttributeValues:attribute index:index maxCount:maxCount];
3534 const AccessibilityObject::AccessibilityChildrenVector& children = m_object->children();
3535 unsigned childCount = children.size();
3536 if (index >= childCount)