WebCore/accessibility/mac/AccessibilityObjectWrapper.mm
changeset 0 4f2f89ce4247
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm	Fri Sep 17 09:02:29 2010 +0300
@@ -0,0 +1,2710 @@
+/*
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "AccessibilityObjectWrapper.h"
+
+#if HAVE(ACCESSIBILITY)
+
+#import "AXObjectCache.h"
+#import "AccessibilityARIAGridRow.h"
+#import "AccessibilityListBox.h"
+#import "AccessibilityList.h"
+#import "AccessibilityRenderObject.h"
+#import "AccessibilityTable.h"
+#import "AccessibilityTableCell.h"
+#import "AccessibilityTableRow.h"
+#import "AccessibilityTableColumn.h"
+#import "ColorMac.h"
+#import "Frame.h"
+#import "HTMLAnchorElement.h"
+#import "HTMLAreaElement.h"
+#import "HTMLFrameOwnerElement.h"
+#import "HTMLImageElement.h"
+#import "HTMLInputElement.h"
+#import "HTMLTextAreaElement.h"
+#import "LocalizedStrings.h"
+#import "RenderTextControl.h"
+#import "RenderView.h"
+#import "RenderWidget.h"
+#import "SelectionController.h"
+#import "SimpleFontData.h"
+#import "TextIterator.h"
+#import "WebCoreFrameView.h"
+#import "WebCoreObjCExtras.h"
+#import "WebCoreViewFactory.h"
+#import "htmlediting.h"
+#import "visible_units.h"
+
+using namespace WebCore;
+using namespace HTMLNames;
+using namespace std;
+
+// Cell Tables
+#ifndef NSAccessibilitySelectedCellsAttribute
+#define NSAccessibilitySelectedCellsAttribute @"AXSelectedCells"
+#endif
+
+#ifndef NSAccessibilityVisibleCellsAttribute
+#define NSAccessibilityVisibleCellsAttribute @"AXVisibleCells"
+#endif
+
+#ifndef NSAccessibilityRowHeaderUIElementsAttribute
+#define NSAccessibilityRowHeaderUIElementsAttribute @"AXRowHeaderUIElements"
+#endif
+
+#ifndef NSAccessibilityRowIndexRangeAttribute
+#define NSAccessibilityRowIndexRangeAttribute @"AXRowIndexRange"
+#endif
+
+#ifndef NSAccessibilityColumnIndexRangeAttribute
+#define NSAccessibilityColumnIndexRangeAttribute @"AXColumnIndexRange"
+#endif
+
+#ifndef NSAccessibilityCellForColumnAndRowParameterizedAttribute
+#define NSAccessibilityCellForColumnAndRowParameterizedAttribute @"AXCellForColumnAndRow"
+#endif
+
+#ifndef NSAccessibilityCellRole
+#define NSAccessibilityCellRole @"AXCell"
+#endif
+
+// Lists
+#ifndef NSAccessibilityContentListSubrole
+#define NSAccessibilityContentListSubrole @"AXContentList"
+#endif
+
+#ifndef NSAccessibilityDefinitionListSubrole
+#define NSAccessibilityDefinitionListSubrole @"AXDefinitionList"
+#endif
+
+// Miscellaneous
+#ifndef NSAccessibilityBlockQuoteLevelAttribute
+#define NSAccessibilityBlockQuoteLevelAttribute @"AXBlockQuoteLevel"
+#endif
+
+#ifndef NSAccessibilityAccessKeyAttribute
+#define NSAccessibilityAccessKeyAttribute @"AXAccessKey"
+#endif
+
+#ifndef NSAccessibilityLanguageAttribute
+#define NSAccessibilityLanguageAttribute @"AXLanguage"
+#endif
+
+#ifndef NSAccessibilityRequiredAttribute
+#define NSAccessibilityRequiredAttribute @"AXRequired"
+#endif
+
+#ifndef NSAccessibilityOwnsAttribute
+#define NSAccessibilityOwnsAttribute @"AXOwns"
+#endif
+
+#ifndef NSAccessibilityGrabbedAttribute
+#define NSAccessibilityGrabbedAttribute @"AXGrabbed"
+#endif
+
+#ifndef NSAccessibilityDropEffectsAttribute
+#define NSAccessibilityDropEffectsAttribute @"AXDropEffects"
+#endif
+
+#ifndef NSAccessibilityARIALiveAttribute
+#define NSAccessibilityARIALiveAttribute @"AXARIALive"
+#endif
+
+#ifndef NSAccessibilityARIAAtomicAttribute
+#define NSAccessibilityARIAAtomicAttribute @"AXARIAAtomic"
+#endif
+
+#ifndef NSAccessibilityARIARelevantAttribute
+#define NSAccessibilityARIARelevantAttribute @"AXARIARelevant"
+#endif
+
+#ifndef NSAccessibilityARIABusyAttribute
+#define NSAccessibilityARIABusyAttribute @"AXARIABusy"
+#endif
+
+#ifndef NSAccessibilityLoadingProgressAttribute
+#define NSAccessibilityLoadingProgressAttribute @"AXLoadingProgress"
+#endif
+
+#ifndef NSAccessibilityHasPopupAttribute
+#define NSAccessibilityHasPopupAttribute @"AXHasPopup"
+#endif
+
+#ifdef BUILDING_ON_TIGER
+typedef unsigned NSUInteger;
+#define NSAccessibilityValueDescriptionAttribute @"AXValueDescription"
+#define NSAccessibilityTimelineSubrole @"AXTimeline"
+#endif
+
+@interface NSObject (WebKitAccessibilityArrayCategory)
+
+- (NSUInteger)accessibilityIndexOfChild:(id)child;
+- (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute;
+- (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount;
+
+@end
+
+@implementation AccessibilityObjectWrapper
+
+- (id)initWithAccessibilityObject:(AccessibilityObject*)axObject
+{
+    [super init];
+
+    m_object = axObject;
+    return self;
+}
+
+- (void)unregisterUniqueIdForUIElement
+{
+    [[WebCoreViewFactory sharedFactory] unregisterUniqueIdForUIElement:self];
+}
+
+- (void)detach
+{
+    // Send unregisterUniqueIdForUIElement unconditionally because if it is
+    // ever accidentally not done (via other bugs in our AX implementation) you
+    // end up with a crash like <rdar://problem/4273149>.  It is safe and not
+    // expensive to send even if the object is not registered.
+    [self unregisterUniqueIdForUIElement];
+    m_object = 0;
+}
+
+- (AccessibilityObject*)accessibilityObject
+{
+    return m_object;
+}
+
+- (NSView*)attachmentView
+{
+    ASSERT(m_object->isAttachment());
+    Widget* widget = m_object->widgetForAttachmentView();
+    if (!widget)
+        return nil;
+    return NSAccessibilityUnignoredDescendant(widget->platformWidget());
+}
+
+static WebCoreTextMarker* textMarkerForVisiblePosition(const VisiblePosition& visiblePos)
+{
+    TextMarkerData textMarkerData;
+    AXObjectCache::textMarkerDataForVisiblePosition(textMarkerData, visiblePos);
+    if (!textMarkerData.axID)
+        return nil;
+    
+    return [[WebCoreViewFactory sharedFactory] textMarkerWithBytes:&textMarkerData length:sizeof(textMarkerData)];
+}
+
+static VisiblePosition visiblePositionForTextMarker(WebCoreTextMarker* textMarker)
+{
+    if (!textMarker)
+        return VisiblePosition();
+    TextMarkerData textMarkerData;
+    if (![[WebCoreViewFactory sharedFactory] getBytes:&textMarkerData fromTextMarker:textMarker length:sizeof(textMarkerData)])
+        return VisiblePosition();
+    
+    return AXObjectCache::visiblePositionForTextMarkerData(textMarkerData);
+}
+
+static VisiblePosition visiblePositionForStartOfTextMarkerRange(WebCoreTextMarkerRange* textMarkerRange)
+{
+    return visiblePositionForTextMarker([[WebCoreViewFactory sharedFactory] startOfTextMarkerRange:textMarkerRange]);
+}
+
+static VisiblePosition visiblePositionForEndOfTextMarkerRange(WebCoreTextMarkerRange* textMarkerRange)
+{
+    return visiblePositionForTextMarker([[WebCoreViewFactory sharedFactory] endOfTextMarkerRange:textMarkerRange]);
+}
+
+static WebCoreTextMarkerRange* textMarkerRangeFromMarkers(WebCoreTextMarker* textMarker1, WebCoreTextMarker* textMarker2)
+{
+    if (!textMarker1 || !textMarker2)
+        return nil;
+        
+    return [[WebCoreViewFactory sharedFactory] textMarkerRangeWithStart:textMarker1 end:textMarker2];
+}
+
+static void AXAttributeStringSetFont(NSMutableAttributedString* attrString, NSString* attribute, NSFont* font, NSRange range)
+{
+    NSDictionary* dict;
+    
+    if (font) {
+        dict = [NSDictionary dictionaryWithObjectsAndKeys:
+            [font fontName]                             , NSAccessibilityFontNameKey,
+            [font familyName]                           , NSAccessibilityFontFamilyKey,
+            [font displayName]                          , NSAccessibilityVisibleNameKey,
+            [NSNumber numberWithFloat:[font pointSize]] , NSAccessibilityFontSizeKey,
+        nil];
+
+        [attrString addAttribute:attribute value:dict range:range];
+    } else
+        [attrString removeAttribute:attribute range:range];
+    
+}
+
+static CGColorRef CreateCGColorIfDifferent(NSColor* nsColor, CGColorRef existingColor)
+{
+    // get color information assuming NSDeviceRGBColorSpace 
+    NSColor* rgbColor = [nsColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+    if (rgbColor == nil)
+        rgbColor = [NSColor blackColor];
+    CGFloat components[4];
+    [rgbColor getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]];
+    
+    // create a new CGColorRef to return
+    CGColorSpaceRef cgColorSpace = CGColorSpaceCreateDeviceRGB();
+    CGColorRef cgColor = CGColorCreate(cgColorSpace, components);
+    CGColorSpaceRelease(cgColorSpace);
+    
+    // check for match with existing color
+    if (existingColor && CGColorEqualToColor(cgColor, existingColor)) {
+        CGColorRelease(cgColor);
+        cgColor = 0;
+    }
+    
+    return cgColor;
+}
+
+static void AXAttributeStringSetColor(NSMutableAttributedString* attrString, NSString* attribute, NSColor* color, NSRange range)
+{
+    if (color) {
+        CGColorRef existingColor = (CGColorRef) [attrString attribute:attribute atIndex:range.location effectiveRange:nil];
+        CGColorRef cgColor = CreateCGColorIfDifferent(color, existingColor);
+        if (cgColor) {
+            [attrString addAttribute:attribute value:(id)cgColor range:range];
+            CGColorRelease(cgColor);
+        }
+    } else
+        [attrString removeAttribute:attribute range:range];
+}
+
+static void AXAttributeStringSetNumber(NSMutableAttributedString* attrString, NSString* attribute, NSNumber* number, NSRange range)
+{
+    if (number)
+        [attrString addAttribute:attribute value:number range:range];
+    else
+        [attrString removeAttribute:attribute range:range];
+}
+
+static void AXAttributeStringSetStyle(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
+{
+    RenderStyle* style = renderer->style();
+
+    // set basic font info
+    AXAttributeStringSetFont(attrString, NSAccessibilityFontTextAttribute, style->font().primaryFont()->getNSFont(), range);
+
+    // set basic colors
+    AXAttributeStringSetColor(attrString, NSAccessibilityForegroundColorTextAttribute, nsColor(style->visitedDependentColor(CSSPropertyColor)), range);
+    AXAttributeStringSetColor(attrString, NSAccessibilityBackgroundColorTextAttribute, nsColor(style->visitedDependentColor(CSSPropertyBackgroundColor)), range);
+
+    // set super/sub scripting
+    EVerticalAlign alignment = style->verticalAlign();
+    if (alignment == SUB)
+        AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:(-1)], range);
+    else if (alignment == SUPER)
+        AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:1], range);
+    else
+        [attrString removeAttribute:NSAccessibilitySuperscriptTextAttribute range:range];
+    
+    // set shadow
+    if (style->textShadow())
+        AXAttributeStringSetNumber(attrString, NSAccessibilityShadowTextAttribute, [NSNumber numberWithBool:YES], range);
+    else
+        [attrString removeAttribute:NSAccessibilityShadowTextAttribute range:range];
+    
+    // set underline and strikethrough
+    int decor = style->textDecorationsInEffect();
+    if ((decor & UNDERLINE) == 0) {
+        [attrString removeAttribute:NSAccessibilityUnderlineTextAttribute range:range];
+        [attrString removeAttribute:NSAccessibilityUnderlineColorTextAttribute range:range];
+    }
+    
+    if ((decor & LINE_THROUGH) == 0) {
+        [attrString removeAttribute:NSAccessibilityStrikethroughTextAttribute range:range];
+        [attrString removeAttribute:NSAccessibilityStrikethroughColorTextAttribute range:range];
+    }
+
+    if ((decor & (UNDERLINE | LINE_THROUGH)) != 0) {
+        // find colors using quirk mode approach (strict mode would use current
+        // color for all but the root line box, which would use getTextDecorationColors)
+        Color underline, overline, linethrough;
+        renderer->getTextDecorationColors(decor, underline, overline, linethrough);
+        
+        if ((decor & UNDERLINE) != 0) {
+            AXAttributeStringSetNumber(attrString, NSAccessibilityUnderlineTextAttribute, [NSNumber numberWithBool:YES], range);
+            AXAttributeStringSetColor(attrString, NSAccessibilityUnderlineColorTextAttribute, nsColor(underline), range);
+        }
+
+        if ((decor & LINE_THROUGH) != 0) {
+            AXAttributeStringSetNumber(attrString, NSAccessibilityStrikethroughTextAttribute, [NSNumber numberWithBool:YES], range);
+            AXAttributeStringSetColor(attrString, NSAccessibilityStrikethroughColorTextAttribute, nsColor(linethrough), range);
+        }
+    }
+}
+
+static int blockquoteLevel(RenderObject* renderer)
+{
+    if (!renderer)
+        return 0;
+    
+    int result = 0;
+    for (Node* node = renderer->node(); node; node = node->parent()) {
+        if (node->hasTagName(blockquoteTag))
+            result += 1;
+    }
+    
+    return result;
+}
+
+static void AXAttributeStringSetBlockquoteLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
+{
+    int quoteLevel = blockquoteLevel(renderer);
+    
+    if (quoteLevel)
+        [attrString addAttribute:NSAccessibilityBlockQuoteLevelAttribute value:[NSNumber numberWithInt:quoteLevel] range:range];
+    else
+        [attrString removeAttribute:NSAccessibilityBlockQuoteLevelAttribute range:range];
+}
+
+static void AXAttributeStringSetSpelling(NSMutableAttributedString* attrString, Node* node, int offset, NSRange range)
+{
+    Vector<DocumentMarker> markers = node->renderer()->document()->markersForNode(node);
+    Vector<DocumentMarker>::iterator markerIt = markers.begin();
+
+    unsigned endOffset = (unsigned)offset + range.length;
+    for ( ; markerIt != markers.end(); markerIt++) {
+        DocumentMarker marker = *markerIt;
+        
+        if (marker.type != DocumentMarker::Spelling)
+            continue;
+        
+        if (marker.endOffset <= (unsigned)offset)
+            continue;
+        
+        if (marker.startOffset > endOffset)
+            break;
+        
+        // add misspelling attribute for the intersection of the marker and the range
+        int rStart = range.location + (marker.startOffset - offset);
+        int rLength = min(marker.endOffset, endOffset) - marker.startOffset;
+        NSRange spellRange = NSMakeRange(rStart, rLength);
+        AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, [NSNumber numberWithBool:YES], spellRange);
+        
+        if (marker.endOffset > endOffset + 1)
+            break;
+    }
+}
+
+static void AXAttributeStringSetHeadingLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
+{
+    if (!renderer)
+        return;
+    
+    AccessibilityObject* parentObject = renderer->document()->axObjectCache()->getOrCreate(renderer->parent());
+    int parentHeadingLevel = parentObject->headingLevel();
+    
+    if (parentHeadingLevel)
+        [attrString addAttribute:@"AXHeadingLevel" value:[NSNumber numberWithInt:parentHeadingLevel] range:range];
+    else
+        [attrString removeAttribute:@"AXHeadingLevel" range:range];
+}
+
+static void AXAttributeStringSetElement(NSMutableAttributedString* attrString, NSString* attribute, AccessibilityObject* object, NSRange range)
+{
+    if (object && object->isAccessibilityRenderObject()) {
+        // make a serializable AX object
+        
+        RenderObject* renderer = static_cast<AccessibilityRenderObject*>(object)->renderer();
+        if (!renderer)
+            return;
+        
+        Document* doc = renderer->document();
+        if (!doc)
+            return;
+        
+        AXObjectCache* cache = doc->axObjectCache();
+        if (!cache)
+            return;
+
+        AXUIElementRef axElement = [[WebCoreViewFactory sharedFactory] AXUIElementForElement:object->wrapper()];
+        if (axElement) {
+            [attrString addAttribute:attribute value:(id)axElement range:range];
+            CFRelease(axElement);
+        }
+    } else
+        [attrString removeAttribute:attribute range:range];
+}
+
+static void AXAttributedStringAppendText(NSMutableAttributedString* attrString, Node* node, int offset, const UChar* chars, int length)
+{
+    // skip invisible text
+    if (!node->renderer())
+        return;
+
+    // easier to calculate the range before appending the string
+    NSRange attrStringRange = NSMakeRange([attrString length], length);
+    
+    // append the string from this node
+    [[attrString mutableString] appendString:[NSString stringWithCharacters:chars length:length]];
+
+    // add new attributes and remove irrelevant inherited ones
+    // NOTE: color attributes are handled specially because -[NSMutableAttributedString addAttribute: value: range:] does not merge
+    // identical colors.  Workaround is to not replace an existing color attribute if it matches what we are adding.  This also means
+    // we cannot just pre-remove all inherited attributes on the appended string, so we have to remove the irrelevant ones individually.
+
+    // remove inherited attachment from prior AXAttributedStringAppendReplaced
+    [attrString removeAttribute:NSAccessibilityAttachmentTextAttribute range:attrStringRange];
+    
+    // set new attributes
+    AXAttributeStringSetStyle(attrString, node->renderer(), attrStringRange);
+    AXAttributeStringSetHeadingLevel(attrString, node->renderer(), attrStringRange);
+    AXAttributeStringSetBlockquoteLevel(attrString, node->renderer(), attrStringRange);
+    AXAttributeStringSetElement(attrString, NSAccessibilityLinkTextAttribute, AccessibilityObject::anchorElementForNode(node), attrStringRange);
+    
+    // do spelling last because it tends to break up the range
+    AXAttributeStringSetSpelling(attrString, node, offset, attrStringRange);
+}
+
+static NSString* nsStringForReplacedNode(Node* replacedNode)
+{
+    // we should always be given a rendered node and a replaced node, but be safe
+    // replaced nodes are either attachments (widgets) or images
+    if (!replacedNode || !replacedNode->renderer() || !replacedNode->renderer()->isReplaced() || replacedNode->isTextNode()) {
+        ASSERT_NOT_REACHED();
+        return nil;
+    }
+
+    // create an AX object, but skip it if it is not supposed to be seen
+    RefPtr<AccessibilityObject> obj = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer());
+    if (obj->accessibilityIsIgnored())
+        return nil;
+    
+    // use the attachmentCharacter to represent the replaced node
+    const UniChar attachmentChar = NSAttachmentCharacter;
+    return [NSString stringWithCharacters:&attachmentChar length:1];
+}
+
+- (NSAttributedString*)doAXAttributedStringForTextMarkerRange:(WebCoreTextMarkerRange*)textMarkerRange
+{
+    if (!m_object)
+        return nil;
+    
+    // extract the start and end VisiblePosition
+    VisiblePosition startVisiblePosition = visiblePositionForStartOfTextMarkerRange(textMarkerRange);
+    if (startVisiblePosition.isNull())
+        return nil;
+
+    VisiblePosition endVisiblePosition = visiblePositionForEndOfTextMarkerRange(textMarkerRange);
+    if (endVisiblePosition.isNull())
+        return nil;
+
+    VisiblePositionRange visiblePositionRange(startVisiblePosition, endVisiblePosition);
+    // iterate over the range to build the AX attributed string
+    NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] init];
+    TextIterator it(makeRange(startVisiblePosition, endVisiblePosition).get());
+    while (!it.atEnd()) {
+        // locate the node and starting offset for this range
+        int exception = 0;
+        Node* node = it.range()->startContainer(exception);
+        ASSERT(node == it.range()->endContainer(exception));
+        int offset = it.range()->startOffset(exception);
+
+        // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX)
+        if (it.length() != 0) {
+            // Add the text of the list marker item if necessary.
+            String listMarkerText = m_object->listMarkerTextForNodeAndPosition(node, VisiblePosition(it.range()->startPosition()));
+            if (!listMarkerText.isEmpty())
+                AXAttributedStringAppendText(attrString, node, offset, listMarkerText.characters(), listMarkerText.length());
+            
+            AXAttributedStringAppendText(attrString, node, offset, it.characters(), it.length());
+        } else {
+            Node* replacedNode = node->childNode(offset);
+            NSString *attachmentString = nsStringForReplacedNode(replacedNode);
+            if (attachmentString) {
+                NSRange attrStringRange = NSMakeRange([attrString length], [attachmentString length]);
+
+                // append the placeholder string
+                [[attrString mutableString] appendString:attachmentString];
+
+                // remove all inherited attributes
+                [attrString setAttributes:nil range:attrStringRange];
+
+                // add the attachment attribute
+                AccessibilityObject* obj = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer());
+                AXAttributeStringSetElement(attrString, NSAccessibilityAttachmentTextAttribute, obj, attrStringRange);
+            }
+        }
+        it.advance();
+    }
+
+    return [attrString autorelease];
+}
+
+static WebCoreTextMarkerRange* textMarkerRangeFromVisiblePositions(VisiblePosition startPosition, VisiblePosition endPosition)
+{
+    WebCoreTextMarker* startTextMarker = textMarkerForVisiblePosition(startPosition);
+    WebCoreTextMarker* endTextMarker   = textMarkerForVisiblePosition(endPosition);
+    return textMarkerRangeFromMarkers(startTextMarker, endTextMarker);
+}
+
+- (NSArray*)accessibilityActionNames
+{
+    if (!m_object)
+        return nil;
+
+    m_object->updateBackingStore();
+    if (!m_object)
+        return nil;
+
+    static NSArray* actionElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityPressAction, NSAccessibilityShowMenuAction, nil];
+    static NSArray* defaultElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityShowMenuAction, nil];
+    static NSArray* menuElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityCancelAction, NSAccessibilityPressAction, nil];
+    static NSArray* sliderActions = [[NSArray alloc] initWithObjects: NSAccessibilityIncrementAction, NSAccessibilityDecrementAction, nil];
+
+    NSArray *actions;
+    if (m_object->actionElement()) 
+        actions = actionElementActions;
+    else if (m_object->isMenuRelated())
+        actions = menuElementActions;
+    else if (m_object->isSlider())
+        actions = sliderActions;
+    else if (m_object->isAttachment())
+        actions = [[self attachmentView] accessibilityActionNames];
+    else
+        actions = defaultElementActions;
+
+    return actions;
+}
+
+- (NSArray*)additionalAccessibilityAttributeNames
+{
+    if (!m_object)
+        return nil;
+
+    NSMutableArray *additional = [NSMutableArray array];
+    if (m_object->supportsARIAOwns())
+        [additional addObject:NSAccessibilityOwnsAttribute];
+
+    if (m_object->isScrollbar())
+        [additional addObject:NSAccessibilityOrientationAttribute];
+    
+    if (m_object->supportsARIADragging())
+        [additional addObject:NSAccessibilityGrabbedAttribute];
+
+    if (m_object->supportsARIADropping())
+        [additional addObject:NSAccessibilityDropEffectsAttribute];
+
+    if (m_object->isDataTable() && static_cast<AccessibilityTable*>(m_object)->supportsSelectedRows())
+        [additional addObject:NSAccessibilitySelectedRowsAttribute];        
+    
+    if (m_object->supportsARIALiveRegion()) {
+        [additional addObject:NSAccessibilityARIALiveAttribute];
+        [additional addObject:NSAccessibilityARIARelevantAttribute];
+    }
+        
+    // If an object is a child of a live region, then add these
+    if (m_object->isInsideARIALiveRegion()) {
+        [additional addObject:NSAccessibilityARIAAtomicAttribute];
+        [additional addObject:NSAccessibilityARIABusyAttribute];
+    }
+    
+    if (m_object->ariaHasPopup())
+        [additional addObject:NSAccessibilityHasPopupAttribute];
+    
+    return additional;
+}
+
+- (NSArray*)accessibilityAttributeNames
+{
+    if (!m_object)
+        return nil;
+    
+    m_object->updateBackingStore();
+    if (!m_object)
+        return nil;
+    
+    if (m_object->isAttachment())
+        return [[self attachmentView] accessibilityAttributeNames];
+
+    static NSArray* attributes = nil;
+    static NSArray* anchorAttrs = nil;
+    static NSArray* webAreaAttrs = nil;
+    static NSArray* textAttrs = nil;
+    static NSArray* listBoxAttrs = nil;
+    static NSArray* rangeAttrs = nil;
+    static NSArray* commonMenuAttrs = nil;
+    static NSArray* menuAttrs = nil;
+    static NSArray* menuBarAttrs = nil;
+    static NSArray* menuItemAttrs = nil;
+    static NSArray* menuButtonAttrs = nil;
+    static NSArray* controlAttrs = nil;
+    static NSArray* tableAttrs = nil;
+    static NSArray* tableRowAttrs = nil;
+    static NSArray* tableColAttrs = nil;
+    static NSArray* tableCellAttrs = nil;
+    static NSArray* groupAttrs = nil;
+    static NSArray* inputImageAttrs = nil;
+    static NSArray* passwordFieldAttrs = nil;
+    static NSArray* tabListAttrs = nil;
+    static NSArray* comboBoxAttrs = nil;
+    static NSArray* outlineAttrs = nil;
+    static NSArray* outlineRowAttrs = nil;
+    static NSArray* buttonAttrs = nil;
+    NSMutableArray* tempArray;
+    if (attributes == nil) {
+        attributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
+                      NSAccessibilitySubroleAttribute,
+                      NSAccessibilityRoleDescriptionAttribute,
+                      NSAccessibilityChildrenAttribute,
+                      NSAccessibilityHelpAttribute,
+                      NSAccessibilityParentAttribute,
+                      NSAccessibilityPositionAttribute,
+                      NSAccessibilitySizeAttribute,
+                      NSAccessibilityTitleAttribute,
+                      NSAccessibilityDescriptionAttribute,
+                      NSAccessibilityValueAttribute,
+                      NSAccessibilityFocusedAttribute,
+                      NSAccessibilityEnabledAttribute,
+                      NSAccessibilityWindowAttribute,
+                      @"AXSelectedTextMarkerRange",
+                      @"AXStartTextMarker",
+                      @"AXEndTextMarker",
+                      @"AXVisited",
+                      NSAccessibilityLinkedUIElementsAttribute,
+                      NSAccessibilitySelectedAttribute,
+                      NSAccessibilityBlockQuoteLevelAttribute,
+                      NSAccessibilityTopLevelUIElementAttribute,
+                      nil];
+    }
+    if (commonMenuAttrs == nil) {
+        commonMenuAttrs = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
+                            NSAccessibilityRoleDescriptionAttribute,
+                            NSAccessibilityChildrenAttribute,
+                            NSAccessibilityParentAttribute,
+                            NSAccessibilityEnabledAttribute,
+                            NSAccessibilityPositionAttribute,
+                            NSAccessibilitySizeAttribute,
+                            nil];
+    }
+    if (anchorAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:attributes];
+        [tempArray addObject:NSAccessibilityURLAttribute];
+        [tempArray addObject:NSAccessibilityAccessKeyAttribute];
+        anchorAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    if (webAreaAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:attributes];
+        [tempArray addObject:@"AXLinkUIElements"];
+        [tempArray addObject:@"AXLoaded"];
+        [tempArray addObject:@"AXLayoutCount"];
+        [tempArray addObject:NSAccessibilityLoadingProgressAttribute];
+        [tempArray addObject:NSAccessibilityURLAttribute];
+        webAreaAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    if (textAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:attributes];
+        [tempArray addObject:NSAccessibilityNumberOfCharactersAttribute];
+        [tempArray addObject:NSAccessibilitySelectedTextAttribute];
+        [tempArray addObject:NSAccessibilitySelectedTextRangeAttribute];
+        [tempArray addObject:NSAccessibilityVisibleCharacterRangeAttribute];
+        [tempArray addObject:NSAccessibilityInsertionPointLineNumberAttribute];
+        [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
+        [tempArray addObject:NSAccessibilityAccessKeyAttribute];
+        [tempArray addObject:NSAccessibilityRequiredAttribute];
+        textAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    if (listBoxAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:attributes];
+        [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
+        [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
+        [tempArray addObject:NSAccessibilityOrientationAttribute];
+        [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
+        [tempArray addObject:NSAccessibilityAccessKeyAttribute];
+        [tempArray addObject:NSAccessibilityRequiredAttribute];
+        listBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    if (rangeAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:attributes];
+        [tempArray addObject:NSAccessibilityTopLevelUIElementAttribute];
+        [tempArray addObject:NSAccessibilityValueAttribute];
+        [tempArray addObject:NSAccessibilityMinValueAttribute];
+        [tempArray addObject:NSAccessibilityMaxValueAttribute];
+        [tempArray addObject:NSAccessibilityOrientationAttribute];
+        [tempArray addObject:NSAccessibilityValueDescriptionAttribute];
+        rangeAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    if (menuBarAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
+        [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
+        [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
+        [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
+        menuBarAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    if (menuAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
+        [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
+        [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
+        [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
+        menuAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    if (menuItemAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
+        [tempArray addObject:NSAccessibilityTitleAttribute];
+        [tempArray addObject:NSAccessibilityHelpAttribute];
+        [tempArray addObject:NSAccessibilitySelectedAttribute];
+        [tempArray addObject:(NSString*)kAXMenuItemCmdCharAttribute];
+        [tempArray addObject:(NSString*)kAXMenuItemCmdVirtualKeyAttribute];
+        [tempArray addObject:(NSString*)kAXMenuItemCmdGlyphAttribute];
+        [tempArray addObject:(NSString*)kAXMenuItemCmdModifiersAttribute];
+        [tempArray addObject:(NSString*)kAXMenuItemMarkCharAttribute];
+        [tempArray addObject:(NSString*)kAXMenuItemPrimaryUIElementAttribute];
+        [tempArray addObject:NSAccessibilityServesAsTitleForUIElementsAttribute];
+        menuItemAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    if (menuButtonAttrs == nil) {
+        menuButtonAttrs = [[NSArray alloc] initWithObjects:NSAccessibilityRoleAttribute,
+            NSAccessibilityRoleDescriptionAttribute,
+            NSAccessibilityParentAttribute,
+            NSAccessibilityPositionAttribute,
+            NSAccessibilitySizeAttribute,
+            NSAccessibilityWindowAttribute,
+            NSAccessibilityTopLevelUIElementAttribute,
+            NSAccessibilityEnabledAttribute,
+            NSAccessibilityFocusedAttribute,
+            NSAccessibilityTitleAttribute,
+            NSAccessibilityChildrenAttribute, nil];
+    }
+    if (controlAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:attributes];
+        [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
+        [tempArray addObject:NSAccessibilityAccessKeyAttribute];
+        [tempArray addObject:NSAccessibilityRequiredAttribute];
+        controlAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    if (buttonAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:attributes];
+        // Buttons should not expose AXValue.
+        [tempArray removeObject:NSAccessibilityValueAttribute];
+        [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
+        [tempArray addObject:NSAccessibilityAccessKeyAttribute];
+        buttonAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    if (comboBoxAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:controlAttrs];
+        [tempArray addObject:NSAccessibilityExpandedAttribute];
+        comboBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];        
+    }
+    if (tableAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:attributes];
+        [tempArray addObject:NSAccessibilityRowsAttribute];
+        [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
+        [tempArray addObject:NSAccessibilityColumnsAttribute];
+        [tempArray addObject:NSAccessibilityVisibleColumnsAttribute];
+        [tempArray addObject:NSAccessibilityVisibleCellsAttribute];
+        [tempArray addObject:(NSString *)kAXColumnHeaderUIElementsAttribute];
+        [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];
+        [tempArray addObject:NSAccessibilityHeaderAttribute];
+        tableAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    if (tableRowAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:attributes];
+        [tempArray addObject:NSAccessibilityIndexAttribute];
+        tableRowAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    if (tableColAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:attributes];
+        [tempArray addObject:NSAccessibilityIndexAttribute];
+        [tempArray addObject:NSAccessibilityHeaderAttribute];
+        [tempArray addObject:NSAccessibilityRowsAttribute];
+        [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
+        tableColAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    if (tableCellAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:attributes];
+        [tempArray addObject:NSAccessibilityRowIndexRangeAttribute];
+        [tempArray addObject:NSAccessibilityColumnIndexRangeAttribute];
+        tableCellAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];        
+    }
+    if (groupAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:attributes];
+        [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
+        groupAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    if (inputImageAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:buttonAttrs];
+        [tempArray addObject:NSAccessibilityURLAttribute];
+        inputImageAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    if (passwordFieldAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:attributes];
+        [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
+        [tempArray addObject:NSAccessibilityRequiredAttribute];
+        passwordFieldAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    if (tabListAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:attributes];
+        [tempArray addObject:NSAccessibilityTabsAttribute];
+        [tempArray addObject:NSAccessibilityContentsAttribute];
+        tabListAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];        
+    }
+    if (outlineAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:attributes];
+        [tempArray addObject:NSAccessibilitySelectedRowsAttribute];
+        [tempArray addObject:NSAccessibilityRowsAttribute];
+        [tempArray addObject:NSAccessibilityColumnsAttribute];
+        outlineAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    if (outlineRowAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:tableRowAttrs];
+        [tempArray addObject:NSAccessibilityDisclosingAttribute];
+        [tempArray addObject:NSAccessibilityDisclosedByRowAttribute];
+        [tempArray addObject:NSAccessibilityDisclosureLevelAttribute];
+        [tempArray addObject:NSAccessibilityDisclosedRowsAttribute];
+        outlineRowAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    
+    NSArray *objectAttributes = attributes;
+    
+    if (m_object->isPasswordField())
+        objectAttributes = passwordFieldAttrs;
+
+    else if (m_object->isWebArea())
+        objectAttributes = webAreaAttrs;
+    
+    else if (m_object->isTextControl())
+        objectAttributes = textAttrs;
+
+    else if (m_object->isAnchor() || m_object->isImage() || m_object->isLink())
+        objectAttributes = anchorAttrs;
+
+    else if (m_object->isDataTable())
+        objectAttributes = tableAttrs;
+    else if (m_object->isTableColumn())
+        objectAttributes = tableColAttrs;
+    else if (m_object->isTableCell())
+        objectAttributes = tableCellAttrs;
+    else if (m_object->isTableRow()) {
+        // An ARIA table row can be collapsed and expanded, so it needs the extra attributes.
+        if (m_object->isARIATreeGridRow())
+            objectAttributes = outlineRowAttrs;
+        else
+            objectAttributes = tableRowAttrs;
+    }
+    
+    else if (m_object->isTree())
+        objectAttributes = outlineAttrs;
+    else if (m_object->isTreeItem())
+        objectAttributes = outlineRowAttrs;
+    
+    else if (m_object->isListBox() || m_object->isList())
+        objectAttributes = listBoxAttrs;
+
+    else if (m_object->isComboBox())
+        objectAttributes = comboBoxAttrs;
+    
+    else if (m_object->isProgressIndicator() || m_object->isSlider())
+        objectAttributes = rangeAttrs;
+
+    // These are processed in order because an input image is a button, and a button is a control.
+    else if (m_object->isInputImage())
+        objectAttributes = inputImageAttrs;
+    else if (m_object->isButton())
+        objectAttributes = buttonAttrs;
+    else if (m_object->isControl())
+        objectAttributes = controlAttrs;
+    
+    else if (m_object->isGroup() || m_object->isListItem())
+        objectAttributes = groupAttrs;
+    else if (m_object->isTabList())
+        objectAttributes = tabListAttrs;
+    
+    else if (m_object->isMenu())
+        objectAttributes = menuAttrs;
+    else if (m_object->isMenuBar())
+        objectAttributes = menuBarAttrs;
+    else if (m_object->isMenuButton())
+        objectAttributes = menuButtonAttrs;
+    else if (m_object->isMenuItem())
+        objectAttributes = menuItemAttrs;
+
+    NSArray *additionalAttributes = [self additionalAccessibilityAttributeNames];
+    if ([additionalAttributes count])
+        objectAttributes = [objectAttributes arrayByAddingObjectsFromArray:additionalAttributes];
+    
+    return objectAttributes;
+}
+
+- (VisiblePositionRange)visiblePositionRangeForTextMarkerRange:(WebCoreTextMarkerRange*) textMarkerRange
+{
+    if (!textMarkerRange)
+        return VisiblePositionRange();
+    return VisiblePositionRange(visiblePositionForStartOfTextMarkerRange(textMarkerRange), visiblePositionForEndOfTextMarkerRange(textMarkerRange));
+}
+
+- (NSArray*)renderWidgetChildren
+{
+    Widget* widget = m_object->widget();
+    if (!widget)
+        return nil;
+    return [(widget->platformWidget()) accessibilityAttributeValue: NSAccessibilityChildrenAttribute];
+}
+
+static void convertToVector(NSArray* array, AccessibilityObject::AccessibilityChildrenVector& vector)
+{
+    unsigned length = [array count];
+    vector.reserveInitialCapacity(length);
+    for (unsigned i = 0; i < length; ++i) {
+        AccessibilityObject* obj = [[array objectAtIndex:i] accessibilityObject];
+        if (obj)
+            vector.append(obj);
+    }
+}
+
+static NSMutableArray* convertToNSArray(const AccessibilityObject::AccessibilityChildrenVector& vector)
+{
+    unsigned length = vector.size();
+    NSMutableArray* array = [NSMutableArray arrayWithCapacity: length];
+    for (unsigned i = 0; i < length; ++i) {
+        AccessibilityObjectWrapper* wrapper = vector[i]->wrapper();
+        ASSERT(wrapper);
+        if (wrapper) {
+            // we want to return the attachment view instead of the object representing the attachment.
+            // otherwise, we get palindrome errors in the AX hierarchy
+            if (vector[i]->isAttachment() && [wrapper attachmentView])
+                [array addObject:[wrapper attachmentView]];
+            else
+                [array addObject:wrapper];
+        }
+    }
+    return array;
+}
+
+- (WebCoreTextMarkerRange*)textMarkerRangeForSelection
+{
+    VisibleSelection selection = m_object->selection();
+    if (selection.isNone())
+        return nil;
+    return textMarkerRangeFromVisiblePositions(selection.visibleStart(), selection.visibleEnd());
+}
+
+- (NSValue*)position
+{
+    IntRect rect = m_object->elementRect();
+    
+    // The Cocoa accessibility API wants the lower-left corner.
+    NSPoint point = NSMakePoint(rect.x(), rect.bottom());
+    FrameView* frameView = m_object->documentFrameView();
+    if (frameView) {
+        NSView* view = frameView->documentView();
+        point = [[view window] convertBaseToScreen: [view convertPoint: point toView:nil]];
+    }
+
+    return [NSValue valueWithPoint: point];
+}
+
+typedef HashMap<int, NSString*> AccessibilityRoleMap;
+
+static const AccessibilityRoleMap& createAccessibilityRoleMap()
+{
+    struct RoleEntry {
+        AccessibilityRole value;
+        NSString* string;
+    };
+    
+    static const RoleEntry roles[] = {
+        { UnknownRole, NSAccessibilityUnknownRole },
+        { ButtonRole, NSAccessibilityButtonRole },
+        { RadioButtonRole, NSAccessibilityRadioButtonRole },
+        { CheckBoxRole, NSAccessibilityCheckBoxRole },
+        { SliderRole, NSAccessibilitySliderRole },
+        { TabGroupRole, NSAccessibilityTabGroupRole },
+        { TextFieldRole, NSAccessibilityTextFieldRole },
+        { StaticTextRole, NSAccessibilityStaticTextRole },
+        { TextAreaRole, NSAccessibilityTextAreaRole },
+        { ScrollAreaRole, NSAccessibilityScrollAreaRole },
+        { PopUpButtonRole, NSAccessibilityPopUpButtonRole },
+        { MenuButtonRole, NSAccessibilityMenuButtonRole },
+        { TableRole, NSAccessibilityTableRole },
+        { ApplicationRole, NSAccessibilityApplicationRole },
+        { GroupRole, NSAccessibilityGroupRole },
+        { RadioGroupRole, NSAccessibilityRadioGroupRole },
+        { ListRole, NSAccessibilityListRole },
+        { DirectoryRole, NSAccessibilityListRole },
+        { ScrollBarRole, NSAccessibilityScrollBarRole },
+        { ValueIndicatorRole, NSAccessibilityValueIndicatorRole },
+        { ImageRole, NSAccessibilityImageRole },
+        { MenuBarRole, NSAccessibilityMenuBarRole },
+        { MenuRole, NSAccessibilityMenuRole },
+        { MenuItemRole, NSAccessibilityMenuItemRole },
+        { ColumnRole, NSAccessibilityColumnRole },
+        { RowRole, NSAccessibilityRowRole },
+        { ToolbarRole, NSAccessibilityToolbarRole },
+        { BusyIndicatorRole, NSAccessibilityBusyIndicatorRole },
+        { ProgressIndicatorRole, NSAccessibilityProgressIndicatorRole },
+        { WindowRole, NSAccessibilityWindowRole },
+        { DrawerRole, NSAccessibilityDrawerRole },
+        { SystemWideRole, NSAccessibilitySystemWideRole },
+        { OutlineRole, NSAccessibilityOutlineRole },
+        { IncrementorRole, NSAccessibilityIncrementorRole },
+        { BrowserRole, NSAccessibilityBrowserRole },
+        { ComboBoxRole, NSAccessibilityComboBoxRole },
+        { SplitGroupRole, NSAccessibilitySplitGroupRole },
+        { SplitterRole, NSAccessibilitySplitterRole },
+        { ColorWellRole, NSAccessibilityColorWellRole },
+        { GrowAreaRole, NSAccessibilityGrowAreaRole },
+        { SheetRole, NSAccessibilitySheetRole },
+        { HelpTagRole, NSAccessibilityHelpTagRole },
+        { MatteRole, NSAccessibilityMatteRole }, 
+        { RulerRole, NSAccessibilityRulerRole },
+        { RulerMarkerRole, NSAccessibilityRulerMarkerRole },
+        { LinkRole, NSAccessibilityLinkRole },
+#ifndef BUILDING_ON_TIGER        
+        { DisclosureTriangleRole, NSAccessibilityDisclosureTriangleRole },
+        { GridRole, NSAccessibilityGridRole },
+#endif
+        { WebCoreLinkRole, NSAccessibilityLinkRole }, 
+        { ImageMapLinkRole, NSAccessibilityLinkRole },
+        { ImageMapRole, @"AXImageMap" },
+        { ListMarkerRole, @"AXListMarker" },
+        { WebAreaRole, @"AXWebArea" },
+        { HeadingRole, @"AXHeading" },
+        { ListBoxRole, NSAccessibilityListRole },
+        { ListBoxOptionRole, NSAccessibilityStaticTextRole },
+#if ACCESSIBILITY_TABLES
+        { CellRole, NSAccessibilityCellRole },
+#else
+        { CellRole, NSAccessibilityGroupRole },
+#endif
+        { TableHeaderContainerRole, NSAccessibilityGroupRole },
+        { DefinitionListDefinitionRole, NSAccessibilityGroupRole },
+        { DefinitionListTermRole, NSAccessibilityGroupRole },
+        { SliderThumbRole, NSAccessibilityValueIndicatorRole },
+        { LandmarkApplicationRole, NSAccessibilityGroupRole },
+        { LandmarkBannerRole, NSAccessibilityGroupRole },
+        { LandmarkComplementaryRole, NSAccessibilityGroupRole },
+        { LandmarkContentInfoRole, NSAccessibilityGroupRole },
+        { LandmarkMainRole, NSAccessibilityGroupRole },
+        { LandmarkNavigationRole, NSAccessibilityGroupRole },
+        { LandmarkSearchRole, NSAccessibilityGroupRole },
+        { ApplicationAlertRole, NSAccessibilityGroupRole },
+        { ApplicationAlertDialogRole, NSAccessibilityGroupRole },
+        { ApplicationDialogRole, NSAccessibilityGroupRole },
+        { ApplicationLogRole, NSAccessibilityGroupRole },
+        { ApplicationMarqueeRole, NSAccessibilityGroupRole },
+        { ApplicationStatusRole, NSAccessibilityGroupRole },
+        { ApplicationTimerRole, NSAccessibilityGroupRole },
+        { DocumentRole, NSAccessibilityGroupRole },
+        { DocumentArticleRole, NSAccessibilityGroupRole },
+        { DocumentMathRole, NSAccessibilityGroupRole },
+        { DocumentNoteRole, NSAccessibilityGroupRole },
+        { DocumentRegionRole, NSAccessibilityGroupRole },
+        { UserInterfaceTooltipRole, NSAccessibilityGroupRole },
+        { TabRole, NSAccessibilityRadioButtonRole },
+        { TabListRole, NSAccessibilityTabGroupRole },
+        { TabPanelRole, NSAccessibilityGroupRole },
+        { TreeRole, NSAccessibilityOutlineRole },
+        { TreeItemRole, NSAccessibilityRowRole },
+        { ListItemRole, NSAccessibilityGroupRole }
+    };
+    AccessibilityRoleMap& roleMap = *new AccessibilityRoleMap;
+    
+    const unsigned numRoles = sizeof(roles) / sizeof(roles[0]);
+    for (unsigned i = 0; i < numRoles; ++i)
+        roleMap.set(roles[i].value, roles[i].string);
+    return roleMap;
+}
+
+static NSString* roleValueToNSString(AccessibilityRole value)
+{
+    ASSERT(value);
+    static const AccessibilityRoleMap& roleMap = createAccessibilityRoleMap();
+    return roleMap.get(value);
+}
+
+- (NSString*)role
+{
+    if (m_object->isAttachment())
+        return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleAttribute];
+    NSString* string = roleValueToNSString(m_object->roleValue());
+    if (string != nil)
+        return string;
+    return NSAccessibilityUnknownRole;
+}
+
+- (NSString*)subrole
+{
+    if (m_object->isPasswordField())
+        return NSAccessibilitySecureTextFieldSubrole;
+    
+    if (m_object->isAttachment()) {
+        NSView* attachView = [self attachmentView];
+        if ([[attachView accessibilityAttributeNames] containsObject:NSAccessibilitySubroleAttribute]) {
+            return [attachView accessibilityAttributeValue:NSAccessibilitySubroleAttribute];
+        }
+    }
+    
+    if (m_object->isTreeItem())
+        return NSAccessibilityOutlineRowSubrole;
+    
+    if (m_object->isList()) {
+        AccessibilityList* listObject = static_cast<AccessibilityList*>(m_object);
+        if (listObject->isUnorderedList() || listObject->isOrderedList())
+            return NSAccessibilityContentListSubrole;
+        if (listObject->isDefinitionList())
+            return NSAccessibilityDefinitionListSubrole;
+    }
+    
+    // ARIA content subroles.
+    switch (m_object->roleValue()) {
+        case LandmarkApplicationRole:
+            return @"AXLandmarkApplication";
+        case LandmarkBannerRole:
+            return @"AXLandmarkBanner";
+        case LandmarkComplementaryRole:
+            return @"AXLandmarkComplementary";
+        case LandmarkContentInfoRole:
+            return @"AXLandmarkContentInfo";
+        case LandmarkMainRole:
+            return @"AXLandmarkMain";
+        case LandmarkNavigationRole:
+            return @"AXLandmarkNavigation";
+        case LandmarkSearchRole:
+            return @"AXLandmarkSearch";
+        case ApplicationAlertRole:
+            return @"AXApplicationAlert";
+        case ApplicationAlertDialogRole:
+            return @"AXApplicationAlertDialog";
+        case ApplicationDialogRole:
+            return @"AXApplicationDialog";
+        case ApplicationLogRole:
+            return @"AXApplicationLog";
+        case ApplicationMarqueeRole:
+            return @"AXApplicationMarquee";
+        case ApplicationStatusRole:
+            return @"AXApplicationStatus";
+        case ApplicationTimerRole:
+            return @"AXApplicationTimer";
+        case DocumentRole:
+            return @"AXDocument";
+        case DocumentArticleRole:
+            return @"AXDocumentArticle";
+        case DocumentMathRole:
+            return @"AXDocumentMath";
+        case DocumentNoteRole:
+            return @"AXDocumentNote";
+        case DocumentRegionRole:
+            return @"AXDocumentRegion";
+        case UserInterfaceTooltipRole:
+            return @"AXUserInterfaceTooltip";
+        case TabPanelRole:
+            return @"AXTabPanel";
+        case DefinitionListTermRole:
+            return @"AXTerm";
+        case DefinitionListDefinitionRole:
+            return @"AXDefinition";
+        // Default doesn't return anything, so roles defined below can be chosen.
+        default:
+            break;
+    }
+    
+    if (m_object->isMediaTimeline())
+        return NSAccessibilityTimelineSubrole;
+
+    return nil;
+}
+
+- (NSString*)roleDescription
+{
+    if (!m_object)
+        return nil;
+
+    // attachments have the AXImage role, but a different subrole
+    if (m_object->isAttachment())
+        return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute];
+    
+    NSString* axRole = [self role];
+    
+    if ([axRole isEqualToString:NSAccessibilityGroupRole]) {
+        switch (m_object->roleValue()) {
+            default:
+                return NSAccessibilityRoleDescription(NSAccessibilityGroupRole, [self subrole]);
+            case LandmarkApplicationRole:
+                return AXARIAContentGroupText(@"ARIALandmarkApplication");
+            case LandmarkBannerRole:
+                return AXARIAContentGroupText(@"ARIALandmarkBanner");
+            case LandmarkComplementaryRole:
+                return AXARIAContentGroupText(@"ARIALandmarkComplementary");
+            case LandmarkContentInfoRole:
+                return AXARIAContentGroupText(@"ARIALandmarkContentInfo");
+            case LandmarkMainRole:
+                return AXARIAContentGroupText(@"ARIALandmarkMain");
+            case LandmarkNavigationRole:
+                return AXARIAContentGroupText(@"ARIALandmarkNavigation");
+            case LandmarkSearchRole:
+                return AXARIAContentGroupText(@"ARIALandmarkSearch");
+            case ApplicationAlertRole:
+                return AXARIAContentGroupText(@"ARIAApplicationAlert");
+            case ApplicationAlertDialogRole:
+                return AXARIAContentGroupText(@"ARIAApplicationAlertDialog");
+            case ApplicationDialogRole:
+                return AXARIAContentGroupText(@"ARIAApplicationDialog");
+            case ApplicationLogRole:
+                return AXARIAContentGroupText(@"ARIAApplicationLog");
+            case ApplicationMarqueeRole:
+                return AXARIAContentGroupText(@"ARIAApplicationMarquee");
+            case ApplicationStatusRole:
+                return AXARIAContentGroupText(@"ARIAApplicationStatus");
+            case ApplicationTimerRole:
+                return AXARIAContentGroupText(@"ARIAApplicationTimer");
+            case DocumentRole:
+                return AXARIAContentGroupText(@"ARIADocument");
+            case DocumentArticleRole:
+                return AXARIAContentGroupText(@"ARIADocumentArticle");
+            case DocumentMathRole:
+                return AXARIAContentGroupText(@"ARIADocumentMath");
+            case DocumentNoteRole:
+                return AXARIAContentGroupText(@"ARIADocumentNote");
+            case DocumentRegionRole:
+                return AXARIAContentGroupText(@"ARIADocumentRegion");
+            case UserInterfaceTooltipRole:
+                return AXARIAContentGroupText(@"ARIAUserInterfaceTooltip");
+            case TabPanelRole:
+                return AXARIAContentGroupText(@"ARIATabPanel");
+            case DefinitionListTermRole:
+                return AXDefinitionListTermText();
+            case DefinitionListDefinitionRole:
+                return AXDefinitionListDefinitionText();
+        }
+    }        
+    
+    if ([axRole isEqualToString:@"AXWebArea"])
+        return AXWebAreaText();
+    
+    if ([axRole isEqualToString:@"AXLink"])
+        return AXLinkText();
+    
+    if ([axRole isEqualToString:@"AXListMarker"])
+        return AXListMarkerText();
+    
+    if ([axRole isEqualToString:@"AXImageMap"])
+        return AXImageMapText();
+
+    if ([axRole isEqualToString:@"AXHeading"])
+        return AXHeadingText();
+
+    // AppKit also returns AXTab for the role description for a tab item.
+    if (m_object->isTabItem())
+        return NSAccessibilityRoleDescription(@"AXTab", nil);
+    
+    // We should try the system default role description for all other roles.
+    // If we get the same string back, then as a last resort, return unknown.
+    NSString* defaultRoleDescription = NSAccessibilityRoleDescription(axRole, [self subrole]);
+    if (![defaultRoleDescription isEqualToString:axRole])
+        return defaultRoleDescription;
+
+    return NSAccessibilityRoleDescription(NSAccessibilityUnknownRole, nil);
+}
+
+// FIXME: split up this function in a better way.  
+// suggestions: Use a hash table that maps attribute names to function calls,
+// or maybe pointers to member functions
+- (id)accessibilityAttributeValue:(NSString*)attributeName
+{
+    if (!m_object)
+        return nil;
+
+    m_object->updateBackingStore();
+    if (!m_object)
+        return nil;
+    
+    if ([attributeName isEqualToString: NSAccessibilityRoleAttribute])
+        return [self role];
+
+    if ([attributeName isEqualToString: NSAccessibilitySubroleAttribute])
+        return [self subrole];
+
+    if ([attributeName isEqualToString: NSAccessibilityRoleDescriptionAttribute])
+        return [self roleDescription];
+
+    if ([attributeName isEqualToString: NSAccessibilityParentAttribute]) {
+        if (m_object->isAccessibilityRenderObject()) {
+            FrameView* fv = static_cast<AccessibilityRenderObject*>(m_object)->frameViewIfRenderView();
+            if (fv)
+                return fv->platformWidget();
+        }
+        
+        // Tree item (changed to AXRows) can only report the tree (AXOutline) as its parent.
+        if (m_object->isTreeItem()) {
+            AccessibilityObject* parent = m_object->parentObjectUnignored();
+            while (parent) {
+                if (parent->isTree())
+                    return parent->wrapper();
+                parent = parent->parentObjectUnignored();
+            }
+        }
+        
+        return m_object->parentObjectUnignored()->wrapper();
+    }
+
+    if ([attributeName isEqualToString: NSAccessibilityChildrenAttribute]) {
+        if (m_object->children().isEmpty()) {
+            NSArray* children = [self renderWidgetChildren];
+            if (children != nil)
+                return children;
+        }
+
+        // The tree's (AXOutline) children are supposed to be its rows and columns.
+        // The ARIA spec doesn't have columns, so we just need rows.
+        if (m_object->isTree())
+            return [self accessibilityAttributeValue:NSAccessibilityRowsAttribute];
+
+        // A tree item should only expose its content as its children (not its rows)
+        if (m_object->isTreeItem()) {
+            AccessibilityObject::AccessibilityChildrenVector contentCopy;
+            m_object->ariaTreeItemContent(contentCopy);
+            return convertToNSArray(contentCopy);
+        }
+        
+        return convertToNSArray(m_object->children());
+    }
+    
+    if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {
+        if (m_object->isListBox()) {
+            AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
+            m_object->selectedChildren(selectedChildrenCopy);
+            return convertToNSArray(selectedChildrenCopy);
+        }
+        return nil;
+    }
+    
+    if ([attributeName isEqualToString: NSAccessibilityVisibleChildrenAttribute]) {
+        if (m_object->isListBox()) {
+            AccessibilityObject::AccessibilityChildrenVector visibleChildrenCopy;
+            m_object->visibleChildren(visibleChildrenCopy);
+            return convertToNSArray(visibleChildrenCopy);
+        }
+        else if (m_object->isList())
+            return [self accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
+
+        return nil;
+    }
+    
+    
+    if (m_object->isWebArea()) {
+        if ([attributeName isEqualToString:@"AXLinkUIElements"]) {
+            AccessibilityObject::AccessibilityChildrenVector links;
+            static_cast<AccessibilityRenderObject*>(m_object)->getDocumentLinks(links);
+            return convertToNSArray(links);
+        }
+        if ([attributeName isEqualToString:@"AXLoaded"])
+            return [NSNumber numberWithBool:m_object->isLoaded()];
+        if ([attributeName isEqualToString:@"AXLayoutCount"])
+            return [NSNumber numberWithInt:m_object->layoutCount()];
+        if ([attributeName isEqualToString:NSAccessibilityLoadingProgressAttribute])
+            return [NSNumber numberWithDouble:m_object->estimatedLoadingProgress()];
+    }
+    
+    if (m_object->isTextControl()) {
+        if ([attributeName isEqualToString: NSAccessibilityNumberOfCharactersAttribute]) {
+            int length = m_object->textLength();
+            if (length < 0)
+                return nil;
+            return [NSNumber numberWithUnsignedInt:length];
+        }
+        if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
+            String selectedText = m_object->selectedText();
+            if (selectedText.isNull())
+                return nil;
+            return (NSString*)selectedText;
+        }
+        if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
+            PlainTextRange textRange = m_object->selectedTextRange();
+            if (textRange.isNull())
+                return [NSValue valueWithRange:NSMakeRange(0, 0)];
+            return [NSValue valueWithRange:NSMakeRange(textRange.start, textRange.length)];
+        }
+        // TODO: Get actual visible range. <rdar://problem/4712101>
+        if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
+            return m_object->isPasswordField() ? nil : [NSValue valueWithRange: NSMakeRange(0, m_object->textLength())];
+        if ([attributeName isEqualToString: NSAccessibilityInsertionPointLineNumberAttribute]) {
+            // if selectionEnd > 0, then there is selected text and this question should not be answered
+            if (m_object->isPasswordField() || m_object->selectionEnd() > 0)
+                return nil;
+            int lineNumber = m_object->lineForPosition(m_object->visiblePositionForIndex(m_object->selectionStart(), true));
+            if (lineNumber < 0)
+                return nil;
+            return [NSNumber numberWithInt:lineNumber];
+        }
+    }
+    
+    if ([attributeName isEqualToString: NSAccessibilityURLAttribute]) {
+        KURL url = m_object->url();
+        if (url.isNull())
+            return nil;
+        return (NSURL*)url;
+    }
+
+    if ([attributeName isEqualToString: @"AXVisited"])
+        return [NSNumber numberWithBool: m_object->isVisited()];
+    
+    if ([attributeName isEqualToString: NSAccessibilityTitleAttribute]) {
+        if (m_object->isAttachment()) {
+            if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityTitleAttribute]) 
+                return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityTitleAttribute];
+        }
+        return m_object->title();
+    }
+    
+    if ([attributeName isEqualToString: NSAccessibilityDescriptionAttribute]) {
+        if (m_object->isAttachment()) {
+            if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityDescriptionAttribute])
+                return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityDescriptionAttribute];
+        }
+        return m_object->accessibilityDescription();
+    }
+
+    if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
+        if (m_object->isAttachment()) {
+            if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityValueAttribute]) 
+                return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityValueAttribute];
+        }
+        if (m_object->isProgressIndicator() || m_object->isSlider() || m_object->isScrollbar())
+            return [NSNumber numberWithFloat:m_object->valueForRange()];
+        if (m_object->hasIntValue())
+            return [NSNumber numberWithInt:m_object->intValue()];
+
+        // radio groups return the selected radio button as the AXValue
+        if (m_object->isRadioGroup()) {
+            AccessibilityObject* radioButton = m_object->selectedRadioButton();
+            if (!radioButton)
+                return nil;
+            return radioButton->wrapper();
+        }
+        
+        if (m_object->isTabList()) {
+            AccessibilityObject* tabItem = m_object->selectedTabItem();
+            if (!tabItem)
+                return nil;
+            return tabItem->wrapper();
+        }
+        
+        if (m_object->isTabItem())
+            return [NSNumber numberWithInt:m_object->isSelected()];
+        
+        return m_object->stringValue();
+    }
+
+    if ([attributeName isEqualToString: NSAccessibilityMinValueAttribute])
+        return [NSNumber numberWithFloat:m_object->minValueForRange()];
+
+    if ([attributeName isEqualToString: NSAccessibilityMaxValueAttribute])
+        return [NSNumber numberWithFloat:m_object->maxValueForRange()];
+
+    if ([attributeName isEqualToString: NSAccessibilityHelpAttribute])
+        return m_object->helpText();
+
+    if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
+        return [NSNumber numberWithBool: m_object->isFocused()];
+
+    if ([attributeName isEqualToString: NSAccessibilityEnabledAttribute])
+        return [NSNumber numberWithBool: m_object->isEnabled()];
+
+    if ([attributeName isEqualToString: NSAccessibilitySizeAttribute]) {
+        IntSize s = m_object->size();
+        return [NSValue valueWithSize: NSMakeSize(s.width(), s.height())];
+    }
+
+    if ([attributeName isEqualToString: NSAccessibilityPositionAttribute])
+        return [self position];
+
+    if ([attributeName isEqualToString: NSAccessibilityWindowAttribute] ||
+        [attributeName isEqualToString: NSAccessibilityTopLevelUIElementAttribute]) {
+        FrameView* fv = m_object->documentFrameView();
+        if (fv)
+            return [fv->platformWidget() window];
+        return nil;
+    }
+    
+    if ([attributeName isEqualToString:NSAccessibilityAccessKeyAttribute]) {
+        AtomicString accessKey = m_object->accessKey();
+        if (accessKey.isNull())
+            return nil;
+        return accessKey;
+    }
+    
+    if ([attributeName isEqualToString:NSAccessibilityTabsAttribute]) {
+        if (m_object->isTabList()) {
+            AccessibilityObject::AccessibilityChildrenVector tabsChildren;
+            m_object->tabChildren(tabsChildren);
+            return convertToNSArray(tabsChildren);
+        }
+    }
+    
+    if ([attributeName isEqualToString:NSAccessibilityContentsAttribute]) {
+        // The contents of a tab list are all the children except the tabs.
+        if (m_object->isTabList()) {
+            AccessibilityObject::AccessibilityChildrenVector children = m_object->children();
+            AccessibilityObject::AccessibilityChildrenVector tabsChildren;
+            m_object->tabChildren(tabsChildren);
+
+            AccessibilityObject::AccessibilityChildrenVector contents;
+            unsigned childrenSize = children.size();
+            for (unsigned k = 0; k < childrenSize; ++k) {
+                if (tabsChildren.find(children[k]) == WTF::notFound)
+                    contents.append(children[k]);
+            }
+            return convertToNSArray(contents);
+        }
+    }    
+    
+    if (m_object->isDataTable()) {
+        // TODO: distinguish between visible and non-visible rows
+        if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] || 
+            [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
+            return convertToNSArray(static_cast<AccessibilityTable*>(m_object)->rows());
+        }
+        // TODO: distinguish between visible and non-visible columns
+        if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute] || 
+            [attributeName isEqualToString:NSAccessibilityVisibleColumnsAttribute]) {
+            return convertToNSArray(static_cast<AccessibilityTable*>(m_object)->columns());
+        }
+        
+        if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
+            AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
+            m_object->selectedChildren(selectedChildrenCopy);
+            return convertToNSArray(selectedChildrenCopy);
+        }
+        
+        // HTML tables don't support these
+        if ([attributeName isEqualToString:NSAccessibilitySelectedColumnsAttribute] || 
+            [attributeName isEqualToString:NSAccessibilitySelectedCellsAttribute])
+            return nil;
+        
+        if ([attributeName isEqualToString:(NSString *)kAXColumnHeaderUIElementsAttribute]) {
+            AccessibilityObject::AccessibilityChildrenVector columnHeaders;
+            static_cast<AccessibilityTable*>(m_object)->columnHeaders(columnHeaders);
+            return convertToNSArray(columnHeaders);            
+        }
+        
+        if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
+            AccessibilityObject* headerContainer = static_cast<AccessibilityTable*>(m_object)->headerContainer();
+            if (headerContainer)
+                return headerContainer->wrapper();
+            return nil;
+        }
+
+        if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
+            AccessibilityObject::AccessibilityChildrenVector rowHeaders;
+            static_cast<AccessibilityTable*>(m_object)->rowHeaders(rowHeaders);
+            return convertToNSArray(rowHeaders);                        
+        }
+        
+        if ([attributeName isEqualToString:NSAccessibilityVisibleCellsAttribute]) {
+            AccessibilityObject::AccessibilityChildrenVector cells;
+            static_cast<AccessibilityTable*>(m_object)->cells(cells);
+            return convertToNSArray(cells);
+        }        
+    }
+    
+    if (m_object->isTableColumn()) {
+        if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
+            return [NSNumber numberWithInt:static_cast<AccessibilityTableColumn*>(m_object)->columnIndex()];
+        
+        // rows attribute for a column is the list of all the elements in that column at each row
+        if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] || 
+            [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
+            return convertToNSArray(static_cast<AccessibilityTableColumn*>(m_object)->children());
+        }
+        if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
+            AccessibilityObject* header = static_cast<AccessibilityTableColumn*>(m_object)->headerObject();
+            if (!header)
+                return nil;
+            return header->wrapper();
+        }
+    }
+    
+    if (m_object->isTableCell()) {
+        if ([attributeName isEqualToString:NSAccessibilityRowIndexRangeAttribute]) {
+            pair<int, int> rowRange;
+            static_cast<AccessibilityTableCell*>(m_object)->rowIndexRange(rowRange);
+            return [NSValue valueWithRange:NSMakeRange(rowRange.first, rowRange.second)];
+        }  
+        if ([attributeName isEqualToString:NSAccessibilityColumnIndexRangeAttribute]) {
+            pair<int, int> columnRange;
+            static_cast<AccessibilityTableCell*>(m_object)->columnIndexRange(columnRange);
+            return [NSValue valueWithRange:NSMakeRange(columnRange.first, columnRange.second)];
+        }  
+    }
+    
+    if (m_object->isTree()) {
+        if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
+            AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
+            m_object->selectedChildren(selectedChildrenCopy);
+            return convertToNSArray(selectedChildrenCopy);
+        }
+        if ([attributeName isEqualToString:NSAccessibilityRowsAttribute]) {
+            AccessibilityObject::AccessibilityChildrenVector rowsCopy;
+            m_object->ariaTreeRows(rowsCopy);
+            return convertToNSArray(rowsCopy);            
+        }
+        
+        // TreeRoles do not support columns, but Mac AX expects to be able to ask about columns at the least.
+        if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute])
+            return [NSArray array];
+    }
+
+    if ([attributeName isEqualToString:NSAccessibilityIndexAttribute]) {
+        if (m_object->isTreeItem()) {
+            AccessibilityObject* parent = m_object->parentObject();
+            for (; parent && !parent->isTree(); parent = parent->parentObject())
+            { }
+            
+            if (!parent)
+                return nil;
+            
+            // Find the index of this item by iterating the parents.
+            AccessibilityObject::AccessibilityChildrenVector rowsCopy;
+            parent->ariaTreeRows(rowsCopy);
+            size_t count = rowsCopy.size();
+            for (size_t k = 0; k < count; ++k)
+                if (rowsCopy[k]->wrapper() == self)
+                    return [NSNumber numberWithUnsignedInt:k];
+            
+            return nil;
+        }
+        if (m_object->isTableRow()) {
+            if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
+                return [NSNumber numberWithInt:static_cast<AccessibilityTableRow*>(m_object)->rowIndex()];
+        }
+    }    
+    
+    // The rows that are considered inside this row. 
+    if ([attributeName isEqualToString:NSAccessibilityDisclosedRowsAttribute]) {
+        if (m_object->isTreeItem()) {
+            AccessibilityObject::AccessibilityChildrenVector rowsCopy;
+            m_object->ariaTreeItemDisclosedRows(rowsCopy);
+            return convertToNSArray(rowsCopy);    
+        } else if (m_object->isARIATreeGridRow()) {
+            AccessibilityObject::AccessibilityChildrenVector rowsCopy;
+            static_cast<AccessibilityARIAGridRow*>(m_object)->disclosedRows(rowsCopy);
+            return convertToNSArray(rowsCopy);    
+        }
+    }
+    
+    // The row that contains this row. It should be the same as the first parent that is a treeitem.
+    if ([attributeName isEqualToString:NSAccessibilityDisclosedByRowAttribute]) {
+        if (m_object->isTreeItem()) {
+            AccessibilityObject* parent = m_object->parentObject();
+            while (parent) {
+                if (parent->isTreeItem())
+                    return parent->wrapper();
+                // If the parent is the tree itself, then this value == nil.
+                if (parent->isTree())
+                    return nil;
+                parent = parent->parentObject();
+            }
+            return nil;
+        } else if (m_object->isARIATreeGridRow()) {
+            AccessibilityObject* row = static_cast<AccessibilityARIAGridRow*>(m_object)->disclosedByRow();
+            if (!row)
+                return nil;
+            return row->wrapper();
+        }
+    }
+
+    if ([attributeName isEqualToString:NSAccessibilityDisclosureLevelAttribute])
+        return [NSNumber numberWithInt:m_object->hierarchicalLevel()];
+    if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
+        return [NSNumber numberWithBool:m_object->isExpanded()];
+    
+    if ((m_object->isListBox() || m_object->isList()) && [attributeName isEqualToString:NSAccessibilityOrientationAttribute])
+        return NSAccessibilityVerticalOrientationValue;
+
+    if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
+        return [self textMarkerRangeForSelection];
+    
+    if (m_object->isAccessibilityRenderObject()) {
+        RenderObject* renderer = static_cast<AccessibilityRenderObject*>(m_object)->renderer();
+        if (!renderer)
+            return nil;
+        
+        if ([attributeName isEqualToString: @"AXStartTextMarker"])
+            return textMarkerForVisiblePosition(startOfDocument(renderer->document()));
+        if ([attributeName isEqualToString: @"AXEndTextMarker"])
+            return textMarkerForVisiblePosition(endOfDocument(renderer->document()));
+
+        if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute])
+            return [NSNumber numberWithInt:blockquoteLevel(renderer)];
+    } else {
+        if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute]) {
+            AccessibilityObject* parent = m_object->parentObjectUnignored();
+            if (!parent)
+                return [NSNumber numberWithInt:0];
+            return [parent->wrapper() accessibilityAttributeValue:NSAccessibilityBlockQuoteLevelAttribute];        
+        }
+    }
+    
+    if ([attributeName isEqualToString: NSAccessibilityLinkedUIElementsAttribute]) {
+        AccessibilityObject::AccessibilityChildrenVector linkedUIElements;
+        m_object->linkedUIElements(linkedUIElements);
+        if (linkedUIElements.size() == 0)
+            return nil;
+        return convertToNSArray(linkedUIElements);
+    }
+
+    if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
+        return [NSNumber numberWithBool:m_object->isSelected()];
+
+    if ([attributeName isEqualToString: NSAccessibilityServesAsTitleForUIElementsAttribute] && m_object->isMenuButton()) {
+        AccessibilityObject* uiElement = static_cast<AccessibilityRenderObject*>(m_object)->menuForMenuButton();
+        if (uiElement)
+            return [NSArray arrayWithObject:uiElement->wrapper()];
+    }
+
+    if ([attributeName isEqualToString:NSAccessibilityTitleUIElementAttribute]) {
+        AccessibilityObject* obj = m_object->titleUIElement();
+        if (obj)
+            return obj->wrapper();
+        return nil;
+    }
+    
+    if ([attributeName isEqualToString:NSAccessibilityValueDescriptionAttribute])
+        return m_object->valueDescription();
+    
+    if ([attributeName isEqualToString:NSAccessibilityOrientationAttribute]) {
+        AccessibilityOrientation elementOrientation = m_object->orientation();
+        if (elementOrientation == AccessibilityOrientationVertical)
+            return NSAccessibilityVerticalOrientationValue;
+        if (elementOrientation == AccessibilityOrientationHorizontal)
+            return NSAccessibilityHorizontalOrientationValue;
+        return nil;
+    }
+    
+    if ([attributeName isEqualToString:NSAccessibilityLanguageAttribute]) 
+        return m_object->language();
+    
+    if ([attributeName isEqualToString:NSAccessibilityExpandedAttribute])
+        return [NSNumber numberWithBool:m_object->isExpanded()];
+    
+    if ([attributeName isEqualToString:NSAccessibilityRequiredAttribute])
+        return [NSNumber numberWithBool:m_object->isRequired()];
+
+    if ([attributeName isEqualToString:NSAccessibilityOwnsAttribute]) {
+        AccessibilityObject::AccessibilityChildrenVector ariaOwns;
+        m_object->ariaOwnsElements(ariaOwns);
+        return convertToNSArray(ariaOwns);
+    }
+    
+    if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
+        return [NSNumber numberWithBool:m_object->isARIAGrabbed()];
+    
+    if ([attributeName isEqualToString:NSAccessibilityDropEffectsAttribute]) {
+        Vector<String> dropEffects;
+        m_object->determineARIADropEffects(dropEffects);
+        size_t length = dropEffects.size();
+
+        NSMutableArray* dropEffectsArray = [NSMutableArray arrayWithCapacity:length];
+        for (size_t i = 0; i < length; ++i)
+            [dropEffectsArray addObject:dropEffects[i]];
+        return dropEffectsArray;
+    }
+    
+    if ([attributeName isEqualToString:NSAccessibilityHasPopupAttribute])
+        return [NSNumber numberWithBool:m_object->ariaHasPopup()];
+    
+    // ARIA Live region attributes.
+    if ([attributeName isEqualToString:NSAccessibilityARIALiveAttribute])
+        return m_object->ariaLiveRegionStatus();
+    if ([attributeName isEqualToString:NSAccessibilityARIARelevantAttribute])
+         return m_object->ariaLiveRegionRelevant();
+    if ([attributeName isEqualToString:NSAccessibilityARIAAtomicAttribute])
+        return [NSNumber numberWithBool:m_object->ariaLiveRegionAtomic()];
+    if ([attributeName isEqualToString:NSAccessibilityARIABusyAttribute])
+        return [NSNumber numberWithBool:m_object->ariaLiveRegionBusy()];
+    
+    // this is used only by DumpRenderTree for testing
+    if ([attributeName isEqualToString:@"AXClickPoint"])
+        return [NSValue valueWithPoint:m_object->clickPoint()];
+    
+    return nil;
+}
+
+- (id)accessibilityFocusedUIElement
+{
+    if (!m_object)
+        return nil;
+
+    m_object->updateBackingStore();
+    if (!m_object)
+        return nil;
+
+    RefPtr<AccessibilityObject> focusedObj = m_object->focusedUIElement();
+
+    if (!focusedObj)
+        return nil;
+    
+    return focusedObj->wrapper();
+}
+
+- (id)accessibilityHitTest:(NSPoint)point
+{
+    if (!m_object)
+        return nil;
+
+    m_object->updateBackingStore();
+    if (!m_object)
+        return nil;
+
+    RefPtr<AccessibilityObject> axObject = m_object->doAccessibilityHitTest(IntPoint(point));
+    if (axObject)
+        return NSAccessibilityUnignoredAncestor(axObject->wrapper());
+    return NSAccessibilityUnignoredAncestor(self);
+}
+
+- (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName
+{
+    if (!m_object)
+        return nil;
+
+    m_object->updateBackingStore();
+    if (!m_object)
+        return nil;
+
+    if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
+        return YES;
+
+    if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
+        return m_object->canSetFocusAttribute();
+
+    if ([attributeName isEqualToString: NSAccessibilityValueAttribute])
+        return m_object->canSetValueAttribute();
+
+    if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
+        return m_object->canSetSelectedAttribute();
+    
+    if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute])
+        return m_object->canSetSelectedChildrenAttribute();
+
+    if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
+        return m_object->canSetExpandedAttribute();
+
+    if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute])
+        return YES;
+
+    if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute] ||
+        [attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute] ||
+        [attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
+        return m_object->canSetTextRangeAttributes();
+    
+    if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
+        return YES;
+    
+    return NO;
+}
+
+// accessibilityShouldUseUniqueId is an AppKit method we override so that
+// objects will be given a unique ID, and therefore allow AppKit to know when they
+// become obsolete (e.g. when the user navigates to a new web page, making this one
+// unrendered but not deallocated because it is in the back/forward cache).
+// It is important to call NSAccessibilityUnregisterUniqueIdForUIElement in the
+// appropriate place (e.g. dealloc) to remove these non-retained references from
+// AppKit's id mapping tables. We do this in detach by calling unregisterUniqueIdForUIElement.
+//
+// Registering an object is also required for observing notifications. Only registered objects can be observed.
+- (BOOL)accessibilityIsIgnored
+{
+    if (!m_object)
+        return nil;
+
+    m_object->updateBackingStore();
+    if (!m_object)
+        return nil;
+
+    if (m_object->isAttachment())
+        return [[self attachmentView] accessibilityIsIgnored];
+    return m_object->accessibilityIsIgnored();
+}
+
+- (NSArray* )accessibilityParameterizedAttributeNames
+{
+    if (!m_object)
+        return nil;
+
+    m_object->updateBackingStore();
+    if (!m_object)
+        return nil;
+
+    if (m_object->isAttachment()) 
+        return nil;
+
+    static NSArray* paramAttrs = nil;
+    static NSArray* textParamAttrs = nil;
+    static NSArray* tableParamAttrs = nil;
+    if (paramAttrs == nil) {
+        paramAttrs = [[NSArray alloc] initWithObjects:
+                      @"AXUIElementForTextMarker",
+                      @"AXTextMarkerRangeForUIElement",
+                      @"AXLineForTextMarker",
+                      @"AXTextMarkerRangeForLine",
+                      @"AXStringForTextMarkerRange",
+                      @"AXTextMarkerForPosition",
+                      @"AXBoundsForTextMarkerRange",
+                      @"AXAttributedStringForTextMarkerRange",
+                      @"AXTextMarkerRangeForUnorderedTextMarkers",
+                      @"AXNextTextMarkerForTextMarker",
+                      @"AXPreviousTextMarkerForTextMarker",
+                      @"AXLeftWordTextMarkerRangeForTextMarker",
+                      @"AXRightWordTextMarkerRangeForTextMarker",
+                      @"AXLeftLineTextMarkerRangeForTextMarker",
+                      @"AXRightLineTextMarkerRangeForTextMarker",
+                      @"AXSentenceTextMarkerRangeForTextMarker",
+                      @"AXParagraphTextMarkerRangeForTextMarker",
+                      @"AXNextWordEndTextMarkerForTextMarker",
+                      @"AXPreviousWordStartTextMarkerForTextMarker",
+                      @"AXNextLineEndTextMarkerForTextMarker",
+                      @"AXPreviousLineStartTextMarkerForTextMarker",
+                      @"AXNextSentenceEndTextMarkerForTextMarker",
+                      @"AXPreviousSentenceStartTextMarkerForTextMarker",
+                      @"AXNextParagraphEndTextMarkerForTextMarker",
+                      @"AXPreviousParagraphStartTextMarkerForTextMarker",
+                      @"AXStyleTextMarkerRangeForTextMarker",
+                      @"AXLengthForTextMarkerRange",
+                      NSAccessibilityBoundsForRangeParameterizedAttribute,
+                      NSAccessibilityStringForRangeParameterizedAttribute,
+                      nil];
+    }
+
+    if (textParamAttrs == nil) {
+        NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
+        [tempArray addObject:(NSString*)kAXLineForIndexParameterizedAttribute];
+        [tempArray addObject:(NSString*)kAXRangeForLineParameterizedAttribute];
+        [tempArray addObject:(NSString*)kAXStringForRangeParameterizedAttribute];
+        [tempArray addObject:(NSString*)kAXRangeForPositionParameterizedAttribute];
+        [tempArray addObject:(NSString*)kAXRangeForIndexParameterizedAttribute];
+        [tempArray addObject:(NSString*)kAXBoundsForRangeParameterizedAttribute];
+        [tempArray addObject:(NSString*)kAXRTFForRangeParameterizedAttribute];
+        [tempArray addObject:(NSString*)kAXAttributedStringForRangeParameterizedAttribute];
+        [tempArray addObject:(NSString*)kAXStyleRangeForIndexParameterizedAttribute];
+        textParamAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    if (tableParamAttrs == nil) {
+        NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
+        [tempArray addObject:NSAccessibilityCellForColumnAndRowParameterizedAttribute];
+        tableParamAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
+    
+    if (m_object->isPasswordField())
+        return [NSArray array];
+    
+    if (!m_object->isAccessibilityRenderObject())
+        return paramAttrs;
+
+    if (m_object->isTextControl())
+        return textParamAttrs;
+    
+    if (m_object->isDataTable())
+        return tableParamAttrs;
+    
+    if (m_object->isMenuRelated())
+        return nil;
+
+    return paramAttrs;
+}
+
+- (void)accessibilityPerformPressAction
+{
+    if (!m_object)
+        return;
+
+    m_object->updateBackingStore();
+    if (!m_object)
+        return;
+
+    if (m_object->isAttachment())
+        [[self attachmentView] accessibilityPerformAction:NSAccessibilityPressAction];
+    else
+        m_object->press();    
+}
+
+- (void)accessibilityPerformIncrementAction
+{
+    if (!m_object)
+        return;
+
+    m_object->updateBackingStore();
+    if (!m_object)
+        return;
+
+    if (m_object->isAttachment())
+        [[self attachmentView] accessibilityPerformAction:NSAccessibilityIncrementAction];
+    else
+        m_object->increment();    
+}
+
+- (void)accessibilityPerformDecrementAction
+{
+    if (!m_object)
+        return;
+
+    m_object->updateBackingStore();
+    if (!m_object)
+        return;
+
+    if (m_object->isAttachment())
+        [[self attachmentView] accessibilityPerformAction:NSAccessibilityDecrementAction];
+    else
+        m_object->decrement();    
+}
+
+- (void)accessibilityPerformShowMenuAction
+{
+    if (m_object->roleValue() == ComboBoxRole)
+        m_object->setIsExpanded(true);
+    else {
+        // This needs to be performed in an iteration of the run loop that did not start from an AX call. 
+        // If it's the same run loop iteration, the menu open notification won't be sent
+        [self performSelector:@selector(accessibilityShowContextMenu) withObject:nil afterDelay:0.0];
+    }
+}
+
+- (void)accessibilityShowContextMenu
+{    
+    FrameView* frameView = m_object->documentFrameView();
+    if (!frameView)
+        return;
+
+    // simulate a click in the middle of the object
+    IntPoint clickPoint = m_object->clickPoint();
+    NSPoint nsClickPoint = NSMakePoint(clickPoint.x(), clickPoint.y());
+    
+    NSView* view = nil;
+    if (m_object->isAttachment())
+        view = [self attachmentView];
+    else
+        view = frameView->documentView();
+    
+    if (!view)
+        return;
+    
+    NSPoint nsScreenPoint = [view convertPoint:nsClickPoint toView:nil];
+    
+    // Show the contextual menu for this event.
+    NSEvent* event = [NSEvent mouseEventWithType:NSRightMouseDown location:nsScreenPoint modifierFlags:0 timestamp:0 windowNumber:[[view window] windowNumber] context:0 eventNumber:0 clickCount:1 pressure:1];
+    NSMenu* menu = [view menuForEvent:event];
+    
+    if (menu)
+        [NSMenu popUpContextMenu:menu withEvent:event forView:view];    
+}
+
+- (void)accessibilityPerformAction:(NSString*)action
+{
+    if (!m_object)
+        return;
+
+    m_object->updateBackingStore();
+    if (!m_object)
+        return;
+
+    if ([action isEqualToString:NSAccessibilityPressAction])
+        [self accessibilityPerformPressAction];
+    
+    else if ([action isEqualToString:NSAccessibilityShowMenuAction])
+        [self accessibilityPerformShowMenuAction];
+
+    else if ([action isEqualToString:NSAccessibilityIncrementAction])
+        [self accessibilityPerformIncrementAction];
+
+    else if ([action isEqualToString:NSAccessibilityDecrementAction])
+        [self accessibilityPerformDecrementAction];
+}
+
+- (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attributeName
+{
+    if (!m_object)
+        return;
+
+    m_object->updateBackingStore();
+    if (!m_object)
+        return;
+
+    WebCoreTextMarkerRange* textMarkerRange = nil;
+    NSNumber*               number = nil;
+    NSString*               string = nil;
+    NSRange                 range = {0, 0};
+    NSArray*                array = nil;
+    
+    // decode the parameter
+    if ([[WebCoreViewFactory sharedFactory] objectIsTextMarkerRange:value])
+        textMarkerRange = (WebCoreTextMarkerRange*) value;
+
+    else if ([value isKindOfClass:[NSNumber self]])
+        number = value;
+
+    else if ([value isKindOfClass:[NSString self]])
+        string = value;
+    
+    else if ([value isKindOfClass:[NSValue self]])
+        range = [value rangeValue];
+    
+    else if ([value isKindOfClass:[NSArray self]])
+        array = value;
+    
+    // handle the command
+    if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"]) {
+        ASSERT(textMarkerRange);
+        m_object->setSelectedVisiblePositionRange([self visiblePositionRangeForTextMarkerRange:textMarkerRange]);        
+    } else if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute]) {
+        ASSERT(number);
+        m_object->setFocused([number intValue] != 0);
+    } else if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
+        if (!string)
+            return;
+        m_object->setValue(string);
+    } else if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute]) {
+        if (!number)
+            return;
+        m_object->setSelected([number boolValue]);
+    } else if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {
+        if (!array || m_object->roleValue() != ListBoxRole)
+            return;
+        AccessibilityObject::AccessibilityChildrenVector selectedChildren;
+        convertToVector(array, selectedChildren);
+        static_cast<AccessibilityListBox*>(m_object)->setSelectedChildren(selectedChildren);
+    } else if (m_object->isTextControl()) {
+        if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
+            m_object->setSelectedText(string);
+        } else if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
+            m_object->setSelectedTextRange(PlainTextRange(range.location, range.length));
+        } else if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute]) {
+            m_object->makeRangeVisible(PlainTextRange(range.location, range.length));
+        }
+    } else if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
+        m_object->setIsExpanded([number boolValue]);
+    else if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
+        AccessibilityObject::AccessibilityChildrenVector selectedRows;
+        convertToVector(array, selectedRows);
+        if (m_object->isTree() || m_object->isDataTable())
+            m_object->setSelectedRows(selectedRows);
+    } else if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
+        m_object->setARIAGrabbed([number boolValue]);
+}
+
+static RenderObject* rendererForView(NSView* view)
+{
+    if (![view conformsToProtocol:@protocol(WebCoreFrameView)])
+        return 0;
+
+    NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view;
+    Frame* frame = [frameView _web_frame];
+    if (!frame)
+        return 0;
+
+    Node* node = frame->document()->ownerElement();
+    if (!node)
+        return 0;
+
+    return node->renderer();
+}
+
+- (id)_accessibilityParentForSubview:(NSView*)subview
+{   
+    RenderObject* renderer = rendererForView(subview);
+    if (!renderer)
+        return nil;
+
+    AccessibilityObject* obj = renderer->document()->axObjectCache()->getOrCreate(renderer);
+    if (obj)
+        return obj->parentObjectUnignored()->wrapper();
+    return nil;
+}
+
+- (NSString*)accessibilityActionDescription:(NSString*)action
+{
+    // we have no custom actions
+    return NSAccessibilityActionDescription(action);
+}
+
+// The CFAttributedStringType representation of the text associated with this accessibility
+// object that is specified by the given range.
+- (NSAttributedString*)doAXAttributedStringForRange:(NSRange)range
+{
+    PlainTextRange textRange = PlainTextRange(range.location, range.length);
+    VisiblePositionRange visiblePosRange = m_object->visiblePositionRangeForRange(textRange);
+    return [self doAXAttributedStringForTextMarkerRange:textMarkerRangeFromVisiblePositions(visiblePosRange.start, visiblePosRange.end)];
+}
+
+// The RTF representation of the text associated with this accessibility object that is
+// specified by the given range.
+- (NSData*)doAXRTFForRange:(NSRange)range
+{
+    NSAttributedString* attrString = [self doAXAttributedStringForRange:range];
+    return [attrString RTFFromRange: NSMakeRange(0, [attrString length]) documentAttributes: nil];
+}
+
+- (id)accessibilityAttributeValue:(NSString*)attribute forParameter:(id)parameter
+{
+    WebCoreTextMarker* textMarker = nil;
+    WebCoreTextMarkerRange* textMarkerRange = nil;
+    NSNumber* number = nil;
+    NSArray* array = nil;
+    RefPtr<AccessibilityObject> uiElement = 0;
+    NSPoint point = NSZeroPoint;
+    bool pointSet = false;
+    NSRange range = {0, 0};
+    bool rangeSet = false;
+    
+    // basic parameter validation
+    if (!m_object || !attribute || !parameter)
+        return nil;
+
+    m_object->updateBackingStore();
+    if (!m_object)
+        return nil;
+    
+    // common parameter type check/casting.  Nil checks in handlers catch wrong type case.
+    // NOTE: This assumes nil is not a valid parameter, because it is indistinguishable from
+    // a parameter of the wrong type.
+    if ([[WebCoreViewFactory sharedFactory] objectIsTextMarker:parameter])
+        textMarker = (WebCoreTextMarker*) parameter;
+
+    else if ([[WebCoreViewFactory sharedFactory] objectIsTextMarkerRange:parameter])
+        textMarkerRange = (WebCoreTextMarkerRange*) parameter;
+
+    else if ([parameter isKindOfClass:[AccessibilityObjectWrapper self]])
+        uiElement = [(AccessibilityObjectWrapper*)parameter accessibilityObject];
+
+    else if ([parameter isKindOfClass:[NSNumber self]])
+        number = parameter;
+
+    else if ([parameter isKindOfClass:[NSArray self]])
+        array = parameter;
+
+    else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSPoint)) == 0) {
+        pointSet = true;
+        point = [(NSValue*)parameter pointValue];
+
+    } else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSRange)) == 0) {
+        rangeSet = true;
+        range = [(NSValue*)parameter rangeValue];
+    } else {
+        // Attribute type is not supported. Allow super to handle.
+        return [super accessibilityAttributeValue:attribute forParameter:parameter];
+    }
+    
+    // dispatch
+    if ([attribute isEqualToString: @"AXUIElementForTextMarker"]) {
+        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        return m_object->accessibilityObjectForPosition(visiblePos)->wrapper();
+    }
+
+    if ([attribute isEqualToString: @"AXTextMarkerRangeForUIElement"]) {
+        VisiblePositionRange vpRange = uiElement.get()->visiblePositionRange();
+        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+    }
+
+    if ([attribute isEqualToString: @"AXLineForTextMarker"]) {
+        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        return [NSNumber numberWithUnsignedInt:m_object->lineForPosition(visiblePos)];
+    }
+
+    if ([attribute isEqualToString: @"AXTextMarkerRangeForLine"]) {
+        VisiblePositionRange vpRange = m_object->visiblePositionRangeForLine([number intValue]);
+        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+    }
+
+    if ([attribute isEqualToString: @"AXStringForTextMarkerRange"]) {
+        VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
+        return m_object->stringForVisiblePositionRange(visiblePosRange);
+    }
+
+    if ([attribute isEqualToString: @"AXTextMarkerForPosition"]) {
+        IntPoint webCorePoint = IntPoint(point);
+        return pointSet ? textMarkerForVisiblePosition(m_object->visiblePositionForPoint(webCorePoint)) : nil;
+    }
+
+    if ([attribute isEqualToString: @"AXBoundsForTextMarkerRange"]) {
+        VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
+        NSRect rect = m_object->boundsForVisiblePositionRange(visiblePosRange);
+        return [NSValue valueWithRect:rect];
+    }
+    
+    if ([attribute isEqualToString:NSAccessibilityBoundsForRangeParameterizedAttribute]) {
+        VisiblePosition start = m_object->visiblePositionForIndex(range.location);
+        VisiblePosition end = m_object->visiblePositionForIndex(range.location+range.length);
+        if (start.isNull() || end.isNull())
+            return nil;
+        NSRect rect = m_object->boundsForVisiblePositionRange(VisiblePositionRange(start, end));
+        return [NSValue valueWithRect:rect];
+    }
+    
+    if ([attribute isEqualToString:NSAccessibilityStringForRangeParameterizedAttribute]) {
+        VisiblePosition start = m_object->visiblePositionForIndex(range.location);
+        VisiblePosition end = m_object->visiblePositionForIndex(range.location+range.length);
+        if (start.isNull() || end.isNull())
+            return nil;
+        return m_object->stringForVisiblePositionRange(VisiblePositionRange(start, end));
+    }
+
+    if ([attribute isEqualToString: @"AXAttributedStringForTextMarkerRange"])
+        return [self doAXAttributedStringForTextMarkerRange:textMarkerRange];
+
+    if ([attribute isEqualToString: @"AXTextMarkerRangeForUnorderedTextMarkers"]) {
+        if ([array count] < 2)
+            return nil;
+
+        WebCoreTextMarker* textMarker1 = (WebCoreTextMarker*) [array objectAtIndex:0];
+        WebCoreTextMarker* textMarker2 = (WebCoreTextMarker*) [array objectAtIndex:1];
+        if (![[WebCoreViewFactory sharedFactory] objectIsTextMarker:textMarker1] 
+            || ![[WebCoreViewFactory sharedFactory] objectIsTextMarker:textMarker2])
+            return nil;
+
+        VisiblePosition visiblePos1 = visiblePositionForTextMarker(textMarker1);
+        VisiblePosition visiblePos2 = visiblePositionForTextMarker(textMarker2);
+        VisiblePositionRange vpRange = m_object->visiblePositionRangeForUnorderedPositions(visiblePos1, visiblePos2);
+        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+    }
+
+    if ([attribute isEqualToString: @"AXNextTextMarkerForTextMarker"]) {
+        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        return textMarkerForVisiblePosition(m_object->nextVisiblePosition(visiblePos));
+    }
+
+    if ([attribute isEqualToString: @"AXPreviousTextMarkerForTextMarker"]) {
+        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        return textMarkerForVisiblePosition(m_object->previousVisiblePosition(visiblePos));
+    }
+
+    if ([attribute isEqualToString: @"AXLeftWordTextMarkerRangeForTextMarker"]) {
+        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        VisiblePositionRange vpRange = m_object->positionOfLeftWord(visiblePos);
+        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+    }
+
+    if ([attribute isEqualToString: @"AXRightWordTextMarkerRangeForTextMarker"]) {
+        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        VisiblePositionRange vpRange = m_object->positionOfRightWord(visiblePos);
+        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+    }
+
+    if ([attribute isEqualToString: @"AXLeftLineTextMarkerRangeForTextMarker"]) {
+        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        VisiblePositionRange vpRange = m_object->leftLineVisiblePositionRange(visiblePos);
+        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+    }
+
+    if ([attribute isEqualToString: @"AXRightLineTextMarkerRangeForTextMarker"]) {
+        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        VisiblePositionRange vpRange = m_object->rightLineVisiblePositionRange(visiblePos);
+        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+    }
+
+    if ([attribute isEqualToString: @"AXSentenceTextMarkerRangeForTextMarker"]) {
+        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        VisiblePositionRange vpRange = m_object->sentenceForPosition(visiblePos);
+        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+    }
+
+    if ([attribute isEqualToString: @"AXParagraphTextMarkerRangeForTextMarker"]) {
+        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        VisiblePositionRange vpRange = m_object->paragraphForPosition(visiblePos);
+        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+    }
+
+    if ([attribute isEqualToString: @"AXNextWordEndTextMarkerForTextMarker"]) {
+        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        return textMarkerForVisiblePosition(m_object->nextWordEnd(visiblePos));
+    }
+    
+    if ([attribute isEqualToString: @"AXPreviousWordStartTextMarkerForTextMarker"]) {
+        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        return textMarkerForVisiblePosition(m_object->previousWordStart(visiblePos));
+    }
+
+    if ([attribute isEqualToString: @"AXNextLineEndTextMarkerForTextMarker"]) {
+        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        return textMarkerForVisiblePosition(m_object->nextLineEndPosition(visiblePos));
+    }
+
+    if ([attribute isEqualToString: @"AXPreviousLineStartTextMarkerForTextMarker"]) {
+        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        return textMarkerForVisiblePosition(m_object->previousLineStartPosition(visiblePos));
+    }
+
+    if ([attribute isEqualToString: @"AXNextSentenceEndTextMarkerForTextMarker"]) {
+        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        return textMarkerForVisiblePosition(m_object->nextSentenceEndPosition(visiblePos));
+    }
+
+    if ([attribute isEqualToString: @"AXPreviousSentenceStartTextMarkerForTextMarker"]) {
+        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        return textMarkerForVisiblePosition(m_object->previousSentenceStartPosition(visiblePos));
+    }
+
+    if ([attribute isEqualToString: @"AXNextParagraphEndTextMarkerForTextMarker"]) {
+        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        return textMarkerForVisiblePosition(m_object->nextParagraphEndPosition(visiblePos));
+    }
+
+    if ([attribute isEqualToString: @"AXPreviousParagraphStartTextMarkerForTextMarker"]) {
+        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        return textMarkerForVisiblePosition(m_object->previousParagraphStartPosition(visiblePos));
+    }
+
+    if ([attribute isEqualToString: @"AXStyleTextMarkerRangeForTextMarker"]) {
+        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        VisiblePositionRange vpRange = m_object->styleRangeForPosition(visiblePos);
+        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+    }
+
+    if ([attribute isEqualToString: @"AXLengthForTextMarkerRange"]) {
+        VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
+        int length = m_object->lengthForVisiblePositionRange(visiblePosRange);
+        if (length < 0)
+            return nil;
+        return [NSNumber numberWithInt:length];
+    }
+
+    if (m_object->isDataTable()) {
+        if ([attribute isEqualToString:NSAccessibilityCellForColumnAndRowParameterizedAttribute]) {
+            if (array == nil || [array count] != 2)
+                return nil;
+            AccessibilityTableCell* cell = static_cast<AccessibilityTable*>(m_object)->cellForColumnAndRow([[array objectAtIndex:0] unsignedIntValue], [[array objectAtIndex:1] unsignedIntValue]);
+            if (!cell)
+                return nil;
+            
+            return cell->wrapper();
+        }
+    }
+
+    if (m_object->isTextControl()) {
+        if ([attribute isEqualToString: (NSString *)kAXLineForIndexParameterizedAttribute]) {
+            int lineNumber = m_object->doAXLineForIndex([number intValue]);
+            if (lineNumber < 0)
+                return nil;
+            return [NSNumber numberWithUnsignedInt:lineNumber];
+        }
+
+        if ([attribute isEqualToString: (NSString *)kAXRangeForLineParameterizedAttribute]) {
+            PlainTextRange textRange = m_object->doAXRangeForLine([number intValue]);
+            return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];
+        }
+
+        if ([attribute isEqualToString: (NSString*)kAXStringForRangeParameterizedAttribute]) {
+            PlainTextRange plainTextRange = PlainTextRange(range.location, range.length);
+            return rangeSet ? (id)(m_object->doAXStringForRange(plainTextRange)) : nil;
+        }
+
+        if ([attribute isEqualToString: (NSString*)kAXRangeForPositionParameterizedAttribute]) {
+            if (!pointSet)
+                return nil;
+            IntPoint webCorePoint = IntPoint(point);
+            PlainTextRange textRange = m_object->doAXRangeForPosition(webCorePoint);
+            return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];
+        }
+
+        if ([attribute isEqualToString: (NSString*)kAXRangeForIndexParameterizedAttribute]) {
+            PlainTextRange textRange = m_object->doAXRangeForIndex([number intValue]);
+            return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];
+        }
+
+        if ([attribute isEqualToString: (NSString*)kAXBoundsForRangeParameterizedAttribute]) {
+            if (!rangeSet)
+                return nil;
+            PlainTextRange plainTextRange = PlainTextRange(range.location, range.length);
+            NSRect rect = m_object->doAXBoundsForRange(plainTextRange);
+            return [NSValue valueWithRect:rect];
+        }
+
+        if ([attribute isEqualToString: (NSString*)kAXRTFForRangeParameterizedAttribute])
+            return rangeSet ? [self doAXRTFForRange:range] : nil;
+
+        if ([attribute isEqualToString: (NSString*)kAXAttributedStringForRangeParameterizedAttribute])
+            return rangeSet ? [self doAXAttributedStringForRange:range] : nil;
+
+        if ([attribute isEqualToString: (NSString*)kAXStyleRangeForIndexParameterizedAttribute]) {
+            PlainTextRange textRange = m_object->doAXStyleRangeForIndex([number intValue]);
+            return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];
+        }
+    }
+
+    // There are some parameters that super handles that are not explicitly returned by the list of the element's attributes.
+    // In that case it must be passed to super. 
+    return [super accessibilityAttributeValue:attribute forParameter:parameter];
+}
+
+- (BOOL)accessibilityShouldUseUniqueId
+{
+    return m_object->accessibilityShouldUseUniqueId();
+}
+
+// API that AppKit uses for faster access
+- (NSUInteger)accessibilityIndexOfChild:(id)child
+{
+    if (!m_object)
+        return NSNotFound;
+
+    m_object->updateBackingStore();
+    if (!m_object)
+        return NSNotFound;
+    
+    // Tree objects return their rows as their children. We can use the original method
+    // here, because we won't gain any speed up.
+    if (m_object->isTree())
+        return [super accessibilityIndexOfChild:child];
+       
+    const AccessibilityObject::AccessibilityChildrenVector& children = m_object->children();
+       
+    if (children.isEmpty())
+        return [[self renderWidgetChildren] indexOfObject:child];
+    
+    unsigned count = children.size();
+    for (unsigned k = 0; k < count; ++k) {
+        AccessibilityObjectWrapper* wrapper = children[k]->wrapper();
+        if (wrapper == child || (children[k]->isAttachment() && [wrapper attachmentView] == child)) 
+            return k;
+    }
+
+    return NSNotFound;
+}
+
+- (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute
+{
+    if (!m_object)
+        return 0;
+
+    m_object->updateBackingStore();
+    if (!m_object)
+        return 0;
+    
+    if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
+        // Tree items object returns a different set of children than those that are in children()
+        // because an AXOutline (the mac role is becomes) has some odd stipulations.
+        if (m_object->isTree() || m_object->isTreeItem())
+            return [[self accessibilityAttributeValue:NSAccessibilityChildrenAttribute] count];
+        
+        const AccessibilityObject::AccessibilityChildrenVector& children = m_object->children();
+        if (children.isEmpty())
+            return [[self renderWidgetChildren] count];
+        
+        return children.size();
+    }
+    
+    return [super accessibilityArrayAttributeCount:attribute];
+}
+
+- (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount 
+{
+    if (!m_object)
+        return nil;
+
+    m_object->updateBackingStore();
+    if (!m_object)
+        return nil;
+    
+    if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
+        if (m_object->children().isEmpty()) {
+            NSArray *children = [self renderWidgetChildren];
+            if (!children) 
+                return nil;
+            
+            NSUInteger childCount = [children count];
+            if (index >= childCount)
+                return nil;
+            
+            NSUInteger arrayLength = min(childCount - index, maxCount);
+            return [children subarrayWithRange:NSMakeRange(index, arrayLength)];
+        } else if (m_object->isTree()) {
+            // Tree objects return their rows as their children. We can use the original method in this case.
+            return [super accessibilityArrayAttributeValues:attribute index:index maxCount:maxCount];
+        }
+        
+        const AccessibilityObject::AccessibilityChildrenVector& children = m_object->children();
+        unsigned childCount = children.size();
+        if (index >= childCount)
+            return nil;
+        
+        unsigned available = min(childCount - index, maxCount);
+        
+        NSMutableArray *subarray = [NSMutableArray arrayWithCapacity:available];
+        for (unsigned added = 0; added < available; ++index, ++added) {
+            AccessibilityObjectWrapper* wrapper = children[index]->wrapper();
+            if (wrapper) {
+                // The attachment view should be returned, otherwise AX palindrome errors occur.
+                if (children[index]->isAttachment() && [wrapper attachmentView])
+                    [subarray addObject:[wrapper attachmentView]];
+                else
+                    [subarray addObject:wrapper];
+            }
+        }
+        
+        return subarray;
+    }
+    
+    return [super accessibilityArrayAttributeValues:attribute index:index maxCount:maxCount];
+}
+
+// This is set by DRT when it wants to listen for notifications.
+static BOOL accessibilityShouldRepostNotifications;
+- (void)accessibilitySetShouldRepostNotifications:(BOOL)repost
+{
+    accessibilityShouldRepostNotifications = repost;
+}
+
+- (void)accessibilityPostedNotification:(NSString *)notificationName
+{
+    if (accessibilityShouldRepostNotifications) {
+        NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:notificationName, @"notificationName", nil];
+        [[NSNotificationCenter defaultCenter] postNotificationName:@"AXDRTNotification" object:nil userInfo:userInfo];
+    }
+}
+
+@end
+
+#endif // HAVE(ACCESSIBILITY)