AX: Calls to AXObjectCache should prefer Node over Renderer
[WebKit-https.git] / Source / WebCore / accessibility / mac / WebAccessibilityObjectWrapper.mm
1 /*
2  * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
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.
16  *
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.
27  */
28
29 #import "config.h"
30 #import "WebAccessibilityObjectWrapper.h"
31
32 #if HAVE(ACCESSIBILITY)
33
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"
45 #import "Chrome.h"
46 #import "ColorMac.h"
47 #import "ContextMenuController.h"
48 #import "Frame.h"
49 #import "FrameLoaderClient.h"
50 #import "FrameSelection.h"
51 #import "HTMLAnchorElement.h"
52 #import "HTMLAreaElement.h"
53 #import "HTMLFrameOwnerElement.h"
54 #import "HTMLImageElement.h"
55 #import "HTMLInputElement.h"
56 #import "HTMLNames.h"
57 #import "HTMLTextAreaElement.h"
58 #import "LocalizedStrings.h"
59 #import "Page.h"
60 #import "RenderTextControl.h"
61 #import "RenderView.h"
62 #import "RenderWidget.h"
63 #import "ScrollView.h"
64 #import "SimpleFontData.h"
65 #import "TextCheckerClient.h"
66 #import "TextCheckingHelper.h"
67 #import "TextIterator.h"
68 #import "WebCoreFrameView.h"
69 #import "WebCoreObjCExtras.h"
70 #import "WebCoreSystemInterface.h"
71 #import "htmlediting.h"
72 #import "visible_units.h"
73
74 using namespace WebCore;
75 using namespace HTMLNames;
76 using namespace std;
77
78 // Cell Tables
79 #ifndef NSAccessibilitySelectedCellsAttribute
80 #define NSAccessibilitySelectedCellsAttribute @"AXSelectedCells"
81 #endif
82
83 #ifndef NSAccessibilityVisibleCellsAttribute
84 #define NSAccessibilityVisibleCellsAttribute @"AXVisibleCells"
85 #endif
86
87 #ifndef NSAccessibilityRowHeaderUIElementsAttribute
88 #define NSAccessibilityRowHeaderUIElementsAttribute @"AXRowHeaderUIElements"
89 #endif
90
91 #ifndef NSAccessibilityRowIndexRangeAttribute
92 #define NSAccessibilityRowIndexRangeAttribute @"AXRowIndexRange"
93 #endif
94
95 #ifndef NSAccessibilityColumnIndexRangeAttribute
96 #define NSAccessibilityColumnIndexRangeAttribute @"AXColumnIndexRange"
97 #endif
98
99 #ifndef NSAccessibilityCellForColumnAndRowParameterizedAttribute
100 #define NSAccessibilityCellForColumnAndRowParameterizedAttribute @"AXCellForColumnAndRow"
101 #endif
102
103 #ifndef NSAccessibilityCellRole
104 #define NSAccessibilityCellRole @"AXCell"
105 #endif
106
107 // Lists
108 #ifndef NSAccessibilityContentListSubrole
109 #define NSAccessibilityContentListSubrole @"AXContentList"
110 #endif
111
112 #ifndef NSAccessibilityDefinitionListSubrole
113 #define NSAccessibilityDefinitionListSubrole @"AXDefinitionList"
114 #endif
115
116 // Miscellaneous
117 #ifndef NSAccessibilityBlockQuoteLevelAttribute
118 #define NSAccessibilityBlockQuoteLevelAttribute @"AXBlockQuoteLevel"
119 #endif
120
121 #ifndef NSAccessibilityAccessKeyAttribute
122 #define NSAccessibilityAccessKeyAttribute @"AXAccessKey"
123 #endif
124
125 #ifndef NSAccessibilityLanguageAttribute
126 #define NSAccessibilityLanguageAttribute @"AXLanguage"
127 #endif
128
129 #ifndef NSAccessibilityRequiredAttribute
130 #define NSAccessibilityRequiredAttribute @"AXRequired"
131 #endif
132
133 #ifndef NSAccessibilityInvalidAttribute
134 #define NSAccessibilityInvalidAttribute @"AXInvalid"
135 #endif
136
137 #ifndef NSAccessibilityOwnsAttribute
138 #define NSAccessibilityOwnsAttribute @"AXOwns"
139 #endif
140
141 #ifndef NSAccessibilityGrabbedAttribute
142 #define NSAccessibilityGrabbedAttribute @"AXGrabbed"
143 #endif
144
145 #ifndef NSAccessibilityDropEffectsAttribute
146 #define NSAccessibilityDropEffectsAttribute @"AXDropEffects"
147 #endif
148
149 #ifndef NSAccessibilityARIALiveAttribute
150 #define NSAccessibilityARIALiveAttribute @"AXARIALive"
151 #endif
152
153 #ifndef NSAccessibilityARIAAtomicAttribute
154 #define NSAccessibilityARIAAtomicAttribute @"AXARIAAtomic"
155 #endif
156
157 #ifndef NSAccessibilityARIARelevantAttribute
158 #define NSAccessibilityARIARelevantAttribute @"AXARIARelevant"
159 #endif
160
161 #ifndef NSAccessibilityARIABusyAttribute
162 #define NSAccessibilityARIABusyAttribute @"AXARIABusy"
163 #endif
164
165 #ifndef NSAccessibilityLoadingProgressAttribute
166 #define NSAccessibilityLoadingProgressAttribute @"AXLoadingProgress"
167 #endif
168
169 #ifndef NSAccessibilityHasPopupAttribute
170 #define NSAccessibilityHasPopupAttribute @"AXHasPopup"
171 #endif
172
173 #ifndef NSAccessibilityPlaceholderValueAttribute
174 #define NSAccessibilityPlaceholderValueAttribute @"AXPlaceholderValue"
175 #endif
176
177 // Search
178 #ifndef NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute
179 #define NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute @"AXUIElementsForSearchPredicate"
180 #endif
181
182 // Search Keys
183 #ifndef NSAccessibilityAnyTypeSearchKey
184 #define NSAccessibilityAnyTypeSearchKey @"AXAnyTypeSearchKey"
185 #endif
186
187 #ifndef NSAccessibilityBlockquoteSameLevelSearchKey
188 #define NSAccessibilityBlockquoteSameLevelSearchKey @"AXBlockquoteSameLevelSearchKey"
189 #endif
190
191 #ifndef NSAccessibilityBlockquoteSearchKey
192 #define NSAccessibilityBlockquoteSearchKey @"AXBlockquoteSearchKey"
193 #endif
194
195 #ifndef NSAccessibilityBoldFontSearchKey
196 #define NSAccessibilityBoldFontSearchKey @"AXBoldFontSearchKey"
197 #endif
198
199 #ifndef NSAccessibilityButtonSearchKey
200 #define NSAccessibilityButtonSearchKey @"AXButtonSearchKey"
201 #endif
202
203 #ifndef NSAccessibilityCheckBoxSearchKey
204 #define NSAccessibilityCheckBoxSearchKey @"AXCheckBoxSearchKey"
205 #endif
206
207 #ifndef NSAccessibilityControlSearchKey
208 #define NSAccessibilityControlSearchKey @"AXControlSearchKey"
209 #endif
210
211 #ifndef NSAccessibilityDifferentTypeSearchKey
212 #define NSAccessibilityDifferentTypeSearchKey @"AXDifferentTypeSearchKey"
213 #endif
214
215 #ifndef NSAccessibilityFontChangeSearchKey
216 #define NSAccessibilityFontChangeSearchKey @"AXFontChangeSearchKey"
217 #endif
218
219 #ifndef NSAccessibilityFontColorChangeSearchKey
220 #define NSAccessibilityFontColorChangeSearchKey @"AXFontColorChangeSearchKey"
221 #endif
222
223 #ifndef NSAccessibilityFrameSearchKey
224 #define NSAccessibilityFrameSearchKey @"AXFrameSearchKey"
225 #endif
226
227 #ifndef NSAccessibilityGraphicSearchKey
228 #define NSAccessibilityGraphicSearchKey @"AXGraphicSearchKey"
229 #endif
230
231 #ifndef NSAccessibilityHeadingLevel1SearchKey
232 #define NSAccessibilityHeadingLevel1SearchKey @"AXHeadingLevel1SearchKey"
233 #endif
234
235 #ifndef NSAccessibilityHeadingLevel2SearchKey
236 #define NSAccessibilityHeadingLevel2SearchKey @"AXHeadingLevel2SearchKey"
237 #endif
238
239 #ifndef NSAccessibilityHeadingLevel3SearchKey
240 #define NSAccessibilityHeadingLevel3SearchKey @"AXHeadingLevel3SearchKey"
241 #endif
242
243 #ifndef NSAccessibilityHeadingLevel4SearchKey
244 #define NSAccessibilityHeadingLevel4SearchKey @"AXHeadingLevel4SearchKey"
245 #endif
246
247 #ifndef NSAccessibilityHeadingLevel5SearchKey
248 #define NSAccessibilityHeadingLevel5SearchKey @"AXHeadingLevel5SearchKey"
249 #endif
250
251 #ifndef NSAccessibilityHeadingLevel6SearchKey
252 #define NSAccessibilityHeadingLevel6SearchKey @"AXHeadingLevel6SearchKey"
253 #endif
254
255 #ifndef NSAccessibilityHeadingSameLevelSearchKey
256 #define NSAccessibilityHeadingSameLevelSearchKey @"AXHeadingSameLevelSearchKey"
257 #endif
258
259 #ifndef NSAccessibilityHeadingSearchKey
260 #define NSAccessibilityHeadingSearchKey @"AXHeadingSearchKey"
261 #endif
262
263 #ifndef NSAccessibilityHighlightedSearchKey
264 #define NSAccessibilityHighlightedSearchKey @"AXHighlightedSearchKey"
265 #endif
266
267 #ifndef NSAccessibilityItalicFontSearchKey
268 #define NSAccessibilityItalicFontSearchKey @"AXItalicFontSearchKey"
269 #endif
270
271 #ifndef NSAccessibilityLandmarkSearchKey
272 #define NSAccessibilityLandmarkSearchKey @"AXLandmarkSearchKey"
273 #endif
274
275 #ifndef NSAccessibilityLinkSearchKey
276 #define NSAccessibilityLinkSearchKey @"AXLinkSearchKey"
277 #endif
278
279 #ifndef NSAccessibilityListSearchKey
280 #define NSAccessibilityListSearchKey @"AXListSearchKey"
281 #endif
282
283 #ifndef NSAccessibilityLiveRegionSearchKey
284 #define NSAccessibilityLiveRegionSearchKey @"AXLiveRegionSearchKey"
285 #endif
286
287 #ifndef NSAccessibilityMisspelledWordSearchKey
288 #define NSAccessibilityMisspelledWordSearchKey @"AXMisspelledWordSearchKey"
289 #endif
290
291 #ifndef NSAccessibilityPlainTextSearchKey
292 #define NSAccessibilityPlainTextSearchKey @"AXPlainTextSearchKey"
293 #endif
294
295 #ifndef NSAccessibilityRadioGroupSearchKey
296 #define NSAccessibilityRadioGroupSearchKey @"AXRadioGroupSearchKey"
297 #endif
298
299 #ifndef NSAccessibilitySameTypeSearchKey
300 #define NSAccessibilitySameTypeSearchKey @"AXSameTypeSearchKey"
301 #endif
302
303 #ifndef NSAccessibilityStaticTextSearchKey
304 #define NSAccessibilityStaticTextSearchKey @"AXStaticTextSearchKey"
305 #endif
306
307 #ifndef NSAccessibilityStyleChangeSearchKey
308 #define NSAccessibilityStyleChangeSearchKey @"AXStyleChangeSearchKey"
309 #endif
310
311 #ifndef NSAccessibilityTableSameLevelSearchKey
312 #define NSAccessibilityTableSameLevelSearchKey @"AXTableSameLevelSearchKey"
313 #endif
314
315 #ifndef NSAccessibilityTableSearchKey
316 #define NSAccessibilityTableSearchKey @"AXTableSearchKey"
317 #endif
318
319 #ifndef NSAccessibilityTextFieldSearchKey
320 #define NSAccessibilityTextFieldSearchKey @"AXTextFieldSearchKey"
321 #endif
322
323 #ifndef NSAccessibilityUnderlineSearchKey
324 #define NSAccessibilityUnderlineSearchKey @"AXUnderlineSearchKey"
325 #endif
326
327 #ifndef NSAccessibilityUnvisitedLinkSearchKey
328 #define NSAccessibilityUnvisitedLinkSearchKey @"AXUnvisitedLinkSearchKey"
329 #endif
330
331 #ifndef NSAccessibilityVisitedLinkSearchKey
332 #define NSAccessibilityVisitedLinkSearchKey @"AXVisitedLinkSearchKey"
333 #endif
334
335 #define NSAccessibilityTextMarkerIsValidParameterizedAttribute @"AXTextMarkerIsValid"
336 #define NSAccessibilityIndexForTextMarkerParameterizedAttribute @"AXIndexForTextMarker"
337 #define NSAccessibilityTextMarkerForIndexParameterizedAttribute @"AXTextMarkerForIndex"
338
339 @interface NSObject (WebKitAccessibilityArrayCategory)
340
341 - (NSUInteger)accessibilityIndexOfChild:(id)child;
342 - (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute;
343 - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount;
344
345 @end
346
347 @implementation WebAccessibilityObjectWrapper
348
349 - (id)initWithAccessibilityObject:(AccessibilityObject*)axObject
350 {
351     if (!(self = [super init]))
352         return nil;
353
354     m_object = axObject;
355     return self;
356 }
357
358 - (void)unregisterUniqueIdForUIElement
359 {
360     wkUnregisterUniqueIdForElement(self);
361 }
362
363 - (void)detach
364 {
365     // Send unregisterUniqueIdForUIElement unconditionally because if it is
366     // ever accidentally not done (via other bugs in our AX implementation) you
367     // end up with a crash like <rdar://problem/4273149>.  It is safe and not
368     // expensive to send even if the object is not registered.
369     [self unregisterUniqueIdForUIElement];
370     m_object = 0;
371 }
372
373 - (BOOL)updateObjectBackingStore
374 {
375     // Calling updateBackingStore() can invalidate this element so self must be retained.
376     // If it does become invalidated, m_object will be nil.
377     [[self retain] autorelease];
378     
379     if (!m_object)
380         return NO;
381     
382     m_object->updateBackingStore();
383     if (!m_object)
384         return NO;
385     
386     return YES;
387 }
388
389 - (AccessibilityObject*)accessibilityObject
390 {
391     return m_object;
392 }
393
394 - (NSView*)attachmentView
395 {
396     ASSERT(m_object->isAttachment());
397     Widget* widget = m_object->widgetForAttachmentView();
398     if (!widget)
399         return nil;
400     return NSAccessibilityUnignoredDescendant(widget->platformWidget());
401 }
402
403 #pragma mark SystemInterface wrappers
404
405 static inline id CFAutoreleaseHelper(CFTypeRef obj)
406 {
407     if (obj)
408         CFMakeCollectable(obj);
409     [(id)obj autorelease];
410     return (id)obj;
411 }
412
413 static inline BOOL AXObjectIsTextMarker(id obj)
414 {
415     return obj != nil && CFGetTypeID(obj) == wkGetAXTextMarkerTypeID();    
416 }
417
418 static inline BOOL AXObjectIsTextMarkerRange(id obj)
419 {
420     return obj != nil && CFGetTypeID(obj) == wkGetAXTextMarkerRangeTypeID();    
421 }
422
423 static id AXTextMarkerRange(id startMarker, id endMarker)
424 {
425     ASSERT(startMarker != nil);
426     ASSERT(endMarker != nil);
427     ASSERT(CFGetTypeID(startMarker) == wkGetAXTextMarkerTypeID());
428     ASSERT(CFGetTypeID(endMarker) == wkGetAXTextMarkerTypeID());
429     return CFAutoreleaseHelper(wkCreateAXTextMarkerRange((CFTypeRef)startMarker, (CFTypeRef)endMarker));
430 }
431
432 static id AXTextMarkerRangeStart(id range)
433 {
434     ASSERT(range != nil);
435     ASSERT(CFGetTypeID(range) == wkGetAXTextMarkerRangeTypeID());
436     return CFAutoreleaseHelper(wkCopyAXTextMarkerRangeStart(range));    
437 }
438
439 static id AXTextMarkerRangeEnd(id range)
440 {
441     ASSERT(range != nil);
442     ASSERT(CFGetTypeID(range) == wkGetAXTextMarkerRangeTypeID());
443     return CFAutoreleaseHelper(wkCopyAXTextMarkerRangeEnd(range));    
444 }
445
446 #pragma mark Search helpers
447
448 typedef HashMap<String, AccessibilitySearchKey> AccessibilitySearchKeyMap;
449
450 struct SearchKeyEntry {
451     String key;
452     AccessibilitySearchKey value;
453 };
454
455 static AccessibilitySearchKeyMap* createAccessibilitySearchKeyMap()
456 {
457     const SearchKeyEntry searchKeys[] = {
458         { NSAccessibilityAnyTypeSearchKey, AnyTypeSearchKey },
459         { NSAccessibilityBlockquoteSameLevelSearchKey, BlockquoteSameLevelSearchKey },
460         { NSAccessibilityBlockquoteSearchKey, BlockquoteSearchKey },
461         { NSAccessibilityBoldFontSearchKey, BoldFontSearchKey },
462         { NSAccessibilityButtonSearchKey, ButtonSearchKey },
463         { NSAccessibilityCheckBoxSearchKey, CheckBoxSearchKey },
464         { NSAccessibilityControlSearchKey, ControlSearchKey },
465         { NSAccessibilityDifferentTypeSearchKey, DifferentTypeSearchKey },
466         { NSAccessibilityFontChangeSearchKey, FontChangeSearchKey },
467         { NSAccessibilityFontColorChangeSearchKey, FontColorChangeSearchKey },
468         { NSAccessibilityFrameSearchKey, FrameSearchKey },
469         { NSAccessibilityGraphicSearchKey, GraphicSearchKey },
470         { NSAccessibilityHeadingLevel1SearchKey, HeadingLevel1SearchKey },
471         { NSAccessibilityHeadingLevel2SearchKey, HeadingLevel2SearchKey },
472         { NSAccessibilityHeadingLevel3SearchKey, HeadingLevel3SearchKey },
473         { NSAccessibilityHeadingLevel4SearchKey, HeadingLevel4SearchKey },
474         { NSAccessibilityHeadingLevel5SearchKey, HeadingLevel5SearchKey },
475         { NSAccessibilityHeadingLevel6SearchKey, HeadingLevel6SearchKey },
476         { NSAccessibilityHeadingSameLevelSearchKey, HeadingSameLevelSearchKey },
477         { NSAccessibilityHeadingSearchKey, HeadingSearchKey },
478         { NSAccessibilityHighlightedSearchKey, HighlightedSearchKey },
479         { NSAccessibilityItalicFontSearchKey, ItalicFontSearchKey },
480         { NSAccessibilityLandmarkSearchKey, LandmarkSearchKey },
481         { NSAccessibilityLinkSearchKey, LinkSearchKey },
482         { NSAccessibilityListSearchKey, ListSearchKey },
483         { NSAccessibilityLiveRegionSearchKey, LiveRegionSearchKey },
484         { NSAccessibilityMisspelledWordSearchKey, MisspelledWordSearchKey },
485         { NSAccessibilityPlainTextSearchKey, PlainTextSearchKey },
486         { NSAccessibilityRadioGroupSearchKey, RadioGroupSearchKey },
487         { NSAccessibilitySameTypeSearchKey, SameTypeSearchKey },
488         { NSAccessibilityStaticTextSearchKey, StaticTextSearchKey },
489         { NSAccessibilityStyleChangeSearchKey, StyleChangeSearchKey },
490         { NSAccessibilityTableSameLevelSearchKey, TableSameLevelSearchKey },
491         { NSAccessibilityTableSearchKey, TableSearchKey },
492         { NSAccessibilityTextFieldSearchKey, TextFieldSearchKey },
493         { NSAccessibilityUnderlineSearchKey, UnderlineSearchKey },
494         { NSAccessibilityUnvisitedLinkSearchKey, UnvisitedLinkSearchKey },
495         { NSAccessibilityVisitedLinkSearchKey, VisitedLinkSearchKey }
496     };
497     
498     AccessibilitySearchKeyMap* searchKeyMap = new AccessibilitySearchKeyMap;
499     for (size_t i = 0; i < WTF_ARRAY_LENGTH(searchKeys); i++)
500         searchKeyMap->set(searchKeys[i].key, searchKeys[i].value);
501     
502     return searchKeyMap;
503 }
504
505 static AccessibilitySearchKey accessibilitySearchKeyForString(const String& value)
506 {
507     if (value.isEmpty())
508         return AnyTypeSearchKey;
509     
510     static const AccessibilitySearchKeyMap* searchKeyMap = createAccessibilitySearchKeyMap();
511     
512     AccessibilitySearchKey searchKey = searchKeyMap->get(value);
513     
514     return searchKey ? searchKey : AnyTypeSearchKey;
515 }
516
517 #pragma mark Text Marker helpers
518
519 static id textMarkerForVisiblePosition(AXObjectCache* cache, const VisiblePosition& visiblePos)
520 {
521     ASSERT(cache);
522     
523     TextMarkerData textMarkerData;
524     cache->textMarkerDataForVisiblePosition(textMarkerData, visiblePos);
525     if (!textMarkerData.axID)
526         return nil;
527     
528     return CFAutoreleaseHelper(wkCreateAXTextMarker(&textMarkerData, sizeof(textMarkerData)));
529 }
530
531 - (id)textMarkerForVisiblePosition:(const VisiblePosition &)visiblePos
532 {
533     return textMarkerForVisiblePosition(m_object->axObjectCache(), visiblePos);
534 }
535
536 static VisiblePosition visiblePositionForTextMarker(AXObjectCache* cache, CFTypeRef textMarker)
537 {
538     ASSERT(cache);
539
540     if (!textMarker)
541         return VisiblePosition();
542     TextMarkerData textMarkerData;
543     if (!wkGetBytesFromAXTextMarker(textMarker, &textMarkerData, sizeof(textMarkerData)))
544         return VisiblePosition();
545     
546     return cache->visiblePositionForTextMarkerData(textMarkerData);
547 }
548
549 - (VisiblePosition)visiblePositionForTextMarker:(id)textMarker
550 {
551     return visiblePositionForTextMarker(m_object->axObjectCache(), textMarker);
552 }
553
554 static VisiblePosition visiblePositionForStartOfTextMarkerRange(AXObjectCache *cache, id textMarkerRange)
555 {
556     return visiblePositionForTextMarker(cache, AXTextMarkerRangeStart(textMarkerRange));
557 }
558
559 static VisiblePosition visiblePositionForEndOfTextMarkerRange(AXObjectCache *cache, id textMarkerRange)
560 {
561     return visiblePositionForTextMarker(cache, AXTextMarkerRangeEnd(textMarkerRange));
562 }
563
564 static id textMarkerRangeFromMarkers(id textMarker1, id textMarker2)
565 {
566     if (!textMarker1 || !textMarker2)
567         return nil;
568         
569     return AXTextMarkerRange(textMarker1, textMarker2);
570 }
571
572 // When modifying attributed strings, the range can come from a source which may provide faulty information (e.g. the spell checker).
573 // To protect against such cases the range should be validated before adding or removing attributes.
574 static BOOL AXAttributedStringRangeIsValid(NSAttributedString* attrString, NSRange range)
575 {
576     return (range.location < [attrString length] && NSMaxRange(range) <= [attrString length]);
577 }
578
579 static void AXAttributeStringSetFont(NSMutableAttributedString* attrString, NSString* attribute, NSFont* font, NSRange range)
580 {
581     if (!AXAttributedStringRangeIsValid(attrString, range))
582         return;
583     
584     if (font) {
585         NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
586             [font fontName]                             , NSAccessibilityFontNameKey,
587             [font familyName]                           , NSAccessibilityFontFamilyKey,
588             [font displayName]                          , NSAccessibilityVisibleNameKey,
589             [NSNumber numberWithFloat:[font pointSize]] , NSAccessibilityFontSizeKey,
590         nil];
591
592         [attrString addAttribute:attribute value:dict range:range];
593     } else
594         [attrString removeAttribute:attribute range:range];
595     
596 }
597
598 static CGColorRef CreateCGColorIfDifferent(NSColor* nsColor, CGColorRef existingColor)
599 {
600     // get color information assuming NSDeviceRGBColorSpace 
601     NSColor* rgbColor = [nsColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
602     if (rgbColor == nil)
603         rgbColor = [NSColor blackColor];
604     CGFloat components[4];
605     [rgbColor getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]];
606     
607     // create a new CGColorRef to return
608     CGColorSpaceRef cgColorSpace = CGColorSpaceCreateDeviceRGB();
609     CGColorRef cgColor = CGColorCreate(cgColorSpace, components);
610     CGColorSpaceRelease(cgColorSpace);
611     
612     // check for match with existing color
613     if (existingColor && CGColorEqualToColor(cgColor, existingColor)) {
614         CGColorRelease(cgColor);
615         cgColor = 0;
616     }
617     
618     return cgColor;
619 }
620
621 static void AXAttributeStringSetColor(NSMutableAttributedString* attrString, NSString* attribute, NSColor* color, NSRange range)
622 {
623     if (!AXAttributedStringRangeIsValid(attrString, range))
624         return;
625
626     if (color) {
627         CGColorRef existingColor = (CGColorRef) [attrString attribute:attribute atIndex:range.location effectiveRange:nil];
628         CGColorRef cgColor = CreateCGColorIfDifferent(color, existingColor);
629         if (cgColor) {
630             [attrString addAttribute:attribute value:(id)cgColor range:range];
631             CGColorRelease(cgColor);
632         }
633     } else
634         [attrString removeAttribute:attribute range:range];
635 }
636
637 static void AXAttributeStringSetNumber(NSMutableAttributedString* attrString, NSString* attribute, NSNumber* number, NSRange range)
638 {
639     if (!AXAttributedStringRangeIsValid(attrString, range))
640         return;
641
642     if (number)
643         [attrString addAttribute:attribute value:number range:range];
644     else
645         [attrString removeAttribute:attribute range:range];
646 }
647
648 static void AXAttributeStringSetStyle(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
649 {
650     RenderStyle* style = renderer->style();
651
652     // set basic font info
653     AXAttributeStringSetFont(attrString, NSAccessibilityFontTextAttribute, style->font().primaryFont()->getNSFont(), range);
654
655     // set basic colors
656     AXAttributeStringSetColor(attrString, NSAccessibilityForegroundColorTextAttribute, nsColor(style->visitedDependentColor(CSSPropertyColor)), range);
657     AXAttributeStringSetColor(attrString, NSAccessibilityBackgroundColorTextAttribute, nsColor(style->visitedDependentColor(CSSPropertyBackgroundColor)), range);
658
659     // set super/sub scripting
660     EVerticalAlign alignment = style->verticalAlign();
661     if (alignment == SUB)
662         AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:(-1)], range);
663     else if (alignment == SUPER)
664         AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:1], range);
665     else
666         [attrString removeAttribute:NSAccessibilitySuperscriptTextAttribute range:range];
667     
668     // set shadow
669     if (style->textShadow())
670         AXAttributeStringSetNumber(attrString, NSAccessibilityShadowTextAttribute, [NSNumber numberWithBool:YES], range);
671     else
672         [attrString removeAttribute:NSAccessibilityShadowTextAttribute range:range];
673     
674     // set underline and strikethrough
675     int decor = style->textDecorationsInEffect();
676     if ((decor & UNDERLINE) == 0) {
677         [attrString removeAttribute:NSAccessibilityUnderlineTextAttribute range:range];
678         [attrString removeAttribute:NSAccessibilityUnderlineColorTextAttribute range:range];
679     }
680     
681     if ((decor & LINE_THROUGH) == 0) {
682         [attrString removeAttribute:NSAccessibilityStrikethroughTextAttribute range:range];
683         [attrString removeAttribute:NSAccessibilityStrikethroughColorTextAttribute range:range];
684     }
685
686     if ((decor & (UNDERLINE | LINE_THROUGH)) != 0) {
687         // find colors using quirk mode approach (strict mode would use current
688         // color for all but the root line box, which would use getTextDecorationColors)
689         Color underline, overline, linethrough;
690         renderer->getTextDecorationColors(decor, underline, overline, linethrough);
691         
692         if ((decor & UNDERLINE) != 0) {
693             AXAttributeStringSetNumber(attrString, NSAccessibilityUnderlineTextAttribute, [NSNumber numberWithBool:YES], range);
694             AXAttributeStringSetColor(attrString, NSAccessibilityUnderlineColorTextAttribute, nsColor(underline), range);
695         }
696
697         if ((decor & LINE_THROUGH) != 0) {
698             AXAttributeStringSetNumber(attrString, NSAccessibilityStrikethroughTextAttribute, [NSNumber numberWithBool:YES], range);
699             AXAttributeStringSetColor(attrString, NSAccessibilityStrikethroughColorTextAttribute, nsColor(linethrough), range);
700         }
701     }
702     
703     // Indicate background highlighting.
704     for (Node* node = renderer->node(); node; node = node->parentNode()) {
705         if (node->hasTagName(markTag))
706             AXAttributeStringSetNumber(attrString, @"AXHighlight", [NSNumber numberWithBool:YES], range);
707     }
708 }
709
710 static void AXAttributeStringSetBlockquoteLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
711 {
712     if (!AXAttributedStringRangeIsValid(attrString, range))
713         return;
714
715     AccessibilityObject* obj = renderer->document()->axObjectCache()->getOrCreate(renderer);
716     int quoteLevel = obj->blockquoteLevel();
717     
718     if (quoteLevel)
719         [attrString addAttribute:NSAccessibilityBlockQuoteLevelAttribute value:[NSNumber numberWithInt:quoteLevel] range:range];
720     else
721         [attrString removeAttribute:NSAccessibilityBlockQuoteLevelAttribute range:range];
722 }
723
724 static void AXAttributeStringSetSpelling(NSMutableAttributedString* attrString, Node* node, const UChar* chars, int charLength, NSRange range)
725 {
726     if (unifiedTextCheckerEnabled(node->document()->frame())) {
727         // Check the spelling directly since document->markersForNode() does not store the misspelled marking when the cursor is in a word.
728         TextCheckerClient* checker = node->document()->frame()->editor()->textChecker();
729
730         // checkTextOfParagraph is the only spelling/grammar checker implemented in WK1 and WK2
731         Vector<TextCheckingResult> results;
732         checkTextOfParagraph(checker, chars, charLength, TextCheckingTypeSpelling, results);
733
734         size_t size = results.size();
735         NSNumber* trueValue = [NSNumber numberWithBool:YES];
736         for (unsigned i = 0; i < size; i++) {
737             const TextCheckingResult& result = results[i];
738             AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, trueValue, NSMakeRange(result.location + range.location, result.length));
739         }
740         return;
741     }
742
743     int currentPosition = 0;
744     while (charLength > 0) {
745         const UChar* charData = chars + currentPosition;
746         TextCheckerClient* checker = node->document()->frame()->editor()->textChecker();
747         
748         int misspellingLocation = -1;
749         int misspellingLength = 0;
750         checker->checkSpellingOfString(charData, charLength, &misspellingLocation, &misspellingLength);
751         if (misspellingLocation == -1 || !misspellingLength)
752             break;
753         
754         NSRange spellRange = NSMakeRange(range.location + currentPosition + misspellingLocation, misspellingLength);
755         AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, [NSNumber numberWithBool:YES], spellRange);
756         charLength -= (misspellingLocation + misspellingLength);
757         currentPosition += (misspellingLocation + misspellingLength);
758     }
759 }
760
761 static void AXAttributeStringSetHeadingLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
762 {
763     if (!renderer)
764         return;
765     
766     if (!AXAttributedStringRangeIsValid(attrString, range))
767         return;
768     
769     // Sometimes there are objects between the text and the heading. 
770     // In those cases the parent hierarchy should be queried to see if there is a heading level.
771     int parentHeadingLevel = 0;
772     AccessibilityObject* parentObject = renderer->document()->axObjectCache()->getOrCreate(renderer->parent());
773     for (; parentObject; parentObject = parentObject->parentObject()) {
774         parentHeadingLevel = parentObject->headingLevel();
775         if (parentHeadingLevel)
776             break;
777     }
778     
779     if (parentHeadingLevel)
780         [attrString addAttribute:@"AXHeadingLevel" value:[NSNumber numberWithInt:parentHeadingLevel] range:range];
781     else
782         [attrString removeAttribute:@"AXHeadingLevel" range:range];
783 }
784
785 static void AXAttributeStringSetElement(NSMutableAttributedString* attrString, NSString* attribute, AccessibilityObject* object, NSRange range)
786 {
787     if (!AXAttributedStringRangeIsValid(attrString, range))
788         return;
789
790     if (object && object->isAccessibilityRenderObject()) {
791         // make a serializable AX object
792         
793         RenderObject* renderer = static_cast<AccessibilityRenderObject*>(object)->renderer();
794         if (!renderer)
795             return;
796         
797         Document* doc = renderer->document();
798         if (!doc)
799             return;
800         
801         AXObjectCache* cache = doc->axObjectCache();
802         if (!cache)
803             return;
804
805         AXUIElementRef axElement = wkCreateAXUIElementRef(object->wrapper());
806         if (axElement) {
807             [attrString addAttribute:attribute value:(id)axElement range:range];
808             CFRelease(axElement);
809         }
810     } else
811         [attrString removeAttribute:attribute range:range];
812 }
813
814 static void AXAttributedStringAppendText(NSMutableAttributedString* attrString, Node* node, const UChar* chars, int length)
815 {
816     // skip invisible text
817     if (!node->renderer())
818         return;
819
820     // easier to calculate the range before appending the string
821     NSRange attrStringRange = NSMakeRange([attrString length], length);
822     
823     // append the string from this node
824     [[attrString mutableString] appendString:[NSString stringWithCharacters:chars length:length]];
825
826     // add new attributes and remove irrelevant inherited ones
827     // NOTE: color attributes are handled specially because -[NSMutableAttributedString addAttribute: value: range:] does not merge
828     // identical colors.  Workaround is to not replace an existing color attribute if it matches what we are adding.  This also means
829     // we cannot just pre-remove all inherited attributes on the appended string, so we have to remove the irrelevant ones individually.
830
831     // remove inherited attachment from prior AXAttributedStringAppendReplaced
832     [attrString removeAttribute:NSAccessibilityAttachmentTextAttribute range:attrStringRange];
833     [attrString removeAttribute:NSAccessibilityMisspelledTextAttribute range:attrStringRange];
834     
835     // set new attributes
836     AXAttributeStringSetStyle(attrString, node->renderer(), attrStringRange);
837     AXAttributeStringSetHeadingLevel(attrString, node->renderer(), attrStringRange);
838     AXAttributeStringSetBlockquoteLevel(attrString, node->renderer(), attrStringRange);
839     AXAttributeStringSetElement(attrString, NSAccessibilityLinkTextAttribute, AccessibilityObject::anchorElementForNode(node), attrStringRange);
840     
841     // do spelling last because it tends to break up the range
842     AXAttributeStringSetSpelling(attrString, node, chars, length, attrStringRange);
843 }
844
845 static NSString* nsStringForReplacedNode(Node* replacedNode)
846 {
847     // we should always be given a rendered node and a replaced node, but be safe
848     // replaced nodes are either attachments (widgets) or images
849     if (!replacedNode || !replacedNode->renderer() || !replacedNode->renderer()->isReplaced() || replacedNode->isTextNode()) {
850         ASSERT_NOT_REACHED();
851         return nil;
852     }
853
854     // create an AX object, but skip it if it is not supposed to be seen
855     RefPtr<AccessibilityObject> obj = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer());
856     if (obj->accessibilityIsIgnored())
857         return nil;
858     
859     // use the attachmentCharacter to represent the replaced node
860     const UniChar attachmentChar = NSAttachmentCharacter;
861     return [NSString stringWithCharacters:&attachmentChar length:1];
862 }
863
864 - (NSAttributedString*)doAXAttributedStringForTextMarkerRange:(id)textMarkerRange
865 {
866     if (!m_object)
867         return nil;
868     
869     // extract the start and end VisiblePosition
870     VisiblePosition startVisiblePosition = visiblePositionForStartOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);
871     if (startVisiblePosition.isNull())
872         return nil;
873
874     VisiblePosition endVisiblePosition = visiblePositionForEndOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);
875     if (endVisiblePosition.isNull())
876         return nil;
877
878     VisiblePositionRange visiblePositionRange(startVisiblePosition, endVisiblePosition);
879     // iterate over the range to build the AX attributed string
880     NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] init];
881     TextIterator it(makeRange(startVisiblePosition, endVisiblePosition).get());
882     while (!it.atEnd()) {
883         // locate the node and starting offset for this range
884         int exception = 0;
885         Node* node = it.range()->startContainer(exception);
886         ASSERT(node == it.range()->endContainer(exception));
887         int offset = it.range()->startOffset(exception);
888
889         // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX)
890         if (it.length() != 0) {
891             // Add the text of the list marker item if necessary.
892             String listMarkerText = m_object->listMarkerTextForNodeAndPosition(node, VisiblePosition(it.range()->startPosition()));
893             if (!listMarkerText.isEmpty())
894                 AXAttributedStringAppendText(attrString, node, listMarkerText.characters(), listMarkerText.length());
895             
896             AXAttributedStringAppendText(attrString, node, it.characters(), it.length());
897         } else {
898             Node* replacedNode = node->childNode(offset);
899             NSString *attachmentString = nsStringForReplacedNode(replacedNode);
900             if (attachmentString) {
901                 NSRange attrStringRange = NSMakeRange([attrString length], [attachmentString length]);
902
903                 // append the placeholder string
904                 [[attrString mutableString] appendString:attachmentString];
905
906                 // remove all inherited attributes
907                 [attrString setAttributes:nil range:attrStringRange];
908
909                 // add the attachment attribute
910                 AccessibilityObject* obj = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer());
911                 AXAttributeStringSetElement(attrString, NSAccessibilityAttachmentTextAttribute, obj, attrStringRange);
912             }
913         }
914         it.advance();
915     }
916
917     return [attrString autorelease];
918 }
919
920 static id textMarkerRangeFromVisiblePositions(AXObjectCache *cache, VisiblePosition startPosition, VisiblePosition endPosition)
921 {
922     id startTextMarker = textMarkerForVisiblePosition(cache, startPosition);
923     id endTextMarker = textMarkerForVisiblePosition(cache, endPosition);
924     return textMarkerRangeFromMarkers(startTextMarker, endTextMarker);
925 }
926
927 - (id)textMarkerRangeFromVisiblePositions:(VisiblePosition)startPosition endPosition:(VisiblePosition)endPosition
928 {
929     return textMarkerRangeFromVisiblePositions(m_object->axObjectCache(), startPosition, endPosition);
930 }
931
932 - (NSArray*)accessibilityActionNames
933 {
934     if (![self updateObjectBackingStore])
935         return nil;
936
937     static NSArray* actionElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityPressAction, NSAccessibilityShowMenuAction, nil];
938     static NSArray* defaultElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityShowMenuAction, nil];
939     static NSArray* menuElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityCancelAction, NSAccessibilityPressAction, nil];
940     static NSArray* sliderActions = [[NSArray alloc] initWithObjects: NSAccessibilityIncrementAction, NSAccessibilityDecrementAction, nil];
941
942     NSArray *actions;
943     if (m_object->actionElement() || m_object->isButton()) 
944         actions = actionElementActions;
945     else if (m_object->isMenuRelated())
946         actions = menuElementActions;
947     else if (m_object->isSlider())
948         actions = sliderActions;
949     else if (m_object->isAttachment())
950         actions = [[self attachmentView] accessibilityActionNames];
951     else
952         actions = defaultElementActions;
953
954     return actions;
955 }
956
957 - (NSArray*)additionalAccessibilityAttributeNames
958 {
959     if (!m_object)
960         return nil;
961
962     NSMutableArray *additional = [NSMutableArray array];
963     if (m_object->supportsARIAOwns())
964         [additional addObject:NSAccessibilityOwnsAttribute];
965
966     if (m_object->supportsARIAExpanded())
967         [additional addObject:NSAccessibilityExpandedAttribute];
968     
969     if (m_object->isScrollbar())
970         [additional addObject:NSAccessibilityOrientationAttribute];
971     
972     if (m_object->supportsARIADragging())
973         [additional addObject:NSAccessibilityGrabbedAttribute];
974
975     if (m_object->supportsARIADropping())
976         [additional addObject:NSAccessibilityDropEffectsAttribute];
977
978     if (m_object->isAccessibilityTable() && static_cast<AccessibilityTable*>(m_object)->supportsSelectedRows())
979         [additional addObject:NSAccessibilitySelectedRowsAttribute];        
980     
981     if (m_object->supportsARIALiveRegion()) {
982         [additional addObject:NSAccessibilityARIALiveAttribute];
983         [additional addObject:NSAccessibilityARIARelevantAttribute];
984     }
985     
986     if (m_object->sortDirection() != SortDirectionNone)
987         [additional addObject:NSAccessibilitySortDirectionAttribute];
988         
989     // If an object is a child of a live region, then add these
990     if (m_object->isInsideARIALiveRegion()) {
991         [additional addObject:NSAccessibilityARIAAtomicAttribute];
992         [additional addObject:NSAccessibilityARIABusyAttribute];
993     }
994     
995     if (m_object->ariaHasPopup())
996         [additional addObject:NSAccessibilityHasPopupAttribute];
997     
998     return additional;
999 }
1000
1001 - (NSArray*)accessibilityAttributeNames
1002 {
1003     if (![self updateObjectBackingStore])
1004         return nil;
1005     
1006     if (m_object->isAttachment())
1007         return [[self attachmentView] accessibilityAttributeNames];
1008
1009     static NSArray* attributes = nil;
1010     static NSArray* anchorAttrs = nil;
1011     static NSArray* webAreaAttrs = nil;
1012     static NSArray* textAttrs = nil;
1013     static NSArray* listAttrs = nil;
1014     static NSArray* listBoxAttrs = nil;
1015     static NSArray* rangeAttrs = nil;
1016     static NSArray* commonMenuAttrs = nil;
1017     static NSArray* menuAttrs = nil;
1018     static NSArray* menuBarAttrs = nil;
1019     static NSArray* menuItemAttrs = nil;
1020     static NSArray* menuButtonAttrs = nil;
1021     static NSArray* controlAttrs = nil;
1022     static NSArray* tableAttrs = nil;
1023     static NSArray* tableRowAttrs = nil;
1024     static NSArray* tableColAttrs = nil;
1025     static NSArray* tableCellAttrs = nil;
1026     static NSArray* groupAttrs = nil;
1027     static NSArray* inputImageAttrs = nil;
1028     static NSArray* passwordFieldAttrs = nil;
1029     static NSArray* tabListAttrs = nil;
1030     static NSArray* comboBoxAttrs = nil;
1031     static NSArray* outlineAttrs = nil;
1032     static NSArray* outlineRowAttrs = nil;
1033     static NSArray* buttonAttrs = nil;
1034     static NSArray* scrollViewAttrs = nil;
1035     static NSArray* incrementorAttrs = nil;
1036     NSMutableArray* tempArray;
1037     if (attributes == nil) {
1038         attributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1039                       NSAccessibilitySubroleAttribute,
1040                       NSAccessibilityRoleDescriptionAttribute,
1041                       NSAccessibilityChildrenAttribute,
1042                       NSAccessibilityHelpAttribute,
1043                       NSAccessibilityParentAttribute,
1044                       NSAccessibilityPositionAttribute,
1045                       NSAccessibilitySizeAttribute,
1046                       NSAccessibilityTitleAttribute,
1047                       NSAccessibilityDescriptionAttribute,
1048                       NSAccessibilityValueAttribute,
1049                       NSAccessibilityFocusedAttribute,
1050                       NSAccessibilityEnabledAttribute,
1051                       NSAccessibilityWindowAttribute,
1052                       @"AXSelectedTextMarkerRange",
1053                       @"AXStartTextMarker",
1054                       @"AXEndTextMarker",
1055                       @"AXVisited",
1056                       NSAccessibilityLinkedUIElementsAttribute,
1057                       NSAccessibilitySelectedAttribute,
1058                       NSAccessibilityBlockQuoteLevelAttribute,
1059                       NSAccessibilityTopLevelUIElementAttribute,
1060                       nil];
1061     }
1062     if (commonMenuAttrs == nil) {
1063         commonMenuAttrs = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1064                             NSAccessibilityRoleDescriptionAttribute,
1065                             NSAccessibilityChildrenAttribute,
1066                             NSAccessibilityParentAttribute,
1067                             NSAccessibilityEnabledAttribute,
1068                             NSAccessibilityPositionAttribute,
1069                             NSAccessibilitySizeAttribute,
1070                             nil];
1071     }
1072     if (anchorAttrs == nil) {
1073         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1074         [tempArray addObject:NSAccessibilityURLAttribute];
1075         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1076         anchorAttrs = [[NSArray alloc] initWithArray:tempArray];
1077         [tempArray release];
1078     }
1079     if (webAreaAttrs == nil) {
1080         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1081         [tempArray addObject:@"AXLinkUIElements"];
1082         [tempArray addObject:@"AXLoaded"];
1083         [tempArray addObject:@"AXLayoutCount"];
1084         [tempArray addObject:NSAccessibilityLoadingProgressAttribute];
1085         [tempArray addObject:NSAccessibilityURLAttribute];
1086         webAreaAttrs = [[NSArray alloc] initWithArray:tempArray];
1087         [tempArray release];
1088     }
1089     if (textAttrs == nil) {
1090         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1091         [tempArray addObject:NSAccessibilityNumberOfCharactersAttribute];
1092         [tempArray addObject:NSAccessibilitySelectedTextAttribute];
1093         [tempArray addObject:NSAccessibilitySelectedTextRangeAttribute];
1094         [tempArray addObject:NSAccessibilityVisibleCharacterRangeAttribute];
1095         [tempArray addObject:NSAccessibilityInsertionPointLineNumberAttribute];
1096         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1097         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1098         [tempArray addObject:NSAccessibilityRequiredAttribute];
1099         [tempArray addObject:NSAccessibilityInvalidAttribute];
1100         [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1101         textAttrs = [[NSArray alloc] initWithArray:tempArray];
1102         [tempArray release];
1103     }
1104     if (listAttrs == nil) {
1105         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1106         [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1107         [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1108         [tempArray addObject:NSAccessibilityOrientationAttribute];
1109         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1110         listAttrs = [[NSArray alloc] initWithArray:tempArray];
1111         [tempArray release];
1112     }
1113     if (listBoxAttrs == nil) {
1114         tempArray = [[NSMutableArray alloc] initWithArray:listAttrs];    
1115         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1116         [tempArray addObject:NSAccessibilityRequiredAttribute];
1117         [tempArray addObject:NSAccessibilityInvalidAttribute];
1118         listBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1119         [tempArray release];
1120     }
1121     if (rangeAttrs == nil) {
1122         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1123         [tempArray addObject:NSAccessibilityMinValueAttribute];
1124         [tempArray addObject:NSAccessibilityMaxValueAttribute];
1125         [tempArray addObject:NSAccessibilityOrientationAttribute];
1126         [tempArray addObject:NSAccessibilityValueDescriptionAttribute];
1127         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1128         rangeAttrs = [[NSArray alloc] initWithArray:tempArray];
1129         [tempArray release];
1130     }
1131     if (menuBarAttrs == nil) {
1132         tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1133         [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1134         [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1135         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1136         menuBarAttrs = [[NSArray alloc] initWithArray:tempArray];
1137         [tempArray release];
1138     }
1139     if (menuAttrs == nil) {
1140         tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1141         [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1142         [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1143         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1144         menuAttrs = [[NSArray alloc] initWithArray:tempArray];
1145         [tempArray release];
1146     }
1147     if (menuItemAttrs == nil) {
1148         tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1149         [tempArray addObject:NSAccessibilityTitleAttribute];
1150         [tempArray addObject:NSAccessibilityHelpAttribute];
1151         [tempArray addObject:NSAccessibilitySelectedAttribute];
1152         [tempArray addObject:(NSString*)kAXMenuItemCmdCharAttribute];
1153         [tempArray addObject:(NSString*)kAXMenuItemCmdVirtualKeyAttribute];
1154         [tempArray addObject:(NSString*)kAXMenuItemCmdGlyphAttribute];
1155         [tempArray addObject:(NSString*)kAXMenuItemCmdModifiersAttribute];
1156         [tempArray addObject:(NSString*)kAXMenuItemMarkCharAttribute];
1157         [tempArray addObject:(NSString*)kAXMenuItemPrimaryUIElementAttribute];
1158         [tempArray addObject:NSAccessibilityServesAsTitleForUIElementsAttribute];
1159         menuItemAttrs = [[NSArray alloc] initWithArray:tempArray];
1160         [tempArray release];
1161     }
1162     if (menuButtonAttrs == nil) {
1163         menuButtonAttrs = [[NSArray alloc] initWithObjects:NSAccessibilityRoleAttribute,
1164             NSAccessibilityRoleDescriptionAttribute,
1165             NSAccessibilityParentAttribute,
1166             NSAccessibilityPositionAttribute,
1167             NSAccessibilitySizeAttribute,
1168             NSAccessibilityWindowAttribute,
1169             NSAccessibilityEnabledAttribute,
1170             NSAccessibilityFocusedAttribute,
1171             NSAccessibilityTitleAttribute,
1172             NSAccessibilityChildrenAttribute, nil];
1173     }
1174     if (controlAttrs == nil) {
1175         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1176         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1177         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1178         [tempArray addObject:NSAccessibilityRequiredAttribute];
1179         [tempArray addObject:NSAccessibilityInvalidAttribute];
1180         controlAttrs = [[NSArray alloc] initWithArray:tempArray];
1181         [tempArray release];
1182     }
1183     if (incrementorAttrs == nil) {
1184         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1185         [tempArray addObject:NSAccessibilityIncrementButtonAttribute];
1186         [tempArray addObject:NSAccessibilityDecrementButtonAttribute];
1187         incrementorAttrs = [[NSArray alloc] initWithArray:tempArray];
1188         [tempArray release];
1189     }
1190     if (buttonAttrs == nil) {
1191         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1192         // Buttons should not expose AXValue.
1193         [tempArray removeObject:NSAccessibilityValueAttribute];
1194         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1195         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1196         buttonAttrs = [[NSArray alloc] initWithArray:tempArray];
1197         [tempArray release];
1198     }
1199     if (comboBoxAttrs == nil) {
1200         tempArray = [[NSMutableArray alloc] initWithArray:controlAttrs];
1201         [tempArray addObject:NSAccessibilityExpandedAttribute];
1202         comboBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1203         [tempArray release];        
1204     }
1205     if (tableAttrs == nil) {
1206         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1207         [tempArray addObject:NSAccessibilityRowsAttribute];
1208         [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1209         [tempArray addObject:NSAccessibilityColumnsAttribute];
1210         [tempArray addObject:NSAccessibilityVisibleColumnsAttribute];
1211         [tempArray addObject:NSAccessibilityVisibleCellsAttribute];
1212         [tempArray addObject:(NSString *)kAXColumnHeaderUIElementsAttribute];
1213         [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];
1214         [tempArray addObject:NSAccessibilityHeaderAttribute];
1215         tableAttrs = [[NSArray alloc] initWithArray:tempArray];
1216         [tempArray release];
1217     }
1218     if (tableRowAttrs == nil) {
1219         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1220         [tempArray addObject:NSAccessibilityIndexAttribute];
1221         tableRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1222         [tempArray release];
1223     }
1224     if (tableColAttrs == nil) {
1225         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1226         [tempArray addObject:NSAccessibilityIndexAttribute];
1227         [tempArray addObject:NSAccessibilityHeaderAttribute];
1228         [tempArray addObject:NSAccessibilityRowsAttribute];
1229         [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1230         tableColAttrs = [[NSArray alloc] initWithArray:tempArray];
1231         [tempArray release];
1232     }
1233     if (tableCellAttrs == nil) {
1234         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1235         [tempArray addObject:NSAccessibilityRowIndexRangeAttribute];
1236         [tempArray addObject:NSAccessibilityColumnIndexRangeAttribute];
1237         tableCellAttrs = [[NSArray alloc] initWithArray:tempArray];
1238         [tempArray release];        
1239     }
1240     if (groupAttrs == nil) {
1241         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1242         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1243         groupAttrs = [[NSArray alloc] initWithArray:tempArray];
1244         [tempArray release];
1245     }
1246     if (inputImageAttrs == nil) {
1247         tempArray = [[NSMutableArray alloc] initWithArray:buttonAttrs];
1248         [tempArray addObject:NSAccessibilityURLAttribute];
1249         inputImageAttrs = [[NSArray alloc] initWithArray:tempArray];
1250         [tempArray release];
1251     }
1252     if (passwordFieldAttrs == nil) {
1253         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1254         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1255         [tempArray addObject:NSAccessibilityRequiredAttribute];
1256         [tempArray addObject:NSAccessibilityInvalidAttribute];
1257         [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1258         passwordFieldAttrs = [[NSArray alloc] initWithArray:tempArray];
1259         [tempArray release];
1260     }
1261     if (tabListAttrs == nil) {
1262         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1263         [tempArray addObject:NSAccessibilityTabsAttribute];
1264         [tempArray addObject:NSAccessibilityContentsAttribute];
1265         tabListAttrs = [[NSArray alloc] initWithArray:tempArray];
1266         [tempArray release];        
1267     }
1268     if (outlineAttrs == nil) {
1269         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1270         [tempArray addObject:NSAccessibilitySelectedRowsAttribute];
1271         [tempArray addObject:NSAccessibilityRowsAttribute];
1272         [tempArray addObject:NSAccessibilityColumnsAttribute];
1273         outlineAttrs = [[NSArray alloc] initWithArray:tempArray];
1274         [tempArray release];
1275     }
1276     if (outlineRowAttrs == nil) {
1277         tempArray = [[NSMutableArray alloc] initWithArray:tableRowAttrs];
1278         [tempArray addObject:NSAccessibilityDisclosingAttribute];
1279         [tempArray addObject:NSAccessibilityDisclosedByRowAttribute];
1280         [tempArray addObject:NSAccessibilityDisclosureLevelAttribute];
1281         [tempArray addObject:NSAccessibilityDisclosedRowsAttribute];
1282         outlineRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1283         [tempArray release];
1284     }
1285     if (scrollViewAttrs == nil) {
1286         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1287         [tempArray addObject:NSAccessibilityContentsAttribute];
1288         [tempArray addObject:NSAccessibilityHorizontalScrollBarAttribute];
1289         [tempArray addObject:NSAccessibilityVerticalScrollBarAttribute];
1290         scrollViewAttrs = [[NSArray alloc] initWithArray:tempArray];
1291         [tempArray release];
1292     }
1293     
1294     NSArray *objectAttributes = attributes;
1295     
1296     if (m_object->isPasswordField())
1297         objectAttributes = passwordFieldAttrs;
1298
1299     else if (m_object->isWebArea())
1300         objectAttributes = webAreaAttrs;
1301     
1302     else if (m_object->isTextControl())
1303         objectAttributes = textAttrs;
1304
1305     else if (m_object->isAnchor() || m_object->isImage() || m_object->isLink())
1306         objectAttributes = anchorAttrs;
1307
1308     else if (m_object->isAccessibilityTable())
1309         objectAttributes = tableAttrs;
1310     else if (m_object->isTableColumn())
1311         objectAttributes = tableColAttrs;
1312     else if (m_object->isTableCell())
1313         objectAttributes = tableCellAttrs;
1314     else if (m_object->isTableRow()) {
1315         // An ARIA table row can be collapsed and expanded, so it needs the extra attributes.
1316         if (m_object->isARIATreeGridRow())
1317             objectAttributes = outlineRowAttrs;
1318         else
1319             objectAttributes = tableRowAttrs;
1320     }
1321     
1322     else if (m_object->isTree())
1323         objectAttributes = outlineAttrs;
1324     else if (m_object->isTreeItem())
1325         objectAttributes = outlineRowAttrs;
1326     
1327     else if (m_object->isListBox())
1328         objectAttributes = listBoxAttrs;
1329     else if (m_object->isList())
1330         objectAttributes = listAttrs;
1331     
1332     else if (m_object->isComboBox())
1333         objectAttributes = comboBoxAttrs;
1334     
1335     else if (m_object->isProgressIndicator() || m_object->isSlider())
1336         objectAttributes = rangeAttrs;
1337
1338     // These are processed in order because an input image is a button, and a button is a control.
1339     else if (m_object->isInputImage())
1340         objectAttributes = inputImageAttrs;
1341     else if (m_object->isButton())
1342         objectAttributes = buttonAttrs;
1343     else if (m_object->isControl())
1344         objectAttributes = controlAttrs;
1345     
1346     else if (m_object->isGroup() || m_object->isListItem())
1347         objectAttributes = groupAttrs;
1348     else if (m_object->isTabList())
1349         objectAttributes = tabListAttrs;
1350     else if (m_object->isScrollView())
1351         objectAttributes = scrollViewAttrs;
1352     else if (m_object->isSpinButton())
1353         objectAttributes = incrementorAttrs;
1354     
1355     else if (m_object->isMenu())
1356         objectAttributes = menuAttrs;
1357     else if (m_object->isMenuBar())
1358         objectAttributes = menuBarAttrs;
1359     else if (m_object->isMenuButton())
1360         objectAttributes = menuButtonAttrs;
1361     else if (m_object->isMenuItem())
1362         objectAttributes = menuItemAttrs;
1363     
1364     NSArray *additionalAttributes = [self additionalAccessibilityAttributeNames];
1365     if ([additionalAttributes count])
1366         objectAttributes = [objectAttributes arrayByAddingObjectsFromArray:additionalAttributes];
1367     
1368     return objectAttributes;
1369 }
1370
1371 - (VisiblePositionRange)visiblePositionRangeForTextMarkerRange:(id)textMarkerRange
1372 {
1373     if (!textMarkerRange)
1374         return VisiblePositionRange();
1375     AXObjectCache* cache = m_object->axObjectCache();
1376     return VisiblePositionRange(visiblePositionForStartOfTextMarkerRange(cache, textMarkerRange), visiblePositionForEndOfTextMarkerRange(cache, textMarkerRange));
1377 }
1378
1379 - (NSArray*)renderWidgetChildren
1380 {
1381     Widget* widget = m_object->widget();
1382     if (!widget)
1383         return nil;
1384     return [(widget->platformWidget()) accessibilityAttributeValue: NSAccessibilityChildrenAttribute];
1385 }
1386
1387 - (id)remoteAccessibilityParentObject
1388 {
1389     if (!m_object || !m_object->document() || !m_object->document()->frame())
1390         return nil;
1391     
1392     return m_object->document()->frame()->loader()->client()->accessibilityRemoteObject();
1393 }
1394
1395 static void convertToVector(NSArray* array, AccessibilityObject::AccessibilityChildrenVector& vector)
1396 {
1397     unsigned length = [array count];
1398     vector.reserveInitialCapacity(length);
1399     for (unsigned i = 0; i < length; ++i) {
1400         AccessibilityObject* obj = [[array objectAtIndex:i] accessibilityObject];
1401         if (obj)
1402             vector.append(obj);
1403     }
1404 }
1405
1406 static NSMutableArray* convertToNSArray(const AccessibilityObject::AccessibilityChildrenVector& vector)
1407 {
1408     unsigned length = vector.size();
1409     NSMutableArray* array = [NSMutableArray arrayWithCapacity: length];
1410     for (unsigned i = 0; i < length; ++i) {
1411         WebAccessibilityObjectWrapper* wrapper = vector[i]->wrapper();
1412         ASSERT(wrapper);
1413         if (wrapper) {
1414             // we want to return the attachment view instead of the object representing the attachment.
1415             // otherwise, we get palindrome errors in the AX hierarchy
1416             if (vector[i]->isAttachment() && [wrapper attachmentView])
1417                 [array addObject:[wrapper attachmentView]];
1418             else
1419                 [array addObject:wrapper];
1420         }
1421     }
1422     return array;
1423 }
1424
1425 - (id)textMarkerRangeForSelection
1426 {
1427     VisibleSelection selection = m_object->selection();
1428     if (selection.isNone())
1429         return nil;
1430     return [self textMarkerRangeFromVisiblePositions:selection.visibleStart() endPosition:selection.visibleEnd()];
1431 }
1432
1433 - (NSValue *)position
1434 {
1435     IntRect rect = pixelSnappedIntRect(m_object->elementRect());
1436     NSPoint point;
1437     
1438     FrameView* frameView = m_object->documentFrameView();
1439
1440     // WebKit1 code path... platformWidget() exists.
1441     if (frameView && frameView->platformWidget()) {
1442     
1443         // The Cocoa accessibility API wants the lower-left corner.
1444         point = NSMakePoint(rect.x(), rect.maxY());
1445         
1446         if (frameView) {
1447             NSView* view = frameView->documentView();
1448             point = [[view window] convertBaseToScreen:[view convertPoint: point toView:nil]];
1449         }
1450     } else {
1451         
1452         // Find the appropriate scroll view to use to convert the contents to the window.
1453         ScrollView* scrollView = 0;
1454         for (AccessibilityObject* parent = m_object->parentObject(); parent; parent = parent->parentObject()) {
1455             if (parent->isAccessibilityScrollView()) {
1456                 scrollView = toAccessibilityScrollView(parent)->scrollView();
1457                 break;
1458             }
1459         }
1460
1461         if (scrollView)
1462             rect = scrollView->contentsToRootView(rect);
1463         
1464         if (m_object->page())
1465             point = m_object->page()->chrome()->rootViewToScreen(rect).location();
1466         else
1467             point = rect.location();
1468     }
1469     
1470     return [NSValue valueWithPoint:point];
1471 }
1472
1473 typedef HashMap<int, NSString*> AccessibilityRoleMap;
1474
1475 static const AccessibilityRoleMap& createAccessibilityRoleMap()
1476 {
1477     struct RoleEntry {
1478         AccessibilityRole value;
1479         NSString* string;
1480     };
1481     
1482     static const RoleEntry roles[] = {
1483         { UnknownRole, NSAccessibilityUnknownRole },
1484         { ButtonRole, NSAccessibilityButtonRole },
1485         { RadioButtonRole, NSAccessibilityRadioButtonRole },
1486         { CheckBoxRole, NSAccessibilityCheckBoxRole },
1487         { SliderRole, NSAccessibilitySliderRole },
1488         { TabGroupRole, NSAccessibilityTabGroupRole },
1489         { TextFieldRole, NSAccessibilityTextFieldRole },
1490         { StaticTextRole, NSAccessibilityStaticTextRole },
1491         { TextAreaRole, NSAccessibilityTextAreaRole },
1492         { ScrollAreaRole, NSAccessibilityScrollAreaRole },
1493         { PopUpButtonRole, NSAccessibilityPopUpButtonRole },
1494         { MenuButtonRole, NSAccessibilityMenuButtonRole },
1495         { TableRole, NSAccessibilityTableRole },
1496         { ApplicationRole, NSAccessibilityApplicationRole },
1497         { GroupRole, NSAccessibilityGroupRole },
1498         { RadioGroupRole, NSAccessibilityRadioGroupRole },
1499         { ListRole, NSAccessibilityListRole },
1500         { DirectoryRole, NSAccessibilityListRole },
1501         { ScrollBarRole, NSAccessibilityScrollBarRole },
1502         { ValueIndicatorRole, NSAccessibilityValueIndicatorRole },
1503         { ImageRole, NSAccessibilityImageRole },
1504         { MenuBarRole, NSAccessibilityMenuBarRole },
1505         { MenuRole, NSAccessibilityMenuRole },
1506         { MenuItemRole, NSAccessibilityMenuItemRole },
1507         { ColumnRole, NSAccessibilityColumnRole },
1508         { RowRole, NSAccessibilityRowRole },
1509         { ToolbarRole, NSAccessibilityToolbarRole },
1510         { BusyIndicatorRole, NSAccessibilityBusyIndicatorRole },
1511         { ProgressIndicatorRole, NSAccessibilityProgressIndicatorRole },
1512         { WindowRole, NSAccessibilityWindowRole },
1513         { DrawerRole, NSAccessibilityDrawerRole },
1514         { SystemWideRole, NSAccessibilitySystemWideRole },
1515         { OutlineRole, NSAccessibilityOutlineRole },
1516         { IncrementorRole, NSAccessibilityIncrementorRole },
1517         { BrowserRole, NSAccessibilityBrowserRole },
1518         { ComboBoxRole, NSAccessibilityComboBoxRole },
1519         { SplitGroupRole, NSAccessibilitySplitGroupRole },
1520         { SplitterRole, NSAccessibilitySplitterRole },
1521         { ColorWellRole, NSAccessibilityColorWellRole },
1522         { GrowAreaRole, NSAccessibilityGrowAreaRole },
1523         { SheetRole, NSAccessibilitySheetRole },
1524         { HelpTagRole, NSAccessibilityHelpTagRole },
1525         { MatteRole, NSAccessibilityMatteRole }, 
1526         { RulerRole, NSAccessibilityRulerRole },
1527         { RulerMarkerRole, NSAccessibilityRulerMarkerRole },
1528         { LinkRole, NSAccessibilityLinkRole },
1529         { DisclosureTriangleRole, NSAccessibilityDisclosureTriangleRole },
1530         { GridRole, NSAccessibilityGridRole },
1531         { WebCoreLinkRole, NSAccessibilityLinkRole }, 
1532         { ImageMapLinkRole, NSAccessibilityLinkRole },
1533         { ImageMapRole, @"AXImageMap" },
1534         { ListMarkerRole, @"AXListMarker" },
1535         { WebAreaRole, @"AXWebArea" },
1536         { HeadingRole, @"AXHeading" },
1537         { ListBoxRole, NSAccessibilityListRole },
1538         { ListBoxOptionRole, NSAccessibilityStaticTextRole },
1539 #if ACCESSIBILITY_TABLES
1540         { CellRole, NSAccessibilityCellRole },
1541 #else
1542         { CellRole, NSAccessibilityGroupRole },
1543 #endif
1544         { TableHeaderContainerRole, NSAccessibilityGroupRole },
1545         { DefinitionListDefinitionRole, NSAccessibilityGroupRole },
1546         { DefinitionListTermRole, NSAccessibilityGroupRole },
1547         { SliderThumbRole, NSAccessibilityValueIndicatorRole },
1548         { LandmarkApplicationRole, NSAccessibilityGroupRole },
1549         { LandmarkBannerRole, NSAccessibilityGroupRole },
1550         { LandmarkComplementaryRole, NSAccessibilityGroupRole },
1551         { LandmarkContentInfoRole, NSAccessibilityGroupRole },
1552         { LandmarkMainRole, NSAccessibilityGroupRole },
1553         { LandmarkNavigationRole, NSAccessibilityGroupRole },
1554         { LandmarkSearchRole, NSAccessibilityGroupRole },
1555         { ApplicationAlertRole, NSAccessibilityGroupRole },
1556         { ApplicationAlertDialogRole, NSAccessibilityGroupRole },
1557         { ApplicationDialogRole, NSAccessibilityGroupRole },
1558         { ApplicationLogRole, NSAccessibilityGroupRole },
1559         { ApplicationMarqueeRole, NSAccessibilityGroupRole },
1560         { ApplicationStatusRole, NSAccessibilityGroupRole },
1561         { ApplicationTimerRole, NSAccessibilityGroupRole },
1562         { DocumentRole, NSAccessibilityGroupRole },
1563         { DocumentArticleRole, NSAccessibilityGroupRole },
1564         { DocumentMathRole, NSAccessibilityGroupRole },
1565         { DocumentNoteRole, NSAccessibilityGroupRole },
1566         { DocumentRegionRole, NSAccessibilityGroupRole },
1567         { UserInterfaceTooltipRole, NSAccessibilityGroupRole },
1568         { TabRole, NSAccessibilityRadioButtonRole },
1569         { TabListRole, NSAccessibilityTabGroupRole },
1570         { TabPanelRole, NSAccessibilityGroupRole },
1571         { TreeRole, NSAccessibilityOutlineRole },
1572         { TreeItemRole, NSAccessibilityRowRole },
1573         { ListItemRole, NSAccessibilityGroupRole },
1574         { ParagraphRole, NSAccessibilityGroupRole },
1575         { LabelRole, NSAccessibilityGroupRole },
1576         { DivRole, NSAccessibilityGroupRole },
1577         { FormRole, NSAccessibilityGroupRole },
1578         { SpinButtonRole, NSAccessibilityIncrementorRole },
1579         { FooterRole, NSAccessibilityGroupRole }
1580     };
1581     AccessibilityRoleMap& roleMap = *new AccessibilityRoleMap;
1582     
1583     const unsigned numRoles = sizeof(roles) / sizeof(roles[0]);
1584     for (unsigned i = 0; i < numRoles; ++i)
1585         roleMap.set(roles[i].value, roles[i].string);
1586     return roleMap;
1587 }
1588
1589 static NSString* roleValueToNSString(AccessibilityRole value)
1590 {
1591     ASSERT(value);
1592     static const AccessibilityRoleMap& roleMap = createAccessibilityRoleMap();
1593     return roleMap.get(value);
1594 }
1595
1596 - (NSString*)role
1597 {
1598     if (m_object->isAttachment())
1599         return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleAttribute];
1600     NSString* string = roleValueToNSString(m_object->roleValue());
1601     if (string != nil)
1602         return string;
1603     return NSAccessibilityUnknownRole;
1604 }
1605
1606 - (NSString*)subrole
1607 {
1608     if (m_object->isPasswordField())
1609         return NSAccessibilitySecureTextFieldSubrole;
1610     if (m_object->isSearchField())
1611         return NSAccessibilitySearchFieldSubrole;
1612     
1613     if (m_object->isAttachment()) {
1614         NSView* attachView = [self attachmentView];
1615         if ([[attachView accessibilityAttributeNames] containsObject:NSAccessibilitySubroleAttribute]) {
1616             return [attachView accessibilityAttributeValue:NSAccessibilitySubroleAttribute];
1617         }
1618     }
1619     
1620     if (m_object->isSpinButtonPart()) {
1621         if (toAccessibilitySpinButtonPart(m_object)->isIncrementor())
1622             return NSAccessibilityIncrementArrowSubrole;
1623
1624         return NSAccessibilityDecrementArrowSubrole;
1625     }
1626     
1627     if (m_object->isTreeItem())
1628         return NSAccessibilityOutlineRowSubrole;
1629     
1630     if (m_object->isList()) {
1631         AccessibilityList* listObject = static_cast<AccessibilityList*>(m_object);
1632         if (listObject->isUnorderedList() || listObject->isOrderedList())
1633             return NSAccessibilityContentListSubrole;
1634         if (listObject->isDefinitionList())
1635             return NSAccessibilityDefinitionListSubrole;
1636     }
1637     
1638     // ARIA content subroles.
1639     switch (m_object->roleValue()) {
1640         case LandmarkApplicationRole:
1641             return @"AXLandmarkApplication";
1642         case LandmarkBannerRole:
1643             return @"AXLandmarkBanner";
1644         case LandmarkComplementaryRole:
1645             return @"AXLandmarkComplementary";
1646         // Footer roles should appear as content info types.
1647         case FooterRole:
1648         case LandmarkContentInfoRole:
1649             return @"AXLandmarkContentInfo";
1650         case LandmarkMainRole:
1651             return @"AXLandmarkMain";
1652         case LandmarkNavigationRole:
1653             return @"AXLandmarkNavigation";
1654         case LandmarkSearchRole:
1655             return @"AXLandmarkSearch";
1656         case ApplicationAlertRole:
1657             return @"AXApplicationAlert";
1658         case ApplicationAlertDialogRole:
1659             return @"AXApplicationAlertDialog";
1660         case ApplicationDialogRole:
1661             return @"AXApplicationDialog";
1662         case ApplicationLogRole:
1663             return @"AXApplicationLog";
1664         case ApplicationMarqueeRole:
1665             return @"AXApplicationMarquee";
1666         case ApplicationStatusRole:
1667             return @"AXApplicationStatus";
1668         case ApplicationTimerRole:
1669             return @"AXApplicationTimer";
1670         case DocumentRole:
1671             return @"AXDocument";
1672         case DocumentArticleRole:
1673             return @"AXDocumentArticle";
1674         case DocumentMathRole:
1675             return @"AXDocumentMath";
1676         case DocumentNoteRole:
1677             return @"AXDocumentNote";
1678         case DocumentRegionRole:
1679             return @"AXDocumentRegion";
1680         case UserInterfaceTooltipRole:
1681             return @"AXUserInterfaceTooltip";
1682         case TabPanelRole:
1683             return @"AXTabPanel";
1684         case DefinitionListTermRole:
1685             return @"AXTerm";
1686         case DefinitionListDefinitionRole:
1687             return @"AXDefinition";
1688         // Default doesn't return anything, so roles defined below can be chosen.
1689         default:
1690             break;
1691     }
1692     
1693     if (m_object->isMediaTimeline())
1694         return NSAccessibilityTimelineSubrole;
1695
1696     return nil;
1697 }
1698
1699 - (NSString*)roleDescription
1700 {
1701     if (!m_object)
1702         return nil;
1703
1704     // attachments have the AXImage role, but a different subrole
1705     if (m_object->isAttachment())
1706         return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute];
1707     
1708     NSString* axRole = [self role];
1709     
1710     if ([axRole isEqualToString:NSAccessibilityGroupRole]) {
1711         switch (m_object->roleValue()) {
1712             default:
1713                 return NSAccessibilityRoleDescription(NSAccessibilityGroupRole, [self subrole]);
1714             case LandmarkApplicationRole:
1715                 return AXARIAContentGroupText(@"ARIALandmarkApplication");
1716             case LandmarkBannerRole:
1717                 return AXARIAContentGroupText(@"ARIALandmarkBanner");
1718             case LandmarkComplementaryRole:
1719                 return AXARIAContentGroupText(@"ARIALandmarkComplementary");
1720             case LandmarkContentInfoRole:
1721                 return AXARIAContentGroupText(@"ARIALandmarkContentInfo");
1722             case LandmarkMainRole:
1723                 return AXARIAContentGroupText(@"ARIALandmarkMain");
1724             case LandmarkNavigationRole:
1725                 return AXARIAContentGroupText(@"ARIALandmarkNavigation");
1726             case LandmarkSearchRole:
1727                 return AXARIAContentGroupText(@"ARIALandmarkSearch");
1728             case ApplicationAlertRole:
1729                 return AXARIAContentGroupText(@"ARIAApplicationAlert");
1730             case ApplicationAlertDialogRole:
1731                 return AXARIAContentGroupText(@"ARIAApplicationAlertDialog");
1732             case ApplicationDialogRole:
1733                 return AXARIAContentGroupText(@"ARIAApplicationDialog");
1734             case ApplicationLogRole:
1735                 return AXARIAContentGroupText(@"ARIAApplicationLog");
1736             case ApplicationMarqueeRole:
1737                 return AXARIAContentGroupText(@"ARIAApplicationMarquee");
1738             case ApplicationStatusRole:
1739                 return AXARIAContentGroupText(@"ARIAApplicationStatus");
1740             case ApplicationTimerRole:
1741                 return AXARIAContentGroupText(@"ARIAApplicationTimer");
1742             case DocumentRole:
1743                 return AXARIAContentGroupText(@"ARIADocument");
1744             case DocumentArticleRole:
1745                 return AXARIAContentGroupText(@"ARIADocumentArticle");
1746             case DocumentMathRole:
1747                 return AXARIAContentGroupText(@"ARIADocumentMath");
1748             case DocumentNoteRole:
1749                 return AXARIAContentGroupText(@"ARIADocumentNote");
1750             case DocumentRegionRole:
1751                 return AXARIAContentGroupText(@"ARIADocumentRegion");
1752             case UserInterfaceTooltipRole:
1753                 return AXARIAContentGroupText(@"ARIAUserInterfaceTooltip");
1754             case TabPanelRole:
1755                 return AXARIAContentGroupText(@"ARIATabPanel");
1756             case DefinitionListTermRole:
1757                 return AXDefinitionListTermText();
1758             case DefinitionListDefinitionRole:
1759                 return AXDefinitionListDefinitionText();
1760             case FooterRole:
1761                 return AXFooterRoleDescriptionText();
1762         }
1763     }        
1764     
1765     if ([axRole isEqualToString:@"AXWebArea"])
1766         return AXWebAreaText();
1767     
1768     if ([axRole isEqualToString:@"AXLink"])
1769         return AXLinkText();
1770     
1771     if ([axRole isEqualToString:@"AXListMarker"])
1772         return AXListMarkerText();
1773     
1774     if ([axRole isEqualToString:@"AXImageMap"])
1775         return AXImageMapText();
1776
1777     if ([axRole isEqualToString:@"AXHeading"])
1778         return AXHeadingText();
1779
1780     // AppKit also returns AXTab for the role description for a tab item.
1781     if (m_object->isTabItem())
1782         return NSAccessibilityRoleDescription(@"AXTab", nil);
1783     
1784     // We should try the system default role description for all other roles.
1785     // If we get the same string back, then as a last resort, return unknown.
1786     NSString* defaultRoleDescription = NSAccessibilityRoleDescription(axRole, [self subrole]);
1787     if (![defaultRoleDescription isEqualToString:axRole])
1788         return defaultRoleDescription;
1789
1790     return NSAccessibilityRoleDescription(NSAccessibilityUnknownRole, nil);
1791 }
1792
1793 - (id)scrollViewParent
1794 {
1795     if (!m_object || !m_object->isAccessibilityScrollView())
1796         return nil;
1797     
1798     // If this scroll view provides it's parent object (because it's a sub-frame), then
1799     // we should not find the remoteAccessibilityParent.
1800     if (m_object->parentObject())
1801         return nil;
1802     
1803     AccessibilityScrollView* scrollView = toAccessibilityScrollView(m_object);
1804     ScrollView* scroll = scrollView->scrollView();
1805     if (!scroll)
1806         return nil;
1807     
1808     if (scroll->platformWidget())
1809         return NSAccessibilityUnignoredAncestor(scroll->platformWidget());
1810
1811     return [self remoteAccessibilityParentObject];
1812 }
1813
1814 // FIXME: split up this function in a better way.  
1815 // suggestions: Use a hash table that maps attribute names to function calls,
1816 // or maybe pointers to member functions
1817 - (id)accessibilityAttributeValue:(NSString*)attributeName
1818 {
1819     if (![self updateObjectBackingStore])
1820         return nil;
1821     
1822     if ([attributeName isEqualToString: NSAccessibilityRoleAttribute])
1823         return [self role];
1824
1825     if ([attributeName isEqualToString: NSAccessibilitySubroleAttribute])
1826         return [self subrole];
1827
1828     if ([attributeName isEqualToString: NSAccessibilityRoleDescriptionAttribute])
1829         return [self roleDescription];
1830
1831     if ([attributeName isEqualToString: NSAccessibilityParentAttribute]) {
1832
1833         // This will return the parent of the AXWebArea, if this is a web area.
1834         id scrollViewParent = [self scrollViewParent];
1835         if (scrollViewParent)
1836             return scrollViewParent;
1837         
1838         // Tree item (changed to AXRows) can only report the tree (AXOutline) as its parent.
1839         if (m_object->isTreeItem()) {
1840             AccessibilityObject* parent = m_object->parentObjectUnignored();
1841             while (parent) {
1842                 if (parent->isTree())
1843                     return parent->wrapper();
1844                 parent = parent->parentObjectUnignored();
1845             }
1846         }
1847         
1848         AccessibilityObject* parent = m_object->parentObjectUnignored();
1849         if (!parent)
1850             return nil;
1851
1852         // In WebKit1, the scroll view is provided by the system (the attachment view), so the parent
1853         // should be reported directly as such.
1854         if (m_object->isWebArea() && parent->isAttachment())
1855             return [parent->wrapper() attachmentView];
1856         
1857         return parent->wrapper();
1858     }
1859
1860     if ([attributeName isEqualToString: NSAccessibilityChildrenAttribute]) {
1861         if (m_object->children().isEmpty()) {
1862             NSArray* children = [self renderWidgetChildren];
1863             if (children != nil)
1864                 return children;
1865         }
1866
1867         // The tree's (AXOutline) children are supposed to be its rows and columns.
1868         // The ARIA spec doesn't have columns, so we just need rows.
1869         if (m_object->isTree())
1870             return [self accessibilityAttributeValue:NSAccessibilityRowsAttribute];
1871
1872         // A tree item should only expose its content as its children (not its rows)
1873         if (m_object->isTreeItem()) {
1874             AccessibilityObject::AccessibilityChildrenVector contentCopy;
1875             m_object->ariaTreeItemContent(contentCopy);
1876             return convertToNSArray(contentCopy);
1877         }
1878         
1879         return convertToNSArray(m_object->children());
1880     }
1881     
1882     if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {
1883         if (m_object->isListBox()) {
1884             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
1885             m_object->selectedChildren(selectedChildrenCopy);
1886             return convertToNSArray(selectedChildrenCopy);
1887         }
1888         return nil;
1889     }
1890     
1891     if ([attributeName isEqualToString: NSAccessibilityVisibleChildrenAttribute]) {
1892         if (m_object->isListBox()) {
1893             AccessibilityObject::AccessibilityChildrenVector visibleChildrenCopy;
1894             m_object->visibleChildren(visibleChildrenCopy);
1895             return convertToNSArray(visibleChildrenCopy);
1896         }
1897         else if (m_object->isList())
1898             return [self accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
1899
1900         return nil;
1901     }
1902     
1903     
1904     if (m_object->isWebArea()) {
1905         if ([attributeName isEqualToString:@"AXLinkUIElements"]) {
1906             AccessibilityObject::AccessibilityChildrenVector links;
1907             static_cast<AccessibilityRenderObject*>(m_object)->getDocumentLinks(links);
1908             return convertToNSArray(links);
1909         }
1910         if ([attributeName isEqualToString:@"AXLoaded"])
1911             return [NSNumber numberWithBool:m_object->isLoaded()];
1912         if ([attributeName isEqualToString:@"AXLayoutCount"])
1913             return [NSNumber numberWithInt:m_object->layoutCount()];
1914         if ([attributeName isEqualToString:NSAccessibilityLoadingProgressAttribute])
1915             return [NSNumber numberWithDouble:m_object->estimatedLoadingProgress()];
1916     }
1917     
1918     if (m_object->isTextControl()) {
1919         if ([attributeName isEqualToString: NSAccessibilityNumberOfCharactersAttribute]) {
1920             int length = m_object->textLength();
1921             if (length < 0)
1922                 return nil;
1923             return [NSNumber numberWithUnsignedInt:length];
1924         }
1925         if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
1926             String selectedText = m_object->selectedText();
1927             if (selectedText.isNull())
1928                 return nil;
1929             return (NSString*)selectedText;
1930         }
1931         if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
1932             PlainTextRange textRange = m_object->selectedTextRange();
1933             if (textRange.isNull())
1934                 return [NSValue valueWithRange:NSMakeRange(0, 0)];
1935             return [NSValue valueWithRange:NSMakeRange(textRange.start, textRange.length)];
1936         }
1937         // TODO: Get actual visible range. <rdar://problem/4712101>
1938         if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
1939             return m_object->isPasswordField() ? nil : [NSValue valueWithRange: NSMakeRange(0, m_object->textLength())];
1940         if ([attributeName isEqualToString: NSAccessibilityInsertionPointLineNumberAttribute]) {
1941             // if selectionEnd > 0, then there is selected text and this question should not be answered
1942             if (m_object->isPasswordField() || m_object->selectionEnd() > 0)
1943                 return nil;
1944
1945             AccessibilityObject* focusedObject = m_object->focusedUIElement();
1946             if (focusedObject != m_object)
1947                 return nil;
1948
1949             VisiblePosition focusedPosition = focusedObject->visiblePositionForIndex(focusedObject->selectionStart(), true);
1950             int lineNumber = m_object->lineForPosition(focusedPosition);
1951             if (lineNumber < 0)
1952                 return nil;
1953
1954             return [NSNumber numberWithInt:lineNumber];
1955         }
1956     }
1957     
1958     if ([attributeName isEqualToString: NSAccessibilityURLAttribute]) {
1959         KURL url = m_object->url();
1960         if (url.isNull())
1961             return nil;
1962         return (NSURL*)url;
1963     }
1964
1965     if (m_object->isSpinButton()) {
1966         if ([attributeName isEqualToString:NSAccessibilityIncrementButtonAttribute])
1967             return toAccessibilitySpinButton(m_object)->incrementButton()->wrapper();
1968         if ([attributeName isEqualToString:NSAccessibilityDecrementButtonAttribute])
1969             return toAccessibilitySpinButton(m_object)->decrementButton()->wrapper();
1970     }
1971     
1972     if ([attributeName isEqualToString: @"AXVisited"])
1973         return [NSNumber numberWithBool: m_object->isVisited()];
1974     
1975     if ([attributeName isEqualToString: NSAccessibilityTitleAttribute]) {
1976         if (m_object->isAttachment()) {
1977             if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityTitleAttribute]) 
1978                 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityTitleAttribute];
1979         }
1980         return m_object->title();
1981     }
1982     
1983     if ([attributeName isEqualToString: NSAccessibilityDescriptionAttribute]) {
1984         if (m_object->isAttachment()) {
1985             if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityDescriptionAttribute])
1986                 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityDescriptionAttribute];
1987         }
1988         return m_object->accessibilityDescription();
1989     }
1990
1991     if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
1992         if (m_object->isAttachment()) {
1993             if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityValueAttribute]) 
1994                 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityValueAttribute];
1995         }
1996         if (m_object->isProgressIndicator() || m_object->isSlider() || m_object->isScrollbar())
1997             return [NSNumber numberWithFloat:m_object->valueForRange()];
1998         if (m_object->roleValue() == SliderThumbRole)
1999             return [NSNumber numberWithFloat:m_object->parentObject()->valueForRange()];
2000         if (m_object->isHeading())
2001             return [NSNumber numberWithInt:m_object->headingLevel()];
2002         
2003         if (m_object->isCheckboxOrRadio()) {
2004             switch (m_object->checkboxOrRadioValue()) {
2005             case ButtonStateOff:
2006                 return [NSNumber numberWithInt:0];
2007             case ButtonStateOn:
2008                 return [NSNumber numberWithInt:1];
2009             case ButtonStateMixed:
2010                 return [NSNumber numberWithInt:2];
2011             }
2012         }
2013
2014         // radio groups return the selected radio button as the AXValue
2015         if (m_object->isRadioGroup()) {
2016             AccessibilityObject* radioButton = m_object->selectedRadioButton();
2017             if (!radioButton)
2018                 return nil;
2019             return radioButton->wrapper();
2020         }
2021         
2022         if (m_object->isTabList()) {
2023             AccessibilityObject* tabItem = m_object->selectedTabItem();
2024             if (!tabItem)
2025                 return nil;
2026             return tabItem->wrapper();
2027         }
2028         
2029         if (m_object->isTabItem())
2030             return [NSNumber numberWithInt:m_object->isSelected()];
2031         
2032         return m_object->stringValue();
2033     }
2034
2035     if ([attributeName isEqualToString: NSAccessibilityMinValueAttribute])
2036         return [NSNumber numberWithFloat:m_object->minValueForRange()];
2037
2038     if ([attributeName isEqualToString: NSAccessibilityMaxValueAttribute])
2039         return [NSNumber numberWithFloat:m_object->maxValueForRange()];
2040
2041     if ([attributeName isEqualToString: NSAccessibilityHelpAttribute])
2042         return m_object->helpText();
2043
2044     if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
2045         return [NSNumber numberWithBool: m_object->isFocused()];
2046
2047     if ([attributeName isEqualToString: NSAccessibilityEnabledAttribute])
2048         return [NSNumber numberWithBool: m_object->isEnabled()];
2049
2050     if ([attributeName isEqualToString: NSAccessibilitySizeAttribute]) {
2051         IntSize s = m_object->pixelSnappedSize();
2052         return [NSValue valueWithSize: NSMakeSize(s.width(), s.height())];
2053     }
2054
2055     if ([attributeName isEqualToString: NSAccessibilityPositionAttribute])
2056         return [self position];
2057
2058     if ([attributeName isEqualToString: NSAccessibilityWindowAttribute] ||
2059         [attributeName isEqualToString: NSAccessibilityTopLevelUIElementAttribute]) {
2060         
2061         id remoteParent = [self remoteAccessibilityParentObject];
2062         if (remoteParent)
2063             return [remoteParent accessibilityAttributeValue:attributeName];
2064         
2065         FrameView* fv = m_object->documentFrameView();
2066         if (fv)
2067             return [fv->platformWidget() window];
2068         return nil;
2069     }
2070     
2071     if ([attributeName isEqualToString:NSAccessibilityAccessKeyAttribute]) {
2072         AtomicString accessKey = m_object->accessKey();
2073         if (accessKey.isNull())
2074             return nil;
2075         return accessKey;
2076     }
2077     
2078     if ([attributeName isEqualToString:NSAccessibilityTabsAttribute]) {
2079         if (m_object->isTabList()) {
2080             AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2081             m_object->tabChildren(tabsChildren);
2082             return convertToNSArray(tabsChildren);
2083         }
2084     }
2085     
2086     if ([attributeName isEqualToString:NSAccessibilityContentsAttribute]) {
2087         // The contents of a tab list are all the children except the tabs.
2088         if (m_object->isTabList()) {
2089             AccessibilityObject::AccessibilityChildrenVector children = m_object->children();
2090             AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2091             m_object->tabChildren(tabsChildren);
2092
2093             AccessibilityObject::AccessibilityChildrenVector contents;
2094             unsigned childrenSize = children.size();
2095             for (unsigned k = 0; k < childrenSize; ++k) {
2096                 if (tabsChildren.find(children[k]) == WTF::notFound)
2097                     contents.append(children[k]);
2098             }
2099             return convertToNSArray(contents);
2100         } else if (m_object->isScrollView()) {
2101             AccessibilityObject::AccessibilityChildrenVector children = m_object->children();
2102             
2103             // A scrollView's contents are everything except the scroll bars.
2104             AccessibilityObject::AccessibilityChildrenVector contents;
2105             unsigned childrenSize = children.size();
2106             for (unsigned k = 0; k < childrenSize; ++k) {
2107                 if (!children[k]->isScrollbar())
2108                     contents.append(children[k]);
2109             }
2110             return convertToNSArray(contents);            
2111         }
2112     }    
2113     
2114     if (m_object->isAccessibilityTable()) {
2115         // TODO: distinguish between visible and non-visible rows
2116         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] || 
2117             [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
2118             return convertToNSArray(static_cast<AccessibilityTable*>(m_object)->rows());
2119         }
2120         // TODO: distinguish between visible and non-visible columns
2121         if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute] || 
2122             [attributeName isEqualToString:NSAccessibilityVisibleColumnsAttribute]) {
2123             return convertToNSArray(static_cast<AccessibilityTable*>(m_object)->columns());
2124         }
2125         
2126         if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2127             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2128             m_object->selectedChildren(selectedChildrenCopy);
2129             return convertToNSArray(selectedChildrenCopy);
2130         }
2131         
2132         // HTML tables don't support these
2133         if ([attributeName isEqualToString:NSAccessibilitySelectedColumnsAttribute] || 
2134             [attributeName isEqualToString:NSAccessibilitySelectedCellsAttribute])
2135             return nil;
2136         
2137         if ([attributeName isEqualToString:(NSString *)kAXColumnHeaderUIElementsAttribute]) {
2138             AccessibilityObject::AccessibilityChildrenVector columnHeaders;
2139             static_cast<AccessibilityTable*>(m_object)->columnHeaders(columnHeaders);
2140             return convertToNSArray(columnHeaders);            
2141         }
2142         
2143         if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2144             AccessibilityObject* headerContainer = static_cast<AccessibilityTable*>(m_object)->headerContainer();
2145             if (headerContainer)
2146                 return headerContainer->wrapper();
2147             return nil;
2148         }
2149
2150         if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
2151             AccessibilityObject::AccessibilityChildrenVector rowHeaders;
2152             static_cast<AccessibilityTable*>(m_object)->rowHeaders(rowHeaders);
2153             return convertToNSArray(rowHeaders);                        
2154         }
2155         
2156         if ([attributeName isEqualToString:NSAccessibilityVisibleCellsAttribute]) {
2157             AccessibilityObject::AccessibilityChildrenVector cells;
2158             static_cast<AccessibilityTable*>(m_object)->cells(cells);
2159             return convertToNSArray(cells);
2160         }        
2161     }
2162     
2163     if (m_object->isTableColumn()) {
2164         if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2165             return [NSNumber numberWithInt:static_cast<AccessibilityTableColumn*>(m_object)->columnIndex()];
2166         
2167         // rows attribute for a column is the list of all the elements in that column at each row
2168         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] || 
2169             [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
2170             return convertToNSArray(static_cast<AccessibilityTableColumn*>(m_object)->children());
2171         }
2172         if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2173             AccessibilityObject* header = static_cast<AccessibilityTableColumn*>(m_object)->headerObject();
2174             if (!header)
2175                 return nil;
2176             return header->wrapper();
2177         }
2178     }
2179     
2180     if (m_object->isTableCell()) {
2181         if ([attributeName isEqualToString:NSAccessibilityRowIndexRangeAttribute]) {
2182             pair<int, int> rowRange;
2183             static_cast<AccessibilityTableCell*>(m_object)->rowIndexRange(rowRange);
2184             return [NSValue valueWithRange:NSMakeRange(rowRange.first, rowRange.second)];
2185         }  
2186         if ([attributeName isEqualToString:NSAccessibilityColumnIndexRangeAttribute]) {
2187             pair<int, int> columnRange;
2188             static_cast<AccessibilityTableCell*>(m_object)->columnIndexRange(columnRange);
2189             return [NSValue valueWithRange:NSMakeRange(columnRange.first, columnRange.second)];
2190         }  
2191     }
2192     
2193     if (m_object->isTree()) {
2194         if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2195             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2196             m_object->selectedChildren(selectedChildrenCopy);
2197             return convertToNSArray(selectedChildrenCopy);
2198         }
2199         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute]) {
2200             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2201             m_object->ariaTreeRows(rowsCopy);
2202             return convertToNSArray(rowsCopy);            
2203         }
2204         
2205         // TreeRoles do not support columns, but Mac AX expects to be able to ask about columns at the least.
2206         if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute])
2207             return [NSArray array];
2208     }
2209
2210     if ([attributeName isEqualToString:NSAccessibilityIndexAttribute]) {
2211         if (m_object->isTreeItem()) {
2212             AccessibilityObject* parent = m_object->parentObject();
2213             for (; parent && !parent->isTree(); parent = parent->parentObject())
2214             { }
2215             
2216             if (!parent)
2217                 return nil;
2218             
2219             // Find the index of this item by iterating the parents.
2220             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2221             parent->ariaTreeRows(rowsCopy);
2222             size_t count = rowsCopy.size();
2223             for (size_t k = 0; k < count; ++k)
2224                 if (rowsCopy[k]->wrapper() == self)
2225                     return [NSNumber numberWithUnsignedInt:k];
2226             
2227             return nil;
2228         }
2229         if (m_object->isTableRow()) {
2230             if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2231                 return [NSNumber numberWithInt:static_cast<AccessibilityTableRow*>(m_object)->rowIndex()];
2232         }
2233     }    
2234     
2235     // The rows that are considered inside this row. 
2236     if ([attributeName isEqualToString:NSAccessibilityDisclosedRowsAttribute]) {
2237         if (m_object->isTreeItem()) {
2238             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2239             m_object->ariaTreeItemDisclosedRows(rowsCopy);
2240             return convertToNSArray(rowsCopy);    
2241         } else if (m_object->isARIATreeGridRow()) {
2242             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2243             static_cast<AccessibilityARIAGridRow*>(m_object)->disclosedRows(rowsCopy);
2244             return convertToNSArray(rowsCopy);    
2245         }
2246     }
2247     
2248     // The row that contains this row. It should be the same as the first parent that is a treeitem.
2249     if ([attributeName isEqualToString:NSAccessibilityDisclosedByRowAttribute]) {
2250         if (m_object->isTreeItem()) {
2251             AccessibilityObject* parent = m_object->parentObject();
2252             while (parent) {
2253                 if (parent->isTreeItem())
2254                     return parent->wrapper();
2255                 // If the parent is the tree itself, then this value == nil.
2256                 if (parent->isTree())
2257                     return nil;
2258                 parent = parent->parentObject();
2259             }
2260             return nil;
2261         } else if (m_object->isARIATreeGridRow()) {
2262             AccessibilityObject* row = static_cast<AccessibilityARIAGridRow*>(m_object)->disclosedByRow();
2263             if (!row)
2264                 return nil;
2265             return row->wrapper();
2266         }
2267     }
2268
2269     if ([attributeName isEqualToString:NSAccessibilityDisclosureLevelAttribute])
2270         return [NSNumber numberWithInt:m_object->hierarchicalLevel()];
2271     if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
2272         return [NSNumber numberWithBool:m_object->isExpanded()];
2273     
2274     if ((m_object->isListBox() || m_object->isList()) && [attributeName isEqualToString:NSAccessibilityOrientationAttribute])
2275         return NSAccessibilityVerticalOrientationValue;
2276
2277     if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
2278         return [self textMarkerRangeForSelection];
2279     
2280     if (m_object->renderer()) {
2281         if ([attributeName isEqualToString: @"AXStartTextMarker"])
2282             return [self textMarkerForVisiblePosition:startOfDocument(m_object->renderer()->document())];
2283         if ([attributeName isEqualToString: @"AXEndTextMarker"])
2284             return [self textMarkerForVisiblePosition:endOfDocument(m_object->renderer()->document())];
2285     }
2286     
2287     if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute])
2288         return [NSNumber numberWithInt:m_object->blockquoteLevel()];
2289     if ([attributeName isEqualToString:@"AXTableLevel"])
2290         return [NSNumber numberWithInt:m_object->tableLevel()];
2291     
2292     if ([attributeName isEqualToString: NSAccessibilityLinkedUIElementsAttribute]) {
2293         AccessibilityObject::AccessibilityChildrenVector linkedUIElements;
2294         m_object->linkedUIElements(linkedUIElements);
2295         if (linkedUIElements.size() == 0)
2296             return nil;
2297         return convertToNSArray(linkedUIElements);
2298     }
2299
2300     if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
2301         return [NSNumber numberWithBool:m_object->isSelected()];
2302
2303     if ([attributeName isEqualToString: NSAccessibilityServesAsTitleForUIElementsAttribute] && m_object->isMenuButton()) {
2304         AccessibilityObject* uiElement = static_cast<AccessibilityRenderObject*>(m_object)->menuForMenuButton();
2305         if (uiElement)
2306             return [NSArray arrayWithObject:uiElement->wrapper()];
2307     }
2308
2309     if ([attributeName isEqualToString:NSAccessibilityTitleUIElementAttribute]) {
2310         if (!m_object->exposesTitleUIElement())
2311             return nil;
2312         
2313         AccessibilityObject* obj = m_object->titleUIElement();
2314         if (obj)
2315             return obj->wrapper();
2316         return nil;
2317     }
2318     
2319     if ([attributeName isEqualToString:NSAccessibilityValueDescriptionAttribute])
2320         return m_object->valueDescription();
2321     
2322     if ([attributeName isEqualToString:NSAccessibilityOrientationAttribute]) {
2323         AccessibilityOrientation elementOrientation = m_object->orientation();
2324         if (elementOrientation == AccessibilityOrientationVertical)
2325             return NSAccessibilityVerticalOrientationValue;
2326         if (elementOrientation == AccessibilityOrientationHorizontal)
2327             return NSAccessibilityHorizontalOrientationValue;
2328         return nil;
2329     }
2330     
2331     if ([attributeName isEqualToString:NSAccessibilityHorizontalScrollBarAttribute]) {
2332         AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationHorizontal);
2333         if (scrollBar)
2334             return scrollBar->wrapper();
2335         return nil;
2336     }
2337     if ([attributeName isEqualToString:NSAccessibilityVerticalScrollBarAttribute]) {
2338         AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationVertical);
2339         if (scrollBar)
2340             return scrollBar->wrapper();
2341         return nil;
2342     }
2343     
2344     if ([attributeName isEqualToString:NSAccessibilitySortDirectionAttribute]) {
2345         switch (m_object->sortDirection()) {
2346         case SortDirectionAscending:
2347             return NSAccessibilityAscendingSortDirectionValue;
2348         case SortDirectionDescending:
2349             return NSAccessibilityDescendingSortDirectionValue;
2350         default:
2351             return NSAccessibilityUnknownSortDirectionValue;
2352         }
2353     }
2354     
2355     if ([attributeName isEqualToString:NSAccessibilityLanguageAttribute]) 
2356         return m_object->language();
2357     
2358     if ([attributeName isEqualToString:NSAccessibilityExpandedAttribute])
2359         return [NSNumber numberWithBool:m_object->isExpanded()];
2360     
2361     if ([attributeName isEqualToString:NSAccessibilityRequiredAttribute])
2362         return [NSNumber numberWithBool:m_object->isRequired()];
2363
2364     if ([attributeName isEqualToString:NSAccessibilityInvalidAttribute])
2365         return m_object->invalidStatus();
2366     
2367     if ([attributeName isEqualToString:NSAccessibilityOwnsAttribute]) {
2368         AccessibilityObject::AccessibilityChildrenVector ariaOwns;
2369         m_object->ariaOwnsElements(ariaOwns);
2370         return convertToNSArray(ariaOwns);
2371     }
2372     
2373     if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
2374         return [NSNumber numberWithBool:m_object->isARIAGrabbed()];
2375     
2376     if ([attributeName isEqualToString:NSAccessibilityDropEffectsAttribute]) {
2377         Vector<String> dropEffects;
2378         m_object->determineARIADropEffects(dropEffects);
2379         size_t length = dropEffects.size();
2380
2381         NSMutableArray* dropEffectsArray = [NSMutableArray arrayWithCapacity:length];
2382         for (size_t i = 0; i < length; ++i)
2383             [dropEffectsArray addObject:dropEffects[i]];
2384         return dropEffectsArray;
2385     }
2386     
2387     if ([attributeName isEqualToString:NSAccessibilityPlaceholderValueAttribute])
2388         return m_object->placeholderValue();
2389     
2390     if ([attributeName isEqualToString:NSAccessibilityHasPopupAttribute])
2391         return [NSNumber numberWithBool:m_object->ariaHasPopup()];
2392     
2393     // ARIA Live region attributes.
2394     if ([attributeName isEqualToString:NSAccessibilityARIALiveAttribute])
2395         return m_object->ariaLiveRegionStatus();
2396     if ([attributeName isEqualToString:NSAccessibilityARIARelevantAttribute])
2397          return m_object->ariaLiveRegionRelevant();
2398     if ([attributeName isEqualToString:NSAccessibilityARIAAtomicAttribute])
2399         return [NSNumber numberWithBool:m_object->ariaLiveRegionAtomic()];
2400     if ([attributeName isEqualToString:NSAccessibilityARIABusyAttribute])
2401         return [NSNumber numberWithBool:m_object->ariaLiveRegionBusy()];
2402     
2403     // this is used only by DumpRenderTree for testing
2404     if ([attributeName isEqualToString:@"AXClickPoint"])
2405         return [NSValue valueWithPoint:m_object->clickPoint()];
2406     
2407     // This is used by DRT to verify CSS3 speech works.
2408     if ([attributeName isEqualToString:@"AXDRTSpeechAttribute"]) {
2409         ESpeak speakProperty = m_object->speakProperty();
2410         switch (speakProperty) {
2411         case SpeakNone:
2412             return @"none";
2413         case SpeakSpellOut:
2414             return @"spell-out";
2415         case SpeakDigits:
2416             return @"digits";
2417         case SpeakLiteralPunctuation:
2418             return @"literal-punctuation";
2419         case SpeakNoPunctuation:
2420             return @"no-punctuation";
2421         default:
2422         case SpeakNormal:
2423             return @"normal";
2424         }
2425     }
2426     
2427     return nil;
2428 }
2429
2430 - (id)accessibilityFocusedUIElement
2431 {
2432     if (![self updateObjectBackingStore])
2433         return nil;
2434
2435     RefPtr<AccessibilityObject> focusedObj = m_object->focusedUIElement();
2436
2437     if (!focusedObj)
2438         return nil;
2439     
2440     return focusedObj->wrapper();
2441 }
2442
2443 - (id)accessibilityHitTest:(NSPoint)point
2444 {
2445     if (![self updateObjectBackingStore])
2446         return nil;
2447
2448     m_object->updateChildrenIfNecessary();
2449     RefPtr<AccessibilityObject> axObject = m_object->accessibilityHitTest(IntPoint(point));
2450     if (axObject)
2451         return NSAccessibilityUnignoredAncestor(axObject->wrapper());
2452     return NSAccessibilityUnignoredAncestor(self);
2453 }
2454
2455 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName
2456 {
2457     if (![self updateObjectBackingStore])
2458         return nil;
2459
2460     if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
2461         return YES;
2462
2463     if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
2464         return m_object->canSetFocusAttribute();
2465
2466     if ([attributeName isEqualToString: NSAccessibilityValueAttribute])
2467         return m_object->canSetValueAttribute();
2468
2469     if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
2470         return m_object->canSetSelectedAttribute();
2471     
2472     if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute])
2473         return m_object->canSetSelectedChildrenAttribute();
2474
2475     if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
2476         return m_object->canSetExpandedAttribute();
2477
2478     if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute])
2479         return YES;
2480
2481     if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute] ||
2482         [attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute] ||
2483         [attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
2484         return m_object->canSetTextRangeAttributes();
2485     
2486     if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
2487         return YES;
2488     
2489     return NO;
2490 }
2491
2492 // accessibilityShouldUseUniqueId is an AppKit method we override so that
2493 // objects will be given a unique ID, and therefore allow AppKit to know when they
2494 // become obsolete (e.g. when the user navigates to a new web page, making this one
2495 // unrendered but not deallocated because it is in the back/forward cache).
2496 // It is important to call NSAccessibilityUnregisterUniqueIdForUIElement in the
2497 // appropriate place (e.g. dealloc) to remove these non-retained references from
2498 // AppKit's id mapping tables. We do this in detach by calling unregisterUniqueIdForUIElement.
2499 //
2500 // Registering an object is also required for observing notifications. Only registered objects can be observed.
2501 - (BOOL)accessibilityIsIgnored
2502 {
2503     if (![self updateObjectBackingStore])
2504         return YES;
2505
2506     if (m_object->isAttachment())
2507         return [[self attachmentView] accessibilityIsIgnored];
2508     return m_object->accessibilityIsIgnored();
2509 }
2510
2511 - (NSArray* )accessibilityParameterizedAttributeNames
2512 {
2513     if (![self updateObjectBackingStore])
2514         return nil;
2515
2516     if (m_object->isAttachment()) 
2517         return nil;
2518
2519     static NSArray* paramAttrs = nil;
2520     static NSArray* textParamAttrs = nil;
2521     static NSArray* tableParamAttrs = nil;
2522     static NSArray* webAreaParamAttrs = nil;
2523     if (paramAttrs == nil) {
2524         paramAttrs = [[NSArray alloc] initWithObjects:
2525                       @"AXUIElementForTextMarker",
2526                       @"AXTextMarkerRangeForUIElement",
2527                       @"AXLineForTextMarker",
2528                       @"AXTextMarkerRangeForLine",
2529                       @"AXStringForTextMarkerRange",
2530                       @"AXTextMarkerForPosition",
2531                       @"AXBoundsForTextMarkerRange",
2532                       @"AXAttributedStringForTextMarkerRange",
2533                       @"AXTextMarkerRangeForUnorderedTextMarkers",
2534                       @"AXNextTextMarkerForTextMarker",
2535                       @"AXPreviousTextMarkerForTextMarker",
2536                       @"AXLeftWordTextMarkerRangeForTextMarker",
2537                       @"AXRightWordTextMarkerRangeForTextMarker",
2538                       @"AXLeftLineTextMarkerRangeForTextMarker",
2539                       @"AXRightLineTextMarkerRangeForTextMarker",
2540                       @"AXSentenceTextMarkerRangeForTextMarker",
2541                       @"AXParagraphTextMarkerRangeForTextMarker",
2542                       @"AXNextWordEndTextMarkerForTextMarker",
2543                       @"AXPreviousWordStartTextMarkerForTextMarker",
2544                       @"AXNextLineEndTextMarkerForTextMarker",
2545                       @"AXPreviousLineStartTextMarkerForTextMarker",
2546                       @"AXNextSentenceEndTextMarkerForTextMarker",
2547                       @"AXPreviousSentenceStartTextMarkerForTextMarker",
2548                       @"AXNextParagraphEndTextMarkerForTextMarker",
2549                       @"AXPreviousParagraphStartTextMarkerForTextMarker",
2550                       @"AXStyleTextMarkerRangeForTextMarker",
2551                       @"AXLengthForTextMarkerRange",
2552                       NSAccessibilityBoundsForRangeParameterizedAttribute,
2553                       NSAccessibilityStringForRangeParameterizedAttribute,
2554                       NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute,
2555                       nil];
2556     }
2557
2558     if (textParamAttrs == nil) {
2559         NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
2560         [tempArray addObject:(NSString*)kAXLineForIndexParameterizedAttribute];
2561         [tempArray addObject:(NSString*)kAXRangeForLineParameterizedAttribute];
2562         [tempArray addObject:(NSString*)kAXStringForRangeParameterizedAttribute];
2563         [tempArray addObject:(NSString*)kAXRangeForPositionParameterizedAttribute];
2564         [tempArray addObject:(NSString*)kAXRangeForIndexParameterizedAttribute];
2565         [tempArray addObject:(NSString*)kAXBoundsForRangeParameterizedAttribute];
2566         [tempArray addObject:(NSString*)kAXRTFForRangeParameterizedAttribute];
2567         [tempArray addObject:(NSString*)kAXAttributedStringForRangeParameterizedAttribute];
2568         [tempArray addObject:(NSString*)kAXStyleRangeForIndexParameterizedAttribute];
2569         textParamAttrs = [[NSArray alloc] initWithArray:tempArray];
2570         [tempArray release];
2571     }
2572     if (tableParamAttrs == nil) {
2573         NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
2574         [tempArray addObject:NSAccessibilityCellForColumnAndRowParameterizedAttribute];
2575         tableParamAttrs = [[NSArray alloc] initWithArray:tempArray];
2576         [tempArray release];
2577     }
2578     if (!webAreaParamAttrs) {
2579         NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
2580         [tempArray addObject:NSAccessibilityTextMarkerForIndexParameterizedAttribute];
2581         [tempArray addObject:NSAccessibilityTextMarkerIsValidParameterizedAttribute];
2582         [tempArray addObject:NSAccessibilityIndexForTextMarkerParameterizedAttribute];
2583         webAreaParamAttrs = [[NSArray alloc] initWithArray:tempArray];
2584         [tempArray release];
2585     }
2586     
2587     if (m_object->isPasswordField())
2588         return [NSArray array];
2589     
2590     if (!m_object->isAccessibilityRenderObject())
2591         return paramAttrs;
2592
2593     if (m_object->isTextControl())
2594         return textParamAttrs;
2595     
2596     if (m_object->isAccessibilityTable())
2597         return tableParamAttrs;
2598     
2599     if (m_object->isMenuRelated())
2600         return nil;
2601
2602     if (m_object->isWebArea())
2603         return webAreaParamAttrs;
2604     
2605     return paramAttrs;
2606 }
2607
2608 - (void)accessibilityPerformPressAction
2609 {
2610     if (![self updateObjectBackingStore])
2611         return;
2612
2613     if (m_object->isAttachment())
2614         [[self attachmentView] accessibilityPerformAction:NSAccessibilityPressAction];
2615     else
2616         m_object->press();    
2617 }
2618
2619 - (void)accessibilityPerformIncrementAction
2620 {
2621     if (![self updateObjectBackingStore])
2622         return;
2623
2624     if (m_object->isAttachment())
2625         [[self attachmentView] accessibilityPerformAction:NSAccessibilityIncrementAction];
2626     else
2627         m_object->increment();    
2628 }
2629
2630 - (void)accessibilityPerformDecrementAction
2631 {
2632     if (![self updateObjectBackingStore])
2633         return;
2634
2635     if (m_object->isAttachment())
2636         [[self attachmentView] accessibilityPerformAction:NSAccessibilityDecrementAction];
2637     else
2638         m_object->decrement();    
2639 }
2640
2641 - (void)accessibilityPerformShowMenuAction
2642 {
2643     if (m_object->roleValue() == ComboBoxRole)
2644         m_object->setIsExpanded(true);
2645     else {
2646         // This needs to be performed in an iteration of the run loop that did not start from an AX call. 
2647         // If it's the same run loop iteration, the menu open notification won't be sent
2648         [self performSelector:@selector(accessibilityShowContextMenu) withObject:nil afterDelay:0.0];
2649     }
2650 }
2651
2652 - (void)accessibilityShowContextMenu
2653 {    
2654     FrameView* frameView = m_object->documentFrameView();
2655     if (!frameView)
2656         return;
2657     Frame* frame = frameView->frame();
2658     if (!frame)
2659         return;
2660     Page* page = frame->page();
2661     if (!page)
2662         return;
2663     page->contextMenuController()->showContextMenuAt(frame, m_object->clickPoint());
2664 }
2665
2666 - (void)accessibilityPerformAction:(NSString*)action
2667 {
2668     if (![self updateObjectBackingStore])
2669         return;
2670
2671     if ([action isEqualToString:NSAccessibilityPressAction])
2672         [self accessibilityPerformPressAction];
2673     
2674     else if ([action isEqualToString:NSAccessibilityShowMenuAction])
2675         [self accessibilityPerformShowMenuAction];
2676
2677     else if ([action isEqualToString:NSAccessibilityIncrementAction])
2678         [self accessibilityPerformIncrementAction];
2679
2680     else if ([action isEqualToString:NSAccessibilityDecrementAction])
2681         [self accessibilityPerformDecrementAction];
2682 }
2683
2684 - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attributeName
2685 {
2686     if (![self updateObjectBackingStore])
2687         return;
2688
2689     id textMarkerRange = nil;
2690     NSNumber*               number = nil;
2691     NSString*               string = nil;
2692     NSRange                 range = {0, 0};
2693     NSArray*                array = nil;
2694     
2695     // decode the parameter
2696     if (AXObjectIsTextMarkerRange(value))
2697         textMarkerRange = value;
2698
2699     else if ([value isKindOfClass:[NSNumber self]])
2700         number = value;
2701
2702     else if ([value isKindOfClass:[NSString self]])
2703         string = value;
2704     
2705     else if ([value isKindOfClass:[NSValue self]])
2706         range = [value rangeValue];
2707     
2708     else if ([value isKindOfClass:[NSArray self]])
2709         array = value;
2710     
2711     // handle the command
2712     if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"]) {
2713         ASSERT(textMarkerRange);
2714         m_object->setSelectedVisiblePositionRange([self visiblePositionRangeForTextMarkerRange:textMarkerRange]);        
2715     } else if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute]) {
2716         ASSERT(number);
2717         m_object->setFocused([number intValue] != 0);
2718     } else if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
2719         if (number && m_object->canSetNumericValue())
2720             m_object->setValue([number floatValue]);
2721         else if (string)
2722             m_object->setValue(string);
2723     } else if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute]) {
2724         if (!number)
2725             return;
2726         m_object->setSelected([number boolValue]);
2727     } else if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {
2728         if (!array || m_object->roleValue() != ListBoxRole)
2729             return;
2730         AccessibilityObject::AccessibilityChildrenVector selectedChildren;
2731         convertToVector(array, selectedChildren);
2732         static_cast<AccessibilityListBox*>(m_object)->setSelectedChildren(selectedChildren);
2733     } else if (m_object->isTextControl()) {
2734         if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
2735             m_object->setSelectedText(string);
2736         } else if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
2737             m_object->setSelectedTextRange(PlainTextRange(range.location, range.length));
2738         } else if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute]) {
2739             m_object->makeRangeVisible(PlainTextRange(range.location, range.length));
2740         }
2741     } else if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
2742         m_object->setIsExpanded([number boolValue]);
2743     else if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2744         AccessibilityObject::AccessibilityChildrenVector selectedRows;
2745         convertToVector(array, selectedRows);
2746         if (m_object->isTree() || m_object->isAccessibilityTable())
2747             m_object->setSelectedRows(selectedRows);
2748     } else if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
2749         m_object->setARIAGrabbed([number boolValue]);
2750 }
2751
2752 static RenderObject* rendererForView(NSView* view)
2753 {
2754     if (![view conformsToProtocol:@protocol(WebCoreFrameView)])
2755         return 0;
2756
2757     NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view;
2758     Frame* frame = [frameView _web_frame];
2759     if (!frame)
2760         return 0;
2761
2762     Node* node = frame->document()->ownerElement();
2763     if (!node)
2764         return 0;
2765
2766     return node->renderer();
2767 }
2768
2769 - (id)_accessibilityParentForSubview:(NSView*)subview
2770 {   
2771     RenderObject* renderer = rendererForView(subview);
2772     if (!renderer)
2773         return nil;
2774
2775     AccessibilityObject* obj = renderer->document()->axObjectCache()->getOrCreate(renderer);
2776     if (obj)
2777         return obj->parentObjectUnignored()->wrapper();
2778     return nil;
2779 }
2780
2781 - (NSString*)accessibilityActionDescription:(NSString*)action
2782 {
2783     // we have no custom actions
2784     return NSAccessibilityActionDescription(action);
2785 }
2786
2787 // The CFAttributedStringType representation of the text associated with this accessibility
2788 // object that is specified by the given range.
2789 - (NSAttributedString*)doAXAttributedStringForRange:(NSRange)range
2790 {
2791     PlainTextRange textRange = PlainTextRange(range.location, range.length);
2792     VisiblePositionRange visiblePosRange = m_object->visiblePositionRangeForRange(textRange);
2793     return [self doAXAttributedStringForTextMarkerRange:[self textMarkerRangeFromVisiblePositions:visiblePosRange.start endPosition:visiblePosRange.end]];
2794 }
2795
2796 - (NSRange)_convertToNSRange:(Range*)range
2797 {
2798     NSRange result = NSMakeRange(NSNotFound, 0);
2799     if (!range || !range->startContainer())
2800         return result;
2801
2802     Document* document = m_object->document();
2803     if (!document)
2804         return result;
2805
2806     size_t location;
2807     size_t length;
2808     TextIterator::getLocationAndLengthFromRange(document->documentElement(), range, location, length);
2809     result.location = location;
2810     result.length = length;
2811
2812     return result;
2813 }
2814
2815 - (NSInteger)_indexForTextMarker:(id)marker
2816 {
2817     if (!marker)
2818         return NSNotFound;
2819     
2820     VisibleSelection selection([self visiblePositionForTextMarker:marker]);    
2821     return [self _convertToNSRange:selection.toNormalizedRange().get()].location;
2822 }
2823
2824 - (id)_textMarkerForIndex:(NSInteger)textIndex
2825 {
2826     Document* document = m_object->document();
2827     if (!document)
2828         return nil;
2829     
2830     PassRefPtr<Range> textRange = TextIterator::rangeFromLocationAndLength(document->documentElement(), textIndex, 0);
2831     if (!textRange || !textRange->boundaryPointsValid())
2832         return nil;
2833
2834     VisiblePosition position(textRange->startPosition());
2835     return [self textMarkerForVisiblePosition:position];
2836 }
2837
2838 // The RTF representation of the text associated with this accessibility object that is
2839 // specified by the given range.
2840 - (NSData*)doAXRTFForRange:(NSRange)range
2841 {
2842     NSAttributedString* attrString = [self doAXAttributedStringForRange:range];
2843     return [attrString RTFFromRange: NSMakeRange(0, [attrString length]) documentAttributes: nil];
2844 }
2845
2846 - (id)accessibilityAttributeValue:(NSString*)attribute forParameter:(id)parameter
2847 {
2848     id textMarker = nil;
2849     id textMarkerRange = nil;
2850     NSNumber* number = nil;
2851     NSArray* array = nil;
2852     NSDictionary* dictionary = nil;
2853     RefPtr<AccessibilityObject> uiElement = 0;
2854     NSPoint point = NSZeroPoint;
2855     bool pointSet = false;
2856     NSRange range = {0, 0};
2857     bool rangeSet = false;
2858     
2859     // basic parameter validation
2860     if (!m_object || !attribute || !parameter)
2861         return nil;
2862
2863     if (![self updateObjectBackingStore])
2864         return nil;
2865     
2866     // common parameter type check/casting.  Nil checks in handlers catch wrong type case.
2867     // NOTE: This assumes nil is not a valid parameter, because it is indistinguishable from
2868     // a parameter of the wrong type.
2869     if (AXObjectIsTextMarker(parameter))
2870         textMarker = parameter;
2871
2872     else if (AXObjectIsTextMarkerRange(parameter))
2873         textMarkerRange = parameter;
2874
2875     else if ([parameter isKindOfClass:[WebAccessibilityObjectWrapper self]])
2876         uiElement = [(WebAccessibilityObjectWrapper*)parameter accessibilityObject];
2877
2878     else if ([parameter isKindOfClass:[NSNumber self]])
2879         number = parameter;
2880
2881     else if ([parameter isKindOfClass:[NSArray self]])
2882         array = parameter;
2883
2884     else if ([parameter isKindOfClass:[NSDictionary self]])
2885         dictionary = parameter;
2886
2887     else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSPoint)) == 0) {
2888         pointSet = true;
2889         point = [(NSValue*)parameter pointValue];
2890
2891     } else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSRange)) == 0) {
2892         rangeSet = true;
2893         range = [(NSValue*)parameter rangeValue];
2894     } else {
2895         // Attribute type is not supported. Allow super to handle.
2896         return [super accessibilityAttributeValue:attribute forParameter:parameter];
2897     }
2898     
2899     // dispatch
2900     if ([attribute isEqualToString:NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute]) {
2901         AccessibilityObject* startObject = 0;
2902         if ([[dictionary objectForKey:@"AXStartElement"] isKindOfClass:[WebAccessibilityObjectWrapper self]])
2903             startObject = [(WebAccessibilityObjectWrapper*)[dictionary objectForKey:@"AXStartElement"] accessibilityObject];
2904         
2905         AccessibilitySearchDirection searchDirection = SearchDirectionNext;
2906         if ([[dictionary objectForKey:@"AXDirection"] isKindOfClass:[NSString self]])
2907             searchDirection = ([(NSString*)[dictionary objectForKey:@"AXDirection"] isEqualToString:@"AXDirectionNext"]) ? SearchDirectionNext : SearchDirectionPrevious;
2908         
2909         AccessibilitySearchKey searchKey = AnyTypeSearchKey;
2910         if ([[dictionary objectForKey:@"AXSearchKey"] isKindOfClass:[NSString self]])
2911             searchKey = accessibilitySearchKeyForString((CFStringRef)[dictionary objectForKey:@"AXSearchKey"]);
2912         
2913         String searchText;
2914         if ([[dictionary objectForKey:@"AXSearchText"] isKindOfClass:[NSString self]])
2915             searchText = (CFStringRef)[dictionary objectForKey:@"AXSearchText"];
2916         
2917         unsigned resultsLimit = 0;
2918         if ([[dictionary objectForKey:@"AXResultsLimit"] isKindOfClass:[NSNumber self]])
2919             resultsLimit = [(NSNumber*)[dictionary objectForKey:@"AXResultsLimit"] unsignedIntValue];
2920         
2921         AccessibilitySearchCriteria criteria = {startObject, searchDirection, searchKey, &searchText, resultsLimit};
2922
2923         AccessibilityObject::AccessibilityChildrenVector results;
2924         m_object->findMatchingObjects(&criteria, results);
2925         
2926         return convertToNSArray(results);
2927     }
2928
2929     if ([attribute isEqualToString:NSAccessibilityTextMarkerIsValidParameterizedAttribute]) {
2930         VisiblePosition pos = [self visiblePositionForTextMarker:textMarker];
2931         return [NSNumber numberWithBool:!pos.isNull()];
2932     }
2933     if ([attribute isEqualToString:NSAccessibilityIndexForTextMarkerParameterizedAttribute]) {
2934         return [NSNumber numberWithInteger:[self _indexForTextMarker:textMarker]];
2935     }
2936     if ([attribute isEqualToString:NSAccessibilityTextMarkerForIndexParameterizedAttribute]) {
2937         return [self _textMarkerForIndex:[number integerValue]];
2938     }
2939     
2940     if ([attribute isEqualToString:@"AXUIElementForTextMarker"]) {
2941         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2942         AccessibilityObject* axObject = m_object->accessibilityObjectForPosition(visiblePos);
2943         if (!axObject)
2944             return nil;
2945         return axObject->wrapper();
2946     }
2947
2948     if ([attribute isEqualToString:@"AXTextMarkerRangeForUIElement"]) {
2949         VisiblePositionRange vpRange = uiElement.get()->visiblePositionRange();
2950         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
2951     }
2952
2953     if ([attribute isEqualToString:@"AXLineForTextMarker"]) {
2954         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2955         return [NSNumber numberWithUnsignedInt:m_object->lineForPosition(visiblePos)];
2956     }
2957
2958     if ([attribute isEqualToString:@"AXTextMarkerRangeForLine"]) {
2959         VisiblePositionRange vpRange = m_object->visiblePositionRangeForLine([number intValue]);
2960         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
2961     }
2962
2963     if ([attribute isEqualToString:@"AXStringForTextMarkerRange"]) {
2964         VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
2965         return m_object->stringForVisiblePositionRange(visiblePosRange);
2966     }
2967
2968     if ([attribute isEqualToString:@"AXTextMarkerForPosition"]) {
2969         IntPoint webCorePoint = IntPoint(point);
2970         return pointSet ? [self textMarkerForVisiblePosition:m_object->visiblePositionForPoint(webCorePoint)] : nil;
2971     }
2972
2973     if ([attribute isEqualToString:@"AXBoundsForTextMarkerRange"]) {
2974         VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
2975         NSRect rect = m_object->boundsForVisiblePositionRange(visiblePosRange);
2976         return [NSValue valueWithRect:rect];
2977     }
2978     
2979     if ([attribute isEqualToString:NSAccessibilityBoundsForRangeParameterizedAttribute]) {
2980         VisiblePosition start = m_object->visiblePositionForIndex(range.location);
2981         VisiblePosition end = m_object->visiblePositionForIndex(range.location+range.length);
2982         if (start.isNull() || end.isNull())
2983             return nil;
2984         NSRect rect = m_object->boundsForVisiblePositionRange(VisiblePositionRange(start, end));
2985         return [NSValue valueWithRect:rect];
2986     }
2987     
2988     if ([attribute isEqualToString:NSAccessibilityStringForRangeParameterizedAttribute]) {
2989         VisiblePosition start = m_object->visiblePositionForIndex(range.location);
2990         VisiblePosition end = m_object->visiblePositionForIndex(range.location+range.length);
2991         if (start.isNull() || end.isNull())
2992             return nil;
2993         return m_object->stringForVisiblePositionRange(VisiblePositionRange(start, end));
2994     }
2995
2996     if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"])
2997         return [self doAXAttributedStringForTextMarkerRange:textMarkerRange];
2998
2999     if ([attribute isEqualToString:@"AXTextMarkerRangeForUnorderedTextMarkers"]) {
3000         if ([array count] < 2)
3001             return nil;
3002
3003         id textMarker1 = [array objectAtIndex:0];
3004         id textMarker2 = [array objectAtIndex:1];
3005         if (!AXObjectIsTextMarker(textMarker1) || !AXObjectIsTextMarker(textMarker2))
3006             return nil;
3007
3008         VisiblePosition visiblePos1 = [self visiblePositionForTextMarker:(textMarker1)];
3009         VisiblePosition visiblePos2 = [self visiblePositionForTextMarker:(textMarker2)];
3010         VisiblePositionRange vpRange = m_object->visiblePositionRangeForUnorderedPositions(visiblePos1, visiblePos2);
3011         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3012     }
3013
3014     if ([attribute isEqualToString:@"AXNextTextMarkerForTextMarker"]) {
3015         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3016         return [self textMarkerForVisiblePosition:m_object->nextVisiblePosition(visiblePos)];
3017     }
3018
3019     if ([attribute isEqualToString:@"AXPreviousTextMarkerForTextMarker"]) {
3020         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3021         return [self textMarkerForVisiblePosition:m_object->previousVisiblePosition(visiblePos)];
3022     }
3023
3024     if ([attribute isEqualToString:@"AXLeftWordTextMarkerRangeForTextMarker"]) {
3025         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3026         VisiblePositionRange vpRange = m_object->positionOfLeftWord(visiblePos);
3027         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3028     }
3029
3030     if ([attribute isEqualToString:@"AXRightWordTextMarkerRangeForTextMarker"]) {
3031         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3032         VisiblePositionRange vpRange = m_object->positionOfRightWord(visiblePos);
3033         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3034     }
3035
3036     if ([attribute isEqualToString:@"AXLeftLineTextMarkerRangeForTextMarker"]) {
3037         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3038         VisiblePositionRange vpRange = m_object->leftLineVisiblePositionRange(visiblePos);
3039         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3040     }
3041
3042     if ([attribute isEqualToString:@"AXRightLineTextMarkerRangeForTextMarker"]) {
3043         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3044         VisiblePositionRange vpRange = m_object->rightLineVisiblePositionRange(visiblePos);
3045         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3046     }
3047
3048     if ([attribute isEqualToString:@"AXSentenceTextMarkerRangeForTextMarker"]) {
3049         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3050         VisiblePositionRange vpRange = m_object->sentenceForPosition(visiblePos);
3051         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3052     }
3053
3054     if ([attribute isEqualToString:@"AXParagraphTextMarkerRangeForTextMarker"]) {
3055         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3056         VisiblePositionRange vpRange = m_object->paragraphForPosition(visiblePos);
3057         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3058     }
3059
3060     if ([attribute isEqualToString:@"AXNextWordEndTextMarkerForTextMarker"]) {
3061         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3062         return [self textMarkerForVisiblePosition:m_object->nextWordEnd(visiblePos)];
3063     }
3064     
3065     if ([attribute isEqualToString:@"AXPreviousWordStartTextMarkerForTextMarker"]) {
3066         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3067         return [self textMarkerForVisiblePosition:m_object->previousWordStart(visiblePos)];
3068     }
3069
3070     if ([attribute isEqualToString:@"AXNextLineEndTextMarkerForTextMarker"]) {
3071         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3072         return [self textMarkerForVisiblePosition:m_object->nextLineEndPosition(visiblePos)];
3073     }
3074
3075     if ([attribute isEqualToString:@"AXPreviousLineStartTextMarkerForTextMarker"]) {
3076         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3077         return [self textMarkerForVisiblePosition:m_object->previousLineStartPosition(visiblePos)];
3078     }
3079
3080     if ([attribute isEqualToString:@"AXNextSentenceEndTextMarkerForTextMarker"]) {
3081         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3082         return [self textMarkerForVisiblePosition:m_object->nextSentenceEndPosition(visiblePos)];
3083     }
3084
3085     if ([attribute isEqualToString:@"AXPreviousSentenceStartTextMarkerForTextMarker"]) {
3086         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3087         return [self textMarkerForVisiblePosition:m_object->previousSentenceStartPosition(visiblePos)];
3088     }
3089