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 "WebAccessibilityObjectWrapperMac.h"
32 #if HAVE(ACCESSIBILITY)
34 #import "AXObjectCache.h"
35 #import "AccessibilityARIAGridRow.h"
36 #import "AccessibilityList.h"
37 #import "AccessibilityListBox.h"
38 #import "AccessibilityRenderObject.h"
39 #import "AccessibilityScrollView.h"
40 #import "AccessibilitySpinButton.h"
41 #import "AccessibilityTable.h"
42 #import "AccessibilityTableCell.h"
43 #import "AccessibilityTableColumn.h"
44 #import "AccessibilityTableRow.h"
46 #import "ChromeClient.h"
48 #import "ContextMenuController.h"
52 #import "FrameLoaderClient.h"
53 #import "FrameSelection.h"
54 #import "HTMLAnchorElement.h"
55 #import "HTMLAreaElement.h"
56 #import "HTMLFrameOwnerElement.h"
57 #import "HTMLImageElement.h"
58 #import "HTMLInputElement.h"
60 #import "HTMLTextAreaElement.h"
61 #import "LocalizedStrings.h"
63 #import "RenderTextControl.h"
64 #import "RenderView.h"
65 #import "RenderWidget.h"
66 #import "ScrollView.h"
67 #import "SimpleFontData.h"
68 #import "TextCheckerClient.h"
69 #import "TextCheckingHelper.h"
70 #import "TextIterator.h"
71 #import "VisibleUnits.h"
72 #import "WebCoreFrameView.h"
73 #import "WebCoreObjCExtras.h"
74 #import "WebCoreSystemInterface.h"
75 #import "htmlediting.h"
76 #import <wtf/ObjcRuntimeExtras.h>
78 using namespace WebCore;
79 using namespace HTMLNames;
83 #ifndef NSAccessibilitySelectedCellsAttribute
84 #define NSAccessibilitySelectedCellsAttribute @"AXSelectedCells"
87 #ifndef NSAccessibilityVisibleCellsAttribute
88 #define NSAccessibilityVisibleCellsAttribute @"AXVisibleCells"
91 #ifndef NSAccessibilityRowHeaderUIElementsAttribute
92 #define NSAccessibilityRowHeaderUIElementsAttribute @"AXRowHeaderUIElements"
95 #ifndef NSAccessibilityRowIndexRangeAttribute
96 #define NSAccessibilityRowIndexRangeAttribute @"AXRowIndexRange"
99 #ifndef NSAccessibilityColumnIndexRangeAttribute
100 #define NSAccessibilityColumnIndexRangeAttribute @"AXColumnIndexRange"
103 #ifndef NSAccessibilityCellForColumnAndRowParameterizedAttribute
104 #define NSAccessibilityCellForColumnAndRowParameterizedAttribute @"AXCellForColumnAndRow"
107 #ifndef NSAccessibilityCellRole
108 #define NSAccessibilityCellRole @"AXCell"
112 #ifndef NSAccessibilityContentListSubrole
113 #define NSAccessibilityContentListSubrole @"AXContentList"
116 #ifndef NSAccessibilityDefinitionListSubrole
117 #define NSAccessibilityDefinitionListSubrole @"AXDefinitionList"
120 #ifndef NSAccessibilityDescriptionListSubrole
121 #define NSAccessibilityDescriptionListSubrole @"AXDescriptionList"
125 #ifndef NSAccessibilityBlockQuoteLevelAttribute
126 #define NSAccessibilityBlockQuoteLevelAttribute @"AXBlockQuoteLevel"
129 #ifndef NSAccessibilityAccessKeyAttribute
130 #define NSAccessibilityAccessKeyAttribute @"AXAccessKey"
133 #ifndef NSAccessibilityLanguageAttribute
134 #define NSAccessibilityLanguageAttribute @"AXLanguage"
137 #ifndef NSAccessibilityRequiredAttribute
138 #define NSAccessibilityRequiredAttribute @"AXRequired"
141 #ifndef NSAccessibilityInvalidAttribute
142 #define NSAccessibilityInvalidAttribute @"AXInvalid"
145 #ifndef NSAccessibilityOwnsAttribute
146 #define NSAccessibilityOwnsAttribute @"AXOwns"
149 #ifndef NSAccessibilityGrabbedAttribute
150 #define NSAccessibilityGrabbedAttribute @"AXGrabbed"
153 #ifndef NSAccessibilityDropEffectsAttribute
154 #define NSAccessibilityDropEffectsAttribute @"AXDropEffects"
157 #ifndef NSAccessibilityARIALiveAttribute
158 #define NSAccessibilityARIALiveAttribute @"AXARIALive"
161 #ifndef NSAccessibilityARIAAtomicAttribute
162 #define NSAccessibilityARIAAtomicAttribute @"AXARIAAtomic"
165 #ifndef NSAccessibilityARIARelevantAttribute
166 #define NSAccessibilityARIARelevantAttribute @"AXARIARelevant"
169 #ifndef NSAccessibilityElementBusyAttribute
170 #define NSAccessibilityElementBusyAttribute @"AXElementBusy"
173 #ifndef NSAccessibilityARIAPosInSetAttribute
174 #define NSAccessibilityARIAPosInSetAttribute @"AXARIAPosInSet"
177 #ifndef NSAccessibilityARIASetSizeAttribute
178 #define NSAccessibilityARIASetSizeAttribute @"AXARIASetSize"
181 #ifndef NSAccessibilityLoadingProgressAttribute
182 #define NSAccessibilityLoadingProgressAttribute @"AXLoadingProgress"
185 #ifndef NSAccessibilityHasPopupAttribute
186 #define NSAccessibilityHasPopupAttribute @"AXHasPopup"
189 #ifndef NSAccessibilityPlaceholderValueAttribute
190 #define NSAccessibilityPlaceholderValueAttribute @"AXPlaceholderValue"
194 #ifndef NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute
195 #define NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute @"AXUIElementsForSearchPredicate"
199 #ifndef NSAccessibilityAnyTypeSearchKey
200 #define NSAccessibilityAnyTypeSearchKey @"AXAnyTypeSearchKey"
203 #ifndef NSAccessibilityBlockquoteSameLevelSearchKey
204 #define NSAccessibilityBlockquoteSameLevelSearchKey @"AXBlockquoteSameLevelSearchKey"
207 #ifndef NSAccessibilityBlockquoteSearchKey
208 #define NSAccessibilityBlockquoteSearchKey @"AXBlockquoteSearchKey"
211 #ifndef NSAccessibilityBoldFontSearchKey
212 #define NSAccessibilityBoldFontSearchKey @"AXBoldFontSearchKey"
215 #ifndef NSAccessibilityButtonSearchKey
216 #define NSAccessibilityButtonSearchKey @"AXButtonSearchKey"
219 #ifndef NSAccessibilityCheckBoxSearchKey
220 #define NSAccessibilityCheckBoxSearchKey @"AXCheckBoxSearchKey"
223 #ifndef NSAccessibilityControlSearchKey
224 #define NSAccessibilityControlSearchKey @"AXControlSearchKey"
227 #ifndef NSAccessibilityDifferentTypeSearchKey
228 #define NSAccessibilityDifferentTypeSearchKey @"AXDifferentTypeSearchKey"
231 #ifndef NSAccessibilityFontChangeSearchKey
232 #define NSAccessibilityFontChangeSearchKey @"AXFontChangeSearchKey"
235 #ifndef NSAccessibilityFontColorChangeSearchKey
236 #define NSAccessibilityFontColorChangeSearchKey @"AXFontColorChangeSearchKey"
239 #ifndef NSAccessibilityFrameSearchKey
240 #define NSAccessibilityFrameSearchKey @"AXFrameSearchKey"
243 #ifndef NSAccessibilityGraphicSearchKey
244 #define NSAccessibilityGraphicSearchKey @"AXGraphicSearchKey"
247 #ifndef NSAccessibilityHeadingLevel1SearchKey
248 #define NSAccessibilityHeadingLevel1SearchKey @"AXHeadingLevel1SearchKey"
251 #ifndef NSAccessibilityHeadingLevel2SearchKey
252 #define NSAccessibilityHeadingLevel2SearchKey @"AXHeadingLevel2SearchKey"
255 #ifndef NSAccessibilityHeadingLevel3SearchKey
256 #define NSAccessibilityHeadingLevel3SearchKey @"AXHeadingLevel3SearchKey"
259 #ifndef NSAccessibilityHeadingLevel4SearchKey
260 #define NSAccessibilityHeadingLevel4SearchKey @"AXHeadingLevel4SearchKey"
263 #ifndef NSAccessibilityHeadingLevel5SearchKey
264 #define NSAccessibilityHeadingLevel5SearchKey @"AXHeadingLevel5SearchKey"
267 #ifndef NSAccessibilityHeadingLevel6SearchKey
268 #define NSAccessibilityHeadingLevel6SearchKey @"AXHeadingLevel6SearchKey"
271 #ifndef NSAccessibilityHeadingSameLevelSearchKey
272 #define NSAccessibilityHeadingSameLevelSearchKey @"AXHeadingSameLevelSearchKey"
275 #ifndef NSAccessibilityHeadingSearchKey
276 #define NSAccessibilityHeadingSearchKey @"AXHeadingSearchKey"
279 #ifndef NSAccessibilityHighlightedSearchKey
280 #define NSAccessibilityHighlightedSearchKey @"AXHighlightedSearchKey"
283 #ifndef NSAccessibilityItalicFontSearchKey
284 #define NSAccessibilityItalicFontSearchKey @"AXItalicFontSearchKey"
287 #ifndef NSAccessibilityLandmarkSearchKey
288 #define NSAccessibilityLandmarkSearchKey @"AXLandmarkSearchKey"
291 #ifndef NSAccessibilityLinkSearchKey
292 #define NSAccessibilityLinkSearchKey @"AXLinkSearchKey"
295 #ifndef NSAccessibilityListSearchKey
296 #define NSAccessibilityListSearchKey @"AXListSearchKey"
299 #ifndef NSAccessibilityLiveRegionSearchKey
300 #define NSAccessibilityLiveRegionSearchKey @"AXLiveRegionSearchKey"
303 #ifndef NSAccessibilityMisspelledWordSearchKey
304 #define NSAccessibilityMisspelledWordSearchKey @"AXMisspelledWordSearchKey"
307 #ifndef NSAccessibilityPlainTextSearchKey
308 #define NSAccessibilityPlainTextSearchKey @"AXPlainTextSearchKey"
311 #ifndef NSAccessibilityRadioGroupSearchKey
312 #define NSAccessibilityRadioGroupSearchKey @"AXRadioGroupSearchKey"
315 #ifndef NSAccessibilitySameTypeSearchKey
316 #define NSAccessibilitySameTypeSearchKey @"AXSameTypeSearchKey"
319 #ifndef NSAccessibilityStaticTextSearchKey
320 #define NSAccessibilityStaticTextSearchKey @"AXStaticTextSearchKey"
323 #ifndef NSAccessibilityStyleChangeSearchKey
324 #define NSAccessibilityStyleChangeSearchKey @"AXStyleChangeSearchKey"
327 #ifndef NSAccessibilityTableSameLevelSearchKey
328 #define NSAccessibilityTableSameLevelSearchKey @"AXTableSameLevelSearchKey"
331 #ifndef NSAccessibilityTableSearchKey
332 #define NSAccessibilityTableSearchKey @"AXTableSearchKey"
335 #ifndef NSAccessibilityTextFieldSearchKey
336 #define NSAccessibilityTextFieldSearchKey @"AXTextFieldSearchKey"
339 #ifndef NSAccessibilityUnderlineSearchKey
340 #define NSAccessibilityUnderlineSearchKey @"AXUnderlineSearchKey"
343 #ifndef NSAccessibilityUnvisitedLinkSearchKey
344 #define NSAccessibilityUnvisitedLinkSearchKey @"AXUnvisitedLinkSearchKey"
347 #ifndef NSAccessibilityVisitedLinkSearchKey
348 #define NSAccessibilityVisitedLinkSearchKey @"AXVisitedLinkSearchKey"
351 #define NSAccessibilityTextMarkerIsValidParameterizedAttribute @"AXTextMarkerIsValid"
352 #define NSAccessibilityIndexForTextMarkerParameterizedAttribute @"AXIndexForTextMarker"
353 #define NSAccessibilityTextMarkerForIndexParameterizedAttribute @"AXTextMarkerForIndex"
355 #ifndef NSAccessibilityScrollToVisibleAction
356 #define NSAccessibilityScrollToVisibleAction @"AXScrollToVisible"
359 #ifndef NSAccessibilityPathAttribute
360 #define NSAccessibilityPathAttribute @"AXPath"
363 #define NSAccessibilityDOMIdentifierAttribute @"AXDOMIdentifier"
364 #define NSAccessibilityDOMClassListAttribute @"AXDOMClassList"
367 #define NSAccessibilityMathRootRadicandAttribute @"AXMathRootRadicand"
368 #define NSAccessibilityMathRootIndexAttribute @"AXMathRootIndex"
369 #define NSAccessibilityMathFractionDenominatorAttribute @"AXMathFractionDenominator"
370 #define NSAccessibilityMathFractionNumeratorAttribute @"AXMathFractionNumerator"
371 #define NSAccessibilityMathBaseAttribute @"AXMathBase"
372 #define NSAccessibilityMathSubscriptAttribute @"AXMathSubscript"
373 #define NSAccessibilityMathSuperscriptAttribute @"AXMathSuperscript"
374 #define NSAccessibilityMathUnderAttribute @"AXMathUnder"
375 #define NSAccessibilityMathOverAttribute @"AXMathOver"
376 #define NSAccessibilityMathFencedOpenAttribute @"AXMathFencedOpen"
377 #define NSAccessibilityMathFencedCloseAttribute @"AXMathFencedClose"
378 #define NSAccessibilityMathLineThicknessAttribute @"AXMathLineThickness"
379 #define NSAccessibilityMathPrescriptsAttribute @"AXMathPrescripts"
380 #define NSAccessibilityMathPostscriptsAttribute @"AXMathPostscripts"
382 @implementation WebAccessibilityObjectWrapper
384 - (void)unregisterUniqueIdForUIElement
386 wkUnregisterUniqueIdForElement(self);
391 // Send unregisterUniqueIdForUIElement unconditionally because if it is
392 // ever accidentally not done (via other bugs in our AX implementation) you
393 // end up with a crash like <rdar://problem/4273149>. It is safe and not
394 // expensive to send even if the object is not registered.
395 [self unregisterUniqueIdForUIElement];
401 ASSERT(m_object->isAttachment());
402 Widget* widget = m_object->widgetForAttachmentView();
405 return NSAccessibilityUnignoredDescendant(widget->platformWidget());
408 #pragma mark SystemInterface wrappers
410 static inline BOOL AXObjectIsTextMarker(id obj)
412 return obj != nil && CFGetTypeID(obj) == wkGetAXTextMarkerTypeID();
415 static inline BOOL AXObjectIsTextMarkerRange(id obj)
417 return obj != nil && CFGetTypeID(obj) == wkGetAXTextMarkerRangeTypeID();
420 static id AXTextMarkerRange(id startMarker, id endMarker)
422 ASSERT(startMarker != nil);
423 ASSERT(endMarker != nil);
424 ASSERT(CFGetTypeID(startMarker) == wkGetAXTextMarkerTypeID());
425 ASSERT(CFGetTypeID(endMarker) == wkGetAXTextMarkerTypeID());
426 return CFBridgingRelease(wkCreateAXTextMarkerRange((CFTypeRef)startMarker, (CFTypeRef)endMarker));
429 static id AXTextMarkerRangeStart(id range)
431 ASSERT(range != nil);
432 ASSERT(CFGetTypeID(range) == wkGetAXTextMarkerRangeTypeID());
433 return CFBridgingRelease(wkCopyAXTextMarkerRangeStart(range));
436 static id AXTextMarkerRangeEnd(id range)
438 ASSERT(range != nil);
439 ASSERT(CFGetTypeID(range) == wkGetAXTextMarkerRangeTypeID());
440 return CFBridgingRelease(wkCopyAXTextMarkerRangeEnd(range));
443 #pragma mark Search helpers
445 typedef HashMap<String, AccessibilitySearchKey> AccessibilitySearchKeyMap;
447 struct SearchKeyEntry {
449 AccessibilitySearchKey value;
452 static AccessibilitySearchKeyMap* createAccessibilitySearchKeyMap()
454 const SearchKeyEntry searchKeys[] = {
455 { NSAccessibilityAnyTypeSearchKey, AnyTypeSearchKey },
456 { NSAccessibilityBlockquoteSameLevelSearchKey, BlockquoteSameLevelSearchKey },
457 { NSAccessibilityBlockquoteSearchKey, BlockquoteSearchKey },
458 { NSAccessibilityBoldFontSearchKey, BoldFontSearchKey },
459 { NSAccessibilityButtonSearchKey, ButtonSearchKey },
460 { NSAccessibilityCheckBoxSearchKey, CheckBoxSearchKey },
461 { NSAccessibilityControlSearchKey, ControlSearchKey },
462 { NSAccessibilityDifferentTypeSearchKey, DifferentTypeSearchKey },
463 { NSAccessibilityFontChangeSearchKey, FontChangeSearchKey },
464 { NSAccessibilityFontColorChangeSearchKey, FontColorChangeSearchKey },
465 { NSAccessibilityFrameSearchKey, FrameSearchKey },
466 { NSAccessibilityGraphicSearchKey, GraphicSearchKey },
467 { NSAccessibilityHeadingLevel1SearchKey, HeadingLevel1SearchKey },
468 { NSAccessibilityHeadingLevel2SearchKey, HeadingLevel2SearchKey },
469 { NSAccessibilityHeadingLevel3SearchKey, HeadingLevel3SearchKey },
470 { NSAccessibilityHeadingLevel4SearchKey, HeadingLevel4SearchKey },
471 { NSAccessibilityHeadingLevel5SearchKey, HeadingLevel5SearchKey },
472 { NSAccessibilityHeadingLevel6SearchKey, HeadingLevel6SearchKey },
473 { NSAccessibilityHeadingSameLevelSearchKey, HeadingSameLevelSearchKey },
474 { NSAccessibilityHeadingSearchKey, HeadingSearchKey },
475 { NSAccessibilityHighlightedSearchKey, HighlightedSearchKey },
476 { NSAccessibilityItalicFontSearchKey, ItalicFontSearchKey },
477 { NSAccessibilityLandmarkSearchKey, LandmarkSearchKey },
478 { NSAccessibilityLinkSearchKey, LinkSearchKey },
479 { NSAccessibilityListSearchKey, ListSearchKey },
480 { NSAccessibilityLiveRegionSearchKey, LiveRegionSearchKey },
481 { NSAccessibilityMisspelledWordSearchKey, MisspelledWordSearchKey },
482 { NSAccessibilityPlainTextSearchKey, PlainTextSearchKey },
483 { NSAccessibilityRadioGroupSearchKey, RadioGroupSearchKey },
484 { NSAccessibilitySameTypeSearchKey, SameTypeSearchKey },
485 { NSAccessibilityStaticTextSearchKey, StaticTextSearchKey },
486 { NSAccessibilityStyleChangeSearchKey, StyleChangeSearchKey },
487 { NSAccessibilityTableSameLevelSearchKey, TableSameLevelSearchKey },
488 { NSAccessibilityTableSearchKey, TableSearchKey },
489 { NSAccessibilityTextFieldSearchKey, TextFieldSearchKey },
490 { NSAccessibilityUnderlineSearchKey, UnderlineSearchKey },
491 { NSAccessibilityUnvisitedLinkSearchKey, UnvisitedLinkSearchKey },
492 { NSAccessibilityVisitedLinkSearchKey, VisitedLinkSearchKey }
495 AccessibilitySearchKeyMap* searchKeyMap = new AccessibilitySearchKeyMap;
496 for (size_t i = 0; i < WTF_ARRAY_LENGTH(searchKeys); i++)
497 searchKeyMap->set(searchKeys[i].key, searchKeys[i].value);
502 static AccessibilitySearchKey accessibilitySearchKeyForString(const String& value)
505 return AnyTypeSearchKey;
507 static const AccessibilitySearchKeyMap* searchKeyMap = createAccessibilitySearchKeyMap();
509 AccessibilitySearchKey searchKey = searchKeyMap->get(value);
511 return searchKey ? searchKey : AnyTypeSearchKey;
514 #pragma mark Text Marker helpers
516 static id textMarkerForVisiblePosition(AXObjectCache* cache, const VisiblePosition& visiblePos)
520 TextMarkerData textMarkerData;
521 cache->textMarkerDataForVisiblePosition(textMarkerData, visiblePos);
522 if (!textMarkerData.axID)
525 return CFBridgingRelease(wkCreateAXTextMarker(&textMarkerData, sizeof(textMarkerData)));
528 - (id)textMarkerForVisiblePosition:(const VisiblePosition &)visiblePos
530 return textMarkerForVisiblePosition(m_object->axObjectCache(), visiblePos);
533 static VisiblePosition visiblePositionForTextMarker(AXObjectCache* cache, CFTypeRef textMarker)
538 return VisiblePosition();
539 TextMarkerData textMarkerData;
540 if (!wkGetBytesFromAXTextMarker(textMarker, &textMarkerData, sizeof(textMarkerData)))
541 return VisiblePosition();
543 return cache->visiblePositionForTextMarkerData(textMarkerData);
546 - (VisiblePosition)visiblePositionForTextMarker:(id)textMarker
548 return visiblePositionForTextMarker(m_object->axObjectCache(), textMarker);
551 static VisiblePosition visiblePositionForStartOfTextMarkerRange(AXObjectCache *cache, id textMarkerRange)
553 return visiblePositionForTextMarker(cache, AXTextMarkerRangeStart(textMarkerRange));
556 static VisiblePosition visiblePositionForEndOfTextMarkerRange(AXObjectCache *cache, id textMarkerRange)
558 return visiblePositionForTextMarker(cache, AXTextMarkerRangeEnd(textMarkerRange));
561 static id textMarkerRangeFromMarkers(id textMarker1, id textMarker2)
563 if (!textMarker1 || !textMarker2)
566 return AXTextMarkerRange(textMarker1, textMarker2);
569 // When modifying attributed strings, the range can come from a source which may provide faulty information (e.g. the spell checker).
570 // To protect against such cases the range should be validated before adding or removing attributes.
571 static BOOL AXAttributedStringRangeIsValid(NSAttributedString* attrString, NSRange range)
573 return (range.location < [attrString length] && NSMaxRange(range) <= [attrString length]);
576 static void AXAttributeStringSetFont(NSMutableAttributedString* attrString, NSString* attribute, NSFont* font, NSRange range)
578 if (!AXAttributedStringRangeIsValid(attrString, range))
582 NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
583 [font fontName] , NSAccessibilityFontNameKey,
584 [font familyName] , NSAccessibilityFontFamilyKey,
585 [font displayName] , NSAccessibilityVisibleNameKey,
586 [NSNumber numberWithFloat:[font pointSize]] , NSAccessibilityFontSizeKey,
589 [attrString addAttribute:attribute value:dict range:range];
591 [attrString removeAttribute:attribute range:range];
595 static CGColorRef CreateCGColorIfDifferent(NSColor* nsColor, CGColorRef existingColor)
597 // get color information assuming NSDeviceRGBColorSpace
598 NSColor* rgbColor = [nsColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
600 rgbColor = [NSColor blackColor];
601 CGFloat components[4];
602 [rgbColor getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]];
604 // create a new CGColorRef to return
605 CGColorSpaceRef cgColorSpace = CGColorSpaceCreateDeviceRGB();
606 CGColorRef cgColor = CGColorCreate(cgColorSpace, components);
607 CGColorSpaceRelease(cgColorSpace);
609 // check for match with existing color
610 if (existingColor && CGColorEqualToColor(cgColor, existingColor)) {
611 CGColorRelease(cgColor);
618 static void AXAttributeStringSetColor(NSMutableAttributedString* attrString, NSString* attribute, NSColor* color, NSRange range)
620 if (!AXAttributedStringRangeIsValid(attrString, range))
624 CGColorRef existingColor = (CGColorRef) [attrString attribute:attribute atIndex:range.location effectiveRange:nil];
625 CGColorRef cgColor = CreateCGColorIfDifferent(color, existingColor);
627 [attrString addAttribute:attribute value:(id)cgColor range:range];
628 CGColorRelease(cgColor);
631 [attrString removeAttribute:attribute range:range];
634 static void AXAttributeStringSetNumber(NSMutableAttributedString* attrString, NSString* attribute, NSNumber* number, NSRange range)
636 if (!AXAttributedStringRangeIsValid(attrString, range))
640 [attrString addAttribute:attribute value:number range:range];
642 [attrString removeAttribute:attribute range:range];
645 static void AXAttributeStringSetStyle(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
647 RenderStyle* style = renderer->style();
649 // set basic font info
650 AXAttributeStringSetFont(attrString, NSAccessibilityFontTextAttribute, style->font().primaryFont()->getNSFont(), range);
653 AXAttributeStringSetColor(attrString, NSAccessibilityForegroundColorTextAttribute, nsColor(style->visitedDependentColor(CSSPropertyColor)), range);
654 AXAttributeStringSetColor(attrString, NSAccessibilityBackgroundColorTextAttribute, nsColor(style->visitedDependentColor(CSSPropertyBackgroundColor)), range);
656 // set super/sub scripting
657 EVerticalAlign alignment = style->verticalAlign();
658 if (alignment == SUB)
659 AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:(-1)], range);
660 else if (alignment == SUPER)
661 AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:1], range);
663 [attrString removeAttribute:NSAccessibilitySuperscriptTextAttribute range:range];
666 if (style->textShadow())
667 AXAttributeStringSetNumber(attrString, NSAccessibilityShadowTextAttribute, [NSNumber numberWithBool:YES], range);
669 [attrString removeAttribute:NSAccessibilityShadowTextAttribute range:range];
671 // set underline and strikethrough
672 int decor = style->textDecorationsInEffect();
673 if ((decor & TextDecorationUnderline) == 0) {
674 [attrString removeAttribute:NSAccessibilityUnderlineTextAttribute range:range];
675 [attrString removeAttribute:NSAccessibilityUnderlineColorTextAttribute range:range];
678 if ((decor & TextDecorationLineThrough) == 0) {
679 [attrString removeAttribute:NSAccessibilityStrikethroughTextAttribute range:range];
680 [attrString removeAttribute:NSAccessibilityStrikethroughColorTextAttribute range:range];
683 if ((decor & (TextDecorationUnderline | TextDecorationLineThrough)) != 0) {
684 // find colors using quirk mode approach (strict mode would use current
685 // color for all but the root line box, which would use getTextDecorationColors)
686 Color underline, overline, linethrough;
687 renderer->getTextDecorationColors(decor, underline, overline, linethrough);
689 if ((decor & TextDecorationUnderline) != 0) {
690 AXAttributeStringSetNumber(attrString, NSAccessibilityUnderlineTextAttribute, [NSNumber numberWithBool:YES], range);
691 AXAttributeStringSetColor(attrString, NSAccessibilityUnderlineColorTextAttribute, nsColor(underline), range);
694 if ((decor & TextDecorationLineThrough) != 0) {
695 AXAttributeStringSetNumber(attrString, NSAccessibilityStrikethroughTextAttribute, [NSNumber numberWithBool:YES], range);
696 AXAttributeStringSetColor(attrString, NSAccessibilityStrikethroughColorTextAttribute, nsColor(linethrough), range);
700 // Indicate background highlighting.
701 for (Node* node = renderer->node(); node; node = node->parentNode()) {
702 if (node->hasTagName(markTag))
703 AXAttributeStringSetNumber(attrString, @"AXHighlight", [NSNumber numberWithBool:YES], range);
707 static void AXAttributeStringSetBlockquoteLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
709 if (!AXAttributedStringRangeIsValid(attrString, range))
712 AccessibilityObject* obj = renderer->document().axObjectCache()->getOrCreate(renderer);
713 int quoteLevel = obj->blockquoteLevel();
716 [attrString addAttribute:NSAccessibilityBlockQuoteLevelAttribute value:[NSNumber numberWithInt:quoteLevel] range:range];
718 [attrString removeAttribute:NSAccessibilityBlockQuoteLevelAttribute range:range];
721 static void AXAttributeStringSetSpelling(NSMutableAttributedString* attrString, Node* node, const UChar* chars, int charLength, NSRange range)
723 if (unifiedTextCheckerEnabled(node->document().frame())) {
724 // Check the spelling directly since document->markersForNode() does not store the misspelled marking when the cursor is in a word.
725 TextCheckerClient* checker = node->document().frame()->editor().textChecker();
727 // checkTextOfParagraph is the only spelling/grammar checker implemented in WK1 and WK2
728 Vector<TextCheckingResult> results;
729 checkTextOfParagraph(checker, chars, charLength, TextCheckingTypeSpelling, results);
731 size_t size = results.size();
732 NSNumber* trueValue = [NSNumber numberWithBool:YES];
733 for (unsigned i = 0; i < size; i++) {
734 const TextCheckingResult& result = results[i];
735 AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, trueValue, NSMakeRange(result.location + range.location, result.length));
736 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
737 AXAttributeStringSetNumber(attrString, NSAccessibilityMarkedMisspelledTextAttribute, trueValue, NSMakeRange(result.location + range.location, result.length));
743 int currentPosition = 0;
744 while (charLength > 0) {
745 const UChar* charData = chars + currentPosition;
746 TextCheckerClient* checker = node->document().frame()->editor().textChecker();
748 int misspellingLocation = -1;
749 int misspellingLength = 0;
750 checker->checkSpellingOfString(charData, charLength, &misspellingLocation, &misspellingLength);
751 if (misspellingLocation == -1 || !misspellingLength)
754 NSRange spellRange = NSMakeRange(range.location + currentPosition + misspellingLocation, misspellingLength);
755 AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, [NSNumber numberWithBool:YES], spellRange);
756 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
757 AXAttributeStringSetNumber(attrString, NSAccessibilityMarkedMisspelledTextAttribute, [NSNumber numberWithBool:YES], spellRange);
759 charLength -= (misspellingLocation + misspellingLength);
760 currentPosition += (misspellingLocation + misspellingLength);
764 static void AXAttributeStringSetHeadingLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
769 if (!AXAttributedStringRangeIsValid(attrString, range))
772 // Sometimes there are objects between the text and the heading.
773 // In those cases the parent hierarchy should be queried to see if there is a heading level.
774 int parentHeadingLevel = 0;
775 AccessibilityObject* parentObject = renderer->document().axObjectCache()->getOrCreate(renderer->parent());
776 for (; parentObject; parentObject = parentObject->parentObject()) {
777 parentHeadingLevel = parentObject->headingLevel();
778 if (parentHeadingLevel)
782 if (parentHeadingLevel)
783 [attrString addAttribute:@"AXHeadingLevel" value:[NSNumber numberWithInt:parentHeadingLevel] range:range];
785 [attrString removeAttribute:@"AXHeadingLevel" range:range];
788 static void AXAttributeStringSetElement(NSMutableAttributedString* attrString, NSString* attribute, AccessibilityObject* object, NSRange range)
790 if (!AXAttributedStringRangeIsValid(attrString, range))
793 if (object && object->isAccessibilityRenderObject()) {
794 // make a serializable AX object
796 RenderObject* renderer = static_cast<AccessibilityRenderObject*>(object)->renderer();
800 AXObjectCache* cache = renderer->document().axObjectCache();
804 AXUIElementRef axElement = wkCreateAXUIElementRef(object->wrapper());
806 [attrString addAttribute:attribute value:(id)axElement range:range];
807 CFRelease(axElement);
810 [attrString removeAttribute:attribute range:range];
813 static void AXAttributedStringAppendText(NSMutableAttributedString* attrString, Node* node, const UChar* chars, int length)
815 // skip invisible text
816 if (!node->renderer())
819 // easier to calculate the range before appending the string
820 NSRange attrStringRange = NSMakeRange([attrString length], length);
822 // append the string from this node
823 [[attrString mutableString] appendString:[NSString stringWithCharacters:chars length:length]];
825 // add new attributes and remove irrelevant inherited ones
826 // NOTE: color attributes are handled specially because -[NSMutableAttributedString addAttribute: value: range:] does not merge
827 // identical colors. Workaround is to not replace an existing color attribute if it matches what we are adding. This also means
828 // we cannot just pre-remove all inherited attributes on the appended string, so we have to remove the irrelevant ones individually.
830 // remove inherited attachment from prior AXAttributedStringAppendReplaced
831 [attrString removeAttribute:NSAccessibilityAttachmentTextAttribute range:attrStringRange];
832 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
833 [attrString removeAttribute:NSAccessibilityMarkedMisspelledTextAttribute range:attrStringRange];
835 [attrString removeAttribute:NSAccessibilityMisspelledTextAttribute range:attrStringRange];
837 // set new attributes
838 AXAttributeStringSetStyle(attrString, node->renderer(), attrStringRange);
839 AXAttributeStringSetHeadingLevel(attrString, node->renderer(), attrStringRange);
840 AXAttributeStringSetBlockquoteLevel(attrString, node->renderer(), attrStringRange);
841 AXAttributeStringSetElement(attrString, NSAccessibilityLinkTextAttribute, AccessibilityObject::anchorElementForNode(node), attrStringRange);
843 // do spelling last because it tends to break up the range
844 AXAttributeStringSetSpelling(attrString, node, chars, length, attrStringRange);
847 static NSString* nsStringForReplacedNode(Node* replacedNode)
849 // we should always be given a rendered node and a replaced node, but be safe
850 // replaced nodes are either attachments (widgets) or images
851 if (!replacedNode || !replacedNode->renderer() || !replacedNode->renderer()->isReplaced() || replacedNode->isTextNode()) {
852 ASSERT_NOT_REACHED();
856 // create an AX object, but skip it if it is not supposed to be seen
857 RefPtr<AccessibilityObject> obj = replacedNode->renderer()->document().axObjectCache()->getOrCreate(replacedNode->renderer());
858 if (obj->accessibilityIsIgnored())
861 // use the attachmentCharacter to represent the replaced node
862 const UniChar attachmentChar = NSAttachmentCharacter;
863 return [NSString stringWithCharacters:&attachmentChar length:1];
866 - (NSAttributedString*)doAXAttributedStringForTextMarkerRange:(id)textMarkerRange
871 // extract the start and end VisiblePosition
872 VisiblePosition startVisiblePosition = visiblePositionForStartOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);
873 if (startVisiblePosition.isNull())
876 VisiblePosition endVisiblePosition = visiblePositionForEndOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);
877 if (endVisiblePosition.isNull())
880 VisiblePositionRange visiblePositionRange(startVisiblePosition, endVisiblePosition);
881 // iterate over the range to build the AX attributed string
882 NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] init];
883 TextIterator it(makeRange(startVisiblePosition, endVisiblePosition).get());
884 while (!it.atEnd()) {
885 // locate the node and starting offset for this range
887 Node* node = it.range()->startContainer(exception);
888 ASSERT(node == it.range()->endContainer(exception));
889 int offset = it.range()->startOffset(exception);
891 // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX)
892 if (it.length() != 0) {
893 // Add the text of the list marker item if necessary.
894 String listMarkerText = m_object->listMarkerTextForNodeAndPosition(node, VisiblePosition(it.range()->startPosition()));
895 if (!listMarkerText.isEmpty())
896 AXAttributedStringAppendText(attrString, node, listMarkerText.characters(), listMarkerText.length());
898 AXAttributedStringAppendText(attrString, node, it.characters(), it.length());
900 Node* replacedNode = node->childNode(offset);
901 NSString *attachmentString = nsStringForReplacedNode(replacedNode);
902 if (attachmentString) {
903 NSRange attrStringRange = NSMakeRange([attrString length], [attachmentString length]);
905 // append the placeholder string
906 [[attrString mutableString] appendString:attachmentString];
908 // remove all inherited attributes
909 [attrString setAttributes:nil range:attrStringRange];
911 // add the attachment attribute
912 AccessibilityObject* obj = replacedNode->renderer()->document().axObjectCache()->getOrCreate(replacedNode->renderer());
913 AXAttributeStringSetElement(attrString, NSAccessibilityAttachmentTextAttribute, obj, attrStringRange);
919 return [attrString autorelease];
922 static id textMarkerRangeFromVisiblePositions(AXObjectCache *cache, VisiblePosition startPosition, VisiblePosition endPosition)
924 id startTextMarker = textMarkerForVisiblePosition(cache, startPosition);
925 id endTextMarker = textMarkerForVisiblePosition(cache, endPosition);
926 return textMarkerRangeFromMarkers(startTextMarker, endTextMarker);
929 - (id)textMarkerRangeFromVisiblePositions:(VisiblePosition)startPosition endPosition:(VisiblePosition)endPosition
931 return textMarkerRangeFromVisiblePositions(m_object->axObjectCache(), startPosition, endPosition);
934 - (NSArray*)accessibilityActionNames
936 if (![self updateObjectBackingStore])
939 // All elements should get ShowMenu and ScrollToVisible.
940 // But certain earlier VoiceOver versions do not support scroll to visible, and it confuses them to see it in the list.
941 #if __MAC_OS_X_VERSION_MIN_REQUIRED < 1090
942 static NSArray *defaultElementActions = [[NSArray alloc] initWithObjects:NSAccessibilityShowMenuAction, nil];
944 static NSArray *defaultElementActions = [[NSArray alloc] initWithObjects:NSAccessibilityShowMenuAction, NSAccessibilityScrollToVisibleAction, nil];
947 // Action elements allow Press.
948 // The order is important to VoiceOver, which expects the 'default' action to be the first action. In this case the default action should be press.
949 #if __MAC_OS_X_VERSION_MIN_REQUIRED < 1090
950 static NSArray *actionElementActions = [[NSArray alloc] initWithObjects:NSAccessibilityPressAction, NSAccessibilityShowMenuAction, nil];
952 static NSArray *actionElementActions = [[NSArray alloc] initWithObjects:NSAccessibilityPressAction, NSAccessibilityShowMenuAction, NSAccessibilityScrollToVisibleAction, nil];
955 // Menu elements allow Press and Cancel.
956 static NSArray *menuElementActions = [[actionElementActions arrayByAddingObject:NSAccessibilityCancelAction] retain];
958 // Slider elements allow Increment/Decrement.
959 static NSArray *sliderActions = [[defaultElementActions arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:NSAccessibilityIncrementAction, NSAccessibilityDecrementAction, nil]] retain];
962 if (m_object->actionElement() || m_object->isButton())
963 actions = actionElementActions;
964 else if (m_object->isMenuRelated())
965 actions = menuElementActions;
966 else if (m_object->isSlider())
967 actions = sliderActions;
968 else if (m_object->isAttachment())
969 actions = [[self attachmentView] accessibilityActionNames];
971 actions = defaultElementActions;
976 - (NSArray*)additionalAccessibilityAttributeNames
981 NSMutableArray *additional = [NSMutableArray array];
982 if (m_object->supportsARIAOwns())
983 [additional addObject:NSAccessibilityOwnsAttribute];
985 if (m_object->supportsARIAExpanded())
986 [additional addObject:NSAccessibilityExpandedAttribute];
988 if (m_object->isScrollbar())
989 [additional addObject:NSAccessibilityOrientationAttribute];
991 if (m_object->supportsARIADragging())
992 [additional addObject:NSAccessibilityGrabbedAttribute];
994 if (m_object->supportsARIADropping())
995 [additional addObject:NSAccessibilityDropEffectsAttribute];
997 if (m_object->isAccessibilityTable() && static_cast<AccessibilityTable*>(m_object)->supportsSelectedRows())
998 [additional addObject:NSAccessibilitySelectedRowsAttribute];
1000 if (m_object->supportsARIALiveRegion()) {
1001 [additional addObject:NSAccessibilityARIALiveAttribute];
1002 [additional addObject:NSAccessibilityARIARelevantAttribute];
1005 if (m_object->supportsARIASetSize())
1006 [additional addObject:NSAccessibilityARIASetSizeAttribute];
1007 if (m_object->supportsARIAPosInSet())
1008 [additional addObject:NSAccessibilityARIAPosInSetAttribute];
1010 if (m_object->sortDirection() != SortDirectionNone)
1011 [additional addObject:NSAccessibilitySortDirectionAttribute];
1013 // If an object is a child of a live region, then add these
1014 if (m_object->isInsideARIALiveRegion())
1015 [additional addObject:NSAccessibilityARIAAtomicAttribute];
1016 // All objects should expose the ARIA busy attribute (ARIA 1.1 with ISSUE-538).
1017 [additional addObject:NSAccessibilityElementBusyAttribute];
1019 // Popup buttons on the Mac expose the value attribute.
1020 if (m_object->isPopUpButton()) {
1021 [additional addObject:NSAccessibilityValueAttribute];
1024 if (m_object->supportsRequiredAttribute()) {
1025 [additional addObject:NSAccessibilityRequiredAttribute];
1028 if (m_object->ariaHasPopup())
1029 [additional addObject:NSAccessibilityHasPopupAttribute];
1031 if (m_object->isMathRoot()) {
1032 // The index of a square root is always known, so there's no object associated with it.
1033 if (!m_object->isMathSquareRoot())
1034 [additional addObject:NSAccessibilityMathRootIndexAttribute];
1035 [additional addObject:NSAccessibilityMathRootRadicandAttribute];
1036 } else if (m_object->isMathFraction()) {
1037 [additional addObject:NSAccessibilityMathFractionNumeratorAttribute];
1038 [additional addObject:NSAccessibilityMathFractionDenominatorAttribute];
1039 [additional addObject:NSAccessibilityMathLineThicknessAttribute];
1040 } else if (m_object->isMathSubscriptSuperscript()) {
1041 [additional addObject:NSAccessibilityMathBaseAttribute];
1042 [additional addObject:NSAccessibilityMathSubscriptAttribute];
1043 [additional addObject:NSAccessibilityMathSuperscriptAttribute];
1044 } else if (m_object->isMathUnderOver()) {
1045 [additional addObject:NSAccessibilityMathBaseAttribute];
1046 [additional addObject:NSAccessibilityMathUnderAttribute];
1047 [additional addObject:NSAccessibilityMathOverAttribute];
1048 } else if (m_object->isMathFenced()) {
1049 [additional addObject:NSAccessibilityMathFencedOpenAttribute];
1050 [additional addObject:NSAccessibilityMathFencedCloseAttribute];
1051 } else if (m_object->isMathMultiscript()) {
1052 [additional addObject:NSAccessibilityMathBaseAttribute];
1053 [additional addObject:NSAccessibilityMathPrescriptsAttribute];
1054 [additional addObject:NSAccessibilityMathPostscriptsAttribute];
1057 if (m_object->supportsPath())
1058 [additional addObject:NSAccessibilityPathAttribute];
1063 - (NSArray*)accessibilityAttributeNames
1065 if (![self updateObjectBackingStore])
1068 if (m_object->isAttachment())
1069 return [[self attachmentView] accessibilityAttributeNames];
1071 static NSArray* attributes = nil;
1072 static NSArray* anchorAttrs = nil;
1073 static NSArray* webAreaAttrs = nil;
1074 static NSArray* textAttrs = nil;
1075 static NSArray* listAttrs = nil;
1076 static NSArray* listBoxAttrs = nil;
1077 static NSArray* rangeAttrs = nil;
1078 static NSArray* commonMenuAttrs = nil;
1079 static NSArray* menuAttrs = nil;
1080 static NSArray* menuBarAttrs = nil;
1081 static NSArray* menuItemAttrs = nil;
1082 static NSArray* menuButtonAttrs = nil;
1083 static NSArray* controlAttrs = nil;
1084 static NSArray* tableAttrs = nil;
1085 static NSArray* tableRowAttrs = nil;
1086 static NSArray* tableColAttrs = nil;
1087 static NSArray* tableCellAttrs = nil;
1088 static NSArray* groupAttrs = nil;
1089 static NSArray* inputImageAttrs = nil;
1090 static NSArray* passwordFieldAttrs = nil;
1091 static NSArray* tabListAttrs = nil;
1092 static NSArray* comboBoxAttrs = nil;
1093 static NSArray* outlineAttrs = nil;
1094 static NSArray* outlineRowAttrs = nil;
1095 static NSArray* buttonAttrs = nil;
1096 static NSArray* scrollViewAttrs = nil;
1097 static NSArray* incrementorAttrs = nil;
1098 NSMutableArray* tempArray;
1099 if (attributes == nil) {
1100 attributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1101 NSAccessibilitySubroleAttribute,
1102 NSAccessibilityRoleDescriptionAttribute,
1103 NSAccessibilityChildrenAttribute,
1104 NSAccessibilityHelpAttribute,
1105 NSAccessibilityParentAttribute,
1106 NSAccessibilityPositionAttribute,
1107 NSAccessibilitySizeAttribute,
1108 NSAccessibilityTitleAttribute,
1109 NSAccessibilityDescriptionAttribute,
1110 NSAccessibilityValueAttribute,
1111 NSAccessibilityFocusedAttribute,
1112 NSAccessibilityEnabledAttribute,
1113 NSAccessibilityWindowAttribute,
1114 @"AXSelectedTextMarkerRange",
1115 @"AXStartTextMarker",
1118 NSAccessibilityLinkedUIElementsAttribute,
1119 NSAccessibilitySelectedAttribute,
1120 NSAccessibilityBlockQuoteLevelAttribute,
1121 NSAccessibilityTopLevelUIElementAttribute,
1122 NSAccessibilityLanguageAttribute,
1123 NSAccessibilityDOMIdentifierAttribute,
1124 NSAccessibilityDOMClassListAttribute,
1127 if (commonMenuAttrs == nil) {
1128 commonMenuAttrs = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1129 NSAccessibilityRoleDescriptionAttribute,
1130 NSAccessibilityChildrenAttribute,
1131 NSAccessibilityParentAttribute,
1132 NSAccessibilityEnabledAttribute,
1133 NSAccessibilityPositionAttribute,
1134 NSAccessibilitySizeAttribute,
1137 if (anchorAttrs == nil) {
1138 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1139 [tempArray addObject:NSAccessibilityURLAttribute];
1140 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1141 anchorAttrs = [[NSArray alloc] initWithArray:tempArray];
1142 [tempArray release];
1144 if (webAreaAttrs == nil) {
1145 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1146 // WebAreas should not expose AXSubrole.
1147 [tempArray removeObject:NSAccessibilitySubroleAttribute];
1148 [tempArray addObject:@"AXLinkUIElements"];
1149 [tempArray addObject:@"AXLoaded"];
1150 [tempArray addObject:@"AXLayoutCount"];
1151 [tempArray addObject:NSAccessibilityLoadingProgressAttribute];
1152 [tempArray addObject:NSAccessibilityURLAttribute];
1153 webAreaAttrs = [[NSArray alloc] initWithArray:tempArray];
1154 [tempArray release];
1156 if (textAttrs == nil) {
1157 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1158 [tempArray addObject:NSAccessibilityNumberOfCharactersAttribute];
1159 [tempArray addObject:NSAccessibilitySelectedTextAttribute];
1160 [tempArray addObject:NSAccessibilitySelectedTextRangeAttribute];
1161 [tempArray addObject:NSAccessibilityVisibleCharacterRangeAttribute];
1162 [tempArray addObject:NSAccessibilityInsertionPointLineNumberAttribute];
1163 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1164 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1165 [tempArray addObject:NSAccessibilityRequiredAttribute];
1166 [tempArray addObject:NSAccessibilityInvalidAttribute];
1167 [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1168 textAttrs = [[NSArray alloc] initWithArray:tempArray];
1169 [tempArray release];
1171 if (listAttrs == nil) {
1172 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1173 [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1174 [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1175 [tempArray addObject:NSAccessibilityOrientationAttribute];
1176 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1177 listAttrs = [[NSArray alloc] initWithArray:tempArray];
1178 [tempArray release];
1180 if (listBoxAttrs == nil) {
1181 tempArray = [[NSMutableArray alloc] initWithArray:listAttrs];
1182 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1183 [tempArray addObject:NSAccessibilityRequiredAttribute];
1184 [tempArray addObject:NSAccessibilityInvalidAttribute];
1185 listBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1186 [tempArray release];
1188 if (rangeAttrs == nil) {
1189 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1190 [tempArray addObject:NSAccessibilityMinValueAttribute];
1191 [tempArray addObject:NSAccessibilityMaxValueAttribute];
1192 [tempArray addObject:NSAccessibilityOrientationAttribute];
1193 [tempArray addObject:NSAccessibilityValueDescriptionAttribute];
1194 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1195 rangeAttrs = [[NSArray alloc] initWithArray:tempArray];
1196 [tempArray release];
1198 if (menuBarAttrs == nil) {
1199 tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1200 [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1201 [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1202 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1203 menuBarAttrs = [[NSArray alloc] initWithArray:tempArray];
1204 [tempArray release];
1206 if (menuAttrs == nil) {
1207 tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1208 [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1209 [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1210 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1211 menuAttrs = [[NSArray alloc] initWithArray:tempArray];
1212 [tempArray release];
1214 if (menuItemAttrs == nil) {
1215 tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1216 [tempArray addObject:NSAccessibilityTitleAttribute];
1217 [tempArray addObject:NSAccessibilityHelpAttribute];
1218 [tempArray addObject:NSAccessibilitySelectedAttribute];
1219 [tempArray addObject:NSAccessibilityValueAttribute];
1220 [tempArray addObject:(NSString*)kAXMenuItemCmdCharAttribute];
1221 [tempArray addObject:(NSString*)kAXMenuItemCmdVirtualKeyAttribute];
1222 [tempArray addObject:(NSString*)kAXMenuItemCmdGlyphAttribute];
1223 [tempArray addObject:(NSString*)kAXMenuItemCmdModifiersAttribute];
1224 [tempArray addObject:(NSString*)kAXMenuItemMarkCharAttribute];
1225 [tempArray addObject:(NSString*)kAXMenuItemPrimaryUIElementAttribute];
1226 [tempArray addObject:NSAccessibilityServesAsTitleForUIElementsAttribute];
1227 menuItemAttrs = [[NSArray alloc] initWithArray:tempArray];
1228 [tempArray release];
1230 if (menuButtonAttrs == nil) {
1231 menuButtonAttrs = [[NSArray alloc] initWithObjects:NSAccessibilityRoleAttribute,
1232 NSAccessibilityRoleDescriptionAttribute,
1233 NSAccessibilityParentAttribute,
1234 NSAccessibilityPositionAttribute,
1235 NSAccessibilitySizeAttribute,
1236 NSAccessibilityWindowAttribute,
1237 NSAccessibilityEnabledAttribute,
1238 NSAccessibilityFocusedAttribute,
1239 NSAccessibilityTitleAttribute,
1240 NSAccessibilityChildrenAttribute, nil];
1242 if (controlAttrs == nil) {
1243 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1244 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1245 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1246 [tempArray addObject:NSAccessibilityRequiredAttribute];
1247 [tempArray addObject:NSAccessibilityInvalidAttribute];
1248 controlAttrs = [[NSArray alloc] initWithArray:tempArray];
1249 [tempArray release];
1251 if (incrementorAttrs == nil) {
1252 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1253 [tempArray addObject:NSAccessibilityIncrementButtonAttribute];
1254 [tempArray addObject:NSAccessibilityDecrementButtonAttribute];
1255 [tempArray addObject:NSAccessibilityValueDescriptionAttribute];
1256 [tempArray addObject:NSAccessibilityMinValueAttribute];
1257 [tempArray addObject:NSAccessibilityMaxValueAttribute];
1258 incrementorAttrs = [[NSArray alloc] initWithArray:tempArray];
1259 [tempArray release];
1261 if (buttonAttrs == nil) {
1262 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1263 // Buttons should not expose AXValue.
1264 [tempArray removeObject:NSAccessibilityValueAttribute];
1265 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1266 [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1267 buttonAttrs = [[NSArray alloc] initWithArray:tempArray];
1268 [tempArray release];
1270 if (comboBoxAttrs == nil) {
1271 tempArray = [[NSMutableArray alloc] initWithArray:controlAttrs];
1272 [tempArray addObject:NSAccessibilityExpandedAttribute];
1273 comboBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1274 [tempArray release];
1276 if (tableAttrs == nil) {
1277 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1278 [tempArray addObject:NSAccessibilityRowsAttribute];
1279 [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1280 [tempArray addObject:NSAccessibilityColumnsAttribute];
1281 [tempArray addObject:NSAccessibilityVisibleColumnsAttribute];
1282 [tempArray addObject:NSAccessibilityVisibleCellsAttribute];
1283 [tempArray addObject:(NSString *)kAXColumnHeaderUIElementsAttribute];
1284 [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];
1285 [tempArray addObject:NSAccessibilityHeaderAttribute];
1286 tableAttrs = [[NSArray alloc] initWithArray:tempArray];
1287 [tempArray release];
1289 if (tableRowAttrs == nil) {
1290 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1291 [tempArray addObject:NSAccessibilityIndexAttribute];
1292 tableRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1293 [tempArray release];
1295 if (tableColAttrs == nil) {
1296 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1297 [tempArray addObject:NSAccessibilityIndexAttribute];
1298 [tempArray addObject:NSAccessibilityHeaderAttribute];
1299 [tempArray addObject:NSAccessibilityRowsAttribute];
1300 [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1301 tableColAttrs = [[NSArray alloc] initWithArray:tempArray];
1302 [tempArray release];
1304 if (tableCellAttrs == nil) {
1305 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1306 [tempArray addObject:NSAccessibilityRowIndexRangeAttribute];
1307 [tempArray addObject:NSAccessibilityColumnIndexRangeAttribute];
1308 tableCellAttrs = [[NSArray alloc] initWithArray:tempArray];
1309 [tempArray release];
1311 if (groupAttrs == nil) {
1312 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1313 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1314 groupAttrs = [[NSArray alloc] initWithArray:tempArray];
1315 [tempArray release];
1317 if (inputImageAttrs == nil) {
1318 tempArray = [[NSMutableArray alloc] initWithArray:buttonAttrs];
1319 [tempArray addObject:NSAccessibilityURLAttribute];
1320 inputImageAttrs = [[NSArray alloc] initWithArray:tempArray];
1321 [tempArray release];
1323 if (passwordFieldAttrs == nil) {
1324 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1325 [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1326 [tempArray addObject:NSAccessibilityRequiredAttribute];
1327 [tempArray addObject:NSAccessibilityInvalidAttribute];
1328 [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1329 passwordFieldAttrs = [[NSArray alloc] initWithArray:tempArray];
1330 [tempArray release];
1332 if (tabListAttrs == nil) {
1333 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1334 [tempArray addObject:NSAccessibilityTabsAttribute];
1335 [tempArray addObject:NSAccessibilityContentsAttribute];
1336 tabListAttrs = [[NSArray alloc] initWithArray:tempArray];
1337 [tempArray release];
1339 if (outlineAttrs == nil) {
1340 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1341 [tempArray addObject:NSAccessibilitySelectedRowsAttribute];
1342 [tempArray addObject:NSAccessibilityRowsAttribute];
1343 [tempArray addObject:NSAccessibilityColumnsAttribute];
1344 outlineAttrs = [[NSArray alloc] initWithArray:tempArray];
1345 [tempArray release];
1347 if (outlineRowAttrs == nil) {
1348 tempArray = [[NSMutableArray alloc] initWithArray:tableRowAttrs];
1349 [tempArray addObject:NSAccessibilityDisclosingAttribute];
1350 [tempArray addObject:NSAccessibilityDisclosedByRowAttribute];
1351 [tempArray addObject:NSAccessibilityDisclosureLevelAttribute];
1352 [tempArray addObject:NSAccessibilityDisclosedRowsAttribute];
1353 outlineRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1354 [tempArray release];
1356 if (scrollViewAttrs == nil) {
1357 tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1358 [tempArray addObject:NSAccessibilityContentsAttribute];
1359 [tempArray addObject:NSAccessibilityHorizontalScrollBarAttribute];
1360 [tempArray addObject:NSAccessibilityVerticalScrollBarAttribute];
1361 scrollViewAttrs = [[NSArray alloc] initWithArray:tempArray];
1362 [tempArray release];
1365 NSArray *objectAttributes = attributes;
1367 if (m_object->isPasswordField())
1368 objectAttributes = passwordFieldAttrs;
1370 else if (m_object->isWebArea())
1371 objectAttributes = webAreaAttrs;
1373 else if (m_object->isTextControl())
1374 objectAttributes = textAttrs;
1376 else if (m_object->isAnchor() || m_object->isImage() || m_object->isLink())
1377 objectAttributes = anchorAttrs;
1379 else if (m_object->isAccessibilityTable())
1380 objectAttributes = tableAttrs;
1381 else if (m_object->isTableColumn())
1382 objectAttributes = tableColAttrs;
1383 else if (m_object->isTableCell())
1384 objectAttributes = tableCellAttrs;
1385 else if (m_object->isTableRow()) {
1386 // An ARIA table row can be collapsed and expanded, so it needs the extra attributes.
1387 if (m_object->isARIATreeGridRow())
1388 objectAttributes = outlineRowAttrs;
1390 objectAttributes = tableRowAttrs;
1393 else if (m_object->isTree())
1394 objectAttributes = outlineAttrs;
1395 else if (m_object->isTreeItem())
1396 objectAttributes = outlineRowAttrs;
1398 else if (m_object->isListBox())
1399 objectAttributes = listBoxAttrs;
1400 else if (m_object->isList())
1401 objectAttributes = listAttrs;
1403 else if (m_object->isComboBox())
1404 objectAttributes = comboBoxAttrs;
1406 else if (m_object->isProgressIndicator() || m_object->isSlider())
1407 objectAttributes = rangeAttrs;
1409 // These are processed in order because an input image is a button, and a button is a control.
1410 else if (m_object->isInputImage())
1411 objectAttributes = inputImageAttrs;
1412 else if (m_object->isButton())
1413 objectAttributes = buttonAttrs;
1414 else if (m_object->isControl())
1415 objectAttributes = controlAttrs;
1417 else if (m_object->isGroup() || m_object->isListItem())
1418 objectAttributes = groupAttrs;
1419 else if (m_object->isTabList())
1420 objectAttributes = tabListAttrs;
1421 else if (m_object->isScrollView())
1422 objectAttributes = scrollViewAttrs;
1423 else if (m_object->isSpinButton())
1424 objectAttributes = incrementorAttrs;
1426 else if (m_object->isMenu())
1427 objectAttributes = menuAttrs;
1428 else if (m_object->isMenuBar())
1429 objectAttributes = menuBarAttrs;
1430 else if (m_object->isMenuButton())
1431 objectAttributes = menuButtonAttrs;
1432 else if (m_object->isMenuItem())
1433 objectAttributes = menuItemAttrs;
1435 NSArray *additionalAttributes = [self additionalAccessibilityAttributeNames];
1436 if ([additionalAttributes count])
1437 objectAttributes = [objectAttributes arrayByAddingObjectsFromArray:additionalAttributes];
1439 return objectAttributes;
1442 - (VisiblePositionRange)visiblePositionRangeForTextMarkerRange:(id)textMarkerRange
1444 if (!textMarkerRange)
1445 return VisiblePositionRange();
1446 AXObjectCache* cache = m_object->axObjectCache();
1447 return VisiblePositionRange(visiblePositionForStartOfTextMarkerRange(cache, textMarkerRange), visiblePositionForEndOfTextMarkerRange(cache, textMarkerRange));
1450 - (NSArray*)renderWidgetChildren
1452 Widget* widget = m_object->widget();
1455 return [(widget->platformWidget()) accessibilityAttributeValue: NSAccessibilityChildrenAttribute];
1458 - (id)remoteAccessibilityParentObject
1463 Document* document = m_object->document();
1467 Frame* frame = document->frame();
1471 return frame->loader().client().accessibilityRemoteObject();
1474 static void convertToVector(NSArray* array, AccessibilityObject::AccessibilityChildrenVector& vector)
1476 unsigned length = [array count];
1477 vector.reserveInitialCapacity(length);
1478 for (unsigned i = 0; i < length; ++i) {
1479 AccessibilityObject* obj = [[array objectAtIndex:i] accessibilityObject];
1485 static NSMutableArray* convertToNSArray(const AccessibilityObject::AccessibilityChildrenVector& vector)
1487 unsigned length = vector.size();
1488 NSMutableArray* array = [NSMutableArray arrayWithCapacity: length];
1489 for (unsigned i = 0; i < length; ++i) {
1490 WebAccessibilityObjectWrapper* wrapper = vector[i]->wrapper();
1493 // we want to return the attachment view instead of the object representing the attachment.
1494 // otherwise, we get palindrome errors in the AX hierarchy
1495 if (vector[i]->isAttachment() && [wrapper attachmentView])
1496 [array addObject:[wrapper attachmentView]];
1498 [array addObject:wrapper];
1504 static NSMutableArray *convertStringsToNSArray(const Vector<String>& vector)
1506 size_t length = vector.size();
1507 NSMutableArray *array = [NSMutableArray arrayWithCapacity:length];
1508 for (size_t i = 0; i < length; ++i)
1509 [array addObject:vector[i]];
1513 - (id)textMarkerRangeForSelection
1515 VisibleSelection selection = m_object->selection();
1516 if (selection.isNone())
1518 return [self textMarkerRangeFromVisiblePositions:selection.visibleStart() endPosition:selection.visibleEnd()];
1521 - (CGPoint)convertPointToScreenSpace:(FloatPoint &)point
1523 FrameView* frameView = m_object->documentFrameView();
1525 // WebKit1 code path... platformWidget() exists.
1526 if (frameView && frameView->platformWidget()) {
1528 NSPoint nsPoint = (NSPoint)point;
1529 NSView* view = frameView->documentView();
1530 nsPoint = [[view window] convertBaseToScreen:[view convertPoint:nsPoint toView:nil]];
1531 return CGPointMake(nsPoint.x, nsPoint.y);
1535 // Find the appropriate scroll view to use to convert the contents to the window.
1536 ScrollView* scrollView = 0;
1537 AccessibilityObject* parent = 0;
1538 for (parent = m_object->parentObject(); parent; parent = parent->parentObject()) {
1539 if (parent->isAccessibilityScrollView()) {
1540 scrollView = toAccessibilityScrollView(parent)->scrollView();
1545 IntPoint intPoint = flooredIntPoint(point);
1547 intPoint = scrollView->contentsToRootView(intPoint);
1549 Page* page = m_object->page();
1551 // If we have an empty chrome client (like SVG) then we should use the page
1552 // of the scroll view parent to help us get to the screen rect.
1553 if (parent && page && page->chrome().client().isEmptyChromeClient())
1554 page = parent->page();
1557 IntRect rect = IntRect(intPoint, IntSize(0, 0));
1558 intPoint = page->chrome().rootViewToScreen(rect).location();
1565 static void WebTransformCGPathToNSBezierPath(void *info, const CGPathElement *element)
1567 NSBezierPath *bezierPath = (NSBezierPath *)info;
1568 switch (element->type) {
1569 case kCGPathElementMoveToPoint:
1570 [bezierPath moveToPoint:NSPointFromCGPoint(element->points[0])];
1572 case kCGPathElementAddLineToPoint:
1573 [bezierPath lineToPoint:NSPointFromCGPoint(element->points[0])];
1575 case kCGPathElementAddCurveToPoint:
1576 [bezierPath curveToPoint:NSPointFromCGPoint(element->points[0]) controlPoint1:NSPointFromCGPoint(element->points[1]) controlPoint2:NSPointFromCGPoint(element->points[2])];
1578 case kCGPathElementCloseSubpath:
1579 [bezierPath closePath];
1586 - (NSBezierPath *)bezierPathFromPath:(CGPathRef)path
1588 NSBezierPath *bezierPath = [NSBezierPath bezierPath];
1589 CGPathApply(path, bezierPath, WebTransformCGPathToNSBezierPath);
1593 - (NSBezierPath *)path
1595 Path path = m_object->elementPath();
1599 CGPathRef transformedPath = [self convertPathToScreenSpace:path];
1600 return [self bezierPathFromPath:transformedPath];
1603 - (NSValue *)position
1605 IntRect rect = pixelSnappedIntRect(m_object->elementRect());
1607 // The Cocoa accessibility API wants the lower-left corner.
1608 FloatPoint floatPoint = FloatPoint(rect.x(), rect.maxY());
1610 CGPoint cgPoint = [self convertPointToScreenSpace:floatPoint];
1612 return [NSValue valueWithPoint:NSMakePoint(cgPoint.x, cgPoint.y)];
1615 typedef HashMap<int, NSString*> AccessibilityRoleMap;
1617 static const AccessibilityRoleMap& createAccessibilityRoleMap()
1620 AccessibilityRole value;
1624 static const RoleEntry roles[] = {
1625 { UnknownRole, NSAccessibilityUnknownRole },
1626 { ButtonRole, NSAccessibilityButtonRole },
1627 { RadioButtonRole, NSAccessibilityRadioButtonRole },
1628 { CheckBoxRole, NSAccessibilityCheckBoxRole },
1629 { SliderRole, NSAccessibilitySliderRole },
1630 { TabGroupRole, NSAccessibilityTabGroupRole },
1631 { TextFieldRole, NSAccessibilityTextFieldRole },
1632 { StaticTextRole, NSAccessibilityStaticTextRole },
1633 { TextAreaRole, NSAccessibilityTextAreaRole },
1634 { ScrollAreaRole, NSAccessibilityScrollAreaRole },
1635 { PopUpButtonRole, NSAccessibilityPopUpButtonRole },
1636 { MenuButtonRole, NSAccessibilityMenuButtonRole },
1637 { TableRole, NSAccessibilityTableRole },
1638 { ApplicationRole, NSAccessibilityApplicationRole },
1639 { GroupRole, NSAccessibilityGroupRole },
1640 { RadioGroupRole, NSAccessibilityRadioGroupRole },
1641 { ListRole, NSAccessibilityListRole },
1642 { DirectoryRole, NSAccessibilityListRole },
1643 { ScrollBarRole, NSAccessibilityScrollBarRole },
1644 { ValueIndicatorRole, NSAccessibilityValueIndicatorRole },
1645 { ImageRole, NSAccessibilityImageRole },
1646 { MenuBarRole, NSAccessibilityMenuBarRole },
1647 { MenuRole, NSAccessibilityMenuRole },
1648 { MenuItemRole, NSAccessibilityMenuItemRole },
1649 { MenuItemCheckboxRole, NSAccessibilityMenuItemRole },
1650 { MenuItemRadioRole, NSAccessibilityMenuItemRole },
1651 { ColumnRole, NSAccessibilityColumnRole },
1652 { RowRole, NSAccessibilityRowRole },
1653 { ToolbarRole, NSAccessibilityToolbarRole },
1654 { BusyIndicatorRole, NSAccessibilityBusyIndicatorRole },
1655 { ProgressIndicatorRole, NSAccessibilityProgressIndicatorRole },
1656 { WindowRole, NSAccessibilityWindowRole },
1657 { DrawerRole, NSAccessibilityDrawerRole },
1658 { SystemWideRole, NSAccessibilitySystemWideRole },
1659 { OutlineRole, NSAccessibilityOutlineRole },
1660 { IncrementorRole, NSAccessibilityIncrementorRole },
1661 { BrowserRole, NSAccessibilityBrowserRole },
1662 { ComboBoxRole, NSAccessibilityComboBoxRole },
1663 { SplitGroupRole, NSAccessibilitySplitGroupRole },
1664 { SplitterRole, NSAccessibilitySplitterRole },
1665 { ColorWellRole, NSAccessibilityColorWellRole },
1666 { GrowAreaRole, NSAccessibilityGrowAreaRole },
1667 { SheetRole, NSAccessibilitySheetRole },
1668 { HelpTagRole, NSAccessibilityHelpTagRole },
1669 { MatteRole, NSAccessibilityMatteRole },
1670 { RulerRole, NSAccessibilityRulerRole },
1671 { RulerMarkerRole, NSAccessibilityRulerMarkerRole },
1672 { LinkRole, NSAccessibilityLinkRole },
1673 { DisclosureTriangleRole, NSAccessibilityDisclosureTriangleRole },
1674 { GridRole, NSAccessibilityGridRole },
1675 { WebCoreLinkRole, NSAccessibilityLinkRole },
1676 { ImageMapLinkRole, NSAccessibilityLinkRole },
1677 { ImageMapRole, @"AXImageMap" },
1678 { ListMarkerRole, @"AXListMarker" },
1679 { WebAreaRole, @"AXWebArea" },
1680 { SeamlessWebAreaRole, NSAccessibilityGroupRole },
1681 { HeadingRole, @"AXHeading" },
1682 { ListBoxRole, NSAccessibilityListRole },
1683 { ListBoxOptionRole, NSAccessibilityStaticTextRole },
1684 { CellRole, NSAccessibilityCellRole },
1685 { TableHeaderContainerRole, NSAccessibilityGroupRole },
1686 { RowHeaderRole, NSAccessibilityGroupRole },
1687 { DefinitionRole, NSAccessibilityGroupRole },
1688 { DescriptionListDetailRole, NSAccessibilityGroupRole },
1689 { DescriptionListTermRole, NSAccessibilityGroupRole },
1690 { DescriptionListRole, NSAccessibilityListRole },
1691 { SliderThumbRole, NSAccessibilityValueIndicatorRole },
1692 { LandmarkApplicationRole, NSAccessibilityGroupRole },
1693 { LandmarkBannerRole, NSAccessibilityGroupRole },
1694 { LandmarkComplementaryRole, NSAccessibilityGroupRole },
1695 { LandmarkContentInfoRole, NSAccessibilityGroupRole },
1696 { LandmarkMainRole, NSAccessibilityGroupRole },
1697 { LandmarkNavigationRole, NSAccessibilityGroupRole },
1698 { LandmarkSearchRole, NSAccessibilityGroupRole },
1699 { ApplicationAlertRole, NSAccessibilityGroupRole },
1700 { ApplicationAlertDialogRole, NSAccessibilityGroupRole },
1701 { ApplicationDialogRole, NSAccessibilityGroupRole },
1702 { ApplicationLogRole, NSAccessibilityGroupRole },
1703 { ApplicationMarqueeRole, NSAccessibilityGroupRole },
1704 { ApplicationStatusRole, NSAccessibilityGroupRole },
1705 { ApplicationTimerRole, NSAccessibilityGroupRole },
1706 { DocumentRole, NSAccessibilityGroupRole },
1707 { DocumentArticleRole, NSAccessibilityGroupRole },
1708 { DocumentMathRole, NSAccessibilityGroupRole },
1709 { DocumentNoteRole, NSAccessibilityGroupRole },
1710 { DocumentRegionRole, NSAccessibilityGroupRole },
1711 { UserInterfaceTooltipRole, NSAccessibilityGroupRole },
1712 { TabRole, NSAccessibilityRadioButtonRole },
1713 { TabListRole, NSAccessibilityTabGroupRole },
1714 { TabPanelRole, NSAccessibilityGroupRole },
1715 { TreeRole, NSAccessibilityOutlineRole },
1716 { TreeItemRole, NSAccessibilityRowRole },
1717 { ListItemRole, NSAccessibilityGroupRole },
1718 { ParagraphRole, NSAccessibilityGroupRole },
1719 { LabelRole, NSAccessibilityGroupRole },
1720 { DivRole, NSAccessibilityGroupRole },
1721 { FormRole, NSAccessibilityGroupRole },
1722 { SpinButtonRole, NSAccessibilityIncrementorRole },
1723 { FooterRole, NSAccessibilityGroupRole },
1724 { ToggleButtonRole, NSAccessibilityButtonRole },
1725 { CanvasRole, NSAccessibilityImageRole },
1726 { SVGRootRole, NSAccessibilityGroupRole },
1727 { LegendRole, NSAccessibilityGroupRole },
1728 { MathElementRole, NSAccessibilityGroupRole }
1730 AccessibilityRoleMap& roleMap = *new AccessibilityRoleMap;
1732 const unsigned numRoles = sizeof(roles) / sizeof(roles[0]);
1733 for (unsigned i = 0; i < numRoles; ++i)
1734 roleMap.set(roles[i].value, roles[i].string);
1738 static NSString* roleValueToNSString(AccessibilityRole value)
1741 static const AccessibilityRoleMap& roleMap = createAccessibilityRoleMap();
1742 return roleMap.get(value);
1747 if (m_object->isAttachment())
1748 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleAttribute];
1749 AccessibilityRole role = m_object->roleValue();
1750 if (role == CanvasRole && m_object->canvasHasFallbackContent())
1752 NSString* string = roleValueToNSString(role);
1755 return NSAccessibilityUnknownRole;
1758 - (NSString*)subrole
1760 if (m_object->isPasswordField())
1761 return NSAccessibilitySecureTextFieldSubrole;
1762 if (m_object->isSearchField())
1763 return NSAccessibilitySearchFieldSubrole;
1765 if (m_object->isAttachment()) {
1766 NSView* attachView = [self attachmentView];
1767 if ([[attachView accessibilityAttributeNames] containsObject:NSAccessibilitySubroleAttribute]) {
1768 return [attachView accessibilityAttributeValue:NSAccessibilitySubroleAttribute];
1772 if (m_object->isSpinButtonPart()) {
1773 if (toAccessibilitySpinButtonPart(m_object)->isIncrementor())
1774 return NSAccessibilityIncrementArrowSubrole;
1776 return NSAccessibilityDecrementArrowSubrole;
1779 if (m_object->isFileUploadButton())
1780 return @"AXFileUploadButton";
1782 if (m_object->isTreeItem())
1783 return NSAccessibilityOutlineRowSubrole;
1785 if (m_object->isList()) {
1786 AccessibilityList* listObject = toAccessibilityList(m_object);
1787 if (listObject->isUnorderedList() || listObject->isOrderedList())
1788 return NSAccessibilityContentListSubrole;
1789 if (listObject->isDescriptionList()) {
1790 #if __MAC_OS_X_VERSION_MIN_REQUIRED < 1090
1791 return NSAccessibilityDefinitionListSubrole;
1793 return NSAccessibilityDescriptionListSubrole;
1798 // ARIA content subroles.
1799 switch (m_object->roleValue()) {
1800 case LandmarkApplicationRole:
1801 return @"AXLandmarkApplication";
1802 case LandmarkBannerRole:
1803 return @"AXLandmarkBanner";
1804 case LandmarkComplementaryRole:
1805 return @"AXLandmarkComplementary";
1806 // Footer roles should appear as content info types.
1808 case LandmarkContentInfoRole:
1809 return @"AXLandmarkContentInfo";
1810 case LandmarkMainRole:
1811 return @"AXLandmarkMain";
1812 case LandmarkNavigationRole:
1813 return @"AXLandmarkNavigation";
1814 case LandmarkSearchRole:
1815 return @"AXLandmarkSearch";
1816 case ApplicationAlertRole:
1817 return @"AXApplicationAlert";
1818 case ApplicationAlertDialogRole:
1819 return @"AXApplicationAlertDialog";
1820 case ApplicationDialogRole:
1821 return @"AXApplicationDialog";
1822 case ApplicationLogRole:
1823 return @"AXApplicationLog";
1824 case ApplicationMarqueeRole:
1825 return @"AXApplicationMarquee";
1826 case ApplicationStatusRole:
1827 return @"AXApplicationStatus";
1828 case ApplicationTimerRole:
1829 return @"AXApplicationTimer";
1831 return @"AXDocument";
1832 case DocumentArticleRole:
1833 return @"AXDocumentArticle";
1834 case DocumentMathRole:
1835 return @"AXDocumentMath";
1836 case DocumentNoteRole:
1837 return @"AXDocumentNote";
1838 case DocumentRegionRole:
1839 return @"AXDocumentRegion";
1840 case UserInterfaceTooltipRole:
1841 return @"AXUserInterfaceTooltip";
1843 return @"AXTabPanel";
1844 case DefinitionRole:
1845 return @"AXDefinition";
1846 case DescriptionListTermRole:
1848 case DescriptionListDetailRole:
1849 return @"AXDescription";
1850 // Default doesn't return anything, so roles defined below can be chosen.
1855 if (m_object->roleValue() == MathElementRole) {
1856 if (m_object->isMathFraction())
1857 return @"AXMathFraction";
1858 if (m_object->isMathFenced())
1859 return @"AXMathFenced";
1860 if (m_object->isMathSubscriptSuperscript())
1861 return @"AXMathSubscriptSuperscript";
1862 if (m_object->isMathRow())
1863 return @"AXMathRow";
1864 if (m_object->isMathUnderOver())
1865 return @"AXMathUnderOver";
1866 if (m_object->isMathSquareRoot())
1867 return @"AXMathSquareRoot";
1868 if (m_object->isMathRoot())
1869 return @"AXMathRoot";
1870 if (m_object->isMathText())
1871 return @"AXMathText";
1872 if (m_object->isMathNumber())
1873 return @"AXMathNumber";
1874 if (m_object->isMathIdentifier())
1875 return @"AXMathIdentifier";
1876 if (m_object->isMathTable())
1877 return @"AXMathTable";
1878 if (m_object->isMathTableRow())
1879 return @"AXMathTableRow";
1880 if (m_object->isMathTableCell())
1881 return @"AXMathTableCell";
1882 if (m_object->isMathFenceOperator())
1883 return @"AXMathFenceOperator";
1884 if (m_object->isMathSeparatorOperator())
1885 return @"AXMathSeparatorOperator";
1886 if (m_object->isMathOperator())
1887 return @"AXMathOperator";
1888 if (m_object->isMathMultiscript())
1889 return @"AXMathMultiscript";
1892 if (m_object->isMediaTimeline())
1893 return NSAccessibilityTimelineSubrole;
1898 - (NSString*)roleDescription
1903 // attachments have the AXImage role, but a different subrole
1904 if (m_object->isAttachment())
1905 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute];
1907 NSString* axRole = [self role];
1909 if ([axRole isEqualToString:NSAccessibilityGroupRole]) {
1911 NSString *ariaLandmarkRoleDescription = [self ariaLandmarkRoleDescription];
1912 if (ariaLandmarkRoleDescription)
1913 return ariaLandmarkRoleDescription;
1915 switch (m_object->roleValue()) {
1916 case DefinitionRole:
1917 return AXDefinitionText();
1918 case DescriptionListTermRole:
1919 return AXDescriptionListTermText();
1920 case DescriptionListDetailRole:
1921 return AXDescriptionListDetailText();
1923 return AXFooterRoleDescriptionText();
1925 return NSAccessibilityRoleDescription(NSAccessibilityGroupRole, [self subrole]);
1929 if ([axRole isEqualToString:@"AXWebArea"])
1930 return AXWebAreaText();
1932 if ([axRole isEqualToString:@"AXLink"])
1933 return AXLinkText();
1935 if ([axRole isEqualToString:@"AXListMarker"])
1936 return AXListMarkerText();
1938 if ([axRole isEqualToString:@"AXImageMap"])
1939 return AXImageMapText();
1941 if ([axRole isEqualToString:@"AXHeading"])
1942 return AXHeadingText();
1944 if (m_object->isFileUploadButton())
1945 return AXFileUploadButtonText();
1947 // Only returning for DL (not UL or OL) because description changed with HTML5 from 'definition list' to
1948 // superset 'description list' and does not return the same values in AX API on some OS versions.
1949 if (m_object->isList()) {
1950 AccessibilityList* listObject = toAccessibilityList(m_object);
1951 if (listObject->isDescriptionList())
1952 return AXDescriptionListText();
1955 // AppKit also returns AXTab for the role description for a tab item.
1956 if (m_object->isTabItem())
1957 return NSAccessibilityRoleDescription(@"AXTab", nil);
1959 // We should try the system default role description for all other roles.
1960 // If we get the same string back, then as a last resort, return unknown.
1961 NSString* defaultRoleDescription = NSAccessibilityRoleDescription(axRole, [self subrole]);
1963 // On earlier Mac versions (Lion), using a non-standard subrole would result in a role description
1964 // being returned that looked like AXRole:AXSubrole. To make all platforms have the same role descriptions
1965 // we should fallback on a role description ignoring the subrole in these cases.
1966 if ([defaultRoleDescription isEqualToString:[NSString stringWithFormat:@"%@:%@", axRole, [self subrole]]])
1967 defaultRoleDescription = NSAccessibilityRoleDescription(axRole, nil);
1969 if (![defaultRoleDescription isEqualToString:axRole])
1970 return defaultRoleDescription;
1972 return NSAccessibilityRoleDescription(NSAccessibilityUnknownRole, nil);
1975 - (id)scrollViewParent
1977 if (!m_object || !m_object->isAccessibilityScrollView())
1980 // If this scroll view provides it's parent object (because it's a sub-frame), then
1981 // we should not find the remoteAccessibilityParent.
1982 if (m_object->parentObject())
1985 AccessibilityScrollView* scrollView = toAccessibilityScrollView(m_object);
1986 ScrollView* scroll = scrollView->scrollView();
1990 if (scroll->platformWidget())
1991 return NSAccessibilityUnignoredAncestor(scroll->platformWidget());
1993 return [self remoteAccessibilityParentObject];
1996 // FIXME: split up this function in a better way.
1997 // suggestions: Use a hash table that maps attribute names to function calls,
1998 // or maybe pointers to member functions
1999 - (id)accessibilityAttributeValue:(NSString*)attributeName
2001 if (![self updateObjectBackingStore])
2004 if ([attributeName isEqualToString: NSAccessibilityRoleAttribute])
2007 if ([attributeName isEqualToString: NSAccessibilitySubroleAttribute])
2008 return [self subrole];
2010 if ([attributeName isEqualToString: NSAccessibilityRoleDescriptionAttribute])
2011 return [self roleDescription];
2013 if ([attributeName isEqualToString: NSAccessibilityParentAttribute]) {
2015 // This will return the parent of the AXWebArea, if this is a web area.
2016 id scrollViewParent = [self scrollViewParent];
2017 if (scrollViewParent)
2018 return scrollViewParent;
2020 // Tree item (changed to AXRows) can only report the tree (AXOutline) as its parent.
2021 if (m_object->isTreeItem()) {
2022 AccessibilityObject* parent = m_object->parentObjectUnignored();
2024 if (parent->isTree())
2025 return parent->wrapper();
2026 parent = parent->parentObjectUnignored();
2030 AccessibilityObject* parent = m_object->parentObjectUnignored();
2034 // In WebKit1, the scroll view is provided by the system (the attachment view), so the parent
2035 // should be reported directly as such.
2036 if (m_object->isWebArea() && parent->isAttachment())
2037 return [parent->wrapper() attachmentView];
2039 return parent->wrapper();
2042 if ([attributeName isEqualToString: NSAccessibilityChildrenAttribute]) {
2043 if (m_object->children().isEmpty()) {
2044 NSArray* children = [self renderWidgetChildren];
2045 if (children != nil)
2049 // The tree's (AXOutline) children are supposed to be its rows and columns.
2050 // The ARIA spec doesn't have columns, so we just need rows.
2051 if (m_object->isTree())
2052 return [self accessibilityAttributeValue:NSAccessibilityRowsAttribute];
2054 // A tree item should only expose its content as its children (not its rows)
2055 if (m_object->isTreeItem()) {
2056 AccessibilityObject::AccessibilityChildrenVector contentCopy;
2057 m_object->ariaTreeItemContent(contentCopy);
2058 return convertToNSArray(contentCopy);
2061 return convertToNSArray(m_object->children());
2064 if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {
2065 if (m_object->isListBox()) {
2066 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2067 m_object->selectedChildren(selectedChildrenCopy);
2068 return convertToNSArray(selectedChildrenCopy);
2073 if ([attributeName isEqualToString: NSAccessibilityVisibleChildrenAttribute]) {
2074 if (m_object->isListBox()) {
2075 AccessibilityObject::AccessibilityChildrenVector visibleChildrenCopy;
2076 m_object->visibleChildren(visibleChildrenCopy);
2077 return convertToNSArray(visibleChildrenCopy);
2079 else if (m_object->isList())
2080 return [self accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
2086 if (m_object->isWebArea()) {
2087 if ([attributeName isEqualToString:@"AXLinkUIElements"]) {
2088 AccessibilityObject::AccessibilityChildrenVector links;
2089 static_cast<AccessibilityRenderObject*>(m_object)->getDocumentLinks(links);
2090 return convertToNSArray(links);
2092 if ([attributeName isEqualToString:@"AXLoaded"])
2093 return [NSNumber numberWithBool:m_object->isLoaded()];
2094 if ([attributeName isEqualToString:@"AXLayoutCount"])
2095 return [NSNumber numberWithInt:m_object->layoutCount()];
2096 if ([attributeName isEqualToString:NSAccessibilityLoadingProgressAttribute])
2097 return [NSNumber numberWithDouble:m_object->estimatedLoadingProgress()];
2100 if (m_object->isTextControl()) {
2101 if ([attributeName isEqualToString: NSAccessibilityNumberOfCharactersAttribute]) {
2102 int length = m_object->textLength();
2105 return [NSNumber numberWithUnsignedInt:length];
2107 if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
2108 String selectedText = m_object->selectedText();
2109 if (selectedText.isNull())
2111 return (NSString*)selectedText;
2113 if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
2114 PlainTextRange textRange = m_object->selectedTextRange();
2115 if (textRange.isNull())
2116 return [NSValue valueWithRange:NSMakeRange(0, 0)];
2117 return [NSValue valueWithRange:NSMakeRange(textRange.start, textRange.length)];
2119 // TODO: Get actual visible range. <rdar://problem/4712101>
2120 if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
2121 return m_object->isPasswordField() ? nil : [NSValue valueWithRange: NSMakeRange(0, m_object->textLength())];
2122 if ([attributeName isEqualToString: NSAccessibilityInsertionPointLineNumberAttribute]) {
2123 // if selectionEnd > 0, then there is selected text and this question should not be answered
2124 if (m_object->isPasswordField() || m_object->selectionEnd() > 0)
2127 AccessibilityObject* focusedObject = m_object->focusedUIElement();
2128 if (focusedObject != m_object)
2131 VisiblePosition focusedPosition = focusedObject->visiblePositionForIndex(focusedObject->selectionStart(), true);
2132 int lineNumber = m_object->lineForPosition(focusedPosition);
2136 return [NSNumber numberWithInt:lineNumber];
2140 if ([attributeName isEqualToString: NSAccessibilityURLAttribute]) {
2141 KURL url = m_object->url();
2147 // Only native spin buttons have increment and decrement buttons.
2148 if (m_object->isNativeSpinButton()) {
2149 if ([attributeName isEqualToString:NSAccessibilityIncrementButtonAttribute])
2150 return toAccessibilitySpinButton(m_object)->incrementButton()->wrapper();
2151 if ([attributeName isEqualToString:NSAccessibilityDecrementButtonAttribute])
2152 return toAccessibilitySpinButton(m_object)->decrementButton()->wrapper();
2155 if ([attributeName isEqualToString: @"AXVisited"])
2156 return [NSNumber numberWithBool: m_object->isVisited()];
2158 if ([attributeName isEqualToString: NSAccessibilityTitleAttribute]) {
2159 if (m_object->isAttachment()) {
2160 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityTitleAttribute])
2161 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityTitleAttribute];
2164 // Meter elements should communicate their content via AXValueDescription.
2165 if (m_object->isMeter())
2166 return [NSString string];
2168 return [self accessibilityTitle];
2171 if ([attributeName isEqualToString: NSAccessibilityDescriptionAttribute]) {
2172 if (m_object->isAttachment()) {
2173 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityDescriptionAttribute])
2174 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityDescriptionAttribute];
2176 return [self accessibilityDescription];
2179 if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
2180 if (m_object->isAttachment()) {
2181 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityValueAttribute])
2182 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityValueAttribute];
2184 if (m_object->supportsRangeValue())
2185 return [NSNumber numberWithFloat:m_object->valueForRange()];
2186 if (m_object->roleValue() == SliderThumbRole)
2187 return [NSNumber numberWithFloat:m_object->parentObject()->valueForRange()];
2188 if (m_object->isHeading())
2189 return [NSNumber numberWithInt:m_object->headingLevel()];
2191 if (m_object->isCheckboxOrRadio() || m_object->isMenuItem()) {
2192 switch (m_object->checkboxOrRadioValue()) {
2193 case ButtonStateOff:
2194 return [NSNumber numberWithInt:0];
2196 return [NSNumber numberWithInt:1];
2197 case ButtonStateMixed:
2198 return [NSNumber numberWithInt:2];
2202 // radio groups return the selected radio button as the AXValue
2203 if (m_object->isRadioGroup()) {
2204 AccessibilityObject* radioButton = m_object->selectedRadioButton();
2207 return radioButton->wrapper();
2210 if (m_object->isTabList()) {
2211 AccessibilityObject* tabItem = m_object->selectedTabItem();
2214 return tabItem->wrapper();
2217 if (m_object->isTabItem())
2218 return [NSNumber numberWithInt:m_object->isSelected()];
2220 if (m_object->isColorWell()) {
2222 m_object->colorValue(r, g, b);
2223 return [NSString stringWithFormat:@"rgb %7.5f %7.5f %7.5f 1", r / 255., g / 255., b / 255.];
2226 return m_object->stringValue();
2229 if ([attributeName isEqualToString:(NSString *)kAXMenuItemMarkCharAttribute]) {
2230 const unichar ch = 0x2713; // ✓ used on Mac for selected menu items.
2231 return (m_object->isChecked()) ? [NSString stringWithCharacters:&ch length:1] : nil;
2234 if ([attributeName isEqualToString: NSAccessibilityMinValueAttribute])
2235 return [NSNumber numberWithFloat:m_object->minValueForRange()];
2237 if ([attributeName isEqualToString: NSAccessibilityMaxValueAttribute])
2238 return [NSNumber numberWithFloat:m_object->maxValueForRange()];
2240 if ([attributeName isEqualToString: NSAccessibilityHelpAttribute])
2241 return [self accessibilityHelpText];
2243 if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
2244 return [NSNumber numberWithBool: m_object->isFocused()];
2246 if ([attributeName isEqualToString: NSAccessibilityEnabledAttribute])
2247 return [NSNumber numberWithBool: m_object->isEnabled()];
2249 if ([attributeName isEqualToString: NSAccessibilitySizeAttribute]) {
2250 IntSize s = m_object->pixelSnappedSize();
2251 return [NSValue valueWithSize: NSMakeSize(s.width(), s.height())];
2254 if ([attributeName isEqualToString: NSAccessibilityPositionAttribute])
2255 return [self position];
2256 if ([attributeName isEqualToString:NSAccessibilityPathAttribute])
2259 if ([attributeName isEqualToString: NSAccessibilityWindowAttribute] ||
2260 [attributeName isEqualToString: NSAccessibilityTopLevelUIElementAttribute]) {
2262 id remoteParent = [self remoteAccessibilityParentObject];
2264 return [remoteParent accessibilityAttributeValue:attributeName];
2266 FrameView* fv = m_object->documentFrameView();
2268 return [fv->platformWidget() window];
2272 if ([attributeName isEqualToString:NSAccessibilityAccessKeyAttribute]) {
2273 AtomicString accessKey = m_object->accessKey();
2274 if (accessKey.isNull())
2279 if ([attributeName isEqualToString:NSAccessibilityTabsAttribute]) {
2280 if (m_object->isTabList()) {
2281 AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2282 m_object->tabChildren(tabsChildren);
2283 return convertToNSArray(tabsChildren);
2287 if ([attributeName isEqualToString:NSAccessibilityContentsAttribute]) {
2288 // The contents of a tab list are all the children except the tabs.
2289 if (m_object->isTabList()) {
2290 AccessibilityObject::AccessibilityChildrenVector children = m_object->children();
2291 AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2292 m_object->tabChildren(tabsChildren);
2294 AccessibilityObject::AccessibilityChildrenVector contents;
2295 unsigned childrenSize = children.size();
2296 for (unsigned k = 0; k < childrenSize; ++k) {
2297 if (tabsChildren.find(children[k]) == WTF::notFound)
2298 contents.append(children[k]);
2300 return convertToNSArray(contents);
2301 } else if (m_object->isScrollView()) {
2302 AccessibilityObject::AccessibilityChildrenVector children = m_object->children();
2304 // A scrollView's contents are everything except the scroll bars.
2305 AccessibilityObject::AccessibilityChildrenVector contents;
2306 unsigned childrenSize = children.size();
2307 for (unsigned k = 0; k < childrenSize; ++k) {
2308 if (!children[k]->isScrollbar())
2309 contents.append(children[k]);
2311 return convertToNSArray(contents);
2315 if (m_object->isAccessibilityTable()) {
2316 // TODO: distinguish between visible and non-visible rows
2317 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] ||
2318 [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
2319 return convertToNSArray(static_cast<AccessibilityTable*>(m_object)->rows());
2321 // TODO: distinguish between visible and non-visible columns
2322 if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute] ||
2323 [attributeName isEqualToString:NSAccessibilityVisibleColumnsAttribute]) {
2324 return convertToNSArray(static_cast<AccessibilityTable*>(m_object)->columns());
2327 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2328 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2329 m_object->selectedChildren(selectedChildrenCopy);
2330 return convertToNSArray(selectedChildrenCopy);
2333 // HTML tables don't support these
2334 if ([attributeName isEqualToString:NSAccessibilitySelectedColumnsAttribute] ||
2335 [attributeName isEqualToString:NSAccessibilitySelectedCellsAttribute])
2338 if ([attributeName isEqualToString:(NSString *)kAXColumnHeaderUIElementsAttribute]) {
2339 AccessibilityObject::AccessibilityChildrenVector columnHeaders;
2340 static_cast<AccessibilityTable*>(m_object)->columnHeaders(columnHeaders);
2341 return convertToNSArray(columnHeaders);
2344 if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2345 AccessibilityObject* headerContainer = static_cast<AccessibilityTable*>(m_object)->headerContainer();
2346 if (headerContainer)
2347 return headerContainer->wrapper();
2351 if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
2352 AccessibilityObject::AccessibilityChildrenVector rowHeaders;
2353 static_cast<AccessibilityTable*>(m_object)->rowHeaders(rowHeaders);
2354 return convertToNSArray(rowHeaders);
2357 if ([attributeName isEqualToString:NSAccessibilityVisibleCellsAttribute]) {
2358 AccessibilityObject::AccessibilityChildrenVector cells;
2359 static_cast<AccessibilityTable*>(m_object)->cells(cells);
2360 return convertToNSArray(cells);
2364 if (m_object->isTableColumn()) {
2365 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2366 return [NSNumber numberWithInt:static_cast<AccessibilityTableColumn*>(m_object)->columnIndex()];
2368 // rows attribute for a column is the list of all the elements in that column at each row
2369 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] ||
2370 [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
2371 return convertToNSArray(static_cast<AccessibilityTableColumn*>(m_object)->children());
2373 if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2374 AccessibilityObject* header = static_cast<AccessibilityTableColumn*>(m_object)->headerObject();
2377 return header->wrapper();
2381 if (m_object->isTableCell()) {
2382 if ([attributeName isEqualToString:NSAccessibilityRowIndexRangeAttribute]) {
2383 pair<unsigned, unsigned> rowRange;
2384 static_cast<AccessibilityTableCell*>(m_object)->rowIndexRange(rowRange);
2385 return [NSValue valueWithRange:NSMakeRange(rowRange.first, rowRange.second)];
2387 if ([attributeName isEqualToString:NSAccessibilityColumnIndexRangeAttribute]) {
2388 pair<unsigned, unsigned> columnRange;
2389 static_cast<AccessibilityTableCell*>(m_object)->columnIndexRange(columnRange);
2390 return [NSValue valueWithRange:NSMakeRange(columnRange.first, columnRange.second)];
2394 if (m_object->isTree()) {
2395 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2396 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2397 m_object->selectedChildren(selectedChildrenCopy);
2398 return convertToNSArray(selectedChildrenCopy);
2400 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute]) {
2401 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2402 m_object->ariaTreeRows(rowsCopy);
2403 return convertToNSArray(rowsCopy);
2406 // TreeRoles do not support columns, but Mac AX expects to be able to ask about columns at the least.
2407 if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute])
2408 return [NSArray array];
2411 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute]) {
2412 if (m_object->isTreeItem()) {
2413 AccessibilityObject* parent = m_object->parentObject();
2414 for (; parent && !parent->isTree(); parent = parent->parentObject())
2420 // Find the index of this item by iterating the parents.
2421 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2422 parent->ariaTreeRows(rowsCopy);
2423 size_t count = rowsCopy.size();
2424 for (size_t k = 0; k < count; ++k)
2425 if (rowsCopy[k]->wrapper() == self)
2426 return [NSNumber numberWithUnsignedInt:k];
2430 if (m_object->isTableRow()) {
2431 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2432 return [NSNumber numberWithInt:static_cast<AccessibilityTableRow*>(m_object)->rowIndex()];
2436 // The rows that are considered inside this row.
2437 if ([attributeName isEqualToString:NSAccessibilityDisclosedRowsAttribute]) {
2438 if (m_object->isTreeItem()) {
2439 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2440 m_object->ariaTreeItemDisclosedRows(rowsCopy);
2441 return convertToNSArray(rowsCopy);
2442 } else if (m_object->isARIATreeGridRow()) {
2443 AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2444 static_cast<AccessibilityARIAGridRow*>(m_object)->disclosedRows(rowsCopy);
2445 return convertToNSArray(rowsCopy);
2449 // The row that contains this row. It should be the same as the first parent that is a treeitem.
2450 if ([attributeName isEqualToString:NSAccessibilityDisclosedByRowAttribute]) {
2451 if (m_object->isTreeItem()) {
2452 AccessibilityObject* parent = m_object->parentObject();
2454 if (parent->isTreeItem())
2455 return parent->wrapper();
2456 // If the parent is the tree itself, then this value == nil.
2457 if (parent->isTree())
2459 parent = parent->parentObject();
2462 } else if (m_object->isARIATreeGridRow()) {
2463 AccessibilityObject* row = static_cast<AccessibilityARIAGridRow*>(m_object)->disclosedByRow();
2466 return row->wrapper();
2470 if ([attributeName isEqualToString:NSAccessibilityDisclosureLevelAttribute]) {
2471 // Convert from 1-based level (from aria-level spec) to 0-based level (Mac)
2472 int level = m_object->hierarchicalLevel();
2475 return [NSNumber numberWithInt:level];
2477 if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
2478 return [NSNumber numberWithBool:m_object->isExpanded()];
2480 if ((m_object->isListBox() || m_object->isList()) && [attributeName isEqualToString:NSAccessibilityOrientationAttribute])
2481 return NSAccessibilityVerticalOrientationValue;
2483 if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
2484 return [self textMarkerRangeForSelection];
2486 if (m_object->renderer()) {
2487 if ([attributeName isEqualToString: @"AXStartTextMarker"])
2488 return [self textMarkerForVisiblePosition:startOfDocument(&m_object->renderer()->document())];
2489 if ([attributeName isEqualToString: @"AXEndTextMarker"])
2490 return [self textMarkerForVisiblePosition:endOfDocument(&m_object->renderer()->document())];
2493 if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute])
2494 return [NSNumber numberWithInt:m_object->blockquoteLevel()];
2495 if ([attributeName isEqualToString:@"AXTableLevel"])
2496 return [NSNumber numberWithInt:m_object->tableLevel()];
2498 if ([attributeName isEqualToString: NSAccessibilityLinkedUIElementsAttribute]) {
2499 AccessibilityObject::AccessibilityChildrenVector linkedUIElements;
2500 m_object->linkedUIElements(linkedUIElements);
2501 if (linkedUIElements.size() == 0)
2503 return convertToNSArray(linkedUIElements);
2506 if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
2507 return [NSNumber numberWithBool:m_object->isSelected()];
2509 if ([attributeName isEqualToString: NSAccessibilityServesAsTitleForUIElementsAttribute] && m_object->isMenuButton()) {
2510 AccessibilityObject* uiElement = static_cast<AccessibilityRenderObject*>(m_object)->menuForMenuButton();
2512 return [NSArray arrayWithObject:uiElement->wrapper()];
2515 if ([attributeName isEqualToString:NSAccessibilityTitleUIElementAttribute]) {
2516 if (!m_object->exposesTitleUIElement())
2519 AccessibilityObject* obj = m_object->titleUIElement();
2521 return obj->wrapper();
2525 if ([attributeName isEqualToString:NSAccessibilityValueDescriptionAttribute]) {
2526 if (m_object->isMeter())
2527 return [self accessibilityTitle];
2529 return m_object->valueDescription();
2532 if ([attributeName isEqualToString:NSAccessibilityOrientationAttribute]) {
2533 AccessibilityOrientation elementOrientation = m_object->orientation();
2534 if (elementOrientation == AccessibilityOrientationVertical)
2535 return NSAccessibilityVerticalOrientationValue;
2536 if (elementOrientation == AccessibilityOrientationHorizontal)
2537 return NSAccessibilityHorizontalOrientationValue;
2541 if ([attributeName isEqualToString:NSAccessibilityHorizontalScrollBarAttribute]) {
2542 AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationHorizontal);
2544 return scrollBar->wrapper();
2547 if ([attributeName isEqualToString:NSAccessibilityVerticalScrollBarAttribute]) {
2548 AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationVertical);
2550 return scrollBar->wrapper();
2554 if ([attributeName isEqualToString:NSAccessibilitySortDirectionAttribute]) {
2555 switch (m_object->sortDirection()) {
2556 case SortDirectionAscending:
2557 return NSAccessibilityAscendingSortDirectionValue;
2558 case SortDirectionDescending:
2559 return NSAccessibilityDescendingSortDirectionValue;
2561 return NSAccessibilityUnknownSortDirectionValue;
2565 if ([attributeName isEqualToString:NSAccessibilityLanguageAttribute])
2566 return m_object->language();
2568 if ([attributeName isEqualToString:NSAccessibilityExpandedAttribute])
2569 return [NSNumber numberWithBool:m_object->isExpanded()];
2571 if ([attributeName isEqualToString:NSAccessibilityRequiredAttribute])
2572 return [NSNumber numberWithBool:m_object->isRequired()];
2574 if ([attributeName isEqualToString:NSAccessibilityInvalidAttribute])
2575 return m_object->invalidStatus();
2577 if ([attributeName isEqualToString:NSAccessibilityOwnsAttribute]) {
2578 AccessibilityObject::AccessibilityChildrenVector ariaOwns;
2579 m_object->ariaOwnsElements(ariaOwns);
2580 return convertToNSArray(ariaOwns);
2583 if ([attributeName isEqualToString:NSAccessibilityARIAPosInSetAttribute])
2584 return [NSNumber numberWithInt:m_object->ariaPosInSet()];
2585 if ([attributeName isEqualToString:NSAccessibilityARIASetSizeAttribute])
2586 return [NSNumber numberWithInt:m_object->ariaSetSize()];
2588 if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
2589 return [NSNumber numberWithBool:m_object->isARIAGrabbed()];
2591 if ([attributeName isEqualToString:NSAccessibilityDropEffectsAttribute]) {
2592 Vector<String> dropEffects;
2593 m_object->determineARIADropEffects(dropEffects);
2594 return convertStringsToNSArray(dropEffects);
2597 if ([attributeName isEqualToString:NSAccessibilityPlaceholderValueAttribute])
2598 return m_object->placeholderValue();
2600 if ([attributeName isEqualToString:NSAccessibilityHasPopupAttribute])
2601 return [NSNumber numberWithBool:m_object->ariaHasPopup()];
2603 // ARIA Live region attributes.
2604 if ([attributeName isEqualToString:NSAccessibilityARIALiveAttribute])
2605 return m_object->ariaLiveRegionStatus();
2606 if ([attributeName isEqualToString:NSAccessibilityARIARelevantAttribute])
2607 return m_object->ariaLiveRegionRelevant();
2608 if ([attributeName isEqualToString:NSAccessibilityARIAAtomicAttribute])
2609 return [NSNumber numberWithBool:m_object->ariaLiveRegionAtomic()];
2610 if ([attributeName isEqualToString:NSAccessibilityElementBusyAttribute])
2611 return [NSNumber numberWithBool:m_object->ariaLiveRegionBusy()];
2613 // MathML Attributes.
2614 if (m_object->isMathElement()) {
2615 if ([attributeName isEqualToString:NSAccessibilityMathRootIndexAttribute])
2616 return (m_object->mathRootIndexObject()) ? m_object->mathRootIndexObject()->wrapper() : 0;
2617 if ([attributeName isEqualToString:NSAccessibilityMathRootRadicandAttribute])
2618 return (m_object->mathRadicandObject()) ? m_object->mathRadicandObject()->wrapper() : 0;
2619 if ([attributeName isEqualToString:NSAccessibilityMathFractionNumeratorAttribute])
2620 return (m_object->mathNumeratorObject()) ? m_object->mathNumeratorObject()->wrapper() : 0;
2621 if ([attributeName isEqualToString:NSAccessibilityMathFractionDenominatorAttribute])
2622 return (m_object->mathDenominatorObject()) ? m_object->mathDenominatorObject()->wrapper() : 0;
2623 if ([attributeName isEqualToString:NSAccessibilityMathBaseAttribute])
2624 return (m_object->mathBaseObject()) ? m_object->mathBaseObject()->wrapper() : 0;
2625 if ([attributeName isEqualToString:NSAccessibilityMathSubscriptAttribute])
2626 return (m_object->mathSubscriptObject()) ? m_object->mathSubscriptObject()->wrapper() : 0;
2627 if ([attributeName isEqualToString:NSAccessibilityMathSuperscriptAttribute])
2628 return (m_object->mathSuperscriptObject()) ? m_object->mathSuperscriptObject()->wrapper() : 0;
2629 if ([attributeName isEqualToString:NSAccessibilityMathUnderAttribute])
2630 return (m_object->mathUnderObject()) ? m_object->mathUnderObject()->wrapper() : 0;
2631 if ([attributeName isEqualToString:NSAccessibilityMathOverAttribute])
2632 return (m_object->mathOverObject()) ? m_object->mathOverObject()->wrapper() : 0;
2633 if ([attributeName isEqualToString:NSAccessibilityMathFencedOpenAttribute])
2634 return m_object->mathFencedOpenString();
2635 if ([attributeName isEqualToString:NSAccessibilityMathFencedCloseAttribute])
2636 return m_object->mathFencedCloseString();
2637 if ([attributeName isEqualToString:NSAccessibilityMathLineThicknessAttribute])
2638 return [NSNumber numberWithInteger:m_object->mathLineThickness()];
2639 if ([attributeName isEqualToString:NSAccessibilityMathPostscriptsAttribute])
2640 return [self accessibilityMathPostscriptPairs];
2641 if ([attributeName isEqualToString:NSAccessibilityMathPrescriptsAttribute])
2642 return [self accessibilityMathPrescriptPairs];
2645 if ([attributeName isEqualToString:NSAccessibilityDOMIdentifierAttribute])
2646 return m_object->identifierAttribute();
2647 if ([attributeName isEqualToString:NSAccessibilityDOMClassListAttribute]) {
2648 Vector<String> classList;
2649 m_object->classList(classList);
2650 return convertStringsToNSArray(classList);
2653 // this is used only by DumpRenderTree for testing
2654 if ([attributeName isEqualToString:@"AXClickPoint"])
2655 return [NSValue valueWithPoint:m_object->clickPoint()];
2657 // This is used by DRT to verify CSS3 speech works.
2658 if ([attributeName isEqualToString:@"AXDRTSpeechAttribute"]) {
2659 ESpeak speakProperty = m_object->speakProperty();
2660 switch (speakProperty) {
2664 return @"spell-out";
2667 case SpeakLiteralPunctuation:
2668 return @"literal-punctuation";
2669 case SpeakNoPunctuation:
2670 return @"no-punctuation";
2677 // Used by DRT to find an accessible node by its element id.
2678 if ([attributeName isEqualToString:@"AXDRTElementIdAttribute"])
2679 return m_object->getAttribute(idAttr);
2684 - (NSString *)accessibilityPlatformMathSubscriptKey
2686 return NSAccessibilityMathSubscriptAttribute;
2689 - (NSString *)accessibilityPlatformMathSuperscriptKey
2691 return NSAccessibilityMathSuperscriptAttribute;
2694 - (id)accessibilityFocusedUIElement
2696 if (![self updateObjectBackingStore])
2699 RefPtr<AccessibilityObject> focusedObj = m_object->focusedUIElement();
2704 return focusedObj->wrapper();
2707 - (id)accessibilityHitTest:(NSPoint)point
2709 if (![self updateObjectBackingStore])
2712 m_object->updateChildrenIfNecessary();
2713 RefPtr<AccessibilityObject> axObject = m_object->accessibilityHitTest(IntPoint(point));
2715 return NSAccessibilityUnignoredAncestor(axObject->wrapper());
2716 return NSAccessibilityUnignoredAncestor(self);
2719 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName
2721 if (![self updateObjectBackingStore])
2724 if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
2727 if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
2728 return m_object->canSetFocusAttribute();
2730 if ([attributeName isEqualToString: NSAccessibilityValueAttribute])
2731 return m_object->canSetValueAttribute();
2733 if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
2734 return m_object->canSetSelectedAttribute();
2736 if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute])
2737 return m_object->canSetSelectedChildrenAttribute();
2739 if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
2740 return m_object->canSetExpandedAttribute();
2742 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute])
2745 if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute] ||
2746 [attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute] ||
2747 [attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
2748 return m_object->canSetTextRangeAttributes();
2750 if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
2756 // accessibilityShouldUseUniqueId is an AppKit method we override so that
2757 // objects will be given a unique ID, and therefore allow AppKit to know when they
2758 // become obsolete (e.g. when the user navigates to a new web page, making this one
2759 // unrendered but not deallocated because it is in the back/forward cache).
2760 // It is important to call NSAccessibilityUnregisterUniqueIdForUIElement in the
2761 // appropriate place (e.g. dealloc) to remove these non-retained references from
2762 // AppKit's id mapping tables. We do this in detach by calling unregisterUniqueIdForUIElement.
2764 // Registering an object is also required for observing notifications. Only registered objects can be observed.
2765 - (BOOL)accessibilityIsIgnored
2767 if (![self updateObjectBackingStore])
2770 if (m_object->isAttachment())
2771 return [[self attachmentView] accessibilityIsIgnored];
2772 return m_object->accessibilityIsIgnored();
2775 - (NSArray* )accessibilityParameterizedAttributeNames
2777 if (![self updateObjectBackingStore])
2780 if (m_object->isAttachment())
2783 static NSArray* paramAttrs = nil;
2784 static NSArray* textParamAttrs = nil;
2785 static NSArray* tableParamAttrs = nil;
2786 static NSArray* webAreaParamAttrs = nil;
2787 if (paramAttrs == nil) {
2788 paramAttrs = [[NSArray alloc] initWithObjects:
2789 @"AXUIElementForTextMarker",
2790 @"AXTextMarkerRangeForUIElement",
2791 @"AXLineForTextMarker",
2792 @"AXTextMarkerRangeForLine",
2793 @"AXStringForTextMarkerRange",
2794 @"AXTextMarkerForPosition",
2795 @"AXBoundsForTextMarkerRange",
2796 @"AXAttributedStringForTextMarkerRange",
2797 @"AXTextMarkerRangeForUnorderedTextMarkers",
2798 @"AXNextTextMarkerForTextMarker",
2799 @"AXPreviousTextMarkerForTextMarker",
2800 @"AXLeftWordTextMarkerRangeForTextMarker",
2801 @"AXRightWordTextMarkerRangeForTextMarker",
2802 @"AXLeftLineTextMarkerRangeForTextMarker",
2803 @"AXRightLineTextMarkerRangeForTextMarker",
2804 @"AXSentenceTextMarkerRangeForTextMarker",
2805 @"AXParagraphTextMarkerRangeForTextMarker",
2806 @"AXNextWordEndTextMarkerForTextMarker",
2807 @"AXPreviousWordStartTextMarkerForTextMarker",
2808 @"AXNextLineEndTextMarkerForTextMarker",
2809 @"AXPreviousLineStartTextMarkerForTextMarker",
2810 @"AXNextSentenceEndTextMarkerForTextMarker",
2811 @"AXPreviousSentenceStartTextMarkerForTextMarker",
2812 @"AXNextParagraphEndTextMarkerForTextMarker",
2813 @"AXPreviousParagraphStartTextMarkerForTextMarker",
2814 @"AXStyleTextMarkerRangeForTextMarker",
2815 @"AXLengthForTextMarkerRange",
2816 NSAccessibilityBoundsForRangeParameterizedAttribute,
2817 NSAccessibilityStringForRangeParameterizedAttribute,
2818 NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute,
2822 if (textParamAttrs == nil) {
2823 NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
2824 [tempArray addObject:(NSString*)kAXLineForIndexParameterizedAttribute];
2825 [tempArray addObject:(NSString*)kAXRangeForLineParameterizedAttribute];
2826 [tempArray addObject:(NSString*)kAXStringForRangeParameterizedAttribute];
2827 [tempArray addObject:(NSString*)kAXRangeForPositionParameterizedAttribute];
2828 [tempArray addObject:(NSString*)kAXRangeForIndexParameterizedAttribute];
2829 [tempArray addObject:(NSString*)kAXBoundsForRangeParameterizedAttribute];
2830 [tempArray addObject:(NSString*)kAXRTFForRangeParameterizedAttribute];
2831 [tempArray addObject:(NSString*)kAXAttributedStringForRangeParameterizedAttribute];
2832 [tempArray addObject:(NSString*)kAXStyleRangeForIndexParameterizedAttribute];
2833 textParamAttrs = [[NSArray alloc] initWithArray:tempArray];
2834 [tempArray release];
2836 if (tableParamAttrs == nil) {
2837 NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
2838 [tempArray addObject:NSAccessibilityCellForColumnAndRowParameterizedAttribute];
2839 tableParamAttrs = [[NSArray alloc] initWithArray:tempArray];
2840 [tempArray release];
2842 if (!webAreaParamAttrs) {
2843 NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
2844 [tempArray addObject:NSAccessibilityTextMarkerForIndexParameterizedAttribute];
2845 [tempArray addObject:NSAccessibilityTextMarkerIsValidParameterizedAttribute];
2846 [tempArray addObject:NSAccessibilityIndexForTextMarkerParameterizedAttribute];
2847 webAreaParamAttrs = [[NSArray alloc] initWithArray:tempArray];
2848 [tempArray release];
2851 if (m_object->isPasswordField())
2852 return [NSArray array];
2854 if (!m_object->isAccessibilityRenderObject())
2857 if (m_object->isTextControl())
2858 return textParamAttrs;
2860 if (m_object->isAccessibilityTable())
2861 return tableParamAttrs;
2863 if (m_object->isMenuRelated())
2866 if (m_object->isWebArea())
2867 return webAreaParamAttrs;
2872 - (void)accessibilityPerformPressAction
2874 if (![self updateObjectBackingStore])
2877 if (m_object->isAttachment())
2878 [[self attachmentView] accessibilityPerformAction:NSAccessibilityPressAction];
2883 - (void)accessibilityPerformIncrementAction
2885 if (![self updateObjectBackingStore])
2888 if (m_object->isAttachment())
2889 [[self attachmentView] accessibilityPerformAction:NSAccessibilityIncrementAction];
2891 m_object->increment();
2894 - (void)accessibilityPerformDecrementAction
2896 if (![self updateObjectBackingStore])
2899 if (m_object->isAttachment())
2900 [[self attachmentView] accessibilityPerformAction:NSAccessibilityDecrementAction];
2902 m_object->decrement();
2905 - (void)accessibilityPerformShowMenuAction
2907 if (m_object->roleValue() == ComboBoxRole)
2908 m_object->setIsExpanded(true);
2910 // This needs to be performed in an iteration of the run loop that did not start from an AX call.
2911 // If it's the same run loop iteration, the menu open notification won't be sent
2912 [self performSelector:@selector(accessibilityShowContextMenu) withObject:nil afterDelay:0.0];
2916 - (void)accessibilityShowContextMenu
2918 Page* page = m_object->page();
2922 IntRect rect = pixelSnappedIntRect(m_object->elementRect());
2923 FrameView* frameView = m_object->documentFrameView();
2925 // On WK2, we need to account for the scroll position.
2926 // On WK1, this isn't necessary, it's taken care of by the attachment views.
2927 if (frameView && !frameView->platformWidget()) {
2928 // Find the appropriate scroll view to use to convert the contents to the window.
2929 for (AccessibilityObject* parent = m_object->parentObject(); parent; parent = parent->parentObject()) {
2930 if (parent->isAccessibilityScrollView()) {
2931 ScrollView* scrollView = toAccessibilityScrollView(parent)->scrollView();
2932 rect = scrollView->contentsToRootView(rect);
2938 page->contextMenuController().showContextMenuAt(&page->mainFrame(), rect.center());
2941 - (void)accessibilityScrollToVisible
2943 m_object->scrollToMakeVisible();
2946 - (void)accessibilityPerformAction:(NSString*)action
2948 if (![self updateObjectBackingStore])
2951 if ([action isEqualToString:NSAccessibilityPressAction])
2952 [self accessibilityPerformPressAction];
2954 else if ([action isEqualToString:NSAccessibilityShowMenuAction])
2955 [self accessibilityPerformShowMenuAction];
2957 else if ([action isEqualToString:NSAccessibilityIncrementAction])
2958 [self accessibilityPerformIncrementAction];
2960 else if ([action isEqualToString:NSAccessibilityDecrementAction])
2961 [self accessibilityPerformDecrementAction];
2963 else if ([action isEqualToString:NSAccessibilityScrollToVisibleAction])
2964 [self accessibilityScrollToVisible];
2967 - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attributeName
2969 if (![self updateObjectBackingStore])
2972 id textMarkerRange = nil;
2973 NSNumber* number = nil;
2974 NSString* string = nil;
2975 NSRange range = {0, 0};
2976 NSArray* array = nil;
2978 // decode the parameter
2979 if (AXObjectIsTextMarkerRange(value))
2980 textMarkerRange = value;
2982 else if ([value isKindOfClass:[NSNumber self]])
2985 else if ([value isKindOfClass:[NSString self]])
2988 else if ([value isKindOfClass:[NSValue self]])
2989 range = [value rangeValue];
2991 else if ([value isKindOfClass:[NSArray self]])
2994 // handle the command
2995 if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"]) {
2996 ASSERT(textMarkerRange);
2997 m_object->setSelectedVisiblePositionRange([self visiblePositionRangeForTextMarkerRange:textMarkerRange]);
2998 } else if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute]) {
3001 bool focus = [number boolValue];
3003 // If focus is just set without making the view the first responder, then keyboard focus won't move to the right place.
3004 if (focus && m_object->isWebArea() && !m_object->document()->frame()->selection().isFocusedAndActive()) {
3005 FrameView* frameView = m_object->documentFrameView();
3006 Page* page = m_object->page();
3007 if (page && frameView) {
3008 ChromeClient& chromeClient = page->chrome().client();
3009 chromeClient.focus();
3010 if (frameView->platformWidget())
3011 chromeClient.makeFirstResponder(frameView->platformWidget());
3013 chromeClient.makeFirstResponder();
3017 m_object->setFocused(focus);
3018 } else if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
3019 if (number && m_object->canSetNumericValue())
3020 m_object->setValue([number floatValue]);
3022 m_object->setValue(string);
3023 } else if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute]) {
3026 m_object->setSelected([number boolValue]);
3027 } else if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {
3028 if (!array || m_object->roleValue() != ListBoxRole)
3030 AccessibilityObject::AccessibilityChildrenVector selectedChildren;
3031 convertToVector(array, selectedChildren);
3032 static_cast<AccessibilityListBox*>(m_object)->setSelectedChildren(selectedChildren);
3033 } else if (m_object->isTextControl()) {
3034 if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
3035 m_object->setSelectedText(string);
3036 } else if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
3037 m_object->setSelectedTextRange(PlainTextRange(range.location, range.length));
3038 } else if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute]) {
3039 m_object->makeRangeVisible(PlainTextRange(range.location, range.length));
3041 } else if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
3042 m_object->setIsExpanded([number boolValue]);
3043 else if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
3044 AccessibilityObject::AccessibilityChildrenVector selectedRows;
3045 convertToVector(array, selectedRows);