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