diff options
author | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-20 23:41:51 +0000 |
---|---|---|
committer | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-20 23:41:51 +0000 |
commit | eecf89f0653aea95e400be885ffe98689c2d4c4e (patch) | |
tree | 67f70bb69f9b3a0d914a9513d381177f29475046 | |
parent | 4587873229fd72441369dad26e131959385c92ec (diff) | |
download | chromium_src-eecf89f0653aea95e400be885ffe98689c2d4c4e.zip chromium_src-eecf89f0653aea95e400be885ffe98689c2d4c4e.tar.gz chromium_src-eecf89f0653aea95e400be885ffe98689c2d4c4e.tar.bz2 |
Make AccessibilityNodeData more compact.
The only goal of this tedious changelist is
less memory usage when storing the accessible tree.
The major changes are:
* Make almost everything a "sparse" attribute.
For example, not every element has a name or
value, so make them optional attributes rather
than string fields that always take up memory.
* Use UTF-8 std::strings instead of string16s.
* Use vectors of pairs rather than maps.
If there is any slowdown after this change, we
can speed up lookup in vectors by sorting the
attributes and doing a binary search. There are
also opportunities to do more referencing and
less string copying.
When reviewing, look at the changes to the header
files first and make sure you understand them.
Everything else is just a consequence of those
changes.
BUG=96700
Review URL: https://chromiumcodereview.appspot.com/21269002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@218572 0039d316-1c4b-4281-b951-d872f2087c98
19 files changed, 923 insertions, 627 deletions
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc index ae7efe2..37217c7 100644 --- a/content/browser/accessibility/browser_accessibility.cc +++ b/content/browser/accessibility/browser_accessibility.cc @@ -7,6 +7,7 @@ #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" #include "content/browser/accessibility/browser_accessibility_manager.h" #include "content/common/accessibility_messages.h" @@ -64,22 +65,20 @@ void BrowserAccessibility::InitializeTreeStructure( void BrowserAccessibility::InitializeData(const AccessibilityNodeData& src) { DCHECK_EQ(renderer_id_, src.id); - name_ = src.name; - value_ = src.value; role_ = src.role; state_ = src.state; string_attributes_ = src.string_attributes; int_attributes_ = src.int_attributes; float_attributes_ = src.float_attributes; bool_attributes_ = src.bool_attributes; + intlist_attributes_ = src.intlist_attributes; html_attributes_ = src.html_attributes; location_ = src.location; - indirect_child_ids_ = src.indirect_child_ids; - line_breaks_ = src.line_breaks; - cell_ids_ = src.cell_ids; - unique_cell_ids_ = src.unique_cell_ids; instance_active_ = true; + GetStringAttribute(AccessibilityNodeData::ATTR_NAME, &name_); + GetStringAttribute(AccessibilityNodeData::ATTR_VALUE, &value_); + PreInitialize(); } @@ -223,55 +222,197 @@ void BrowserAccessibility::NativeReleaseReference() { delete this; } +bool BrowserAccessibility::HasBoolAttribute(BoolAttribute attribute) const { + for (size_t i = 0; i < bool_attributes_.size(); ++i) { + if (bool_attributes_[i].first == attribute) + return true; + } + + return false; +} + + +bool BrowserAccessibility::GetBoolAttribute(BoolAttribute attribute) const { + for (size_t i = 0; i < bool_attributes_.size(); ++i) { + if (bool_attributes_[i].first == attribute) + return bool_attributes_[i].second; + } + + return false; +} + bool BrowserAccessibility::GetBoolAttribute( BoolAttribute attribute, bool* value) const { - BoolAttrMap::const_iterator iter = bool_attributes_.find(attribute); - if (iter != bool_attributes_.end()) { - *value = iter->second; - return true; + for (size_t i = 0; i < bool_attributes_.size(); ++i) { + if (bool_attributes_[i].first == attribute) { + *value = bool_attributes_[i].second; + return true; + } + } + + return false; +} + +bool BrowserAccessibility::HasFloatAttribute(FloatAttribute attribute) const { + for (size_t i = 0; i < float_attributes_.size(); ++i) { + if (float_attributes_[i].first == attribute) + return true; } return false; } +float BrowserAccessibility::GetFloatAttribute(FloatAttribute attribute) const { + for (size_t i = 0; i < float_attributes_.size(); ++i) { + if (float_attributes_[i].first == attribute) + return float_attributes_[i].second; + } + + return 0.0; +} + bool BrowserAccessibility::GetFloatAttribute( FloatAttribute attribute, float* value) const { - FloatAttrMap::const_iterator iter = float_attributes_.find(attribute); - if (iter != float_attributes_.end()) { - *value = iter->second; - return true; + for (size_t i = 0; i < float_attributes_.size(); ++i) { + if (float_attributes_[i].first == attribute) { + *value = float_attributes_[i].second; + return true; + } + } + + return false; +} + +bool BrowserAccessibility::HasIntAttribute(IntAttribute attribute) const { + for (size_t i = 0; i < int_attributes_.size(); ++i) { + if (int_attributes_[i].first == attribute) + return true; } return false; } +int BrowserAccessibility::GetIntAttribute(IntAttribute attribute) const { + for (size_t i = 0; i < int_attributes_.size(); ++i) { + if (int_attributes_[i].first == attribute) + return int_attributes_[i].second; + } + + return 0; +} + bool BrowserAccessibility::GetIntAttribute( IntAttribute attribute, int* value) const { - IntAttrMap::const_iterator iter = int_attributes_.find(attribute); - if (iter != int_attributes_.end()) { - *value = iter->second; - return true; + for (size_t i = 0; i < int_attributes_.size(); ++i) { + if (int_attributes_[i].first == attribute) { + *value = int_attributes_[i].second; + return true; + } } return false; } +bool BrowserAccessibility::HasStringAttribute(StringAttribute attribute) const { + for (size_t i = 0; i < string_attributes_.size(); ++i) { + if (string_attributes_[i].first == attribute) + return true; + } + + return false; +} + +const std::string& BrowserAccessibility::GetStringAttribute( + StringAttribute attribute) const { + CR_DEFINE_STATIC_LOCAL(std::string, empty_string, ()); + for (size_t i = 0; i < string_attributes_.size(); ++i) { + if (string_attributes_[i].first == attribute) + return string_attributes_[i].second; + } + + return empty_string; +} + bool BrowserAccessibility::GetStringAttribute( + StringAttribute attribute, std::string* value) const { + for (size_t i = 0; i < string_attributes_.size(); ++i) { + if (string_attributes_[i].first == attribute) { + *value = string_attributes_[i].second; + return true; + } + } + + return false; +} + +string16 BrowserAccessibility::GetString16Attribute( + StringAttribute attribute) const { + std::string value_utf8; + if (!GetStringAttribute(attribute, &value_utf8)) + return string16(); + return UTF8ToUTF16(value_utf8); +} + +bool BrowserAccessibility::GetString16Attribute( StringAttribute attribute, string16* value) const { - StringAttrMap::const_iterator iter = string_attributes_.find(attribute); - if (iter != string_attributes_.end()) { - *value = iter->second; - return true; + std::string value_utf8; + if (!GetStringAttribute(attribute, &value_utf8)) + return false; + *value = UTF8ToUTF16(value_utf8); + return true; +} + +void BrowserAccessibility::SetStringAttribute( + StringAttribute attribute, const std::string& value) { + for (size_t i = 0; i < string_attributes_.size(); ++i) { + if (string_attributes_[i].first == attribute) { + string_attributes_[i].second = value; + return; + } + } + if (!value.empty()) + string_attributes_.push_back(std::make_pair(attribute, value)); +} + +bool BrowserAccessibility::HasIntListAttribute( + AccessibilityNodeData::IntListAttribute attribute) const { + for (size_t i = 0; i < intlist_attributes_.size(); ++i) { + if (intlist_attributes_[i].first == attribute) + return true; + } + + return false; +} + +const std::vector<int32>& BrowserAccessibility::GetIntListAttribute( + AccessibilityNodeData::IntListAttribute attribute) const { + CR_DEFINE_STATIC_LOCAL(std::vector<int32>, empty_vector, ()); + for (size_t i = 0; i < intlist_attributes_.size(); ++i) { + if (intlist_attributes_[i].first == attribute) + return intlist_attributes_[i].second; + } + + return empty_vector; +} + +bool BrowserAccessibility::GetIntListAttribute( + AccessibilityNodeData::IntListAttribute attribute, + std::vector<int32>* value) const { + for (size_t i = 0; i < intlist_attributes_.size(); ++i) { + if (intlist_attributes_[i].first == attribute) { + *value = intlist_attributes_[i].second; + return true; + } } return false; } bool BrowserAccessibility::GetHtmlAttribute( - const char* html_attr, string16* value) const { + const char* html_attr, std::string* value) const { for (size_t i = 0; i < html_attributes_.size(); i++) { - const string16& attr = html_attributes_[i].first; + const std::string& attr = html_attributes_[i].first; if (LowerCaseEqualsASCII(attr, html_attr)) { *value = html_attributes_[i].second; return true; @@ -281,6 +422,15 @@ bool BrowserAccessibility::GetHtmlAttribute( return false; } +bool BrowserAccessibility::GetHtmlAttribute( + const char* html_attr, string16* value) const { + std::string value_utf8; + if (!GetHtmlAttribute(html_attr, &value_utf8)) + return false; + *value = UTF8ToUTF16(value_utf8); + return true; +} + bool BrowserAccessibility::GetAriaTristate( const char* html_attr, bool* is_defined, @@ -327,12 +477,12 @@ bool BrowserAccessibility::IsEditableText() const { role_ == AccessibilityNodeData::ROLE_TEXTAREA); } -string16 BrowserAccessibility::GetTextRecursive() const { +std::string BrowserAccessibility::GetTextRecursive() const { if (!name_.empty()) { return name_; } - string16 result; + std::string result; for (size_t i = 0; i < children_.size(); ++i) result += children_[i]->GetTextRecursive(); return result; diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h index 8fda68f..33eb60d 100644 --- a/content/browser/accessibility/browser_accessibility.h +++ b/content/browser/accessibility/browser_accessibility.h @@ -10,6 +10,7 @@ #include <vector> #include "base/basictypes.h" +#include "base/strings/string16.h" #include "build/build_config.h" #include "content/common/accessibility_node_data.h" #include "content/common/content_export.h" @@ -26,12 +27,6 @@ class BrowserAccessibilityWin; class BrowserAccessibilityGtk; #endif -typedef std::map<AccessibilityNodeData::BoolAttribute, bool> BoolAttrMap; -typedef std::map<AccessibilityNodeData::FloatAttribute, float> FloatAttrMap; -typedef std::map<AccessibilityNodeData::IntAttribute, int> IntAttrMap; -typedef std::map<AccessibilityNodeData::StringAttribute, string16> - StringAttrMap; - //////////////////////////////////////////////////////////////////////////////// // // BrowserAccessibility @@ -136,49 +131,21 @@ class CONTENT_EXPORT BrowserAccessibility { // Accessors // - const BoolAttrMap& bool_attributes() const { - return bool_attributes_; - } - - const FloatAttrMap& float_attributes() const { - return float_attributes_; - } - - const IntAttrMap& int_attributes() const { - return int_attributes_; - } - - const StringAttrMap& string_attributes() const { - return string_attributes_; - } - const std::vector<BrowserAccessibility*>& children() const { return children_; } - const std::vector<std::pair<string16, string16> >& html_attributes() const { + const std::vector<std::pair<std::string, std::string> >& + html_attributes() const { return html_attributes_; } int32 index_in_parent() const { return index_in_parent_; } - const std::vector<int32>& indirect_child_ids() const { - return indirect_child_ids_; - } - const std::vector<int32>& line_breaks() const { - return line_breaks_; - } - const std::vector<int32>& cell_ids() const { - return cell_ids_; - } - const std::vector<int32>& unique_cell_ids() const { - return unique_cell_ids_; - } gfx::Rect location() const { return location_; } BrowserAccessibilityManager* manager() const { return manager_; } - const string16& name() const { return name_; } + const std::string& name() const { return name_; } int32 renderer_id() const { return renderer_id_; } int32 role() const { return role_; } - const string16& role_name() const { return role_name_; } int32 state() const { return state_; } - const string16& value() const { return value_; } + const std::string& value() const { return value_; } bool instance_active() const { return instance_active_; } #if defined(OS_MACOSX) && __OBJC__ @@ -189,29 +156,63 @@ class CONTENT_EXPORT BrowserAccessibility { BrowserAccessibilityGtk* ToBrowserAccessibilityGtk(); #endif - // Retrieve the value of a bool attribute from the bool attribute - // map and returns true if found. - bool GetBoolAttribute( - AccessibilityNodeData::BoolAttribute attr, bool* value) const; - - // Retrieve the value of a float attribute from the float attribute - // map and returns true if found. + // Accessing accessibility attributes: + // + // There are dozens of possible attributes for an accessibility node, + // but only a few tend to apply to any one object, so we store them + // in sparse arrays of <attribute id, attribute value> pairs, organized + // by type (bool, int, float, string, int list). + // + // There are three accessors for each type of attribute: one that returns + // true if the attribute is present and false if not, one that takes a + // pointer argument and returns true if the attribute is present (if you + // need to distinguish between the default value and a missing attribute), + // and another that returns the default value for that type if the + // attribute is not present. In addition, strings can be returned as + // either std::string or string16, for convenience. + + bool HasBoolAttribute(AccessibilityNodeData::BoolAttribute attr) const; + bool GetBoolAttribute(AccessibilityNodeData::BoolAttribute attr) const; + bool GetBoolAttribute(AccessibilityNodeData::BoolAttribute attr, + bool* value) const; + + bool HasFloatAttribute(AccessibilityNodeData::FloatAttribute attr) const; + float GetFloatAttribute(AccessibilityNodeData::FloatAttribute attr) const; bool GetFloatAttribute(AccessibilityNodeData::FloatAttribute attr, float* value) const; - // Retrieve the value of an integer attribute from the integer attribute - // map and returns true if found. + bool HasIntAttribute(AccessibilityNodeData::IntAttribute attribute) const; + int GetIntAttribute(AccessibilityNodeData::IntAttribute attribute) const; bool GetIntAttribute(AccessibilityNodeData::IntAttribute attribute, int* value) const; - // Retrieve the value of a string attribute from the attribute map and - // returns true if found. - bool GetStringAttribute( - AccessibilityNodeData::StringAttribute attribute, string16* value) const; + bool HasStringAttribute( + AccessibilityNodeData::StringAttribute attribute) const; + const std::string& GetStringAttribute( + AccessibilityNodeData::StringAttribute attribute) const; + bool GetStringAttribute(AccessibilityNodeData::StringAttribute attribute, + std::string* value) const; + + bool GetString16Attribute(AccessibilityNodeData::StringAttribute attribute, + string16* value) const; + string16 GetString16Attribute( + AccessibilityNodeData::StringAttribute attribute) const; + + bool HasIntListAttribute( + AccessibilityNodeData::IntListAttribute attribute) const; + const std::vector<int32>& GetIntListAttribute( + AccessibilityNodeData::IntListAttribute attribute) const; + bool GetIntListAttribute(AccessibilityNodeData::IntListAttribute attribute, + std::vector<int32>* value) const; + + void SetStringAttribute( + AccessibilityNodeData::StringAttribute attribute, + const std::string& value); // Retrieve the value of a html attribute from the attribute map and // returns true if found. bool GetHtmlAttribute(const char* attr, string16* value) const; + bool GetHtmlAttribute(const char* attr, std::string* value) const; // Utility method to handle special cases for ARIA booleans, tristates and // booleans which have a "mixed" state. @@ -236,7 +237,7 @@ class CONTENT_EXPORT BrowserAccessibility { bool IsEditableText() const; // Append the text from this node and its children. - string16 GetTextRecursive() const; + std::string GetTextRecursive() const; protected: // Perform platform specific initialization. This can be called multiple times @@ -264,21 +265,23 @@ class CONTENT_EXPORT BrowserAccessibility { std::vector<BrowserAccessibility*> children_; // Accessibility metadata from the renderer - string16 name_; - string16 value_; - BoolAttrMap bool_attributes_; - IntAttrMap int_attributes_; - FloatAttrMap float_attributes_; - StringAttrMap string_attributes_; - std::vector<std::pair<string16, string16> > html_attributes_; + std::string name_; + std::string value_; + std::vector<std::pair< + AccessibilityNodeData::BoolAttribute, bool> > bool_attributes_; + std::vector<std::pair< + AccessibilityNodeData::FloatAttribute, float> > float_attributes_; + std::vector<std::pair< + AccessibilityNodeData::IntAttribute, int> > int_attributes_; + std::vector<std::pair< + AccessibilityNodeData::StringAttribute, std::string> > string_attributes_; + std::vector<std::pair< + AccessibilityNodeData::IntListAttribute, std::vector<int32> > > + intlist_attributes_; + std::vector<std::pair<std::string, std::string> > html_attributes_; int32 role_; int32 state_; - string16 role_name_; gfx::Rect location_; - std::vector<int32> indirect_child_ids_; - std::vector<int32> line_breaks_; - std::vector<int32> cell_ids_; - std::vector<int32> unique_cell_ids_; // BrowserAccessibility objects are reference-counted on some platforms. // When we're done with this object and it's removed from our accessibility diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc index 8ff37ec..a31539a 100644 --- a/content/browser/accessibility/browser_accessibility_android.cc +++ b/content/browser/accessibility/browser_accessibility_android.cc @@ -174,16 +174,15 @@ string16 BrowserAccessibilityAndroid::GetText() const { return string16(); } - string16 description; - GetStringAttribute(AccessibilityNodeData::ATTR_DESCRIPTION, &description); - + string16 description = GetString16Attribute( + AccessibilityNodeData::ATTR_DESCRIPTION); string16 text; if (!name().empty()) - text = name(); + text = base::UTF8ToUTF16(name()); else if (!description.empty()) text = description; else if (!value().empty()) - text = value(); + text = base::UTF8ToUTF16(value()); if (text.empty() && HasOnlyStaticTextChildren()) { for (uint32 i = 0; i < child_count(); i++) { @@ -361,8 +360,8 @@ bool BrowserAccessibilityAndroid::HasOnlyStaticTextChildren() const { } bool BrowserAccessibilityAndroid::IsIframe() const { - string16 html_tag; - GetStringAttribute(AccessibilityNodeData::ATTR_HTML_TAG, &html_tag); + string16 html_tag = GetString16Attribute( + AccessibilityNodeData::ATTR_HTML_TAG); return html_tag == ASCIIToUTF16("iframe"); } @@ -370,9 +369,9 @@ void BrowserAccessibilityAndroid::PostInitialize() { BrowserAccessibility::PostInitialize(); if (IsEditableText()) { - if (value_ != new_value_) { + if (base::UTF8ToUTF16(value_) != new_value_) { old_value_ = new_value_; - new_value_ = value_; + new_value_ = base::UTF8ToUTF16(value_); } } @@ -380,8 +379,8 @@ void BrowserAccessibilityAndroid::PostInitialize() { manager_->NotifyAccessibilityEvent(AccessibilityNotificationAlert, this); string16 live; - if (GetStringAttribute(AccessibilityNodeData::ATTR_CONTAINER_LIVE_STATUS, - &live)) { + if (GetString16Attribute( + AccessibilityNodeData::ATTR_CONTAINER_LIVE_STATUS, &live)) { NotifyLiveRegionUpdate(live); } diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm index 9d49767..8285e9d 100644 --- a/content/browser/accessibility/browser_accessibility_cocoa.mm +++ b/content/browser/accessibility/browser_accessibility_cocoa.mm @@ -33,15 +33,10 @@ namespace { // Returns an autoreleased copy of the AccessibilityNodeData's attribute. NSString* NSStringForStringAttribute( - const std::map<StringAttribute, string16>& attributes, + BrowserAccessibility* browserAccessibility, StringAttribute attribute) { - std::map<StringAttribute, string16>::const_iterator iter = - attributes.find(attribute); - NSString* returnValue = @""; - if (iter != attributes.end()) { - returnValue = base::SysUTF16ToNSString(iter->second); - } - return returnValue; + return base::SysUTF8ToNSString( + browserAccessibility->GetStringAttribute(attribute)); } struct MapEntry { @@ -353,34 +348,29 @@ NSDictionary* attributeToMethodNameMap = nil; - (NSString*)accessKey { return NSStringForStringAttribute( - browserAccessibility_->string_attributes(), - AccessibilityNodeData::ATTR_ACCESS_KEY); + browserAccessibility_, AccessibilityNodeData::ATTR_ACCESS_KEY); } - (NSNumber*)ariaAtomic { - bool boolValue = false; - browserAccessibility_->GetBoolAttribute( - AccessibilityNodeData::ATTR_LIVE_ATOMIC, &boolValue); + bool boolValue = browserAccessibility_->GetBoolAttribute( + AccessibilityNodeData::ATTR_LIVE_ATOMIC); return [NSNumber numberWithBool:boolValue]; } - (NSNumber*)ariaBusy { - bool boolValue = false; - browserAccessibility_->GetBoolAttribute( - AccessibilityNodeData::ATTR_LIVE_BUSY, &boolValue); + bool boolValue = browserAccessibility_->GetBoolAttribute( + AccessibilityNodeData::ATTR_LIVE_BUSY); return [NSNumber numberWithBool:boolValue]; } - (NSString*)ariaLive { return NSStringForStringAttribute( - browserAccessibility_->string_attributes(), - AccessibilityNodeData::ATTR_LIVE_STATUS); + browserAccessibility_, AccessibilityNodeData::ATTR_LIVE_STATUS); } - (NSString*)ariaRelevant { return NSStringForStringAttribute( - browserAccessibility_->string_attributes(), - AccessibilityNodeData::ATTR_LIVE_RELEVANT); + browserAccessibility_, AccessibilityNodeData::ATTR_LIVE_RELEVANT); } // Returns an array of BrowserAccessibilityCocoa objects, representing the @@ -401,10 +391,11 @@ NSDictionary* attributeToMethodNameMap = nil; } // Also, add indirect children (if any). - for (uint32 i = 0; - i < browserAccessibility_->indirect_child_ids().size(); - ++i) { - int32 child_id = browserAccessibility_->indirect_child_ids()[i]; + const std::vector<int32>& indirectChildIds = + browserAccessibility_->GetIntListAttribute( + AccessibilityNodeData::ATTR_INDIRECT_CHILD_IDS); + for (uint32 i = 0; i < indirectChildIds.size(); ++i) { + int32 child_id = indirectChildIds[i]; BrowserAccessibility* child = browserAccessibility_->manager()->GetFromRendererID(child_id); @@ -437,7 +428,8 @@ NSDictionary* attributeToMethodNameMap = nil; NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease]; const std::vector<int32>& uniqueCellIds = - browserAccessibility_->unique_cell_ids(); + browserAccessibility_->GetIntListAttribute( + AccessibilityNodeData::ATTR_UNIQUE_CELL_IDS); for (size_t i = 0; i < uniqueCellIds.size(); ++i) { int id = uniqueCellIds[i]; BrowserAccessibility* cell = @@ -473,35 +465,34 @@ NSDictionary* attributeToMethodNameMap = nil; } - (NSString*)description { - const std::map<StringAttribute, string16>& attributes = - browserAccessibility_->string_attributes(); - std::map<StringAttribute, string16>::const_iterator iter = - attributes.find(AccessibilityNodeData::ATTR_DESCRIPTION); - if (iter != attributes.end()) - return base::SysUTF16ToNSString(iter->second); + std::string description; + if (browserAccessibility_->GetStringAttribute( + AccessibilityNodeData::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]) return @""; - if (!browserAccessibility_->name().empty()) + if (browserAccessibility_->HasStringAttribute( + AccessibilityNodeData::ATTR_NAME)) { 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. - iter = attributes.find(AccessibilityNodeData::ATTR_URL); - if (iter != attributes.end()) { - string16 filename = iter->second; + std::string url; + if (browserAccessibility_->GetStringAttribute( + AccessibilityNodeData::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 = filename.size(); - while (leftIndex > 0 && filename[leftIndex - 1] != '/') - leftIndex--; - string16 basename = filename.substr(leftIndex); - - return base::SysUTF16ToNSString(basename); + size_t leftIndex = url.rfind('/'); + std::string basename = + leftIndex != std::string::npos ? url.substr(leftIndex) : url; + return base::SysUTF8ToNSString(basename); } return @""; @@ -526,9 +517,8 @@ NSDictionary* attributeToMethodNameMap = nil; AccessibilityNodeData::Role role = [self internalRole]; if (role == AccessibilityNodeData::ROLE_ROW || role == AccessibilityNodeData::ROLE_TREE_ITEM) { - int level = 0; - browserAccessibility_->GetIntAttribute( - AccessibilityNodeData::ATTR_HIERARCHICAL_LEVEL, &level); + int level = browserAccessibility_->GetIntAttribute( + AccessibilityNodeData::ATTR_HIERARCHICAL_LEVEL); // Mac disclosureLevel is 0-based, but web levels are 1-based. if (level > 0) level--; @@ -581,23 +571,18 @@ NSDictionary* attributeToMethodNameMap = nil; - (NSString*)help { return NSStringForStringAttribute( - browserAccessibility_->string_attributes(), - AccessibilityNodeData::ATTR_HELP); + browserAccessibility_, AccessibilityNodeData::ATTR_HELP); } - (NSNumber*)index { if ([self internalRole] == AccessibilityNodeData::ROLE_COLUMN) { - int columnIndex; - if (browserAccessibility_->GetIntAttribute( - AccessibilityNodeData::ATTR_TABLE_COLUMN_INDEX, &columnIndex)) { - return [NSNumber numberWithInt:columnIndex]; - } + int columnIndex = browserAccessibility_->GetIntAttribute( + AccessibilityNodeData::ATTR_TABLE_COLUMN_INDEX); + return [NSNumber numberWithInt:columnIndex]; } else if ([self internalRole] == AccessibilityNodeData::ROLE_ROW) { - int rowIndex; - if (browserAccessibility_->GetIntAttribute( - AccessibilityNodeData::ATTR_TABLE_ROW_INDEX, &rowIndex)) { - return [NSNumber numberWithInt:rowIndex]; - } + int rowIndex = browserAccessibility_->GetIntAttribute( + AccessibilityNodeData::ATTR_TABLE_ROW_INDEX); + return [NSNumber numberWithInt:rowIndex]; } return nil; @@ -626,23 +611,20 @@ NSDictionary* attributeToMethodNameMap = nil; } - (NSNumber*)loadingProgress { - float floatValue = 0.0; - browserAccessibility_->GetFloatAttribute( - AccessibilityNodeData::ATTR_DOC_LOADING_PROGRESS, &floatValue); + float floatValue = browserAccessibility_->GetFloatAttribute( + AccessibilityNodeData::ATTR_DOC_LOADING_PROGRESS); return [NSNumber numberWithFloat:floatValue]; } - (NSNumber*)maxValue { - float floatValue = 0.0; - browserAccessibility_->GetFloatAttribute( - AccessibilityNodeData::ATTR_MAX_VALUE_FOR_RANGE, &floatValue); + float floatValue = browserAccessibility_->GetFloatAttribute( + AccessibilityNodeData::ATTR_MAX_VALUE_FOR_RANGE); return [NSNumber numberWithFloat:floatValue]; } - (NSNumber*)minValue { - float floatValue = 0.0; - browserAccessibility_->GetFloatAttribute( - AccessibilityNodeData::ATTR_MIN_VALUE_FOR_RANGE, &floatValue); + float floatValue = browserAccessibility_->GetFloatAttribute( + AccessibilityNodeData::ATTR_MIN_VALUE_FOR_RANGE); return [NSNumber numberWithFloat:floatValue]; } @@ -728,18 +710,15 @@ NSDictionary* attributeToMethodNameMap = nil; if ([role isEqualToString:NSAccessibilityGroupRole] || [role isEqualToString:NSAccessibilityRadioButtonRole]) { - const std::vector<std::pair<string16, string16> >& htmlAttributes = - browserAccessibility_->html_attributes(); - AccessibilityNodeData::Role browserAccessibilityRole = [self internalRole]; - if ((browserAccessibilityRole != AccessibilityNodeData::ROLE_GROUP && - browserAccessibilityRole != AccessibilityNodeData::ROLE_LIST_ITEM) || - browserAccessibilityRole == AccessibilityNodeData::ROLE_TAB) { - for (size_t i = 0; i < htmlAttributes.size(); ++i) { - const std::pair<string16, string16>& htmlAttribute = htmlAttributes[i]; - if (htmlAttribute.first == ASCIIToUTF16("role")) { - // TODO(dtseng): This is not localized; see crbug/84814. - return base::SysUTF16ToNSString(htmlAttribute.second); - } + std::string role; + if (browserAccessibility_->GetHtmlAttribute("role", &role)) { + AccessibilityNodeData::Role internalRole = + [self internalRole]; + if ((internalRole != AccessibilityNodeData::ROLE_GROUP && + internalRole != AccessibilityNodeData::ROLE_LIST_ITEM) || + internalRole == AccessibilityNodeData::ROLE_TAB) { + // TODO(dtseng): This is not localized; see crbug/84814. + return base::SysUTF8ToNSString(role); } } } @@ -767,7 +746,8 @@ NSDictionary* attributeToMethodNameMap = nil; NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease]; const std::vector<int32>& uniqueCellIds = - browserAccessibility_->unique_cell_ids(); + browserAccessibility_->GetIntListAttribute( + AccessibilityNodeData::ATTR_UNIQUE_CELL_IDS); for (size_t i = 0; i < uniqueCellIds.size(); ++i) { int id = uniqueCellIds[i]; BrowserAccessibility* cell = @@ -804,7 +784,8 @@ NSDictionary* attributeToMethodNameMap = nil; } } else if ([self internalRole] == AccessibilityNodeData::ROLE_COLUMN) { const std::vector<int32>& indirectChildIds = - browserAccessibility_->indirect_child_ids(); + browserAccessibility_->GetIntListAttribute( + AccessibilityNodeData::ATTR_INDIRECT_CHILD_IDS); for (uint32 i = 0; i < indirectChildIds.size(); ++i) { int id = indirectChildIds[i]; BrowserAccessibility* rowElement = @@ -832,8 +813,7 @@ NSDictionary* attributeToMethodNameMap = nil; } NSString* htmlTag = NSStringForStringAttribute( - browserAccessibility_->string_attributes(), - AccessibilityNodeData::ATTR_HTML_TAG); + browserAccessibility_, AccessibilityNodeData::ATTR_HTML_TAG); if (browserAccessibilityRole == AccessibilityNodeData::ROLE_LIST) { if ([htmlTag isEqualToString:@"ul"] || @@ -864,7 +844,8 @@ NSDictionary* attributeToMethodNameMap = nil; } - (NSString*)title { - return base::SysUTF16ToNSString(browserAccessibility_->name()); + return NSStringForStringAttribute( + browserAccessibility_, AccessibilityNodeData::ATTR_NAME); } - (id)titleUIElement { @@ -884,9 +865,7 @@ NSDictionary* attributeToMethodNameMap = nil; [[self role] isEqualToString:@"AXWebArea"] ? AccessibilityNodeData::ATTR_DOC_URL : AccessibilityNodeData::ATTR_URL; - return NSStringForStringAttribute( - browserAccessibility_->string_attributes(), - urlAttribute); + return NSStringForStringAttribute(browserAccessibility_, urlAttribute); } - (id)value { @@ -895,7 +874,7 @@ NSDictionary* attributeToMethodNameMap = nil; // to approximate Cocoa ax behavior best as we can. NSString* role = [self role]; if ([role isEqualToString:@"AXHeading"]) { - int level; + int level = 0; if (browserAccessibility_->GetIntAttribute( AccessibilityNodeData::ATTR_HIERARCHICAL_LEVEL, &level)) { return [NSNumber numberWithInt:level]; @@ -913,11 +892,10 @@ NSDictionary* attributeToMethodNameMap = nil; 1 : value; - bool mixed = false; - browserAccessibility_->GetBoolAttribute( - AccessibilityNodeData::ATTR_BUTTON_MIXED, &mixed); - if (mixed) + if (browserAccessibility_->GetBoolAttribute( + AccessibilityNodeData::ATTR_BUTTON_MIXED)) { value = 2; + } return [NSNumber numberWithInt:value]; } else if ([role isEqualToString:NSAccessibilityProgressIndicatorRole] || [role isEqualToString:NSAccessibilitySliderRole] || @@ -928,26 +906,24 @@ NSDictionary* attributeToMethodNameMap = nil; return [NSNumber numberWithFloat:floatValue]; } } else if ([role isEqualToString:NSAccessibilityColorWellRole]) { - int r, g, b; - browserAccessibility_->GetIntAttribute( - AccessibilityNodeData::ATTR_COLOR_VALUE_RED, &r); - browserAccessibility_->GetIntAttribute( - AccessibilityNodeData::ATTR_COLOR_VALUE_GREEN, &g); - browserAccessibility_->GetIntAttribute( - AccessibilityNodeData::ATTR_COLOR_VALUE_BLUE, &b); + int r = browserAccessibility_->GetIntAttribute( + AccessibilityNodeData::ATTR_COLOR_VALUE_RED); + int g = browserAccessibility_->GetIntAttribute( + AccessibilityNodeData::ATTR_COLOR_VALUE_GREEN); + int b = browserAccessibility_->GetIntAttribute( + AccessibilityNodeData::ATTR_COLOR_VALUE_BLUE); // This string matches the one returned by a native Mac color well. return [NSString stringWithFormat:@"rgb %7.5f %7.5f %7.5f 1", r / 255., g / 255., b / 255.]; } - return base::SysUTF16ToNSString(browserAccessibility_->value()); + return NSStringForStringAttribute( + browserAccessibility_, AccessibilityNodeData::ATTR_VALUE); } - (NSString*)valueDescription { - if (!browserAccessibility_->value().empty()) - return base::SysUTF16ToNSString(browserAccessibility_->value()); - else - return nil; + return NSStringForStringAttribute( + browserAccessibility_, AccessibilityNodeData::ATTR_VALUE); } - (NSValue*)visibleCharacterRange { @@ -958,7 +934,8 @@ NSDictionary* attributeToMethodNameMap = nil; - (NSArray*)visibleCells { NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease]; const std::vector<int32>& uniqueCellIds = - browserAccessibility_->unique_cell_ids(); + browserAccessibility_->GetIntListAttribute( + AccessibilityNodeData::ATTR_UNIQUE_CELL_IDS); for (size_t i = 0; i < uniqueCellIds.size(); ++i) { int id = uniqueCellIds[i]; BrowserAccessibility* cell = @@ -1013,7 +990,8 @@ NSDictionary* attributeToMethodNameMap = nil; if ([attribute isEqualToString: NSAccessibilityInsertionPointLineNumberAttribute]) { const std::vector<int32>& line_breaks = - browserAccessibility_->line_breaks(); + browserAccessibility_->GetIntListAttribute( + AccessibilityNodeData::ATTR_LINE_BREAKS); for (int i = 0; i < static_cast<int>(line_breaks.size()); ++i) { if (line_breaks[i] > selStart) return [NSNumber numberWithInt:i]; @@ -1021,8 +999,9 @@ NSDictionary* attributeToMethodNameMap = nil; return [NSNumber numberWithInt:static_cast<int>(line_breaks.size())]; } if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) { - return base::SysUTF16ToNSString(browserAccessibility_->value().substr( - selStart, selLength)); + std::string value = browserAccessibility_->GetStringAttribute( + AccessibilityNodeData::ATTR_VALUE); + return base::SysUTF8ToNSString(value.substr(selStart, selLength)); } if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) { return [NSValue valueWithRange:NSMakeRange(selStart, selLength)]; @@ -1038,14 +1017,17 @@ NSDictionary* attributeToMethodNameMap = nil; if (!browserAccessibility_) return nil; - const std::vector<int32>& line_breaks = browserAccessibility_->line_breaks(); + const std::vector<int32>& line_breaks = + browserAccessibility_->GetIntListAttribute( + AccessibilityNodeData::ATTR_LINE_BREAKS); int len = static_cast<int>(browserAccessibility_->value().size()); if ([attribute isEqualToString: NSAccessibilityStringForRangeParameterizedAttribute]) { NSRange range = [(NSValue*)parameter rangeValue]; - return base::SysUTF16ToNSString( - browserAccessibility_->value().substr(range.location, range.length)); + std::string value = browserAccessibility_->GetStringAttribute( + AccessibilityNodeData::ATTR_VALUE); + return base::SysUTF8ToNSString(value.substr(range.location, range.length)); } if ([attribute isEqualToString: @@ -1081,12 +1063,10 @@ NSDictionary* attributeToMethodNameMap = nil; NSArray* array = parameter; int column = [[array objectAtIndex:0] intValue]; int row = [[array objectAtIndex:1] intValue]; - int num_columns = 0; - int num_rows = 0; - browserAccessibility_->GetIntAttribute( - AccessibilityNodeData::ATTR_TABLE_COLUMN_COUNT, &num_columns); - browserAccessibility_->GetIntAttribute( - AccessibilityNodeData::ATTR_TABLE_ROW_COUNT, &num_rows); + int num_columns = browserAccessibility_->GetIntAttribute( + AccessibilityNodeData::ATTR_TABLE_COLUMN_COUNT); + int num_rows = browserAccessibility_->GetIntAttribute( + AccessibilityNodeData::ATTR_TABLE_ROW_COUNT); if (column < 0 || column >= num_columns || row < 0 || row >= num_rows) { return nil; @@ -1335,16 +1315,15 @@ NSDictionary* attributeToMethodNameMap = nil; } // Live regions. - string16 s; - if (browserAccessibility_->GetStringAttribute( - AccessibilityNodeData::ATTR_LIVE_STATUS, &s)) { + if (browserAccessibility_->HasStringAttribute( + AccessibilityNodeData::ATTR_LIVE_STATUS)) { [ret addObjectsFromArray:[NSArray arrayWithObjects: @"AXARIALive", @"AXARIARelevant", nil]]; } - if (browserAccessibility_->GetStringAttribute( - AccessibilityNodeData::ATTR_CONTAINER_LIVE_STATUS, &s)) { + if (browserAccessibility_->HasStringAttribute( + AccessibilityNodeData::ATTR_CONTAINER_LIVE_STATUS)) { [ret addObjectsFromArray:[NSArray arrayWithObjects: @"AXARIAAtomic", @"AXARIABusy", @@ -1352,9 +1331,8 @@ NSDictionary* attributeToMethodNameMap = nil; } // Title UI Element. - int i; - if (browserAccessibility_->GetIntAttribute( - AccessibilityNodeData::ATTR_TITLE_UI_ELEMENT, &i)) { + if (browserAccessibility_->HasIntAttribute( + AccessibilityNodeData::ATTR_TITLE_UI_ELEMENT)) { [ret addObjectsFromArray:[NSArray arrayWithObjects: NSAccessibilityTitleUIElementAttribute, nil]]; @@ -1387,10 +1365,8 @@ NSDictionary* attributeToMethodNameMap = nil; return GetState(browserAccessibility_, AccessibilityNodeData::STATE_FOCUSABLE); if ([attribute isEqualToString:NSAccessibilityValueAttribute]) { - bool canSetValue = false; - browserAccessibility_->GetBoolAttribute( - AccessibilityNodeData::ATTR_CAN_SET_VALUE, &canSetValue); - return canSetValue; + return browserAccessibility_->GetBoolAttribute( + AccessibilityNodeData::ATTR_CAN_SET_VALUE); } if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute] && ([[self role] isEqualToString:NSAccessibilityTextFieldRole] || diff --git a/content/browser/accessibility/browser_accessibility_gtk.cc b/content/browser/accessibility/browser_accessibility_gtk.cc index 5036428..f1a1f34 100644 --- a/content/browser/accessibility/browser_accessibility_gtk.cc +++ b/content/browser/accessibility/browser_accessibility_gtk.cc @@ -178,7 +178,8 @@ static const gchar* browser_accessibility_get_name(AtkObject* atk_object) { BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object); if (!obj) return NULL; - return obj->atk_acc_name().c_str(); + + return obj->GetStringAttribute(AccessibilityNodeData::ATTR_NAME).c_str(); } static const gchar* browser_accessibility_get_description( @@ -186,7 +187,9 @@ static const gchar* browser_accessibility_get_description( BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object); if (!obj) return NULL; - return obj->atk_acc_description().c_str(); + + return obj->GetStringAttribute( + AccessibilityNodeData::ATTR_DESCRIPTION).c_str(); } static AtkObject* browser_accessibility_get_parent(AtkObject* atk_object) { @@ -467,12 +470,6 @@ bool BrowserAccessibilityGtk::IsNative() const { } void BrowserAccessibilityGtk::InitRoleAndState() { - atk_acc_name_ = UTF16ToUTF8(name()); - - string16 description; - GetStringAttribute(AccessibilityNodeData::ATTR_DESCRIPTION, &description); - atk_acc_description_ = UTF16ToUTF8(description); - switch(role_) { case AccessibilityNodeData::ROLE_DOCUMENT: case AccessibilityNodeData::ROLE_ROOT_WEB_AREA: diff --git a/content/browser/accessibility/browser_accessibility_gtk.h b/content/browser/accessibility/browser_accessibility_gtk.h index 8f3a2e3..c8895e3 100644 --- a/content/browser/accessibility/browser_accessibility_gtk.h +++ b/content/browser/accessibility/browser_accessibility_gtk.h @@ -68,8 +68,6 @@ class BrowserAccessibilityGtk : public BrowserAccessibility { AtkObject* GetAtkObject() const; AtkRole atk_role() { return atk_role_; } - const std::string& atk_acc_name() { return atk_acc_name_; } - const std::string& atk_acc_description() { return atk_acc_description_; } // BrowserAccessibility methods. virtual void PreInitialize() OVERRIDE; @@ -83,8 +81,6 @@ class BrowserAccessibilityGtk : public BrowserAccessibility { AtkObject* atk_object_; AtkRole atk_role_; - std::string atk_acc_name_; - std::string atk_acc_description_; int interface_mask_; private: diff --git a/content/browser/accessibility/browser_accessibility_mac_unittest.mm b/content/browser/accessibility/browser_accessibility_mac_unittest.mm index 45137ec..9f12138 100644 --- a/content/browser/accessibility/browser_accessibility_mac_unittest.mm +++ b/content/browser/accessibility/browser_accessibility_mac_unittest.mm @@ -68,14 +68,13 @@ class BrowserAccessibilityTest : public ui::CocoaTest { root.location.set_width(500); root.location.set_height(100); root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA; - root.string_attributes[AccessibilityNodeData::ATTR_HELP] = - ASCIIToUTF16("HelpText"); + root.AddStringAttribute(AccessibilityNodeData::ATTR_HELP, "HelpText"); root.child_ids.push_back(1001); root.child_ids.push_back(1002); AccessibilityNodeData child1; child1.id = 1001; - child1.name = ASCIIToUTF16("Child1"); + child1.SetName("Child1"); child1.location.set_width(250); child1.location.set_height(100); child1.role = AccessibilityNodeData::ROLE_BUTTON; diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc index 7def574..10c8b54 100644 --- a/content/browser/accessibility/browser_accessibility_manager.cc +++ b/content/browser/accessibility/browser_accessibility_manager.cc @@ -338,11 +338,13 @@ bool BrowserAccessibilityManager::UpdateNode(const AccessibilityNodeData& src) { instance = CreateNode(NULL, src.id, 0); } - if (src.bool_attributes.find( - AccessibilityNodeData::ATTR_UPDATE_LOCATION_ONLY) != - src.bool_attributes.end()) { - instance->SetLocation(src.location); - return true; + // TODO(dmazzoni): avoid a linear scan here. + for (size_t i = 0; i < src.bool_attributes.size(); i++) { + if (src.bool_attributes[i].first == + AccessibilityNodeData::ATTR_UPDATE_LOCATION_ONLY) { + instance->SetLocation(src.location); + return true; + } } // Update all of the node-specific data, like its role, state, name, etc. diff --git a/content/browser/accessibility/browser_accessibility_manager_unittest.cc b/content/browser/accessibility/browser_accessibility_manager_unittest.cc index 5cb03cd..5ba5a2e 100644 --- a/content/browser/accessibility/browser_accessibility_manager_unittest.cc +++ b/content/browser/accessibility/browser_accessibility_manager_unittest.cc @@ -92,19 +92,19 @@ TEST(BrowserAccessibilityManagerTest, TestNoLeaks) { // BrowserAccessibilityManager. AccessibilityNodeData button; button.id = 2; - button.name = UTF8ToUTF16("Button"); + button.SetName("Button"); button.role = AccessibilityNodeData::ROLE_BUTTON; button.state = 0; AccessibilityNodeData checkbox; checkbox.id = 3; - checkbox.name = UTF8ToUTF16("Checkbox"); + checkbox.SetName("Checkbox"); checkbox.role = AccessibilityNodeData::ROLE_CHECKBOX; checkbox.state = 0; AccessibilityNodeData root; root.id = 1; - root.name = UTF8ToUTF16("Document"); + root.SetName("Document"); root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA; root.state = 0; root.child_ids.push_back(2); @@ -170,25 +170,25 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects) { AccessibilityNodeData tree1_child1; tree1_child1.id = 2; - tree1_child1.name = UTF8ToUTF16("Child1"); + tree1_child1.SetName("Child1"); tree1_child1.role = AccessibilityNodeData::ROLE_BUTTON; tree1_child1.state = 0; AccessibilityNodeData tree1_child2; tree1_child2.id = 3; - tree1_child2.name = UTF8ToUTF16("Child2"); + tree1_child2.SetName("Child2"); tree1_child2.role = AccessibilityNodeData::ROLE_BUTTON; tree1_child2.state = 0; AccessibilityNodeData tree1_child3; tree1_child3.id = 4; - tree1_child3.name = UTF8ToUTF16("Child3"); + tree1_child3.SetName("Child3"); tree1_child3.role = AccessibilityNodeData::ROLE_BUTTON; tree1_child3.state = 0; AccessibilityNodeData tree1_root; tree1_root.id = 1; - tree1_root.name = UTF8ToUTF16("Document"); + tree1_root.SetName("Document"); tree1_root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA; tree1_root.state = 0; tree1_root.child_ids.push_back(2); @@ -205,13 +205,13 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects) { AccessibilityNodeData tree2_child0; tree2_child0.id = 5; - tree2_child0.name = UTF8ToUTF16("Child0"); + tree2_child0.SetName("Child0"); tree2_child0.role = AccessibilityNodeData::ROLE_BUTTON; tree2_child0.state = 0; AccessibilityNodeData tree2_root; tree2_root.id = 1; - tree2_root.name = UTF8ToUTF16("DocumentChanged"); + tree2_root.SetName("DocumentChanged"); tree2_root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA; tree2_root.state = 0; tree2_root.child_ids.push_back(5); @@ -302,46 +302,46 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects2) { AccessibilityNodeData tree1_grandchild1; tree1_grandchild1.id = 4; - tree1_grandchild1.name = UTF8ToUTF16("GrandChild1"); + tree1_grandchild1.SetName("GrandChild1"); tree1_grandchild1.role = AccessibilityNodeData::ROLE_BUTTON; tree1_grandchild1.state = 0; AccessibilityNodeData tree1_child1; tree1_child1.id = 3; - tree1_child1.name = UTF8ToUTF16("Child1"); + tree1_child1.SetName("Child1"); tree1_child1.role = AccessibilityNodeData::ROLE_BUTTON; tree1_child1.state = 0; tree1_child1.child_ids.push_back(4); AccessibilityNodeData tree1_grandchild2; tree1_grandchild2.id = 6; - tree1_grandchild2.name = UTF8ToUTF16("GrandChild1"); + tree1_grandchild2.SetName("GrandChild1"); tree1_grandchild2.role = AccessibilityNodeData::ROLE_BUTTON; tree1_grandchild2.state = 0; AccessibilityNodeData tree1_child2; tree1_child2.id = 5; - tree1_child2.name = UTF8ToUTF16("Child2"); + tree1_child2.SetName("Child2"); tree1_child2.role = AccessibilityNodeData::ROLE_BUTTON; tree1_child2.state = 0; tree1_child2.child_ids.push_back(6); AccessibilityNodeData tree1_grandchild3; tree1_grandchild3.id = 8; - tree1_grandchild3.name = UTF8ToUTF16("GrandChild3"); + tree1_grandchild3.SetName("GrandChild3"); tree1_grandchild3.role = AccessibilityNodeData::ROLE_BUTTON; tree1_grandchild3.state = 0; AccessibilityNodeData tree1_child3; tree1_child3.id = 7; - tree1_child3.name = UTF8ToUTF16("Child3"); + tree1_child3.SetName("Child3"); tree1_child3.role = AccessibilityNodeData::ROLE_BUTTON; tree1_child3.state = 0; tree1_child3.child_ids.push_back(8); AccessibilityNodeData tree1_container; tree1_container.id = 2; - tree1_container.name = UTF8ToUTF16("Container"); + tree1_container.SetName("Container"); tree1_container.role = AccessibilityNodeData::ROLE_GROUP; tree1_container.state = 0; tree1_container.child_ids.push_back(3); @@ -350,7 +350,7 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects2) { AccessibilityNodeData tree1_root; tree1_root.id = 1; - tree1_root.name = UTF8ToUTF16("Document"); + tree1_root.SetName("Document"); tree1_root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA; tree1_root.state = 0; tree1_root.child_ids.push_back(2); @@ -369,20 +369,20 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects2) { AccessibilityNodeData tree2_grandchild0; tree2_grandchild0.id = 9; - tree2_grandchild0.name = UTF8ToUTF16("GrandChild0"); + tree2_grandchild0.SetName("GrandChild0"); tree2_grandchild0.role = AccessibilityNodeData::ROLE_BUTTON; tree2_grandchild0.state = 0; AccessibilityNodeData tree2_child0; tree2_child0.id = 10; - tree2_child0.name = UTF8ToUTF16("Child0"); + tree2_child0.SetName("Child0"); tree2_child0.role = AccessibilityNodeData::ROLE_BUTTON; tree2_child0.state = 0; tree2_child0.child_ids.push_back(9); AccessibilityNodeData tree2_container; tree2_container.id = 2; - tree2_container.name = UTF8ToUTF16("Container"); + tree2_container.SetName("Container"); tree2_container.role = AccessibilityNodeData::ROLE_GROUP; tree2_container.state = 0; tree2_container.child_ids.push_back(10); diff --git a/content/browser/accessibility/browser_accessibility_win.cc b/content/browser/accessibility/browser_accessibility_win.cc index 792adc4..614dd8f 100644 --- a/content/browser/accessibility/browser_accessibility_win.cc +++ b/content/browser/accessibility/browser_accessibility_win.cc @@ -457,7 +457,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accName(VARIANT var_id, BSTR* name) { if (!target) return E_INVALIDARG; - string16 name_str = target->name_; + std::string name_str = target->name(); // If the name is empty, see if it's labeled by another element. if (name_str.empty()) { @@ -474,7 +474,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accName(VARIANT var_id, BSTR* name) { if (name_str.empty()) return S_FALSE; - *name = SysAllocString(name_str.c_str()); + *name = SysAllocString(UTF8ToUTF16(name_str).c_str()); DCHECK(*name); return S_OK; @@ -557,8 +557,33 @@ STDMETHODIMP BrowserAccessibilityWin::get_accValue(VARIANT var_id, if (!target) return E_INVALIDARG; - *value = SysAllocString(target->value_.c_str()); + if (target->ia_role() == ROLE_SYSTEM_PROGRESSBAR || + target->ia_role() == ROLE_SYSTEM_SCROLLBAR || + target->ia_role() == ROLE_SYSTEM_SLIDER) { + string16 value_text = target->GetValueText(); + *value = SysAllocString(value_text.c_str()); + DCHECK(*value); + return S_OK; + } + + // Expose color well value. + if (target->ia2_role() == IA2_ROLE_COLOR_CHOOSER) { + int r = target->GetIntAttribute( + AccessibilityNodeData::ATTR_COLOR_VALUE_RED); + int g = target->GetIntAttribute( + AccessibilityNodeData::ATTR_COLOR_VALUE_GREEN); + int b = target->GetIntAttribute( + AccessibilityNodeData::ATTR_COLOR_VALUE_BLUE); + string16 value_text; + value_text = base::IntToString16((r * 100) / 255) + L"% red " + + base::IntToString16((g * 100) / 255) + L"% green " + + base::IntToString16((b * 100) / 255) + L"% blue"; + *value = SysAllocString(value_text.c_str()); + DCHECK(*value); + return S_OK; + } + *value = SysAllocString(UTF8ToUTF16(target->value()).c_str()); DCHECK(*value); return S_OK; } @@ -1014,9 +1039,11 @@ STDMETHODIMP BrowserAccessibilityWin::get_accessibleAt( if (row < 0 || row >= rows || column < 0 || column >= columns) return E_INVALIDARG; - DCHECK_EQ(columns * rows, static_cast<int>(cell_ids_.size())); + const std::vector<int32>& cell_ids = GetIntListAttribute( + AccessibilityNodeData::ATTR_CELL_IDS); + DCHECK_EQ(columns * rows, static_cast<int>(cell_ids.size())); - int cell_id = cell_ids_[row * columns + column]; + int cell_id = cell_ids[row * columns + column]; BrowserAccessibilityWin* cell = GetFromRendererID(cell_id); if (cell) { *accessible = static_cast<IAccessible*>(cell->NewReference()); @@ -1061,10 +1088,14 @@ STDMETHODIMP BrowserAccessibilityWin::get_childIndex(long row, if (row < 0 || row >= rows || column < 0 || column >= columns) return E_INVALIDARG; - DCHECK_EQ(columns * rows, static_cast<int>(cell_ids_.size())); - int cell_id = cell_ids_[row * columns + column]; - for (size_t i = 0; i < unique_cell_ids_.size(); ++i) { - if (unique_cell_ids_[i] == cell_id) { + const std::vector<int32>& cell_ids = GetIntListAttribute( + AccessibilityNodeData::ATTR_CELL_IDS); + const std::vector<int32>& unique_cell_ids = GetIntListAttribute( + AccessibilityNodeData::ATTR_UNIQUE_CELL_IDS); + DCHECK_EQ(columns * rows, static_cast<int>(cell_ids.size())); + int cell_id = cell_ids[row * columns + column]; + for (size_t i = 0; i < unique_cell_ids.size(); ++i) { + if (unique_cell_ids[i] == cell_id) { *cell_index = (long)i; return S_OK; } @@ -1094,13 +1125,17 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnDescription(long column, if (column < 0 || column >= columns) return E_INVALIDARG; + const std::vector<int32>& cell_ids = GetIntListAttribute( + AccessibilityNodeData::ATTR_CELL_IDS); for (int i = 0; i < rows; ++i) { - int cell_id = cell_ids_[i * columns + column]; + int cell_id = cell_ids[i * columns + column]; BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>( manager_->GetFromRendererID(cell_id)); if (cell && cell->role_ == AccessibilityNodeData::ROLE_COLUMN_HEADER) { - if (cell->name_.size() > 0) { - *description = SysAllocString(cell->name_.c_str()); + string16 cell_name = cell->GetString16Attribute( + AccessibilityNodeData::ATTR_NAME); + if (cell_name.size() > 0) { + *description = SysAllocString(cell_name.c_str()); return S_OK; } @@ -1135,7 +1170,9 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnExtentAt( if (row < 0 || row >= rows || column < 0 || column >= columns) return E_INVALIDARG; - int cell_id = cell_ids_[row * columns + column]; + const std::vector<int32>& cell_ids = GetIntListAttribute( + AccessibilityNodeData::ATTR_CELL_IDS); + int cell_id = cell_ids[row * columns + column]; BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>( manager_->GetFromRendererID(cell_id)); int colspan; @@ -1165,13 +1202,15 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnIndex(long cell_index, if (!column_index) return E_INVALIDARG; - int cell_id_count = static_cast<int>(unique_cell_ids_.size()); + const std::vector<int32>& unique_cell_ids = GetIntListAttribute( + AccessibilityNodeData::ATTR_UNIQUE_CELL_IDS); + int cell_id_count = static_cast<int>(unique_cell_ids.size()); if (cell_index < 0) return E_INVALIDARG; if (cell_index >= cell_id_count) return S_FALSE; - int cell_id = unique_cell_ids_[cell_index]; + int cell_id = unique_cell_ids[cell_index]; BrowserAccessibilityWin* cell = manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); int col_index; @@ -1273,13 +1312,17 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowDescription(long row, if (row < 0 || row >= rows) return E_INVALIDARG; + const std::vector<int32>& cell_ids = GetIntListAttribute( + AccessibilityNodeData::ATTR_CELL_IDS); for (int i = 0; i < columns; ++i) { - int cell_id = cell_ids_[row * columns + i]; + int cell_id = cell_ids[row * columns + i]; BrowserAccessibilityWin* cell = manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); if (cell && cell->role_ == AccessibilityNodeData::ROLE_ROW_HEADER) { - if (cell->name_.size() > 0) { - *description = SysAllocString(cell->name_.c_str()); + string16 cell_name = cell->GetString16Attribute( + AccessibilityNodeData::ATTR_NAME); + if (cell_name.size() > 0) { + *description = SysAllocString(cell_name.c_str()); return S_OK; } @@ -1313,7 +1356,9 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowExtentAt(long row, if (row < 0 || row >= rows || column < 0 || column >= columns) return E_INVALIDARG; - int cell_id = cell_ids_[row * columns + column]; + const std::vector<int32>& cell_ids = GetIntListAttribute( + AccessibilityNodeData::ATTR_CELL_IDS); + int cell_id = cell_ids[row * columns + column]; BrowserAccessibilityWin* cell = manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); int rowspan; @@ -1343,13 +1388,15 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowIndex(long cell_index, if (!row_index) return E_INVALIDARG; - int cell_id_count = static_cast<int>(unique_cell_ids_.size()); + const std::vector<int32>& unique_cell_ids = GetIntListAttribute( + AccessibilityNodeData::ATTR_UNIQUE_CELL_IDS); + int cell_id_count = static_cast<int>(unique_cell_ids.size()); if (cell_index < 0) return E_INVALIDARG; if (cell_index >= cell_id_count) return S_FALSE; - int cell_id = unique_cell_ids_[cell_index]; + int cell_id = unique_cell_ids[cell_index]; BrowserAccessibilityWin* cell = manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); int cell_row_index; @@ -1470,13 +1517,15 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowColumnExtentsAtIndex( if (!row || !column || !row_extents || !column_extents || !is_selected) return E_INVALIDARG; - int cell_id_count = static_cast<int>(unique_cell_ids_.size()); + const std::vector<int32>& unique_cell_ids = GetIntListAttribute( + AccessibilityNodeData::ATTR_UNIQUE_CELL_IDS); + int cell_id_count = static_cast<int>(unique_cell_ids.size()); if (index < 0) return E_INVALIDARG; if (index >= cell_id_count) return S_FALSE; - int cell_id = unique_cell_ids_[index]; + int cell_id = unique_cell_ids[index]; BrowserAccessibilityWin* cell = manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); int rowspan; @@ -1610,8 +1659,11 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnHeaderCells( if (columns <= 0 || rows <= 0 || column < 0 || column >= columns) return S_FALSE; + const std::vector<int32>& cell_ids = table->GetIntListAttribute( + AccessibilityNodeData::ATTR_CELL_IDS); + for (int i = 0; i < rows; ++i) { - int cell_id = table->cell_ids()[i * columns + column]; + int cell_id = cell_ids[i * columns + column]; BrowserAccessibilityWin* cell = manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); if (cell && cell->role_ == AccessibilityNodeData::ROLE_COLUMN_HEADER) @@ -1622,7 +1674,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnHeaderCells( (*n_column_header_cells) * sizeof(cell_accessibles[0]))); int index = 0; for (int i = 0; i < rows; ++i) { - int cell_id = table->cell_ids()[i * columns + column]; + int cell_id = cell_ids[i * columns + column]; BrowserAccessibilityWin* cell = manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); if (cell && cell->role_ == AccessibilityNodeData::ROLE_COLUMN_HEADER) { @@ -1706,8 +1758,11 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowHeaderCells( if (columns <= 0 || rows <= 0 || row < 0 || row >= rows) return S_FALSE; + const std::vector<int32>& cell_ids = table->GetIntListAttribute( + AccessibilityNodeData::ATTR_CELL_IDS); + for (int i = 0; i < columns; ++i) { - int cell_id = table->cell_ids()[row * columns + i]; + int cell_id = cell_ids[row * columns + i]; BrowserAccessibilityWin* cell = manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); if (cell && cell->role_ == AccessibilityNodeData::ROLE_ROW_HEADER) @@ -1718,7 +1773,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowHeaderCells( (*n_row_header_cells) * sizeof(cell_accessibles[0]))); int index = 0; for (int i = 0; i < columns; ++i) { - int cell_id = table->cell_ids()[row * columns + i]; + int cell_id = cell_ids[row * columns + i]; BrowserAccessibilityWin* cell = manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); if (cell && cell->role_ == AccessibilityNodeData::ROLE_ROW_HEADER) { @@ -2334,13 +2389,13 @@ STDMETHODIMP BrowserAccessibilityWin::get_nodeInfo( } string16 tag; - if (GetStringAttribute(AccessibilityNodeData::ATTR_HTML_TAG, &tag)) + if (GetString16Attribute(AccessibilityNodeData::ATTR_HTML_TAG, &tag)) *node_name = SysAllocString(tag.c_str()); else *node_name = NULL; *name_space_id = 0; - *node_value = SysAllocString(value_.c_str()); + *node_value = SysAllocString(UTF8ToUTF16(value_).c_str()); *num_children = children_.size(); *unique_id = unique_id_win_; @@ -2373,9 +2428,11 @@ STDMETHODIMP BrowserAccessibilityWin::get_attributes( *num_attribs = html_attributes_.size(); for (unsigned short i = 0; i < *num_attribs; ++i) { - attrib_names[i] = SysAllocString(html_attributes_[i].first.c_str()); + attrib_names[i] = SysAllocString( + UTF8ToUTF16(html_attributes_[i].first).c_str()); name_space_id[i] = 0; - attrib_values[i] = SysAllocString(html_attributes_[i].second.c_str()); + attrib_values[i] = SysAllocString( + UTF8ToUTF16(html_attributes_[i].second).c_str()); } return S_OK; } @@ -2394,10 +2451,11 @@ STDMETHODIMP BrowserAccessibilityWin::get_attributesForNames( for (unsigned short i = 0; i < num_attribs; ++i) { name_space_id[i] = 0; bool found = false; - string16 name = (LPCWSTR)attrib_names[i]; + std::string name = UTF16ToUTF8((LPCWSTR)attrib_names[i]); for (unsigned int j = 0; j < html_attributes_.size(); ++j) { if (html_attributes_[j].first == name) { - attrib_values[i] = SysAllocString(html_attributes_[j].second.c_str()); + attrib_values[i] = SysAllocString( + UTF8ToUTF16(html_attributes_[j].second).c_str()); found = true; break; } @@ -2425,7 +2483,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_computedStyle( string16 display; if (max_style_properties == 0 || - !GetStringAttribute(AccessibilityNodeData::ATTR_DISPLAY, &display)) { + !GetString16Attribute(AccessibilityNodeData::ATTR_DISPLAY, &display)) { *num_style_properties = 0; return S_OK; } @@ -2454,8 +2512,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_computedStyleForProperties( string16 name = (LPCWSTR)style_properties[i]; StringToLowerASCII(&name); if (name == L"display") { - string16 display; - GetStringAttribute(AccessibilityNodeData::ATTR_DISPLAY, &display); + string16 display = GetString16Attribute( + AccessibilityNodeData::ATTR_DISPLAY); style_values[i] = SysAllocString(display.c_str()); } else { style_values[i] = NULL; @@ -2579,12 +2637,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_domText(BSTR* dom_text) { if (!dom_text) return E_INVALIDARG; - if (name_.empty()) - return S_FALSE; - - *dom_text = SysAllocString(name_.c_str()); - DCHECK(*dom_text); - return S_OK; + return GetStringAttributeAsBstr( + AccessibilityNodeData::ATTR_NAME, dom_text); } // @@ -2773,24 +2827,7 @@ void BrowserAccessibilityWin::PreInitialize() { if (ia_role_ == ROLE_SYSTEM_PROGRESSBAR || ia_role_ == ROLE_SYSTEM_SCROLLBAR || ia_role_ == ROLE_SYSTEM_SLIDER) { - float fval; - if (value_.empty() && - GetFloatAttribute(AccessibilityNodeData::ATTR_VALUE_FOR_RANGE, &fval)) { - // TODO(dmazzoni): Use ICU to localize this? - value_ = UTF8ToUTF16(base::DoubleToString(fval)); - } - ia2_attributes_.push_back(L"valuetext:" + value_); - } - - // Expose color well value. - if (ia2_role_ == IA2_ROLE_COLOR_CHOOSER) { - int r, g, b; - GetIntAttribute(AccessibilityNodeData::ATTR_COLOR_VALUE_RED, &r); - GetIntAttribute(AccessibilityNodeData::ATTR_COLOR_VALUE_GREEN, &g); - GetIntAttribute(AccessibilityNodeData::ATTR_COLOR_VALUE_BLUE, &b); - value_ = base::IntToString16((r * 100) / 255) + L"% red " + - base::IntToString16((g * 100) / 255) + L"% green " + - base::IntToString16((b * 100) / 255) + L"% blue"; + ia2_attributes_.push_back(L"valuetext:" + GetValueText()); } // Expose table cell index. @@ -2799,7 +2836,8 @@ void BrowserAccessibilityWin::PreInitialize() { while (table && table->role() != AccessibilityNodeData::ROLE_TABLE) table = table->parent(); if (table) { - const std::vector<int32>& unique_cell_ids = table->unique_cell_ids(); + const std::vector<int32>& unique_cell_ids = table->GetIntListAttribute( + AccessibilityNodeData::ATTR_UNIQUE_CELL_IDS); for (size_t i = 0; i < unique_cell_ids.size(); ++i) { if (unique_cell_ids[i] == renderer_id_) { ia2_attributes_.push_back( @@ -2830,22 +2868,21 @@ void BrowserAccessibilityWin::PreInitialize() { // always returns the primary name in "name" and the secondary name, // if any, in "description". - string16 description, help, title_attr; - int title_elem_id = 0; - GetIntAttribute(AccessibilityNodeData::ATTR_TITLE_UI_ELEMENT, &title_elem_id); - GetStringAttribute(AccessibilityNodeData::ATTR_DESCRIPTION, &description); - GetStringAttribute(AccessibilityNodeData::ATTR_HELP, &help); + int title_elem_id = GetIntAttribute( + AccessibilityNodeData::ATTR_TITLE_UI_ELEMENT); + std::string help = GetStringAttribute(AccessibilityNodeData::ATTR_HELP); + std::string description = GetStringAttribute( + AccessibilityNodeData::ATTR_DESCRIPTION); // WebKit annoyingly puts the title in the description if there's no other // description, which just confuses the rest of the logic. Put it back. // Now "help" is always the value of the "title" attribute, if present. + std::string title_attr; if (GetHtmlAttribute("title", &title_attr) && description == title_attr && help.empty()) { help = description; description.clear(); - string_attributes_[AccessibilityNodeData::ATTR_DESCRIPTION].clear(); - string_attributes_[AccessibilityNodeData::ATTR_HELP] = help; } // Now implement the main logic: the descripion should become the name if @@ -2854,21 +2891,18 @@ void BrowserAccessibilityWin::PreInitialize() { if (!description.empty()) { name_ = description; description.clear(); - string_attributes_[AccessibilityNodeData::ATTR_DESCRIPTION] = description; } if (!help.empty() && description.empty()) { description = help; - string_attributes_[AccessibilityNodeData::ATTR_DESCRIPTION] = help; - string_attributes_[AccessibilityNodeData::ATTR_HELP].clear(); + help.clear(); } if (!description.empty() && name_.empty() && !title_elem_id) { name_ = description; description.clear(); - string_attributes_[AccessibilityNodeData::ATTR_DESCRIPTION].clear(); } // If it's a text field, also consider the placeholder. - string16 placeholder; + std::string placeholder; if (role_ == AccessibilityNodeData::ROLE_TEXT_FIELD && HasState(AccessibilityNodeData::STATE_FOCUSABLE) && GetHtmlAttribute("placeholder", &placeholder)) { @@ -2876,10 +2910,12 @@ void BrowserAccessibilityWin::PreInitialize() { name_ = placeholder; } else if (description.empty()) { description = placeholder; - string_attributes_[AccessibilityNodeData::ATTR_DESCRIPTION] = description; } } + SetStringAttribute(AccessibilityNodeData::ATTR_DESCRIPTION, description); + SetStringAttribute(AccessibilityNodeData::ATTR_HELP, help); + // On Windows, the value of a document should be its url. if (role_ == AccessibilityNodeData::ROLE_ROOT_WEB_AREA || role_ == AccessibilityNodeData::ROLE_WEB_AREA) { @@ -2898,7 +2934,6 @@ void BrowserAccessibilityWin::PreInitialize() { // If this doesn't have a value and is linked then set its value to the url // attribute. This allows screen readers to read an empty link's destination. - string16 url; if (value_.empty() && (ia_state_ & STATE_SYSTEM_LINKED)) GetStringAttribute(AccessibilityNodeData::ATTR_URL, &value_); @@ -2931,7 +2966,7 @@ void BrowserAccessibilityWin::PostInitialize() { for (unsigned int i = 0; i < children().size(); ++i) { BrowserAccessibility* child = children()[i]; if (child->role() == AccessibilityNodeData::ROLE_STATIC_TEXT) { - hypertext_ += child->name(); + hypertext_ += UTF8ToUTF16(child->name()); } else { hyperlink_offset_to_index_[hypertext_.size()] = hyperlinks_.size(); hypertext_ += kEmbeddedCharacter; @@ -3035,7 +3070,7 @@ HRESULT BrowserAccessibilityWin::GetStringAttributeAsBstr( BSTR* value_bstr) { string16 str; - if (!GetStringAttribute(attribute, &str)) + if (!GetString16Attribute(attribute, &str)) return S_FALSE; if (str.empty()) @@ -3051,7 +3086,7 @@ void BrowserAccessibilityWin::StringAttributeToIA2( AccessibilityNodeData::StringAttribute attribute, const char* ia2_attr) { string16 value; - if (GetStringAttribute(attribute, &value)) + if (GetString16Attribute(attribute, &value)) ia2_attributes_.push_back(ASCIIToUTF16(ia2_attr) + L":" + value); } @@ -3069,16 +3104,27 @@ void BrowserAccessibilityWin::IntAttributeToIA2( AccessibilityNodeData::IntAttribute attribute, const char* ia2_attr) { int value; - if (GetIntAttribute(attribute, &value)) + if (GetIntAttribute(attribute, &value)) { ia2_attributes_.push_back(ASCIIToUTF16(ia2_attr) + L":" + base::IntToString16(value)); + } +} + +string16 BrowserAccessibilityWin::GetValueText() { + float fval; + string16 value = UTF8ToUTF16(value_); + if (value.empty() && + GetFloatAttribute(AccessibilityNodeData::ATTR_VALUE_FOR_RANGE, &fval)) { + value = UTF8ToUTF16(base::DoubleToString(fval)); + } + return value; } -const string16& BrowserAccessibilityWin::TextForIAccessibleText() { +string16 BrowserAccessibilityWin::TextForIAccessibleText() { if (IsEditableText()) - return value_; + return UTF8ToUTF16(value_); return (role_ == AccessibilityNodeData::ROLE_STATIC_TEXT) ? - name_ : hypertext_; + UTF8ToUTF16(name_) : hypertext_; } void BrowserAccessibilityWin::HandleSpecialTextOffset(const string16& text, @@ -3111,8 +3157,10 @@ LONG BrowserAccessibilityWin::FindBoundary( ui::TextBoundaryDirection direction) { HandleSpecialTextOffset(text, &start_offset); ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary); + const std::vector<int32>& line_breaks = GetIntListAttribute( + AccessibilityNodeData::ATTR_LINE_BREAKS); return ui::FindAccessibleTextBoundary( - text, line_breaks_, boundary, start_offset, direction); + text, line_breaks, boundary, start_offset, direction); } BrowserAccessibilityWin* BrowserAccessibilityWin::GetFromRendererID( @@ -3184,18 +3232,14 @@ void BrowserAccessibilityWin::InitRoleAndState() { if (GetHtmlAttribute("aria-invalid", &invalid)) ia2_state_ |= IA2_STATE_INVALID_ENTRY; - bool mixed = false; - GetBoolAttribute(AccessibilityNodeData::ATTR_BUTTON_MIXED, &mixed); - if (mixed) + if (GetBoolAttribute(AccessibilityNodeData::ATTR_BUTTON_MIXED)) ia_state_ |= STATE_SYSTEM_MIXED; - bool editable = false; - GetBoolAttribute(AccessibilityNodeData::ATTR_CAN_SET_VALUE, &editable); - if (editable) + if (GetBoolAttribute(AccessibilityNodeData::ATTR_CAN_SET_VALUE)) ia2_state_ |= IA2_STATE_EDITABLE; - string16 html_tag; - GetStringAttribute(AccessibilityNodeData::ATTR_HTML_TAG, &html_tag); + string16 html_tag = GetString16Attribute( + AccessibilityNodeData::ATTR_HTML_TAG); ia_role_ = 0; ia2_role_ = 0; switch (role_) { @@ -3307,8 +3351,8 @@ void BrowserAccessibilityWin::InitRoleAndState() { ia_state_ |= STATE_SYSTEM_READONLY; break; case AccessibilityNodeData::ROLE_GROUP: { - string16 aria_role; - GetStringAttribute(AccessibilityNodeData::ATTR_ROLE, &aria_role); + string16 aria_role = GetString16Attribute( + AccessibilityNodeData::ATTR_ROLE); if (aria_role == L"group" || html_tag == L"fieldset") { ia_role_ = ROLE_SYSTEM_GROUPING; } else if (html_tag == L"li") { @@ -3507,8 +3551,8 @@ void BrowserAccessibilityWin::InitRoleAndState() { ia_role_ = ROLE_SYSTEM_PAGETAB; break; case AccessibilityNodeData::ROLE_TABLE: { - string16 aria_role; - GetStringAttribute(AccessibilityNodeData::ATTR_ROLE, &aria_role); + string16 aria_role = GetString16Attribute( + AccessibilityNodeData::ATTR_ROLE); if (aria_role == L"treegrid") { ia_role_ = ROLE_SYSTEM_OUTLINE; } else { @@ -3609,9 +3653,7 @@ void BrowserAccessibilityWin::InitRoleAndState() { } if (!HasState(AccessibilityNodeData::STATE_READONLY)) ia_state_ &= ~(STATE_SYSTEM_READONLY); - bool aria_readonly = false; - GetBoolAttribute(AccessibilityNodeData::ATTR_ARIA_READONLY, &aria_readonly); - if (aria_readonly) + if (GetBoolAttribute(AccessibilityNodeData::ATTR_ARIA_READONLY)) ia_state_ |= STATE_SYSTEM_READONLY; // The role should always be set. diff --git a/content/browser/accessibility/browser_accessibility_win.h b/content/browser/accessibility/browser_accessibility_win.h index b659932..db8040e 100644 --- a/content/browser/accessibility/browser_accessibility_win.h +++ b/content/browser/accessibility/browser_accessibility_win.h @@ -771,6 +771,7 @@ BrowserAccessibilityWin // Accessors. int32 ia_role() const { return ia_role_; } int32 ia_state() const { return ia_state_; } + const string16& role_name() const { return role_name_; } int32 ia2_role() const { return ia2_role_; } int32 ia2_state() const { return ia2_state_; } const std::vector<string16>& ia2_attributes() const { @@ -816,9 +817,13 @@ BrowserAccessibilityWin void IntAttributeToIA2(AccessibilityNodeData::IntAttribute attribute, const char* ia2_attr); + // Get the value text, which might come from the floating-point + // value for some roles. + string16 GetValueText(); + // Get the text of this node for the purposes of IAccessibleText - it may // be the name, it may be the value, etc. depending on the role. - const string16& TextForIAccessibleText(); + string16 TextForIAccessibleText(); // If offset is a member of IA2TextSpecialOffsets this function updates the // value of offset and returns, otherwise offset remains unchanged. @@ -847,6 +852,7 @@ BrowserAccessibilityWin // IAccessible role and state. int32 ia_role_; int32 ia_state_; + string16 role_name_; // IAccessible2 role and state. int32 ia2_role_; diff --git a/content/browser/accessibility/browser_accessibility_win_unittest.cc b/content/browser/accessibility/browser_accessibility_win_unittest.cc index 98a5d40..c65c1f3 100644 --- a/content/browser/accessibility/browser_accessibility_win_unittest.cc +++ b/content/browser/accessibility/browser_accessibility_win_unittest.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/memory/scoped_ptr.h" +#include "base/strings/utf_string_conversions.h" #include "base/win/scoped_bstr.h" #include "base/win/scoped_comptr.h" #include "base/win/scoped_variant.h" @@ -113,19 +114,19 @@ TEST_F(BrowserAccessibilityTest, TestNoLeaks) { // BrowserAccessibilityManager. AccessibilityNodeData button; button.id = 2; - button.name = L"Button"; + button.SetName("Button"); button.role = AccessibilityNodeData::ROLE_BUTTON; button.state = 0; AccessibilityNodeData checkbox; checkbox.id = 3; - checkbox.name = L"Checkbox"; + checkbox.SetName("Checkbox"); checkbox.role = AccessibilityNodeData::ROLE_CHECKBOX; checkbox.state = 0; AccessibilityNodeData root; root.id = 1; - root.name = L"Document"; + root.SetName("Document"); root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA; root.state = 0; root.child_ids.push_back(2); @@ -183,12 +184,12 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChange) { AccessibilityNodeData text; text.id = 2; text.role = AccessibilityNodeData::ROLE_STATIC_TEXT; - text.name = L"old text"; + text.SetName("old text"); text.state = 0; AccessibilityNodeData root; root.id = 1; - root.name = L"Document"; + root.SetName("Document"); root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA; root.state = 0; root.child_ids.push_back(2); @@ -225,11 +226,15 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChange) { text_accessible.Release(); // Notify the BrowserAccessibilityManager that the text child has changed. - text.name = L"new text"; + AccessibilityNodeData text2; + text2.id = 2; + text2.role = AccessibilityNodeData::ROLE_STATIC_TEXT; + text2.SetName("new text"); + text2.SetName("old text"); AccessibilityHostMsg_NotificationParams param; param.notification_type = AccessibilityNotificationChildrenChanged; - param.nodes.push_back(text); - param.id = text.id; + param.nodes.push_back(text2); + param.id = text2.id; std::vector<AccessibilityHostMsg_NotificationParams> notifications; notifications.push_back(param); manager->OnAccessibilityNotifications(notifications); @@ -314,12 +319,17 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChangeNoLeaks) { } TEST_F(BrowserAccessibilityTest, TestTextBoundaries) { + std::string text1_value = "One two three.\nFour five six."; + AccessibilityNodeData text1; text1.id = 11; text1.role = AccessibilityNodeData::ROLE_TEXT_FIELD; text1.state = 0; - text1.value = L"One two three.\nFour five six."; - text1.line_breaks.push_back(15); + text1.AddStringAttribute(AccessibilityNodeData::ATTR_VALUE, text1_value); + std::vector<int32> line_breaks; + line_breaks.push_back(15); + text1.AddIntListAttribute( + AccessibilityNodeData::ATTR_LINE_BREAKS, line_breaks); AccessibilityNodeData root; root.id = 1; @@ -344,7 +354,7 @@ TEST_F(BrowserAccessibilityTest, TestTextBoundaries) { base::win::ScopedBstr text; ASSERT_EQ(S_OK, text1_obj->get_text(0, text1_len, text.Receive())); - ASSERT_EQ(text1.value, string16(text)); + ASSERT_EQ(text1_value, base::UTF16ToUTF8(string16(text))); text.Reset(); ASSERT_EQ(S_OK, text1_obj->get_text(0, 4, text.Receive())); @@ -405,17 +415,20 @@ TEST_F(BrowserAccessibilityTest, TestTextBoundaries) { } TEST_F(BrowserAccessibilityTest, TestSimpleHypertext) { + const std::string text1_name = "One two three."; + const std::string text2_name = " Four five six."; + AccessibilityNodeData text1; text1.id = 11; text1.role = AccessibilityNodeData::ROLE_STATIC_TEXT; text1.state = 1 << AccessibilityNodeData::STATE_READONLY; - text1.name = L"One two three."; + text1.SetName(text1_name); AccessibilityNodeData text2; text2.id = 12; text2.role = AccessibilityNodeData::ROLE_STATIC_TEXT; text2.state = 1 << AccessibilityNodeData::STATE_READONLY; - text2.name = L" Four five six."; + text2.SetName(text2_name); AccessibilityNodeData root; root.id = 1; @@ -439,7 +452,7 @@ TEST_F(BrowserAccessibilityTest, TestSimpleHypertext) { base::win::ScopedBstr text; ASSERT_EQ(S_OK, root_obj->get_text(0, text_len, text.Receive())); - EXPECT_EQ(text1.name + text2.name, string16(text)); + EXPECT_EQ(text1_name + text2_name, base::UTF16ToUTF8(string16(text))); long hyperlink_count; ASSERT_EQ(S_OK, root_obj->get_nHyperlinks(&hyperlink_count)); @@ -468,22 +481,27 @@ TEST_F(BrowserAccessibilityTest, TestSimpleHypertext) { } TEST_F(BrowserAccessibilityTest, TestComplexHypertext) { + const std::string text1_name = "One two three."; + const std::string text2_name = " Four five six."; + const std::string button1_text_name = "red"; + const std::string link1_text_name = "blue"; + AccessibilityNodeData text1; text1.id = 11; text1.role = AccessibilityNodeData::ROLE_STATIC_TEXT; text1.state = 1 << AccessibilityNodeData::STATE_READONLY; - text1.name = L"One two three."; + text1.SetName(text1_name); AccessibilityNodeData text2; text2.id = 12; text2.role = AccessibilityNodeData::ROLE_STATIC_TEXT; text2.state = 1 << AccessibilityNodeData::STATE_READONLY; - text2.name = L" Four five six."; + text2.SetName(text2_name); AccessibilityNodeData button1, button1_text; button1.id = 13; button1_text.id = 15; - button1_text.name = L"red"; + button1_text.SetName(button1_text_name); button1.role = AccessibilityNodeData::ROLE_BUTTON; button1_text.role = AccessibilityNodeData::ROLE_STATIC_TEXT; button1.state = 1 << AccessibilityNodeData::STATE_READONLY; @@ -493,7 +511,7 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) { AccessibilityNodeData link1, link1_text; link1.id = 14; link1_text.id = 16; - link1_text.name = L"blue"; + link1_text.SetName(link1_text_name); link1.role = AccessibilityNodeData::ROLE_LINK; link1_text.role = AccessibilityNodeData::ROLE_STATIC_TEXT; link1.state = 1 << AccessibilityNodeData::STATE_READONLY; @@ -527,8 +545,10 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) { base::win::ScopedBstr text; ASSERT_EQ(S_OK, root_obj->get_text(0, text_len, text.Receive())); - const string16 embed = BrowserAccessibilityWin::kEmbeddedCharacter; - EXPECT_EQ(text1.name + embed + text2.name + embed, string16(text)); + const std::string embed = base::UTF16ToUTF8( + BrowserAccessibilityWin::kEmbeddedCharacter); + EXPECT_EQ(text1_name + embed + text2_name + embed, + UTF16ToUTF8(string16(text))); text.Reset(); long hyperlink_count; @@ -545,7 +565,8 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) { EXPECT_EQ(S_OK, hyperlink.QueryInterface<IAccessibleText>(hypertext.Receive())); EXPECT_EQ(S_OK, hypertext->get_text(0, 3, text.Receive())); - EXPECT_STREQ(L"red", text); + EXPECT_STREQ(button1_text_name.c_str(), + base::UTF16ToUTF8(string16(text)).c_str()); text.Reset(); hyperlink.Release(); hypertext.Release(); @@ -554,7 +575,8 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) { EXPECT_EQ(S_OK, hyperlink.QueryInterface<IAccessibleText>(hypertext.Receive())); EXPECT_EQ(S_OK, hypertext->get_text(0, 4, text.Receive())); - EXPECT_STREQ(L"blue", text); + EXPECT_STREQ(link1_text_name.c_str(), + base::UTF16ToUTF8(string16(text)).c_str()); text.Reset(); hyperlink.Release(); hypertext.Release(); diff --git a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc index 4f4d93c..1acceab 100644 --- a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc +++ b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc @@ -89,16 +89,15 @@ CrossPlatformAccessibilityBrowserTest::TearDownInProcessBrowserTestFixture() { } // Convenience method to get the value of a particular AccessibilityNodeData -// node attribute as a UTF-8 const char*. +// node attribute as a UTF-8 string. std::string CrossPlatformAccessibilityBrowserTest::GetAttr( const AccessibilityNodeData& node, const AccessibilityNodeData::StringAttribute attr) { - std::map<AccessibilityNodeData::StringAttribute, string16>::const_iterator - iter = node.string_attributes.find(attr); - if (iter != node.string_attributes.end()) - return UTF16ToUTF8(iter->second); - else - return std::string(); + for (size_t i = 0; i < node.string_attributes.size(); ++i) { + if (node.string_attributes[i].first == attr) + return node.string_attributes[i].second; + } + return std::string(); } // Convenience method to get the value of a particular AccessibilityNodeData @@ -106,12 +105,11 @@ std::string CrossPlatformAccessibilityBrowserTest::GetAttr( int CrossPlatformAccessibilityBrowserTest::GetIntAttr( const AccessibilityNodeData& node, const AccessibilityNodeData::IntAttribute attr) { - std::map<AccessibilityNodeData::IntAttribute, int32>::const_iterator iter = - node.int_attributes.find(attr); - if (iter != node.int_attributes.end()) - return iter->second; - else - return -1; + for (size_t i = 0; i < node.int_attributes.size(); ++i) { + if (node.int_attributes[i].first == attr) + return node.int_attributes[i].second; + } + return -1; } // Convenience method to get the value of a particular AccessibilityNodeData @@ -119,12 +117,11 @@ int CrossPlatformAccessibilityBrowserTest::GetIntAttr( bool CrossPlatformAccessibilityBrowserTest::GetBoolAttr( const AccessibilityNodeData& node, const AccessibilityNodeData::BoolAttribute attr) { - std::map<AccessibilityNodeData::BoolAttribute, bool>::const_iterator iter = - node.bool_attributes.find(attr); - if (iter != node.bool_attributes.end()) - return iter->second; - else - return false; + for (size_t i = 0; i < node.bool_attributes.size(); ++i) { + if (node.bool_attributes[i].first == attr) + return node.bool_attributes[i].second; + } + return false; } // Marked flaky per http://crbug.com/101984 @@ -152,7 +149,9 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest, EXPECT_STREQ( "text/html", GetAttr(tree, AccessibilityNodeData::ATTR_DOC_MIMETYPE).c_str()); - EXPECT_STREQ("Accessibility Test", UTF16ToUTF8(tree.name).c_str()); + EXPECT_STREQ( + "Accessibility Test", + GetAttr(tree, AccessibilityNodeData::ATTR_NAME).c_str()); EXPECT_EQ(AccessibilityNodeData::ROLE_ROOT_WEB_AREA, tree.role); // Check properites of the BODY element. @@ -171,15 +170,17 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest, EXPECT_EQ(AccessibilityNodeData::ROLE_BUTTON, button.role); EXPECT_STREQ( "input", GetAttr(button, AccessibilityNodeData::ATTR_HTML_TAG).c_str()); - EXPECT_STREQ("push", UTF16ToUTF8(button.name).c_str()); + EXPECT_STREQ( + "push", + GetAttr(button, AccessibilityNodeData::ATTR_NAME).c_str()); EXPECT_STREQ( "inline-block", GetAttr(button, AccessibilityNodeData::ATTR_DISPLAY).c_str()); ASSERT_EQ(2U, button.html_attributes.size()); - EXPECT_STREQ("type", UTF16ToUTF8(button.html_attributes[0].first).c_str()); - EXPECT_STREQ("button", UTF16ToUTF8(button.html_attributes[0].second).c_str()); - EXPECT_STREQ("value", UTF16ToUTF8(button.html_attributes[1].first).c_str()); - EXPECT_STREQ("push", UTF16ToUTF8(button.html_attributes[1].second).c_str()); + EXPECT_STREQ("type", button.html_attributes[0].first.c_str()); + EXPECT_STREQ("button", button.html_attributes[0].second.c_str()); + EXPECT_STREQ("value", button.html_attributes[1].first.c_str()); + EXPECT_STREQ("push", button.html_attributes[1].second.c_str()); const AccessibilityNodeDataTreeNode& checkbox = body.children[1]; EXPECT_EQ(AccessibilityNodeData::ROLE_CHECKBOX, checkbox.role); @@ -189,10 +190,8 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest, "inline-block", GetAttr(checkbox, AccessibilityNodeData::ATTR_DISPLAY).c_str()); ASSERT_EQ(1U, checkbox.html_attributes.size()); - EXPECT_STREQ( - "type", UTF16ToUTF8(checkbox.html_attributes[0].first).c_str()); - EXPECT_STREQ( - "checkbox", UTF16ToUTF8(checkbox.html_attributes[0].second).c_str()); + EXPECT_STREQ("type", checkbox.html_attributes[0].first.c_str()); + EXPECT_STREQ("checkbox", checkbox.html_attributes[0].second.c_str()); } IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest, @@ -217,7 +216,9 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest, "input", GetAttr(text, AccessibilityNodeData::ATTR_HTML_TAG).c_str()); EXPECT_EQ(0, GetIntAttr(text, AccessibilityNodeData::ATTR_TEXT_SEL_START)); EXPECT_EQ(0, GetIntAttr(text, AccessibilityNodeData::ATTR_TEXT_SEL_END)); - EXPECT_STREQ("Hello, world.", UTF16ToUTF8(text.value).c_str()); + EXPECT_STREQ( + "Hello, world.", + GetAttr(text, AccessibilityNodeData::ATTR_VALUE).c_str()); // TODO(dmazzoni): as soon as more accessibility code is cross-platform, // this code should test that the accessible info is dynamically updated @@ -246,7 +247,9 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest, "input", GetAttr(text, AccessibilityNodeData::ATTR_HTML_TAG).c_str()); EXPECT_EQ(0, GetIntAttr(text, AccessibilityNodeData::ATTR_TEXT_SEL_START)); EXPECT_EQ(13, GetIntAttr(text, AccessibilityNodeData::ATTR_TEXT_SEL_END)); - EXPECT_STREQ("Hello, world.", UTF16ToUTF8(text.value).c_str()); + EXPECT_STREQ( + "Hello, world.", + GetAttr(text, AccessibilityNodeData::ATTR_VALUE).c_str()); } IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest, @@ -276,13 +279,22 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest, const AccessibilityNodeDataTreeNode& column1 = table.children[1]; EXPECT_EQ(AccessibilityNodeData::ROLE_COLUMN, column1.role); EXPECT_EQ(0U, column1.children.size()); - EXPECT_EQ(1U, column1.indirect_child_ids.size()); - EXPECT_EQ(cell1.id, column1.indirect_child_ids[0]); + EXPECT_EQ(1U, column1.intlist_attributes.size()); + EXPECT_EQ(AccessibilityNodeData::ATTR_INDIRECT_CHILD_IDS, + column1.intlist_attributes[0].first); + const std::vector<int32> column1_indirect_child_ids = + column1.intlist_attributes[0].second; + EXPECT_EQ(1U, column1_indirect_child_ids.size()); + EXPECT_EQ(cell1.id, column1_indirect_child_ids[0]); const AccessibilityNodeDataTreeNode& column2 = table.children[2]; EXPECT_EQ(AccessibilityNodeData::ROLE_COLUMN, column2.role); EXPECT_EQ(0U, column2.children.size()); - EXPECT_EQ(1U, column2.indirect_child_ids.size()); - EXPECT_EQ(cell2.id, column2.indirect_child_ids[0]); + EXPECT_EQ(AccessibilityNodeData::ATTR_INDIRECT_CHILD_IDS, + column2.intlist_attributes[0].first); + const std::vector<int32> column2_indirect_child_ids = + column2.intlist_attributes[0].second; + EXPECT_EQ(1U, column2_indirect_child_ids.size()); + EXPECT_EQ(cell2.id, column2_indirect_child_ids[0]); } IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest, @@ -329,7 +341,9 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest, const AccessibilityNodeDataTreeNode& button1 = body.children[0]; EXPECT_EQ(AccessibilityNodeData::ROLE_BUTTON, button1.role); - EXPECT_STREQ("Button 1", UTF16ToUTF8(button1.name).c_str()); + EXPECT_STREQ( + "Button 1", + GetAttr(button1, AccessibilityNodeData::ATTR_NAME).c_str()); const AccessibilityNodeDataTreeNode& iframe = body.children[1]; EXPECT_STREQ("iframe", @@ -349,11 +363,13 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest, const AccessibilityNodeDataTreeNode& button2 = sub_body.children[0]; EXPECT_EQ(AccessibilityNodeData::ROLE_BUTTON, button2.role); - EXPECT_STREQ("Button 2", UTF16ToUTF8(button2.name).c_str()); + EXPECT_STREQ("Button 2", + GetAttr(button2, AccessibilityNodeData::ATTR_NAME).c_str()); const AccessibilityNodeDataTreeNode& button3 = body.children[2]; EXPECT_EQ(AccessibilityNodeData::ROLE_BUTTON, button3.role); - EXPECT_STREQ("Button 3", UTF16ToUTF8(button3.name).c_str()); + EXPECT_STREQ("Button 3", + GetAttr(button3, AccessibilityNodeData::ATTR_NAME).c_str()); } IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest, @@ -413,13 +429,17 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest, const AccessibilityNodeDataTreeNode& cell3 = table.children[1].children[0]; const AccessibilityNodeDataTreeNode& cell4 = table.children[1].children[1]; - ASSERT_EQ(6U, table.cell_ids.size()); - EXPECT_EQ(cell1.id, table.cell_ids[0]); - EXPECT_EQ(cell1.id, table.cell_ids[1]); - EXPECT_EQ(cell2.id, table.cell_ids[2]); - EXPECT_EQ(cell3.id, table.cell_ids[3]); - EXPECT_EQ(cell4.id, table.cell_ids[4]); - EXPECT_EQ(cell4.id, table.cell_ids[5]); + ASSERT_EQ(AccessibilityNodeData::ATTR_CELL_IDS, + table.intlist_attributes[0].first); + const std::vector<int32>& table_cell_ids = + table.intlist_attributes[0].second; + ASSERT_EQ(6U, table_cell_ids.size()); + EXPECT_EQ(cell1.id, table_cell_ids[0]); + EXPECT_EQ(cell1.id, table_cell_ids[1]); + EXPECT_EQ(cell2.id, table_cell_ids[2]); + EXPECT_EQ(cell3.id, table_cell_ids[3]); + EXPECT_EQ(cell4.id, table_cell_ids[4]); + EXPECT_EQ(cell4.id, table_cell_ids[5]); EXPECT_EQ(0, GetIntAttr(cell1, AccessibilityNodeData::ATTR_TABLE_CELL_COLUMN_INDEX)); diff --git a/content/common/accessibility_messages.h b/content/common/accessibility_messages.h index cd75a8c..116c24b 100644 --- a/content/common/accessibility_messages.h +++ b/content/common/accessibility_messages.h @@ -26,14 +26,13 @@ IPC_ENUM_TRAITS(AccessibilityNotification) IPC_ENUM_TRAITS(content::AccessibilityNodeData::BoolAttribute) IPC_ENUM_TRAITS(content::AccessibilityNodeData::FloatAttribute) IPC_ENUM_TRAITS(content::AccessibilityNodeData::IntAttribute) +IPC_ENUM_TRAITS(content::AccessibilityNodeData::IntListAttribute) IPC_ENUM_TRAITS(content::AccessibilityNodeData::Role) IPC_ENUM_TRAITS(content::AccessibilityNodeData::State) IPC_ENUM_TRAITS(content::AccessibilityNodeData::StringAttribute) IPC_STRUCT_TRAITS_BEGIN(content::AccessibilityNodeData) IPC_STRUCT_TRAITS_MEMBER(id) - IPC_STRUCT_TRAITS_MEMBER(name) - IPC_STRUCT_TRAITS_MEMBER(value) IPC_STRUCT_TRAITS_MEMBER(role) IPC_STRUCT_TRAITS_MEMBER(state) IPC_STRUCT_TRAITS_MEMBER(location) @@ -41,12 +40,9 @@ IPC_STRUCT_TRAITS_BEGIN(content::AccessibilityNodeData) IPC_STRUCT_TRAITS_MEMBER(int_attributes) IPC_STRUCT_TRAITS_MEMBER(float_attributes) IPC_STRUCT_TRAITS_MEMBER(bool_attributes) - IPC_STRUCT_TRAITS_MEMBER(child_ids) - IPC_STRUCT_TRAITS_MEMBER(indirect_child_ids) + IPC_STRUCT_TRAITS_MEMBER(intlist_attributes) IPC_STRUCT_TRAITS_MEMBER(html_attributes) - IPC_STRUCT_TRAITS_MEMBER(line_breaks) - IPC_STRUCT_TRAITS_MEMBER(cell_ids) - IPC_STRUCT_TRAITS_MEMBER(unique_cell_ids) + IPC_STRUCT_TRAITS_MEMBER(child_ids) IPC_STRUCT_TRAITS_END() IPC_STRUCT_BEGIN(AccessibilityHostMsg_NotificationParams) diff --git a/content/common/accessibility_node_data.cc b/content/common/accessibility_node_data.cc index 6848dea..dfc3231 100644 --- a/content/common/accessibility_node_data.cc +++ b/content/common/accessibility_node_data.cc @@ -41,6 +41,35 @@ AccessibilityNodeData::AccessibilityNodeData() AccessibilityNodeData::~AccessibilityNodeData() { } +void AccessibilityNodeData::AddStringAttribute( + StringAttribute attribute, const std::string& value) { + string_attributes.push_back(std::make_pair(attribute, value)); +} + +void AccessibilityNodeData::AddIntAttribute( + IntAttribute attribute, int value) { + int_attributes.push_back(std::make_pair(attribute, value)); +} + +void AccessibilityNodeData::AddFloatAttribute( + FloatAttribute attribute, float value) { + float_attributes.push_back(std::make_pair(attribute, value)); +} + +void AccessibilityNodeData::AddBoolAttribute( + BoolAttribute attribute, bool value) { + bool_attributes.push_back(std::make_pair(attribute, value)); +} + +void AccessibilityNodeData::AddIntListAttribute( + IntListAttribute attribute, const std::vector<int32>& value) { + intlist_attributes.push_back(std::make_pair(attribute, value)); +} + +void AccessibilityNodeData::SetName(std::string name) { + string_attributes.push_back(std::make_pair(ATTR_NAME, name)); +} + AccessibilityNodeDataTreeNode::AccessibilityNodeDataTreeNode() : AccessibilityNodeData() { } @@ -270,27 +299,14 @@ std::string AccessibilityNodeData::DebugString(bool recursive) const { if (state & (1 << STATE_VISITED)) result += " VISITED"; - std::string tmp = UTF16ToUTF8(name); - RemoveChars(tmp, "\n", &tmp); - if (!tmp.empty()) - result += " name=" + tmp; - - tmp = UTF16ToUTF8(value); - RemoveChars(tmp, "\n", &tmp); - if (!tmp.empty()) - result += " value=" + tmp; - result += " (" + IntToString(location.x()) + ", " + IntToString(location.y()) + ")-(" + IntToString(location.width()) + ", " + IntToString(location.height()) + ")"; - for (std::map<IntAttribute, int32>::const_iterator iter = - int_attributes.begin(); - iter != int_attributes.end(); - ++iter) { - std::string value = IntToString(iter->second); - switch (iter->first) { + for (size_t i = 0; i < int_attributes.size(); ++i) { + std::string value = IntToString(int_attributes[i].second); + switch (int_attributes[i].first) { case ATTR_SCROLL_X: result += " scroll_x=" + value; break; @@ -366,12 +382,9 @@ std::string AccessibilityNodeData::DebugString(bool recursive) const { } } - for (std::map<StringAttribute, string16>::const_iterator iter = - string_attributes.begin(); - iter != string_attributes.end(); - ++iter) { - std::string value = UTF16ToUTF8(iter->second); - switch (iter->first) { + for (size_t i = 0; i < string_attributes.size(); ++i) { + std::string value = string_attributes[i].second; + switch (string_attributes[i].first) { case ATTR_DOC_URL: result += " doc_url=" + value; break; @@ -423,15 +436,18 @@ std::string AccessibilityNodeData::DebugString(bool recursive) const { case ATTR_URL: result += " url=" + value; break; + case ATTR_NAME: + result += " name=" + value; + break; + case ATTR_VALUE: + result += " value=" + value; + break; } } - for (std::map<FloatAttribute, float>::const_iterator iter = - float_attributes.begin(); - iter != float_attributes.end(); - ++iter) { - std::string value = DoubleToString(iter->second); - switch (iter->first) { + for (size_t i = 0; i < float_attributes.size(); ++i) { + std::string value = DoubleToString(float_attributes[i].second); + switch (float_attributes[i].first) { case ATTR_DOC_LOADING_PROGRESS: result += " doc_progress=" + value; break; @@ -447,12 +463,9 @@ std::string AccessibilityNodeData::DebugString(bool recursive) const { } } - for (std::map<BoolAttribute, bool>::const_iterator iter = - bool_attributes.begin(); - iter != bool_attributes.end(); - ++iter) { - std::string value = iter->second ? "true" : "false"; - switch (iter->first) { + for (size_t i = 0; i < bool_attributes.size(); ++i) { + std::string value = bool_attributes[i].second ? "true" : "false"; + switch (bool_attributes[i].first) { case ATTR_DOC_LOADED: result += " doc_loaded=" + value; break; @@ -483,18 +496,27 @@ std::string AccessibilityNodeData::DebugString(bool recursive) const { } } + for (size_t i = 0; i < intlist_attributes.size(); ++i) { + const std::vector<int32>& values = intlist_attributes[i].second; + switch (intlist_attributes[i].first) { + case ATTR_INDIRECT_CHILD_IDS: + result += " indirect_child_ids=" + IntVectorToString(values); + break; + case ATTR_LINE_BREAKS: + result += " line_breaks=" + IntVectorToString(values); + break; + case ATTR_CELL_IDS: + result += " cell_ids=" + IntVectorToString(values); + break; + case ATTR_UNIQUE_CELL_IDS: + result += " unique_cell_ids=" + IntVectorToString(values); + break; + } + } + if (!child_ids.empty()) result += " child_ids=" + IntVectorToString(child_ids); - if (!indirect_child_ids.empty()) - result += " indirect_child_ids=" + IntVectorToString(indirect_child_ids); - - if (!line_breaks.empty()) - result += " line_breaks=" + IntVectorToString(line_breaks); - - if (!cell_ids.empty()) - result += " cell_ids=" + IntVectorToString(cell_ids); - return result; } diff --git a/content/common/accessibility_node_data.h b/content/common/accessibility_node_data.h index e4a206f..db6db40 100644 --- a/content/common/accessibility_node_data.h +++ b/content/common/accessibility_node_data.h @@ -191,11 +191,13 @@ struct CONTENT_EXPORT AccessibilityNodeData { ATTR_DISPLAY, ATTR_HELP, ATTR_HTML_TAG, + ATTR_NAME, ATTR_LIVE_RELEVANT, ATTR_LIVE_STATUS, ATTR_ROLE, ATTR_SHORTCUT, ATTR_URL, + ATTR_VALUE, }; enum IntAttribute { @@ -276,9 +278,41 @@ struct CONTENT_EXPORT AccessibilityNodeData { ATTR_UPDATE_LOCATION_ONLY, }; + enum IntListAttribute { + // Ids of nodes that are children of this node logically, but are + // not children of this node in the tree structure. As an example, + // a table cell is a child of a row, and an 'indirect' child of a + // column. + ATTR_INDIRECT_CHILD_IDS, + + // Character indices where line breaks occur. + ATTR_LINE_BREAKS, + + // For a table, the cell ids in row-major order, with duplicate entries + // when there's a rowspan or colspan, and with -1 for missing cells. + // There are always exactly rows * columns entries. + ATTR_CELL_IDS, + + // For a table, the unique cell ids in row-major order of their first + // occurrence. + ATTR_UNIQUE_CELL_IDS + }; + AccessibilityNodeData(); virtual ~AccessibilityNodeData(); + void AddStringAttribute(StringAttribute attribute, + const std::string& value); + void AddIntAttribute(IntAttribute attribute, int value); + void AddFloatAttribute(FloatAttribute attribute, float value); + void AddBoolAttribute(BoolAttribute attribute, bool value); + void AddIntListAttribute(IntListAttribute attribute, + const std::vector<int32>& value); + + // Convenience function, mainly for writing unit tests. + // Equivalent to AddStringAttribute(ATTR_NAME, name). + void SetName(std::string name); + #ifndef NDEBUG virtual std::string DebugString(bool recursive) const; #endif @@ -286,28 +320,17 @@ struct CONTENT_EXPORT AccessibilityNodeData { // This is a simple serializable struct. All member variables should be // public and copyable. int32 id; - string16 name; - string16 value; Role role; uint32 state; gfx::Rect location; - std::map<StringAttribute, string16> string_attributes; - std::map<IntAttribute, int32> int_attributes; - std::map<FloatAttribute, float> float_attributes; - std::map<BoolAttribute, bool> bool_attributes; + std::vector<std::pair<StringAttribute, std::string> > string_attributes; + std::vector<std::pair<IntAttribute, int32> > int_attributes; + std::vector<std::pair<FloatAttribute, float> > float_attributes; + std::vector<std::pair<BoolAttribute, bool> > bool_attributes; + std::vector<std::pair<IntListAttribute, std::vector<int32> > > + intlist_attributes; + std::vector<std::pair<std::string, std::string> > html_attributes; std::vector<int32> child_ids; - std::vector<int32> indirect_child_ids; - std::vector<std::pair<string16, string16> > html_attributes; - std::vector<int32> line_breaks; - - // For a table, the cell ids in row-major order, with duplicate entries - // when there's a rowspan or colspan, and with -1 for missing cells. - // There are always exactly rows * columns entries. - std::vector<int32> cell_ids; - - // For a table, the unique cell ids in row-major order of their first - // occurrence. - std::vector<int32> unique_cell_ids; }; // For testing and debugging only: this subclass of AccessibilityNodeData diff --git a/content/renderer/accessibility/accessibility_node_serializer.cc b/content/renderer/accessibility/accessibility_node_serializer.cc index f7a9138..e6cca96 100644 --- a/content/renderer/accessibility/accessibility_node_serializer.cc +++ b/content/renderer/accessibility/accessibility_node_serializer.cc @@ -46,6 +46,10 @@ bool IsParentUnignoredOf(const WebAccessibilityObject& ancestor, return parent.equals(ancestor); } + bool IsTrue(std::string html_value) { + return LowerCaseEqualsASCII(html_value, "true"); +} + // Provides a conversion between the WebKit::WebAccessibilityRole and a role // supported on the Browser side. Listed alphabetically by the // WebKit::WebAccessibilityRole (except for default role). @@ -351,56 +355,64 @@ uint32 ConvertState(const WebAccessibilityObject& o) { void SerializeAccessibilityNode( const WebAccessibilityObject& src, AccessibilityNodeData* dst) { - dst->name = src.title(); dst->role = ConvertRole(src.roleValue()); dst->state = ConvertState(src); dst->location = src.boundingBoxRect(); dst->id = src.axID(); - - if (src.valueDescription().length()) - dst->value = src.valueDescription(); - else - dst->value = src.stringValue(); + std::string name = UTF16ToUTF8(src.title()); + + std::string value; + if (src.valueDescription().length()) { + dst->AddStringAttribute(dst->ATTR_VALUE, + UTF16ToUTF8(src.valueDescription())); + } else { + dst->AddStringAttribute(dst->ATTR_VALUE, UTF16ToUTF8(src.stringValue())); + } if (dst->role == AccessibilityNodeData::ROLE_COLOR_WELL) { int r, g, b; src.colorValue(r, g, b); - dst->int_attributes[dst->ATTR_COLOR_VALUE_RED] = r; - dst->int_attributes[dst->ATTR_COLOR_VALUE_GREEN] = g; - dst->int_attributes[dst->ATTR_COLOR_VALUE_BLUE] = b; + dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_RED, r); + dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_GREEN, g); + dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_BLUE, b); } if (src.accessKey().length()) - dst->string_attributes[dst->ATTR_ACCESS_KEY] = src.accessKey(); + dst->AddStringAttribute(dst->ATTR_ACCESS_KEY, UTF16ToUTF8(src.accessKey())); if (src.actionVerb().length()) - dst->string_attributes[dst->ATTR_ACTION] = src.actionVerb(); + dst->AddStringAttribute(dst->ATTR_ACTION, UTF16ToUTF8(src.actionVerb())); if (src.isAriaReadOnly()) - dst->bool_attributes[dst->ATTR_ARIA_READONLY] = true; + dst->AddBoolAttribute(dst->ATTR_ARIA_READONLY, true); if (src.isButtonStateMixed()) - dst->bool_attributes[dst->ATTR_BUTTON_MIXED] = true; + dst->AddBoolAttribute(dst->ATTR_BUTTON_MIXED, true); if (src.canSetValueAttribute()) - dst->bool_attributes[dst->ATTR_CAN_SET_VALUE] = true; - if (src.accessibilityDescription().length()) - dst->string_attributes[dst->ATTR_DESCRIPTION] = - src.accessibilityDescription(); - if (src.hasComputedStyle()) - dst->string_attributes[dst->ATTR_DISPLAY] = src.computedStyleDisplay(); + dst->AddBoolAttribute(dst->ATTR_CAN_SET_VALUE, true); + if (src.accessibilityDescription().length()) { + dst->AddStringAttribute(dst->ATTR_DESCRIPTION, + UTF16ToUTF8(src.accessibilityDescription())); + } + if (src.hasComputedStyle()) { + dst->AddStringAttribute(dst->ATTR_DISPLAY, + UTF16ToUTF8(src.computedStyleDisplay())); + } if (src.helpText().length()) - dst->string_attributes[dst->ATTR_HELP] = src.helpText(); - if (src.keyboardShortcut().length()) - dst->string_attributes[dst->ATTR_SHORTCUT] = src.keyboardShortcut(); + dst->AddStringAttribute(dst->ATTR_HELP, UTF16ToUTF8(src.helpText())); + if (src.keyboardShortcut().length()) { + dst->AddStringAttribute(dst->ATTR_SHORTCUT, + UTF16ToUTF8(src.keyboardShortcut())); + } if (!src.titleUIElement().isDetached()) { - dst->int_attributes[dst->ATTR_TITLE_UI_ELEMENT] = - src.titleUIElement().axID(); + dst->AddIntAttribute(dst->ATTR_TITLE_UI_ELEMENT, + src.titleUIElement().axID()); } if (!src.url().isEmpty()) - dst->string_attributes[dst->ATTR_URL] = src.url().spec().utf16(); + dst->AddStringAttribute(dst->ATTR_URL, src.url().spec()); if (dst->role == dst->ROLE_HEADING) - dst->int_attributes[dst->ATTR_HIERARCHICAL_LEVEL] = src.headingLevel(); + dst->AddIntAttribute(dst->ATTR_HIERARCHICAL_LEVEL, src.headingLevel()); else if ((dst->role == dst->ROLE_TREE_ITEM || dst->role == dst->ROLE_ROW) && src.hierarchicalLevel() > 0) { - dst->int_attributes[dst->ATTR_HIERARCHICAL_LEVEL] = src.hierarchicalLevel(); + dst->AddIntAttribute(dst->ATTR_HIERARCHICAL_LEVEL, src.hierarchicalLevel()); } // Treat the active list box item as focused. @@ -412,6 +424,10 @@ void SerializeAccessibilityNode( WebNode node = src.node(); bool is_iframe = false; + std::string live_atomic; + std::string live_busy; + std::string live_status; + std::string live_relevant; if (!node.isNull() && node.isElementNode()) { WebElement element = node.to<WebElement>(); @@ -423,143 +439,163 @@ void SerializeAccessibilityNode( // TODO(ctguil): The tagName in WebKit is lower cased but // HTMLElement::nodeName calls localNameUpper. Consider adding // a WebElement method that returns the original lower cased tagName. - dst->string_attributes[dst->ATTR_HTML_TAG] = - StringToLowerASCII(string16(element.tagName())); + dst->AddStringAttribute( + dst->ATTR_HTML_TAG, + StringToLowerASCII(UTF16ToUTF8(element.tagName()))); for (unsigned i = 0; i < element.attributeCount(); ++i) { - string16 name = StringToLowerASCII(string16( + std::string name = StringToLowerASCII(UTF16ToUTF8( element.attributeLocalName(i))); - string16 value = element.attributeValue(i); - dst->html_attributes.push_back( - std::pair<string16, string16>(name, value)); + std::string value = UTF16ToUTF8(element.attributeValue(i)); + dst->html_attributes.push_back(std::make_pair(name, value)); } if (dst->role == dst->ROLE_EDITABLE_TEXT || dst->role == dst->ROLE_TEXTAREA || dst->role == dst->ROLE_TEXT_FIELD) { - dst->int_attributes[dst->ATTR_TEXT_SEL_START] = src.selectionStart(); - dst->int_attributes[dst->ATTR_TEXT_SEL_END] = src.selectionEnd(); + dst->AddIntAttribute(dst->ATTR_TEXT_SEL_START, src.selectionStart()); + dst->AddIntAttribute(dst->ATTR_TEXT_SEL_END, src.selectionEnd()); WebVector<int> src_line_breaks; src.lineBreaks(src_line_breaks); - dst->line_breaks.reserve(src_line_breaks.size()); - for (size_t i = 0; i < src_line_breaks.size(); ++i) - dst->line_breaks.push_back(src_line_breaks[i]); + if (src_line_breaks.size() > 0) { + std::vector<int32> line_breaks; + line_breaks.reserve(src_line_breaks.size()); + for (size_t i = 0; i < src_line_breaks.size(); ++i) + line_breaks.push_back(src_line_breaks[i]); + dst->AddIntListAttribute(dst->ATTR_LINE_BREAKS, line_breaks); + } } // ARIA role. if (element.hasAttribute("role")) { - dst->string_attributes[dst->ATTR_ROLE] = element.getAttribute("role"); + dst->AddStringAttribute(dst->ATTR_ROLE, + UTF16ToUTF8(element.getAttribute("role"))); } // Live region attributes - if (element.hasAttribute("aria-atomic")) { - dst->bool_attributes[dst->ATTR_LIVE_ATOMIC] = - LowerCaseEqualsASCII(element.getAttribute("aria-atomic"), "true"); - } - if (element.hasAttribute("aria-busy")) { - dst->bool_attributes[dst->ATTR_LIVE_BUSY] = - LowerCaseEqualsASCII(element.getAttribute("aria-busy"), "true"); - } - if (element.hasAttribute("aria-live")) { - dst->string_attributes[dst->ATTR_LIVE_STATUS] = - element.getAttribute("aria-live"); - } - if (element.hasAttribute("aria-relevant")) { - dst->string_attributes[dst->ATTR_LIVE_RELEVANT] = - element.getAttribute("aria-relevant"); - } + live_atomic = UTF16ToUTF8(element.getAttribute("aria-atomic")); + live_busy = UTF16ToUTF8(element.getAttribute("aria-busy")); + live_status = UTF16ToUTF8(element.getAttribute("aria-live")); + live_relevant = UTF16ToUTF8(element.getAttribute("aria-relevant")); } // Walk up the parent chain to set live region attributes of containers - + std::string container_live_atomic; + std::string container_live_busy; + std::string container_live_status; + std::string container_live_relevant; WebAccessibilityObject container_accessible = src; while (!container_accessible.isDetached()) { WebNode container_node = container_accessible.node(); if (!container_node.isNull() && container_node.isElementNode()) { - WebElement container_elem = - container_node.to<WebElement>(); + WebElement container_elem = container_node.to<WebElement>(); if (container_elem.hasAttribute("aria-atomic") && - dst->bool_attributes.find(dst->ATTR_CONTAINER_LIVE_ATOMIC) == - dst->bool_attributes.end()) { - dst->bool_attributes[dst->ATTR_CONTAINER_LIVE_ATOMIC] = - LowerCaseEqualsASCII(container_elem.getAttribute("aria-atomic"), - "true"); + container_live_atomic.empty()) { + container_live_atomic = + UTF16ToUTF8(container_elem.getAttribute("aria-atomic")); } if (container_elem.hasAttribute("aria-busy") && - dst->bool_attributes.find(dst->ATTR_CONTAINER_LIVE_BUSY) == - dst->bool_attributes.end()) { - dst->bool_attributes[dst->ATTR_CONTAINER_LIVE_BUSY] = - LowerCaseEqualsASCII(container_elem.getAttribute("aria-busy"), - "true"); + container_live_busy.empty()) { + container_live_busy = + UTF16ToUTF8(container_elem.getAttribute("aria-busy")); } if (container_elem.hasAttribute("aria-live") && - dst->string_attributes.find(dst->ATTR_CONTAINER_LIVE_STATUS) == - dst->string_attributes.end()) { - dst->string_attributes[dst->ATTR_CONTAINER_LIVE_STATUS] = - container_elem.getAttribute("aria-live"); + container_live_status.empty()) { + container_live_status = + UTF16ToUTF8(container_elem.getAttribute("aria-live")); } if (container_elem.hasAttribute("aria-relevant") && - dst->string_attributes.find(dst->ATTR_CONTAINER_LIVE_RELEVANT) == - dst->string_attributes.end()) { - dst->string_attributes[dst->ATTR_CONTAINER_LIVE_RELEVANT] = - container_elem.getAttribute("aria-relevant"); + container_live_relevant.empty()) { + container_live_relevant = + UTF16ToUTF8(container_elem.getAttribute("aria-relevant")); } } container_accessible = container_accessible.parentObject(); } + if (!live_atomic.empty()) + dst->AddBoolAttribute(dst->ATTR_LIVE_ATOMIC, IsTrue(live_atomic)); + if (!live_busy.empty()) + dst->AddBoolAttribute(dst->ATTR_LIVE_BUSY, IsTrue(live_busy)); + if (!live_status.empty()) + dst->AddStringAttribute(dst->ATTR_LIVE_STATUS, live_status); + if (!live_relevant.empty()) + dst->AddStringAttribute(dst->ATTR_LIVE_RELEVANT, live_relevant); + + if (!container_live_atomic.empty()) { + dst->AddBoolAttribute(dst->ATTR_CONTAINER_LIVE_ATOMIC, + IsTrue(container_live_atomic)); + } + if (!container_live_busy.empty()) { + dst->AddBoolAttribute(dst->ATTR_CONTAINER_LIVE_BUSY, + IsTrue(container_live_busy)); + } + if (!container_live_status.empty()) { + dst->AddStringAttribute(dst->ATTR_CONTAINER_LIVE_STATUS, + container_live_status); + } + if (!container_live_relevant.empty()) { + dst->AddStringAttribute(dst->ATTR_CONTAINER_LIVE_RELEVANT, + container_live_relevant); + } + if (dst->role == dst->ROLE_PROGRESS_INDICATOR || dst->role == dst->ROLE_SCROLLBAR || dst->role == dst->ROLE_SLIDER || dst->role == dst->ROLE_SPIN_BUTTON) { - dst->float_attributes[dst->ATTR_VALUE_FOR_RANGE] = src.valueForRange(); - dst->float_attributes[dst->ATTR_MAX_VALUE_FOR_RANGE] = - src.maxValueForRange(); - dst->float_attributes[dst->ATTR_MIN_VALUE_FOR_RANGE] = - src.minValueForRange(); + dst->AddFloatAttribute(dst->ATTR_VALUE_FOR_RANGE, src.valueForRange()); + dst->AddFloatAttribute(dst->ATTR_MAX_VALUE_FOR_RANGE, + src.maxValueForRange()); + dst->AddFloatAttribute(dst->ATTR_MIN_VALUE_FOR_RANGE, + src.minValueForRange()); } if (dst->role == dst->ROLE_DOCUMENT || dst->role == dst->ROLE_WEB_AREA) { - dst->string_attributes[dst->ATTR_HTML_TAG] = ASCIIToUTF16("#document"); + dst->AddStringAttribute(dst->ATTR_HTML_TAG, "#document"); const WebDocument& document = src.document(); - if (dst->name.empty()) - dst->name = document.title(); - dst->string_attributes[dst->ATTR_DOC_TITLE] = document.title(); - dst->string_attributes[dst->ATTR_DOC_URL] = document.url().spec().utf16(); - dst->string_attributes[dst->ATTR_DOC_MIMETYPE] = - ASCIIToUTF16(document.isXHTMLDocument() ? "text/xhtml" : "text/html"); - dst->bool_attributes[dst->ATTR_DOC_LOADED] = src.isLoaded(); - dst->float_attributes[dst->ATTR_DOC_LOADING_PROGRESS] = - src.estimatedLoadingProgress(); + if (name.empty()) + name = UTF16ToUTF8(document.title()); + dst->AddStringAttribute(dst->ATTR_DOC_TITLE, UTF16ToUTF8(document.title())); + dst->AddStringAttribute(dst->ATTR_DOC_URL, document.url().spec()); + dst->AddStringAttribute( + dst->ATTR_DOC_MIMETYPE, + document.isXHTMLDocument() ? "text/xhtml" : "text/html"); + dst->AddBoolAttribute(dst->ATTR_DOC_LOADED, src.isLoaded()); + dst->AddFloatAttribute(dst->ATTR_DOC_LOADING_PROGRESS, + src.estimatedLoadingProgress()); const WebDocumentType& doctype = document.doctype(); - if (!doctype.isNull()) - dst->string_attributes[dst->ATTR_DOC_DOCTYPE] = doctype.name(); + if (!doctype.isNull()) { + dst->AddStringAttribute(dst->ATTR_DOC_DOCTYPE, + UTF16ToUTF8(doctype.name())); + } const gfx::Size& scroll_offset = document.frame()->scrollOffset(); - dst->int_attributes[dst->ATTR_SCROLL_X] = scroll_offset.width(); - dst->int_attributes[dst->ATTR_SCROLL_Y] = scroll_offset.height(); + dst->AddIntAttribute(dst->ATTR_SCROLL_X, scroll_offset.width()); + dst->AddIntAttribute(dst->ATTR_SCROLL_Y, scroll_offset.height()); const gfx::Size& min_offset = document.frame()->minimumScrollOffset(); - dst->int_attributes[dst->ATTR_SCROLL_X_MIN] = min_offset.width(); - dst->int_attributes[dst->ATTR_SCROLL_Y_MIN] = min_offset.height(); + dst->AddIntAttribute(dst->ATTR_SCROLL_X_MIN, min_offset.width()); + dst->AddIntAttribute(dst->ATTR_SCROLL_Y_MIN, min_offset.height()); const gfx::Size& max_offset = document.frame()->maximumScrollOffset(); - dst->int_attributes[dst->ATTR_SCROLL_X_MAX] = max_offset.width(); - dst->int_attributes[dst->ATTR_SCROLL_Y_MAX] = max_offset.height(); + dst->AddIntAttribute(dst->ATTR_SCROLL_X_MAX, max_offset.width()); + dst->AddIntAttribute(dst->ATTR_SCROLL_Y_MAX, max_offset.height()); } if (dst->role == dst->ROLE_TABLE) { int column_count = src.columnCount(); int row_count = src.rowCount(); if (column_count > 0 && row_count > 0) { - std::set<int> unique_cell_id_set; - dst->int_attributes[dst->ATTR_TABLE_COLUMN_COUNT] = column_count; - dst->int_attributes[dst->ATTR_TABLE_ROW_COUNT] = row_count; + std::set<int32> unique_cell_id_set; + std::vector<int32> cell_ids; + std::vector<int32> unique_cell_ids; + dst->AddIntAttribute(dst->ATTR_TABLE_COLUMN_COUNT, column_count); + dst->AddIntAttribute(dst->ATTR_TABLE_ROW_COUNT, row_count); WebAccessibilityObject header = src.headerContainerObject(); if (!header.isDetached()) - dst->int_attributes[dst->ATTR_TABLE_HEADER_ID] = header.axID(); + dst->AddIntAttribute(dst->ATTR_TABLE_HEADER_ID, header.axID()); for (int i = 0; i < column_count * row_count; ++i) { WebAccessibilityObject cell = src.cellForColumnAndRow( i % column_count, i / column_count); @@ -568,39 +604,43 @@ void SerializeAccessibilityNode( cell_id = cell.axID(); if (unique_cell_id_set.find(cell_id) == unique_cell_id_set.end()) { unique_cell_id_set.insert(cell_id); - dst->unique_cell_ids.push_back(cell_id); + unique_cell_ids.push_back(cell_id); } } - dst->cell_ids.push_back(cell_id); + cell_ids.push_back(cell_id); } + dst->AddIntListAttribute(dst->ATTR_CELL_IDS, cell_ids); + dst->AddIntListAttribute(dst->ATTR_UNIQUE_CELL_IDS, unique_cell_ids); } } if (dst->role == dst->ROLE_ROW) { - dst->int_attributes[dst->ATTR_TABLE_ROW_INDEX] = src.rowIndex(); + dst->AddIntAttribute(dst->ATTR_TABLE_ROW_INDEX, src.rowIndex()); WebAccessibilityObject header = src.rowHeader(); if (!header.isDetached()) - dst->int_attributes[dst->ATTR_TABLE_ROW_HEADER_ID] = header.axID(); + dst->AddIntAttribute(dst->ATTR_TABLE_ROW_HEADER_ID, header.axID()); } if (dst->role == dst->ROLE_COLUMN) { - dst->int_attributes[dst->ATTR_TABLE_COLUMN_INDEX] = src.columnIndex(); + dst->AddIntAttribute(dst->ATTR_TABLE_COLUMN_INDEX, src.columnIndex()); WebAccessibilityObject header = src.columnHeader(); if (!header.isDetached()) - dst->int_attributes[dst->ATTR_TABLE_COLUMN_HEADER_ID] = header.axID(); + dst->AddIntAttribute(dst->ATTR_TABLE_COLUMN_HEADER_ID, header.axID()); } if (dst->role == dst->ROLE_CELL || dst->role == dst->ROLE_ROW_HEADER || dst->role == dst->ROLE_COLUMN_HEADER) { - dst->int_attributes[dst->ATTR_TABLE_CELL_COLUMN_INDEX] = - src.cellColumnIndex(); - dst->int_attributes[dst->ATTR_TABLE_CELL_COLUMN_SPAN] = - src.cellColumnSpan(); - dst->int_attributes[dst->ATTR_TABLE_CELL_ROW_INDEX] = src.cellRowIndex(); - dst->int_attributes[dst->ATTR_TABLE_CELL_ROW_SPAN] = src.cellRowSpan(); + dst->AddIntAttribute(dst->ATTR_TABLE_CELL_COLUMN_INDEX, + src.cellColumnIndex()); + dst->AddIntAttribute(dst->ATTR_TABLE_CELL_COLUMN_SPAN, + src.cellColumnSpan()); + dst->AddIntAttribute(dst->ATTR_TABLE_CELL_ROW_INDEX, src.cellRowIndex()); + dst->AddIntAttribute(dst->ATTR_TABLE_CELL_ROW_SPAN, src.cellRowSpan()); } + dst->AddStringAttribute(dst->ATTR_NAME, name); + // Add the ids of *indirect* children - those who are children of this node, // but whose parent is *not* this node. One example is a table // cell, which is a child of both a row and a column. Because the cell's @@ -609,8 +649,13 @@ void SerializeAccessibilityNode( int child_count = src.childCount(); for (int i = 0; i < child_count; ++i) { WebAccessibilityObject child = src.childAt(i); + std::vector<int32> indirect_child_ids; if (!is_iframe && !child.isDetached() && !IsParentUnignoredOf(src, child)) - dst->indirect_child_ids.push_back(child.axID()); + indirect_child_ids.push_back(child.axID()); + if (indirect_child_ids.size() > 0) { + dst->AddIntListAttribute( + dst->ATTR_INDIRECT_CHILD_IDS, indirect_child_ids); + } } } diff --git a/content/renderer/accessibility/renderer_accessibility_complete.cc b/content/renderer/accessibility/renderer_accessibility_complete.cc index abce9c8..1d92ba6 100644 --- a/content/renderer/accessibility/renderer_accessibility_complete.cc +++ b/content/renderer/accessibility/renderer_accessibility_complete.cc @@ -405,8 +405,8 @@ void RendererAccessibilityComplete::AppendLocationChangeNotifications( AccessibilityNodeData& serialized_node = notification_msg.nodes[i]; serialized_node.id = location_changes[i]->id; serialized_node.location = location_changes[i]->location; - serialized_node.bool_attributes[ - AccessibilityNodeData::ATTR_UPDATE_LOCATION_ONLY] = true; + serialized_node.AddBoolAttribute( + AccessibilityNodeData::ATTR_UPDATE_LOCATION_ONLY, true); } notification_msgs->push_back(notification_msg); diff --git a/content/test/accessibility_browser_test_utils.cc b/content/test/accessibility_browser_test_utils.cc index 08534eb..67d159c 100644 --- a/content/test/accessibility_browser_test_utils.cc +++ b/content/test/accessibility_browser_test_utils.cc @@ -57,13 +57,11 @@ bool AccessibilityNotificationWaiter::IsAboutBlank() { // to avoid a possible race condition between the test beginning // listening for accessibility events and "about:blank" loading. const AccessibilityNodeDataTreeNode& root = GetAccessibilityNodeDataTree(); - typedef AccessibilityNodeData::StringAttribute StringAttribute; - std::map<StringAttribute, string16>::const_iterator iter; - iter = root.string_attributes.find(AccessibilityNodeData::ATTR_DOC_URL); - if (iter != root.string_attributes.end()) { - string16 doc_url = iter->second; - if (doc_url == ASCIIToUTF16(kAboutBlankURL)) - return true; + for (size_t i = 0; i < root.string_attributes.size(); ++i) { + if (root.string_attributes[i].first != AccessibilityNodeData::ATTR_DOC_URL) + continue; + const std::string& doc_url = root.string_attributes[i].second; + return doc_url == kAboutBlankURL; } return false; } |