Index: content/browser/accessibility/browser_accessibility_cocoa.mm |
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm |
index 1007e5e653b6a8e8e61f37ff536503b75a5ac084..84cf94c6b60ead6006ce42828c9dc9df53c200f1 100644 |
--- a/content/browser/accessibility/browser_accessibility_cocoa.mm |
+++ b/content/browser/accessibility/browser_accessibility_cocoa.mm |
@@ -552,34 +552,69 @@ bool InitializeAccessibilityTreeSearch( |
} |
- (NSString*)description { |
- std::string description; |
- if (browserAccessibility_->GetStringAttribute( |
- ui::AX_ATTR_DESCRIPTION, &description)) { |
- return base::SysUTF8ToNSString(description); |
- } |
- |
- // If the role is anything other than an image, or if there's |
- // a title or title UI element, just return an empty string. |
- if (![[self role] isEqualToString:NSAccessibilityImageRole]) |
+ // Mac OS X wants static text exposed in AXValue. |
+ if ([self shouldExposeNameInAXValue]) |
return @""; |
- if (browserAccessibility_->HasStringAttribute( |
- ui::AX_ATTR_NAME)) { |
+ |
+ // If the name came from a single related element and it's present in the |
+ // tree, it will be exposed in AXTitleUIElement. |
+ std::vector<int32> labelledby_ids = |
+ browserAccessibility_->GetIntListAttribute(ui::AX_ATTR_LABELLEDBY_IDS); |
+ ui::AXNameFrom nameFrom = static_cast<ui::AXNameFrom>( |
+ browserAccessibility_->GetIntAttribute(ui::AX_ATTR_NAME_FROM)); |
+ if (nameFrom == ui::AX_NAME_FROM_RELATED_ELEMENT && |
+ labelledby_ids.size() == 1 && |
+ browserAccessibility_->manager()->GetFromID(labelledby_ids[0])) { |
return @""; |
} |
- if ([self titleUIElement]) |
- return @""; |
- // The remaining case is an image where there's no other title. |
- // Return the base part of the filename as the description. |
- std::string url; |
- if (browserAccessibility_->GetStringAttribute( |
- ui::AX_ATTR_URL, &url)) { |
- // Given a url like http://foo.com/bar/baz.png, just return the |
- // base name, e.g., "baz.png". |
- size_t leftIndex = url.rfind('/'); |
- std::string basename = |
- leftIndex != std::string::npos ? url.substr(leftIndex) : url; |
- return base::SysUTF8ToNSString(basename); |
+ std::string name = browserAccessibility_->GetStringAttribute( |
+ ui::AX_ATTR_NAME); |
+ if (!name.empty()) { |
+ // On Mac OS X, the accessible name of an object is exposed as its |
+ // title if it comes from visible text, and as its description |
+ // otherwise, but never both. |
+ if (nameFrom == ui::AX_NAME_FROM_CONTENTS || |
+ nameFrom == ui::AX_NAME_FROM_RELATED_ELEMENT || |
+ nameFrom == ui::AX_NAME_FROM_VALUE) { |
+ return @""; |
+ } else { |
+ return base::SysUTF8ToNSString(name); |
+ } |
+ } |
+ |
+ // Given an image where there's no other title, return the base part |
+ // of the filename as the description. |
+ if ([[self role] isEqualToString:NSAccessibilityImageRole]) { |
+ if (browserAccessibility_->HasStringAttribute(ui::AX_ATTR_NAME)) |
+ return @""; |
+ if ([self titleUIElement]) |
+ return @""; |
+ |
+ std::string url; |
+ if (browserAccessibility_->GetStringAttribute( |
+ ui::AX_ATTR_URL, &url)) { |
+ // Given a url like http://foo.com/bar/baz.png, just return the |
+ // base name, e.g., "baz.png". |
+ size_t leftIndex = url.rfind('/'); |
+ std::string basename = |
+ leftIndex != std::string::npos ? url.substr(leftIndex) : url; |
+ return base::SysUTF8ToNSString(basename); |
+ } |
+ } |
+ |
+ // If it's focusable but didn't have any other name or value, compute a name |
+ // from its descendants. |
+ std::string value = browserAccessibility_->GetStringAttribute( |
+ ui::AX_ATTR_VALUE); |
+ if (browserAccessibility_->HasState(ui::AX_STATE_FOCUSABLE) && |
+ !browserAccessibility_->IsControl() && |
+ value.empty() && |
+ [self internalRole] != ui::AX_ROLE_DATE_TIME && |
+ [self internalRole] != ui::AX_ROLE_WEB_AREA && |
+ [self internalRole] != ui::AX_ROLE_ROOT_WEB_AREA) { |
+ return base::SysUTF8ToNSString( |
+ browserAccessibility_->ComputeAccessibleNameFromDescendants()); |
} |
return @""; |
@@ -679,7 +714,7 @@ bool InitializeAccessibilityTreeSearch( |
- (NSString*)help { |
return NSStringForStringAttribute( |
- browserAccessibility_, ui::AX_ATTR_HELP); |
+ browserAccessibility_, ui::AX_ATTR_DESCRIPTION); |
} |
- (NSNumber*)index { |
@@ -735,6 +770,20 @@ bool InitializeAccessibilityTreeSearch( |
} |
- (NSString*)placeholderValue { |
+ ui::AXNameFrom nameFrom = static_cast<ui::AXNameFrom>( |
+ browserAccessibility_->GetIntAttribute(ui::AX_ATTR_NAME_FROM)); |
+ if (nameFrom == ui::AX_NAME_FROM_PLACEHOLDER) { |
+ return NSStringForStringAttribute( |
+ browserAccessibility_, ui::AX_ATTR_NAME); |
+ } |
+ |
+ ui::AXDescriptionFrom descriptionFrom = static_cast<ui::AXDescriptionFrom>( |
+ browserAccessibility_->GetIntAttribute(ui::AX_ATTR_DESCRIPTION_FROM)); |
+ if (descriptionFrom == ui::AX_DESCRIPTION_FROM_PLACEHOLDER) { |
+ return NSStringForStringAttribute( |
+ browserAccessibility_, ui::AX_ATTR_DESCRIPTION); |
+ } |
+ |
return NSStringForStringAttribute( |
browserAccessibility_, ui::AX_ATTR_PLACEHOLDER); |
} |
@@ -753,7 +802,6 @@ bool InitializeAccessibilityTreeSearch( |
- (NSArray*)linkedUIElements { |
NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease]; |
- [self addLinkedUIElementsFromAttribute:ui::AX_ATTR_OWNS_IDS addTo:ret]; |
[self addLinkedUIElementsFromAttribute:ui::AX_ATTR_CONTROLS_IDS addTo:ret]; |
[self addLinkedUIElementsFromAttribute:ui::AX_ATTR_FLOWTO_IDS addTo:ret]; |
if ([ret count] == 0) |
@@ -837,6 +885,19 @@ bool InitializeAccessibilityTreeSearch( |
return static_cast<ui::AXRole>(browserAccessibility_->GetRole()); |
} |
+// Returns true if this should expose its accessible name in AXValue. |
+- (bool)shouldExposeNameInAXValue { |
+ switch ([self internalRole]) { |
+ case ui::AX_ROLE_LIST_BOX_OPTION: |
+ case ui::AX_ROLE_LIST_MARKER: |
+ case ui::AX_ROLE_MENU_LIST_OPTION: |
+ case ui::AX_ROLE_STATIC_TEXT: |
+ return true; |
+ default: |
+ return false; |
+ } |
+} |
+ |
- (content::BrowserAccessibilityDelegate*)delegate { |
return browserAccessibility_->manager() ? |
browserAccessibility_->manager()->delegate() : |
@@ -1177,22 +1238,42 @@ bool InitializeAccessibilityTreeSearch( |
} |
- (NSString*)title { |
- return NSStringForStringAttribute( |
- browserAccessibility_, ui::AX_ATTR_NAME); |
+ // Mac OS X wants static text exposed in AXValue. |
+ if ([self shouldExposeNameInAXValue]) |
+ return @""; |
+ |
+ // If the name came from a single related element and it's present in the |
+ // tree, it will be exposed in AXTitleUIElement. |
+ std::vector<int32> labelledby_ids = |
+ browserAccessibility_->GetIntListAttribute(ui::AX_ATTR_LABELLEDBY_IDS); |
+ ui::AXNameFrom nameFrom = static_cast<ui::AXNameFrom>( |
+ browserAccessibility_->GetIntAttribute(ui::AX_ATTR_NAME_FROM)); |
+ if (nameFrom == ui::AX_NAME_FROM_RELATED_ELEMENT && |
+ labelledby_ids.size() == 1 && |
+ browserAccessibility_->manager()->GetFromID(labelledby_ids[0])) { |
+ return @""; |
+ } |
+ |
+ // On Mac OS X, the accessible name of an object is exposed as its |
+ // title if it comes from visible text, and as its description |
+ // otherwise, but never both. |
+ if (nameFrom == ui::AX_NAME_FROM_CONTENTS || |
+ nameFrom == ui::AX_NAME_FROM_RELATED_ELEMENT || |
+ nameFrom == ui::AX_NAME_FROM_VALUE) { |
+ return NSStringForStringAttribute( |
+ browserAccessibility_, ui::AX_ATTR_NAME); |
+ } |
+ |
+ return nil; |
} |
- (id)titleUIElement { |
- int titleElementId; |
- if (browserAccessibility_->GetIntAttribute( |
- ui::AX_ATTR_TITLE_UI_ELEMENT, &titleElementId)) { |
- BrowserAccessibility* titleElement = |
- browserAccessibility_->manager()->GetFromID(titleElementId); |
- if (titleElement) |
- return titleElement->ToBrowserAccessibilityCocoa(); |
- } |
std::vector<int32> labelledby_ids = |
browserAccessibility_->GetIntListAttribute(ui::AX_ATTR_LABELLEDBY_IDS); |
- if (labelledby_ids.size() == 1) { |
+ ui::AXNameFrom nameFrom = static_cast<ui::AXNameFrom>( |
+ browserAccessibility_->GetIntAttribute(ui::AX_ATTR_NAME_FROM)); |
+ if (nameFrom == ui::AX_NAME_FROM_RELATED_ELEMENT && |
+ labelledby_ids.size() == 1) { |
BrowserAccessibility* titleElement = |
browserAccessibility_->manager()->GetFromID(labelledby_ids[0]); |
if (titleElement) |
@@ -1216,11 +1297,11 @@ bool InitializeAccessibilityTreeSearch( |
} |
- (id)value { |
- // WebCore uses an attachmentView to get the below behavior. |
- // We do not have any native views backing this object, so need |
- // to approximate Cocoa ax behavior best as we can. |
NSString* role = [self role]; |
- if ([role isEqualToString:@"AXHeading"]) { |
+ if ([self shouldExposeNameInAXValue]) { |
+ return NSStringForStringAttribute( |
+ browserAccessibility_, ui::AX_ATTR_NAME); |
+ } else if ([role isEqualToString:@"AXHeading"]) { |
int level = 0; |
if (browserAccessibility_->GetIntAttribute( |
ui::AX_ATTR_HIERARCHICAL_LEVEL, &level)) { |
@@ -1835,10 +1916,9 @@ bool InitializeAccessibilityTreeSearch( |
} |
// Title UI Element. |
- if (browserAccessibility_->HasIntAttribute(ui::AX_ATTR_TITLE_UI_ELEMENT) || |
- (browserAccessibility_->HasIntListAttribute(ui::AX_ATTR_LABELLEDBY_IDS) && |
- browserAccessibility_->GetIntListAttribute(ui::AX_ATTR_LABELLEDBY_IDS) |
- .size() == 1)) { |
+ if (browserAccessibility_->HasIntListAttribute(ui::AX_ATTR_LABELLEDBY_IDS) && |
+ browserAccessibility_->GetIntListAttribute(ui::AX_ATTR_LABELLEDBY_IDS) |
+ .size() > 0) { |
[ret addObjectsFromArray:[NSArray arrayWithObjects: |
NSAccessibilityTitleUIElementAttribute, |
nil]]; |
@@ -1870,8 +1950,9 @@ bool InitializeAccessibilityTreeSearch( |
return NO; |
if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) |
- return GetState(browserAccessibility_, |
- ui::AX_STATE_FOCUSABLE); |
+ if ([self internalRole] == ui::AX_ROLE_DATE_TIME) |
+ return NO; |
+ return GetState(browserAccessibility_, ui::AX_STATE_FOCUSABLE); |
if ([attribute isEqualToString:NSAccessibilityValueAttribute]) { |
return browserAccessibility_->GetBoolAttribute( |
ui::AX_ATTR_CAN_SET_VALUE); |