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