summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornektar <nektar@chromium.org>2016-03-16 15:08:48 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-16 22:12:16 +0000
commit0eebf0cd114b70337c0ae3562786e538bd6aac9d (patch)
tree9781a9cfc4c2084d2fe1f80528095682e0b7857f
parentdf644193ff164f1d3df85d857f2b21b5ba51f77e (diff)
downloadchromium_src-0eebf0cd114b70337c0ae3562786e538bd6aac9d.zip
chromium_src-0eebf0cd114b70337c0ae3562786e538bd6aac9d.tar.gz
chromium_src-0eebf0cd114b70337c0ae3562786e538bd6aac9d.tar.bz2
Implemented the reporting of text style and language information on Windows.
BUG=484228 TESTED=unit test, dump accessibility tree tests, manually with Jaws and NVDA screen readers R=dmazzoni@chromium.org,aboxhall@chromium.org Review URL: https://codereview.chromium.org/1768753003 Cr-Commit-Position: refs/heads/master@{#381560}
-rw-r--r--components/test_runner/web_ax_object_proxy.cc11
-rw-r--r--components/test_runner/web_ax_object_proxy.h1
-rw-r--r--content/browser/accessibility/accessibility_tree_formatter_win.cc83
-rw-r--r--content/browser/accessibility/browser_accessibility.cc80
-rw-r--r--content/browser/accessibility/browser_accessibility.h19
-rw-r--r--content/browser/accessibility/browser_accessibility_android.cc10
-rw-r--r--content/browser/accessibility/browser_accessibility_cocoa.mm11
-rw-r--r--content/browser/accessibility/browser_accessibility_win.cc509
-rw-r--r--content/browser/accessibility/browser_accessibility_win.h39
-rw-r--r--content/browser/accessibility/browser_accessibility_win_unittest.cc115
-rw-r--r--content/browser/accessibility/dump_accessibility_tree_browsertest.cc23
-rw-r--r--content/renderer/accessibility/blink_ax_tree_source.cc33
-rw-r--r--content/test/data/accessibility/aria/aria-invalid-expected-win.txt30
-rw-r--r--content/test/data/accessibility/css/color-expected-blink.txt11
-rw-r--r--content/test/data/accessibility/css/color-expected-win.txt7
-rw-r--r--content/test/data/accessibility/css/color.html17
-rw-r--r--content/test/data/accessibility/css/font-style-expected-blink.txt15
-rw-r--r--content/test/data/accessibility/css/font-style-expected-win.txt9
-rw-r--r--content/test/data/accessibility/css/font-style.html16
-rw-r--r--content/test/data/accessibility/css/language-expected-blink.txt7
-rw-r--r--content/test/data/accessibility/css/language-expected-win.txt5
-rw-r--r--content/test/data/accessibility/css/language.html12
-rw-r--r--content/test/data/accessibility/html/keygen-expected-win.txt4
-rw-r--r--content/test/data/accessibility/html/keygen.html1
-rw-r--r--content/test/data/accessibility/html/optgroup-expected-win.txt2
-rw-r--r--content/test/data/accessibility/html/optgroup.html1
-rw-r--r--third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp37
-rw-r--r--third_party/WebKit/Source/modules/accessibility/AXLayoutObject.h1
-rw-r--r--third_party/WebKit/Source/modules/accessibility/AXObject.h1
-rw-r--r--third_party/WebKit/Source/web/WebAXObject.cpp8
-rw-r--r--third_party/WebKit/public/web/WebAXObject.h1
-rw-r--r--ui/accessibility/ax_enums.idl8
-rw-r--r--ui/accessibility/ax_node_data.cc10
-rw-r--r--ui/accessibility/ax_tree_data.cc22
-rw-r--r--ui/accessibility/ax_tree_data.h6
35 files changed, 914 insertions, 251 deletions
diff --git a/components/test_runner/web_ax_object_proxy.cc b/components/test_runner/web_ax_object_proxy.cc
index 347da31..efc2574 100644
--- a/components/test_runner/web_ax_object_proxy.cc
+++ b/components/test_runner/web_ax_object_proxy.cc
@@ -517,6 +517,7 @@ WebAXObjectProxy::GetObjectTemplateBuilder(v8::Isolate* isolate) {
.SetProperty("backgroundColor", &WebAXObjectProxy::BackgroundColor)
.SetProperty("color", &WebAXObjectProxy::Color)
.SetProperty("colorValue", &WebAXObjectProxy::ColorValue)
+ .SetProperty("fontFamily", &WebAXObjectProxy::FontFamily)
.SetProperty("fontSize", &WebAXObjectProxy::FontSize)
.SetProperty("orientation", &WebAXObjectProxy::Orientation)
.SetProperty("posInSet", &WebAXObjectProxy::PosInSet)
@@ -550,8 +551,7 @@ WebAXObjectProxy::GetObjectTemplateBuilder(v8::Isolate* isolate) {
.SetMethod("cellForColumnAndRow", &WebAXObjectProxy::CellForColumnAndRow)
.SetMethod("setSelectedTextRange",
&WebAXObjectProxy::SetSelectedTextRange)
- .SetMethod("setSelection",
- &WebAXObjectProxy::SetSelection)
+ .SetMethod("setSelection", &WebAXObjectProxy::SetSelection)
.SetMethod("isAttributeSettable", &WebAXObjectProxy::IsAttributeSettable)
.SetMethod("isPressActionSupported",
&WebAXObjectProxy::IsPressActionSupported)
@@ -597,7 +597,6 @@ WebAXObjectProxy::GetObjectTemplateBuilder(v8::Isolate* isolate) {
&WebAXObjectProxy::DescriptionElementCount)
.SetMethod("descriptionElementAtIndex",
&WebAXObjectProxy::DescriptionElementAtIndex);
-
}
v8::Local<v8::Object> WebAXObjectProxy::GetChildAtIndex(unsigned index) {
@@ -896,6 +895,12 @@ unsigned int WebAXObjectProxy::ColorValue() {
return accessibility_object_.colorValue();
}
+std::string WebAXObjectProxy::FontFamily() {
+ accessibility_object_.updateLayoutAndCheckValidity();
+ std::string font_family(accessibility_object_.fontFamily().utf8());
+ return font_family.insert(0, "AXFontFamily: ");
+}
+
float WebAXObjectProxy::FontSize() {
accessibility_object_.updateLayoutAndCheckValidity();
return accessibility_object_.fontSize();
diff --git a/components/test_runner/web_ax_object_proxy.h b/components/test_runner/web_ax_object_proxy.h
index cc7853a..a90a713 100644
--- a/components/test_runner/web_ax_object_proxy.h
+++ b/components/test_runner/web_ax_object_proxy.h
@@ -111,6 +111,7 @@ class WebAXObjectProxy : public gin::Wrappable<WebAXObjectProxy> {
unsigned int Color();
// For input elements of type color.
unsigned int ColorValue();
+ std::string FontFamily();
float FontSize();
std::string Orientation();
int PosInSet();
diff --git a/content/browser/accessibility/accessibility_tree_formatter_win.cc b/content/browser/accessibility/accessibility_tree_formatter_win.cc
index c799846..acb299c 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_win.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_win.cc
@@ -54,36 +54,35 @@ AccessibilityTreeFormatterWin::AccessibilityTreeFormatterWin() {
AccessibilityTreeFormatterWin::~AccessibilityTreeFormatterWin() {
}
-const char* ALL_ATTRIBUTES[] = {
- "name",
- "value",
- "states",
- "attributes",
- "role_name",
- "ia2_hypertext",
- "currentValue",
- "minimumValue",
- "maximumValue",
- "description",
- "default_action",
- "keyboard_shortcut",
- "location",
- "size",
- "index_in_parent",
- "n_relations",
- "group_level",
- "similar_items_in_group",
- "position_in_group",
- "table_rows",
- "table_columns",
- "row_index",
- "column_index",
- "n_characters",
- "caret_offset",
- "n_selections",
- "selection_start",
- "selection_end"
-};
+const char* ALL_ATTRIBUTES[] = {"name",
+ "value",
+ "states",
+ "attributes",
+ "text_attributes",
+ "role_name",
+ "ia2_hypertext",
+ "currentValue",
+ "minimumValue",
+ "maximumValue",
+ "description",
+ "default_action",
+ "keyboard_shortcut",
+ "location",
+ "size",
+ "index_in_parent",
+ "n_relations",
+ "group_level",
+ "similar_items_in_group",
+ "position_in_group",
+ "table_rows",
+ "table_columns",
+ "row_index",
+ "column_index",
+ "n_characters",
+ "caret_offset",
+ "n_selections",
+ "selection_start",
+ "selection_end"};
namespace {
@@ -190,17 +189,29 @@ void AccessibilityTreeFormatterWin::AddProperties(
IAccessibleStateToStringVector(ia_state, &state_strings);
IAccessible2StateToStringVector(ax_object->ia2_state(), &state_strings);
- base::ListValue* states = new base::ListValue;
- for (const auto& state_string : state_strings)
+ scoped_ptr<base::ListValue> states(new base::ListValue());
+ for (const base::string16& state_string : state_strings)
states->AppendString(base::UTF16ToUTF8(state_string));
- dict->Set("states", states);
+ dict->Set("states", std::move(states));
const std::vector<base::string16>& ia2_attributes =
ax_object->ia2_attributes();
- base::ListValue* attributes = new base::ListValue;
- for (const auto& ia2_attribute : ia2_attributes)
+ scoped_ptr<base::ListValue> attributes(new base::ListValue());
+ for (const base::string16& ia2_attribute : ia2_attributes)
attributes->AppendString(base::UTF16ToUTF8(ia2_attribute));
- dict->Set("attributes", attributes);
+ dict->Set("attributes", std::move(attributes));
+
+ ax_object->ComputeStylesIfNeeded();
+ const std::map<int, std::vector<base::string16>>& ia2_text_attributes =
+ ax_object->offset_to_text_attributes();
+ scoped_ptr<base::ListValue> text_attributes(new base::ListValue());
+ for (const auto& style_span : ia2_text_attributes) {
+ int start_offset = style_span.first;
+ text_attributes->AppendString("offset:" + base::IntToString(start_offset));
+ for (const base::string16& text_attribute : style_span.second)
+ text_attributes->AppendString(base::UTF16ToUTF8(text_attribute));
+ }
+ dict->Set("text_attributes", std::move(text_attributes));
dict->SetString("role_name", ax_object->role_name());
dict->SetString("ia2_hypertext", GetIA2Hypertext(*ax_object));
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc
index b45b196..4afad6b 100644
--- a/content/browser/accessibility/browser_accessibility.cc
+++ b/content/browser/accessibility/browser_accessibility.cc
@@ -252,8 +252,9 @@ BrowserAccessibility* BrowserAccessibility::InternalGetChild(
}
BrowserAccessibility* BrowserAccessibility::GetParent() const {
- if (!node_ || !manager_)
- return NULL;
+ if (!instance_active())
+ return nullptr;
+
ui::AXNode* parent = node_->parent();
if (parent)
return manager_->GetFromAXNode(parent);
@@ -384,8 +385,8 @@ gfx::Rect BrowserAccessibility::GetLocalBoundsForRange(int start, int len)
int local_end = overlap_end - child_start;
gfx::Rect child_rect = child->GetLocation();
- int text_direction = child->GetIntAttribute(
- ui::AX_ATTR_TEXT_DIRECTION);
+ auto text_direction = static_cast<ui::AXTextDirection>(
+ child->GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION));
const std::vector<int32_t>& character_offsets =
child->GetIntListAttribute(ui::AX_ATTR_CHARACTER_OFFSETS);
int start_pixel_offset =
@@ -657,6 +658,72 @@ bool BrowserAccessibility::GetFloatAttribute(
return GetData().GetFloatAttribute(attribute, value);
}
+bool BrowserAccessibility::HasInheritedStringAttribute(
+ ui::AXStringAttribute attribute) const {
+ if (!instance_active())
+ return false;
+
+ if (GetData().HasStringAttribute(attribute))
+ return true;
+ return GetParent() && GetParent()->HasInheritedStringAttribute(attribute);
+}
+
+const std::string& BrowserAccessibility::GetInheritedStringAttribute(
+ ui::AXStringAttribute attribute) const {
+ if (!instance_active())
+ return base::EmptyString();
+
+ const BrowserAccessibility* current_object = this;
+ do {
+ if (current_object->GetData().HasStringAttribute(attribute))
+ return current_object->GetData().GetStringAttribute(attribute);
+ current_object = current_object->GetParent();
+ } while (current_object);
+ return base::EmptyString();
+}
+
+bool BrowserAccessibility::GetInheritedStringAttribute(
+ ui::AXStringAttribute attribute,
+ std::string* value) const {
+ if (!instance_active()) {
+ *value = std::string();
+ return false;
+ }
+
+ if (GetData().GetStringAttribute(attribute, value))
+ return true;
+ return GetParent() &&
+ GetParent()->GetData().GetStringAttribute(attribute, value);
+}
+
+base::string16 BrowserAccessibility::GetInheritedString16Attribute(
+ ui::AXStringAttribute attribute) const {
+ if (!instance_active())
+ return base::string16();
+
+ const BrowserAccessibility* current_object = this;
+ do {
+ if (current_object->GetData().HasStringAttribute(attribute))
+ return current_object->GetData().GetString16Attribute(attribute);
+ current_object = current_object->GetParent();
+ } while (current_object);
+ return base::string16();
+}
+
+bool BrowserAccessibility::GetInheritedString16Attribute(
+ ui::AXStringAttribute attribute,
+ base::string16* value) const {
+ if (!instance_active()) {
+ *value = base::string16();
+ return false;
+ }
+
+ if (GetData().GetString16Attribute(attribute, value))
+ return true;
+ return GetParent() &&
+ GetParent()->GetData().GetString16Attribute(attribute, value);
+}
+
bool BrowserAccessibility::HasIntAttribute(
ui::AXIntAttribute attribute) const {
return GetData().HasIntAttribute(attribute);
@@ -691,9 +758,8 @@ base::string16 BrowserAccessibility::GetString16Attribute(
return GetData().GetString16Attribute(attribute);
}
-bool BrowserAccessibility::GetString16Attribute(
- ui::AXStringAttribute attribute,
- base::string16* value) const {
+bool BrowserAccessibility::GetString16Attribute(ui::AXStringAttribute attribute,
+ base::string16* value) const {
return GetData().GetString16Attribute(attribute, value);
}
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h
index ff17bc5..f93eea12 100644
--- a/content/browser/accessibility/browser_accessibility.h
+++ b/content/browser/accessibility/browser_accessibility.h
@@ -194,7 +194,7 @@ class CONTENT_EXPORT BrowserAccessibility {
//
BrowserAccessibilityManager* manager() const { return manager_; }
- bool instance_active() const { return node_ != NULL; }
+ bool instance_active() const { return node_ && manager_; }
ui::AXNode* node() const { return node_; }
int32_t unique_id() const { return unique_id_; }
@@ -246,6 +246,17 @@ class CONTENT_EXPORT BrowserAccessibility {
float GetFloatAttribute(ui::AXFloatAttribute attr) const;
bool GetFloatAttribute(ui::AXFloatAttribute attr, float* value) const;
+ bool HasInheritedStringAttribute(ui::AXStringAttribute attribute) const;
+ const std::string& GetInheritedStringAttribute(
+ ui::AXStringAttribute attribute) const;
+ bool GetInheritedStringAttribute(ui::AXStringAttribute attribute,
+ std::string* value) const;
+
+ base::string16 GetInheritedString16Attribute(
+ ui::AXStringAttribute attribute) const;
+ bool GetInheritedString16Attribute(ui::AXStringAttribute attribute,
+ base::string16* value) const;
+
bool HasIntAttribute(ui::AXIntAttribute attribute) const;
int GetIntAttribute(ui::AXIntAttribute attribute) const;
bool GetIntAttribute(ui::AXIntAttribute attribute, int* value) const;
@@ -256,10 +267,10 @@ class CONTENT_EXPORT BrowserAccessibility {
bool GetStringAttribute(ui::AXStringAttribute attribute,
std::string* value) const;
- bool GetString16Attribute(ui::AXStringAttribute attribute,
- base::string16* value) const;
base::string16 GetString16Attribute(
ui::AXStringAttribute attribute) const;
+ bool GetString16Attribute(ui::AXStringAttribute attribute,
+ base::string16* value) const;
bool HasIntListAttribute(ui::AXIntListAttribute attribute) const;
const std::vector<int32_t>& GetIntListAttribute(
@@ -288,6 +299,8 @@ class CONTENT_EXPORT BrowserAccessibility {
bool* is_defined,
bool* is_mixed) const;
+ base::string16 GetFontFamily() const;
+ base::string16 GetLanguage() const;
virtual base::string16 GetText() const;
// Returns true if the bit corresponding to the given state enum is 1.
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc
index 8257c74..53df249 100644
--- a/content/browser/accessibility/browser_accessibility_android.cc
+++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -13,6 +13,7 @@
#include "content/browser/accessibility/browser_accessibility_manager_android.h"
#include "content/common/accessibility_messages.h"
#include "content/public/common/content_client.h"
+#include "third_party/skia/include/core/SkColor.h"
namespace {
@@ -362,10 +363,11 @@ base::string16 BrowserAccessibilityAndroid::GetText() const {
// For color wells, the color is stored in separate attributes.
// Perhaps we could return color names in the future?
if (GetRole() == ui::AX_ROLE_COLOR_WELL) {
- int color = GetIntAttribute(ui::AX_ATTR_COLOR_VALUE);
- int red = (color >> 16) & 0xFF;
- int green = (color >> 8) & 0xFF;
- int blue = color & 0xFF;
+ unsigned int color =
+ static_cast<unsigned int>(GetIntAttribute(ui::AX_ATTR_COLOR_VALUE));
+ unsigned int red = SkColorGetR(color);
+ unsigned int green = SkColorGetG(color);
+ unsigned int blue = SkColorGetB(color);
return base::UTF8ToUTF16(
base::StringPrintf("#%02X%02X%02X", red, green, blue));
}
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm
index 0574c25..1ae72bd 100644
--- a/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -21,6 +21,7 @@
#include "content/browser/accessibility/browser_accessibility_manager_mac.h"
#include "content/browser/accessibility/one_shot_accessibility_tree_search.h"
#include "content/public/common/content_client.h"
+#include "third_party/skia/include/core/SkColor.h"
#import "ui/accessibility/platform/ax_platform_node_mac.h"
using content::AXTreeIDRegistry;
@@ -1719,11 +1720,11 @@ bool InitializeAccessibilityTreeSearch(
return [NSNumber numberWithFloat:floatValue];
}
} else if ([role isEqualToString:NSAccessibilityColorWellRole]) {
- int color = browserAccessibility_->GetIntAttribute(
- ui::AX_ATTR_COLOR_VALUE);
- int red = (color >> 16) & 0xFF;
- int green = (color >> 8) & 0xFF;
- int blue = color & 0xFF;
+ unsigned int color = static_cast<unsigned int>(
+ browserAccessibility_->GetIntAttribute(ui::AX_ATTR_COLOR_VALUE));
+ unsigned int red = SkColorGetR(color);
+ unsigned int green = SkColorGetG(color);
+ unsigned int blue = SkColorGetB(color);
// This string matches the one returned by a native Mac color well.
return [NSString stringWithFormat:@"rgb %7.5f %7.5f %7.5f 1",
red / 255., green / 255., blue / 255.];
diff --git a/content/browser/accessibility/browser_accessibility_win.cc b/content/browser/accessibility/browser_accessibility_win.cc
index bf3b0af..03c199c 100644
--- a/content/browser/accessibility/browser_accessibility_win.cc
+++ b/content/browser/accessibility/browser_accessibility_win.cc
@@ -20,6 +20,7 @@
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/common/accessibility_messages.h"
#include "content/public/common/content_client.h"
+#include "third_party/skia/include/core/SkColor.h"
#include "ui/accessibility/ax_text_utils.h"
#include "ui/base/win/accessibility_ids_win.h"
#include "ui/base/win/accessibility_misc_utils.h"
@@ -115,9 +116,8 @@ STDMETHODIMP BrowserAccessibilityRelation::get_nTargets(long* n_targets) {
*n_targets = static_cast<long>(target_ids_.size());
- BrowserAccessibilityManager* manager = owner_->manager();
for (long i = *n_targets - 1; i >= 0; --i) {
- BrowserAccessibility* result = manager->GetFromID(target_ids_[i]);
+ BrowserAccessibilityWin* result = owner_->GetFromID(target_ids_[i]);
if (!result || !result->instance_active()) {
*n_targets = 0;
break;
@@ -139,9 +139,7 @@ STDMETHODIMP BrowserAccessibilityRelation::get_target(long target_index,
return E_INVALIDARG;
}
- BrowserAccessibilityManager* manager = owner_->manager();
- BrowserAccessibility* result =
- manager->GetFromID(target_ids_[target_index]);
+ BrowserAccessibility* result = owner_->GetFromID(target_ids_[target_index]);
if (!result || !result->instance_active())
return E_FAIL;
@@ -576,14 +574,15 @@ STDMETHODIMP BrowserAccessibilityWin::get_accValue(VARIANT var_id,
// Expose color well value.
if (target->ia2_role() == IA2_ROLE_COLOR_CHOOSER) {
- int color = target->GetIntAttribute(ui::AX_ATTR_COLOR_VALUE);
- int red = (color >> 16) & 0xFF;
- int green = (color >> 8) & 0xFF;
- int blue = color & 0xFF;
+ unsigned int color = static_cast<unsigned int>(
+ target->GetIntAttribute(ui::AX_ATTR_COLOR_VALUE));
+ unsigned int red = SkColorGetR(color);
+ unsigned int green = SkColorGetG(color);
+ unsigned int blue = SkColorGetB(color);
base::string16 value_text;
- value_text = base::IntToString16((red * 100) / 255) + L"% red " +
- base::IntToString16((green * 100) / 255) + L"% green " +
- base::IntToString16((blue * 100) / 255) + L"% blue";
+ value_text = base::UintToString16(red * 100 / 255) + L"% red " +
+ base::UintToString16(green * 100 / 255) + L"% green " +
+ base::UintToString16(blue * 100 / 255) + L"% blue";
*value = SysAllocString(value_text.c_str());
DCHECK(*value);
return S_OK;
@@ -687,19 +686,16 @@ STDMETHODIMP BrowserAccessibilityWin::role(LONG* role) {
}
STDMETHODIMP BrowserAccessibilityWin::get_attributes(BSTR* attributes) {
- if (!instance_active())
- return E_FAIL;
-
if (!attributes)
return E_INVALIDARG;
+ *attributes = nullptr;
+
+ if (!instance_active())
+ return E_FAIL;
- // The iaccessible2 attributes are a set of key-value pairs
- // separated by semicolons, with a colon between the key and the value.
base::string16 str;
- const std::vector<base::string16>& attributes_list = ia2_attributes();
- for (unsigned int i = 0; i < attributes_list.size(); ++i) {
- str += attributes_list[i] + L';';
- }
+ for (const base::string16& attribute : ia2_attributes())
+ str += attribute + L';';
if (str.empty())
return S_FALSE;
@@ -847,7 +843,6 @@ STDMETHODIMP BrowserAccessibilityWin::scrollTo(IA2ScrollType scroll_type) {
}
manager()->ToBrowserAccessibilityManagerWin()->TrackScrollingObject(this);
-
return S_OK;
}
@@ -1181,8 +1176,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnDescription(long column,
GetIntListAttribute(ui::AX_ATTR_CELL_IDS);
for (int i = 0; i < rows; ++i) {
int cell_id = cell_ids[i * columns + column];
- BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>(
- manager()->GetFromID(cell_id));
+ BrowserAccessibilityWin* cell = GetFromID(cell_id);
if (cell && cell->GetRole() == ui::AX_ROLE_COLUMN_HEADER) {
base::string16 cell_name = cell->GetString16Attribute(
ui::AX_ATTR_NAME);
@@ -1227,8 +1221,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnExtentAt(
const std::vector<int32_t>& cell_ids =
GetIntListAttribute(ui::AX_ATTR_CELL_IDS);
int cell_id = cell_ids[row * columns + column];
- BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>(
- manager()->GetFromID(cell_id));
+ BrowserAccessibilityWin* cell = GetFromID(cell_id);
int colspan;
if (cell &&
cell->GetIntAttribute(
@@ -1265,8 +1258,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnIndex(long cell_index,
return S_FALSE;
int cell_id = unique_cell_ids[cell_index];
- BrowserAccessibilityWin* cell =
- ToBrowserAccessibilityWin(manager()->GetFromID(cell_id));
+ BrowserAccessibilityWin* cell = GetFromID(cell_id);
int col_index;
if (cell &&
cell->GetIntAttribute(
@@ -1370,8 +1362,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowDescription(long row,
GetIntListAttribute(ui::AX_ATTR_CELL_IDS);
for (int i = 0; i < columns; ++i) {
int cell_id = cell_ids[row * columns + i];
- BrowserAccessibilityWin* cell =
- ToBrowserAccessibilityWin(manager()->GetFromID(cell_id));
+ BrowserAccessibilityWin* cell = GetFromID(cell_id);
if (cell && cell->GetRole() == ui::AX_ROLE_ROW_HEADER) {
base::string16 cell_name = cell->GetString16Attribute(
ui::AX_ATTR_NAME);
@@ -1415,8 +1406,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowExtentAt(long row,
const std::vector<int32_t>& cell_ids =
GetIntListAttribute(ui::AX_ATTR_CELL_IDS);
int cell_id = cell_ids[row * columns + column];
- BrowserAccessibilityWin* cell =
- ToBrowserAccessibilityWin(manager()->GetFromID(cell_id));
+ BrowserAccessibilityWin* cell = GetFromID(cell_id);
int rowspan;
if (cell &&
cell->GetIntAttribute(
@@ -1453,8 +1443,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowIndex(long cell_index,
return S_FALSE;
int cell_id = unique_cell_ids[cell_index];
- BrowserAccessibilityWin* cell =
- ToBrowserAccessibilityWin(manager()->GetFromID(cell_id));
+ BrowserAccessibilityWin* cell = GetFromID(cell_id);
int cell_row_index;
if (cell &&
cell->GetIntAttribute(
@@ -1582,8 +1571,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowColumnExtentsAtIndex(
return S_FALSE;
int cell_id = unique_cell_ids[index];
- BrowserAccessibilityWin* cell =
- ToBrowserAccessibilityWin(manager()->GetFromID(cell_id));
+ BrowserAccessibilityWin* cell = GetFromID(cell_id);
int rowspan;
int colspan;
if (cell &&
@@ -1741,8 +1729,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnHeaderCells(
for (int i = 0; i < rows; ++i) {
int cell_id = cell_ids[i * columns + column];
- BrowserAccessibilityWin* cell =
- ToBrowserAccessibilityWin(manager()->GetFromID(cell_id));
+ BrowserAccessibilityWin* cell = GetFromID(cell_id);
if (cell && cell->GetRole() == ui::AX_ROLE_COLUMN_HEADER)
(*n_column_header_cells)++;
}
@@ -2349,15 +2336,40 @@ STDMETHODIMP BrowserAccessibilityWin::setSelection(LONG selection_index,
return S_OK;
}
-//
-// IAccessibleText methods not implemented.
-//
-
STDMETHODIMP BrowserAccessibilityWin::get_attributes(LONG offset,
LONG* start_offset,
LONG* end_offset,
BSTR* text_attributes) {
- return E_NOTIMPL;
+ if (!start_offset || !end_offset || !text_attributes)
+ return E_INVALIDARG;
+
+ *start_offset = *end_offset = 0;
+ *text_attributes = nullptr;
+ if (!instance_active())
+ return E_FAIL;
+
+ const base::string16& text = GetText();
+ HandleSpecialTextOffset(text, &offset);
+ if (offset < 0 || offset > static_cast<LONG>(text.size()))
+ return E_INVALIDARG;
+
+ ComputeStylesIfNeeded();
+ *start_offset = FindStartOfStyle(offset, ui::BACKWARDS_DIRECTION);
+ *end_offset = FindStartOfStyle(offset, ui::FORWARDS_DIRECTION);
+
+ base::string16 attributes_str;
+ const std::vector<base::string16>& attributes =
+ offset_to_text_attributes().find(*start_offset)->second;
+ for (const base::string16& attribute : attributes) {
+ attributes_str += attribute + L';';
+ }
+
+ if (attributes.empty())
+ return S_FALSE;
+
+ *text_attributes = SysAllocString(attributes_str.c_str());
+ DCHECK(*text_attributes);
+ return S_OK;
}
//
@@ -2388,14 +2400,12 @@ STDMETHODIMP BrowserAccessibilityWin::get_hyperlink(
}
int32_t id = hyperlinks()[index];
- BrowserAccessibilityWin* child =
- ToBrowserAccessibilityWin(manager()->GetFromID(id));
- if (child) {
- *hyperlink = static_cast<IAccessibleHyperlink*>(child->NewReference());
- return S_OK;
- }
+ BrowserAccessibilityWin* link = GetFromID(id);
+ if (!link)
+ return E_FAIL;
- return E_FAIL;
+ *hyperlink = static_cast<IAccessibleHyperlink*>(link->NewReference());
+ return S_OK;
}
STDMETHODIMP BrowserAccessibilityWin::get_hyperlinkIndex(
@@ -2973,7 +2983,20 @@ BrowserAccessibilityWin::get_localInterface(void** local_interface) {
}
STDMETHODIMP BrowserAccessibilityWin::get_language(BSTR* language) {
- return E_NOTIMPL;
+ if (!language)
+ return E_INVALIDARG;
+ *language = nullptr;
+
+ if (!instance_active())
+ return E_FAIL;
+
+ base::string16 lang = GetInheritedString16Attribute(ui::AX_ATTR_LANGUAGE);
+ if (lang.empty())
+ lang = L"en-US";
+
+ *language = SysAllocString(lang.c_str());
+ DCHECK(*language);
+ return S_OK;
}
//
@@ -3052,7 +3075,21 @@ STDMETHODIMP BrowserAccessibilityWin::scrollToSubstring(
}
STDMETHODIMP BrowserAccessibilityWin::get_fontFamily(BSTR* font_family) {
- return E_NOTIMPL;
+ if (!font_family)
+ return E_INVALIDARG;
+ *font_family = nullptr;
+
+ if (!instance_active())
+ return E_FAIL;
+
+ base::string16 family =
+ GetInheritedString16Attribute(ui::AX_ATTR_FONT_FAMILY);
+ if (family.empty())
+ return S_FALSE;
+
+ *font_family = SysAllocString(family.c_str());
+ DCHECK(*font_family);
+ return S_OK;
}
//
@@ -3233,6 +3270,45 @@ HRESULT WINAPI BrowserAccessibilityWin::InternalQueryInterface(
this_ptr, entries, iid, object);
}
+void BrowserAccessibilityWin::ComputeStylesIfNeeded() {
+ if (!offset_to_text_attributes().empty())
+ return;
+
+ std::map<int, std::vector<base::string16>> attributes_map;
+ if (PlatformIsLeaf()) {
+ attributes_map[0] = ComputeTextAttributes();
+ win_attributes_->offset_to_text_attributes.swap(attributes_map);
+ return;
+ }
+
+ int start_offset = 0;
+ for (size_t i = 0; i < PlatformChildCount(); ++i) {
+ const auto child = ToBrowserAccessibilityWin(PlatformGetChild(i));
+ DCHECK(child);
+ std::vector<base::string16> attributes(child->ComputeTextAttributes());
+
+ if (attributes_map.empty()) {
+ attributes_map[start_offset] = attributes;
+ } else {
+ // Only add the attributes for this child if we are at the start of a new
+ // style span.
+ std::vector<base::string16> previous_attributes =
+ attributes_map.rbegin()->second;
+ if (!std::equal(attributes.begin(), attributes.end(),
+ previous_attributes.begin())) {
+ attributes_map[start_offset] = attributes;
+ }
+ }
+
+ if (child->IsTextOnlyObject())
+ start_offset += child->GetText().length();
+ else
+ start_offset += 1;
+ }
+
+ win_attributes_->offset_to_text_attributes.swap(attributes_map);
+}
+
base::string16 BrowserAccessibilityWin::GetText() const {
if (PlatformIsChildOfLeaf())
return BrowserAccessibility::GetText();
@@ -3317,44 +3393,6 @@ void BrowserAccessibilityWin::UpdateStep1ComputeWinAttributes() {
}
}
- // Expose invalid state for form controls and elements with aria-invalid.
- int invalid_state;
- if (GetIntAttribute(ui::AX_ATTR_INVALID_STATE, &invalid_state)) {
- // TODO(nektar): Handle the possibility of having multiple aria-invalid
- // attributes defined, e.g., "invalid:spelling,grammar".
- switch (invalid_state) {
- case ui::AX_INVALID_STATE_FALSE:
- win_attributes_->ia2_attributes.push_back(L"invalid:false");
- break;
- case ui::AX_INVALID_STATE_TRUE:
- win_attributes_->ia2_attributes.push_back(L"invalid:true");
- break;
- case ui::AX_INVALID_STATE_SPELLING:
- win_attributes_->ia2_attributes.push_back(L"invalid:spelling");
- break;
- case ui::AX_INVALID_STATE_GRAMMAR:
- win_attributes_->ia2_attributes.push_back(L"invalid:grammar");
- break;
- case ui::AX_INVALID_STATE_OTHER:
- {
- base::string16 aria_invalid_value;
- if (GetString16Attribute(ui::AX_ATTR_ARIA_INVALID_VALUE,
- &aria_invalid_value)) {
- SanitizeStringAttributeForIA2(aria_invalid_value,
- &aria_invalid_value);
- win_attributes_->ia2_attributes.push_back(
- L"invalid:" + aria_invalid_value);
- } else {
- // Set the attribute to L"true", since we cannot be more specific.
- win_attributes_->ia2_attributes.push_back(L"invalid:true");
- }
- }
- break;
- default:
- NOTREACHED();
- }
- }
-
// Expose row or column header sort direction.
int32_t sort_direction;
if ((ia_role() == ROLE_SYSTEM_COLUMNHEADER ||
@@ -3434,8 +3472,7 @@ void BrowserAccessibilityWin::UpdateStep2ComputeHypertext() {
// the character index of each embedded object character to the id of the
// child object it points to.
for (unsigned int i = 0; i < PlatformChildCount(); ++i) {
- BrowserAccessibilityWin* child =
- ToBrowserAccessibilityWin(PlatformGetChild(i));
+ const auto child = ToBrowserAccessibilityWin(PlatformGetChild(i));
DCHECK(child);
// Similar to Firefox, we don't expose text-only objects in IA2 hypertext.
if (child->IsTextOnlyObject()) {
@@ -3573,6 +3610,182 @@ void BrowserAccessibilityWin::OnLocationChanged() {
EVENT_OBJECT_LOCATIONCHANGE, this);
}
+std::vector<base::string16> BrowserAccessibilityWin::ComputeTextAttributes()
+ const {
+ std::vector<base::string16> attributes;
+
+ // We include list markers for now, but there might be other objects that are
+ // auto generated.
+ // TODO(nektar): Compute what objects are auto-generated in Blink.
+ if (GetRole() == ui::AX_ROLE_LIST_MARKER)
+ attributes.push_back(L"auto-generated:true");
+ else
+ attributes.push_back(L"auto-generated:false");
+
+ int color;
+ base::string16 color_value(L"transparent");
+ if (GetIntAttribute(ui::AX_ATTR_BACKGROUND_COLOR, &color)) {
+ unsigned int alpha = SkColorGetA(color);
+ unsigned int red = SkColorGetR(color);
+ unsigned int green = SkColorGetG(color);
+ unsigned int blue = SkColorGetB(color);
+ if (alpha) {
+ color_value = L"rgb(" + base::UintToString16(red) + L',' +
+ base::UintToString16(green) + L',' +
+ base::UintToString16(blue) + L')';
+ }
+ }
+ SanitizeStringAttributeForIA2(color_value, &color_value);
+ attributes.push_back(L"background-color:" + color_value);
+
+ if (GetIntAttribute(ui::AX_ATTR_COLOR, &color)) {
+ unsigned int red = SkColorGetR(color);
+ unsigned int green = SkColorGetG(color);
+ unsigned int blue = SkColorGetB(color);
+ color_value = L"rgb(" + base::UintToString16(red) + L',' +
+ base::UintToString16(green) + L',' +
+ base::UintToString16(blue) + L')';
+ } else {
+ color_value = L"rgb(0,0,0)";
+ }
+ SanitizeStringAttributeForIA2(color_value, &color_value);
+ attributes.push_back(L"color:" + color_value);
+
+ base::string16 font_family(
+ GetInheritedString16Attribute(ui::AX_ATTR_FONT_FAMILY));
+ // Attribute has no default value.
+ if (!font_family.empty()) {
+ SanitizeStringAttributeForIA2(font_family, &font_family);
+ attributes.push_back(L"font-family:" + font_family);
+ }
+
+ float font_size;
+ // Attribute has no default value.
+ if (GetFloatAttribute(ui::AX_ATTR_FONT_SIZE, &font_size)) {
+ // The IA2 Spec requires the value to be in pt, not in pixels.
+ // There are 72 points per inch.
+ // We assume that there are 96 pixels per inch on a standard display.
+ // TODO(nektar): Figure out the current value of pixels per inch.
+ float points = font_size * 72.0 / 96.0;
+ attributes.push_back(L"font-size:" +
+ base::UTF8ToUTF16(base::DoubleToString(points)) +
+ L"pt");
+ }
+
+ auto text_style =
+ static_cast<ui::AXTextStyle>(GetIntAttribute(ui::AX_ATTR_TEXT_STYLE));
+ if (text_style == ui::AX_TEXT_STYLE_NONE) {
+ attributes.push_back(L"font-style:normal");
+ attributes.push_back(L"font-weight:normal");
+ } else {
+ if (text_style & ui::AX_TEXT_STYLE_BOLD)
+ attributes.push_back(L"font-weight:bold");
+
+ base::string16 font_style;
+ if (text_style & ui::AX_TEXT_STYLE_ITALIC)
+ font_style += L",italic";
+ if (text_style & ui::AX_TEXT_STYLE_UNDERLINE)
+ font_style += L",underline";
+ if (text_style & ui::AX_TEXT_STYLE_LINE_THROUGH)
+ font_style += L",line-through";
+ // TODO(nektar): Support more font style attributes in Blink.
+
+ if (font_style.empty()) {
+ font_style = L"normal";
+ } else {
+ // Remove the leading comma.
+ font_style.erase(0, 1);
+ }
+ attributes.push_back(L"font-style:" + font_style);
+ }
+
+ auto invalid_state = static_cast<ui::AXInvalidState>(
+ GetIntAttribute(ui::AX_ATTR_INVALID_STATE));
+ switch (invalid_state) {
+ case ui::AX_INVALID_STATE_NONE:
+ case ui::AX_INVALID_STATE_FALSE:
+ attributes.push_back(L"invalid:false");
+ break;
+ case ui::AX_INVALID_STATE_TRUE:
+ attributes.push_back(L"invalid:true");
+ break;
+ case ui::AX_INVALID_STATE_SPELLING:
+ case ui::AX_INVALID_STATE_GRAMMAR: {
+ base::string16 spelling_grammar_value;
+ if (invalid_state & ui::AX_INVALID_STATE_SPELLING)
+ spelling_grammar_value = L"spelling";
+ else if (invalid_state & ui::AX_INVALID_STATE_GRAMMAR)
+ spelling_grammar_value = L"grammar";
+ else
+ spelling_grammar_value = L"spelling,grammar";
+ attributes.push_back(L"invalid:" + spelling_grammar_value);
+ break;
+ }
+ case ui::AX_INVALID_STATE_OTHER: {
+ base::string16 aria_invalid_value;
+ if (GetString16Attribute(ui::AX_ATTR_ARIA_INVALID_VALUE,
+ &aria_invalid_value)) {
+ SanitizeStringAttributeForIA2(aria_invalid_value, &aria_invalid_value);
+ attributes.push_back(L"invalid:" + aria_invalid_value);
+ } else {
+ // Set the attribute to L"true", since we cannot be more specific.
+ attributes.push_back(L"invalid:true");
+ }
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+
+ base::string16 language(GetInheritedString16Attribute(ui::AX_ATTR_LANGUAGE));
+ // Default value should be L"en-US".
+ if (language.empty()) {
+ attributes.push_back(L"language:en-US");
+ } else {
+ SanitizeStringAttributeForIA2(language, &language);
+ attributes.push_back(L"language:" + language);
+ }
+
+ // TODO(nektar): Add Blink support for the following attributes.
+ // Currently set to their default values as dictated by the IA2 Spec.
+ attributes.push_back(L"text-line-through-mode:continuous");
+ attributes.push_back(L"text-line-through-style:none");
+ // Default value must be the empty string.
+ attributes.push_back(L"text-line-through-text:");
+ attributes.push_back(L"text-line-through-type:none");
+ attributes.push_back(L"text-line-through-width:auto");
+ attributes.push_back(L"text-outline:false");
+ attributes.push_back(L"text-position:baseline");
+ attributes.push_back(L"text-shadow:none");
+ attributes.push_back(L"text-underline-mode:continuous");
+ attributes.push_back(L"text-underline-style:none");
+ attributes.push_back(L"text-underline-type:none");
+ attributes.push_back(L"text-underline-width:auto");
+
+ auto text_direction = static_cast<ui::AXTextDirection>(
+ GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION));
+ switch (text_direction) {
+ case ui::AX_TEXT_DIRECTION_NONE:
+ case ui::AX_TEXT_DIRECTION_LTR:
+ attributes.push_back(L"writing-mode:lr");
+ break;
+ case ui::AX_TEXT_DIRECTION_RTL:
+ attributes.push_back(L"writing-mode:rl");
+ break;
+ case ui::AX_TEXT_DIRECTION_TTB:
+ attributes.push_back(L"writing-mode:tb");
+ break;
+ case ui::AX_TEXT_DIRECTION_BTT:
+ // Not listed in the IA2 Spec.
+ attributes.push_back(L"writing-mode:bt");
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ return attributes;
+}
+
BrowserAccessibilityWin* BrowserAccessibilityWin::NewReference() {
AddRef();
return this;
@@ -3672,6 +3885,23 @@ bool BrowserAccessibilityWin::IsHyperlink() const {
return false;
}
+BrowserAccessibilityWin*
+BrowserAccessibilityWin::GetHyperlinkFromHypertextOffset(int offset) const {
+ std::map<int32_t, int32_t>::iterator iterator =
+ hyperlink_offset_to_index().find(offset);
+ if (iterator == hyperlink_offset_to_index().end())
+ return nullptr;
+
+ int32_t index = iterator->second;
+ DCHECK_GE(index, 0);
+ DCHECK_LT(index, static_cast<int32_t>(hyperlinks().size()));
+ int32_t id = hyperlinks()[index];
+ BrowserAccessibilityWin* hyperlink = GetFromID(id);
+ if (!hyperlink)
+ return nullptr;
+ return hyperlink;
+}
+
int32_t BrowserAccessibilityWin::GetHyperlinkIndexFromChild(
const BrowserAccessibilityWin& child) const {
if (hyperlinks().empty())
@@ -3815,8 +4045,7 @@ int BrowserAccessibilityWin::GetHypertextOffsetFromEndpoint(
int BrowserAccessibilityWin::GetSelectionAnchor() const {
int32_t anchor_id = manager()->GetTreeData().sel_anchor_object_id;
- const auto anchor_object =
- ToBrowserAccessibilityWin(manager()->GetFromID(anchor_id));
+ const BrowserAccessibilityWin* anchor_object = GetFromID(anchor_id);
if (!anchor_object)
return -1;
@@ -3826,8 +4055,7 @@ int BrowserAccessibilityWin::GetSelectionAnchor() const {
int BrowserAccessibilityWin::GetSelectionFocus() const {
int32_t focus_id = manager()->GetTreeData().sel_focus_object_id;
- const auto focus_object =
- ToBrowserAccessibilityWin(manager()->GetFromID(focus_id));
+ const BrowserAccessibilityWin* focus_object = GetFromID(focus_id);
if (!focus_object)
return -1;
@@ -3877,22 +4105,13 @@ void BrowserAccessibilityWin::GetSelectionOffsets(
// the selection.
int* largest_offset =
(*selection_start <= *selection_end) ? selection_end : selection_start;
- auto current_object = const_cast<BrowserAccessibilityWin*>(this);
- LONG hyperlink_index;
- HRESULT hr =
- current_object->get_hyperlinkIndex(*largest_offset, &hyperlink_index);
- if (hr != S_OK)
+ BrowserAccessibilityWin* hyperlink =
+ GetHyperlinkFromHypertextOffset(*largest_offset);
+ if (!hyperlink)
return;
- DCHECK_GE(hyperlink_index, 0);
- base::win::ScopedComPtr<IAccessibleHyperlink> hyperlink;
- hr = current_object->get_hyperlink(hyperlink_index, hyperlink.Receive());
- DCHECK(SUCCEEDED(hr));
- base::win::ScopedComPtr<IAccessibleText> hyperlink_text;
- hr = hyperlink.QueryInterface(hyperlink_text.Receive());
- DCHECK(SUCCEEDED(hr));
LONG n_selections = 0;
- hr = hyperlink_text->get_nSelections(&n_selections);
+ HRESULT hr = hyperlink->get_nSelections(&n_selections);
DCHECK(SUCCEEDED(hr));
if (n_selections > 0)
++(*largest_offset);
@@ -4024,7 +4243,39 @@ LONG BrowserAccessibilityWin::FindBoundary(
text, line_breaks, boundary, start_offset, direction);
}
-BrowserAccessibilityWin* BrowserAccessibilityWin::GetFromID(int32_t id) {
+LONG BrowserAccessibilityWin::FindStartOfStyle(
+ LONG start_offset,
+ ui::TextBoundaryDirection direction) const {
+ LONG text_length = static_cast<LONG>(GetText().length());
+ DCHECK_GE(start_offset, 0);
+ DCHECK_LE(start_offset, text_length);
+
+ switch (direction) {
+ case ui::BACKWARDS_DIRECTION: {
+ if (offset_to_text_attributes().empty())
+ return 0;
+
+ auto iterator = offset_to_text_attributes().upper_bound(start_offset);
+ --iterator;
+ return static_cast<LONG>(iterator->first);
+ }
+ case ui::FORWARDS_DIRECTION: {
+ const auto iterator =
+ offset_to_text_attributes().upper_bound(start_offset);
+ if (iterator == offset_to_text_attributes().end())
+ return text_length;
+ return static_cast<LONG>(iterator->first);
+ }
+ default:
+ NOTREACHED();
+ }
+
+ return start_offset;
+}
+
+BrowserAccessibilityWin* BrowserAccessibilityWin::GetFromID(int32_t id) const {
+ if (!instance_active())
+ return nullptr;
return ToBrowserAccessibilityWin(manager()->GetFromID(id));
}
@@ -4048,6 +4299,25 @@ bool BrowserAccessibilityWin::IsListBoxOptionOrMenuListOption() {
return false;
}
+void BrowserAccessibilityWin::AddRelations(
+ ui::AXIntListAttribute src_attr,
+ const base::string16& iaccessiblerelation_type) {
+ if (!HasIntListAttribute(src_attr))
+ return;
+
+ const std::vector<int32_t>& ids = GetIntListAttribute(src_attr);
+ for (size_t i = 0; i < ids.size(); ++i) {
+ CComObject<BrowserAccessibilityRelation>* relation;
+ HRESULT hr =
+ CComObject<BrowserAccessibilityRelation>::CreateInstance(&relation);
+ DCHECK(SUCCEEDED(hr));
+ relation->AddRef();
+ relation->Initialize(this, iaccessiblerelation_type);
+ relation->AddTarget(ids[i]);
+ relations_.push_back(relation);
+ }
+}
+
void BrowserAccessibilityWin::UpdateRequiredAttributes() {
// Expose slider value.
if (ia_role() == ROLE_SYSTEM_PROGRESSBAR ||
@@ -4111,25 +4381,6 @@ void BrowserAccessibilityWin::UpdateRequiredAttributes() {
}
}
-void BrowserAccessibilityWin::AddRelations(
- ui::AXIntListAttribute src_attr,
- const base::string16& iaccessiblerelation_type) {
- if (!HasIntListAttribute(src_attr))
- return;
-
- const std::vector<int32_t>& ids = GetIntListAttribute(src_attr);
- for (size_t i = 0; i < ids.size(); ++i) {
- CComObject<BrowserAccessibilityRelation>* relation;
- HRESULT hr = CComObject<BrowserAccessibilityRelation>::CreateInstance(
- &relation);
- DCHECK(SUCCEEDED(hr));
- relation->AddRef();
- relation->Initialize(this, iaccessiblerelation_type);
- relation->AddTarget(ids[i]);
- relations_.push_back(relation);
- }
-}
-
void BrowserAccessibilityWin::InitRoleAndState() {
int32_t ia_role = 0;
int32_t ia_state = 0;
diff --git a/content/browser/accessibility/browser_accessibility_win.h b/content/browser/accessibility/browser_accessibility_win.h
index b237be9..82e03ca 100644
--- a/content/browser/accessibility/browser_accessibility_win.h
+++ b/content/browser/accessibility/browser_accessibility_win.h
@@ -709,6 +709,10 @@ BrowserAccessibilityWin
REFIID iid,
void** object);
+ // Computes and caches the IA2 text style attributes for the text and other
+ // embedded child objects.
+ CONTENT_EXPORT void ComputeStylesIfNeeded();
+
CONTENT_EXPORT base::string16 GetText() const override;
// Accessors.
@@ -723,6 +727,10 @@ BrowserAccessibilityWin
base::string16 name() const { return win_attributes_->name; }
base::string16 description() const { return win_attributes_->description; }
base::string16 value() const { return win_attributes_->value; }
+ const std::map<int, std::vector<base::string16>>& offset_to_text_attributes()
+ const {
+ return win_attributes_->offset_to_text_attributes;
+ }
std::map<int32_t, int32_t>& hyperlink_offset_to_index() const {
return win_attributes_->hyperlink_offset_to_index;
}
@@ -731,6 +739,9 @@ BrowserAccessibilityWin
}
private:
+ // Returns the IA2 text attributes for this object.
+ std::vector<base::string16> ComputeTextAttributes() const;
+
// Add one to the reference count and return the same object. Always
// use this method when returning a BrowserAccessibilityWin object as
// an output parameter to a COM interface, never use it otherwise.
@@ -786,6 +797,9 @@ BrowserAccessibilityWin
// Returns true if the current object is an IA2 hyperlink.
bool IsHyperlink() const;
+ // Returns the hyperlink at the given text position, or nullptr if no
+ // hyperlink can be found.
+ BrowserAccessibilityWin* GetHyperlinkFromHypertextOffset(int offset) const;
// Functions for retrieving offsets for hyperlinks and hypertext.
// Return -1 in case of failure.
@@ -847,22 +861,32 @@ BrowserAccessibilityWin
LONG start_offset,
ui::TextBoundaryDirection direction);
- // Return a pointer to the object corresponding to the given id,
- // does not make a new reference.
- BrowserAccessibilityWin* GetFromID(int32_t id);
+ // Searches forward from the given offset until the start of the next style
+ // is found, or searches backward from the given offset until the start of the
+ // current style is found.
+ LONG FindStartOfStyle(LONG start_offset,
+ ui::TextBoundaryDirection direction) const;
+
+ // ID refers to the node ID in the current tree, not the globally unique ID.
+ // TODO(nektar): Could we use globally unique IDs everywhere?
+ // TODO(nektar): Rename this function to GetFromNodeID.
+ BrowserAccessibilityWin* GetFromID(int32_t id) const;
// Returns true if this is a list box option with a parent of type list box,
// or a menu list option with a parent of type menu list popup.
bool IsListBoxOptionOrMenuListOption();
- // Updates object attributes of IA2 with html attributes.
- void UpdateRequiredAttributes();
-
// Given an int list attribute containing the ids of related elements,
// add a new IAccessibleRelation for this object with the given type name.
void AddRelations(ui::AXIntListAttribute src_attr,
const base::string16& iaccessiblerelation_type);
+ // Updates object attributes of IA2 with html attributes.
+ void UpdateRequiredAttributes();
+
+ // Updates the IA2 text style attributes.
+ void UpdateTextAttributes();
+
struct WinAttributes {
WinAttributes();
~WinAttributes();
@@ -887,6 +911,9 @@ BrowserAccessibilityWin
// Hypertext.
base::string16 hypertext;
+ // Maps each style span to its start offset in hypertext.
+ std::map<int, std::vector<base::string16>> offset_to_text_attributes;
+
// Maps the |hypertext_| embedded character offset to an index in
// |hyperlinks_|.
std::map<int32_t, int32_t> hyperlink_offset_to_index;
diff --git a/content/browser/accessibility/browser_accessibility_win_unittest.cc b/content/browser/accessibility/browser_accessibility_win_unittest.cc
index b8b3e77..780d0f4 100644
--- a/content/browser/accessibility/browser_accessibility_win_unittest.cc
+++ b/content/browser/accessibility/browser_accessibility_win_unittest.cc
@@ -1793,6 +1793,121 @@ TEST_F(BrowserAccessibilityTest, TestDeepestFirstLastChild) {
EXPECT_EQ(nullptr, child2_child2_accessible->InternalDeepestLastChild());
}
+TEST_F(BrowserAccessibilityTest, TestInheritedStringAttributes) {
+ ui::AXNodeData root;
+ root.id = 1;
+ root.role = ui::AX_ROLE_ROOT_WEB_AREA;
+ root.AddStringAttribute(ui::AX_ATTR_LANGUAGE, "en-US");
+ root.AddStringAttribute(ui::AX_ATTR_FONT_FAMILY, "Helvetica");
+
+ ui::AXNodeData child1;
+ child1.id = 2;
+ child1.role = ui::AX_ROLE_STATIC_TEXT;
+ root.child_ids.push_back(2);
+
+ ui::AXNodeData child2;
+ child2.id = 3;
+ child2.role = ui::AX_ROLE_STATIC_TEXT;
+ child2.AddStringAttribute(ui::AX_ATTR_LANGUAGE, "fr");
+ child2.AddStringAttribute(ui::AX_ATTR_FONT_FAMILY, "Arial");
+ root.child_ids.push_back(3);
+
+ ui::AXNodeData child2_child1;
+ child2_child1.id = 4;
+ child2_child1.role = ui::AX_ROLE_INLINE_TEXT_BOX;
+ child2.child_ids.push_back(4);
+
+ ui::AXNodeData child2_child2;
+ child2_child2.id = 5;
+ child2_child2.role = ui::AX_ROLE_INLINE_TEXT_BOX;
+ child2.child_ids.push_back(5);
+
+ scoped_ptr<BrowserAccessibilityManager> manager(
+ BrowserAccessibilityManager::Create(
+ MakeAXTreeUpdate(root, child1, child2, child2_child1, child2_child2),
+ nullptr, new CountedBrowserAccessibilityFactory()));
+
+ BrowserAccessibility* root_accessible = manager->GetRoot();
+ ASSERT_NE(nullptr, root_accessible);
+ BrowserAccessibility* child1_accessible =
+ root_accessible->PlatformGetChild(0);
+ ASSERT_NE(nullptr, child1_accessible);
+ BrowserAccessibility* child2_accessible =
+ root_accessible->PlatformGetChild(1);
+ ASSERT_NE(nullptr, child2_accessible);
+ BrowserAccessibility* child2_child1_accessible =
+ child2_accessible->InternalGetChild(0);
+ ASSERT_NE(nullptr, child2_child1_accessible);
+ BrowserAccessibility* child2_child2_accessible =
+ child2_accessible->InternalGetChild(1);
+ ASSERT_NE(nullptr, child2_child2_accessible);
+
+ // Test GetInheritedString16Attribute(attribute).
+ EXPECT_EQ(
+ base::UTF8ToUTF16("en-US"),
+ root_accessible->GetInheritedString16Attribute(ui::AX_ATTR_LANGUAGE));
+ EXPECT_EQ(
+ base::UTF8ToUTF16("en-US"),
+ child1_accessible->GetInheritedString16Attribute(ui::AX_ATTR_LANGUAGE));
+ EXPECT_EQ(
+ base::UTF8ToUTF16("fr"),
+ child2_accessible->GetInheritedString16Attribute(ui::AX_ATTR_LANGUAGE));
+ EXPECT_EQ(base::UTF8ToUTF16("fr"),
+ child2_child1_accessible->GetInheritedString16Attribute(
+ ui::AX_ATTR_LANGUAGE));
+ EXPECT_EQ(base::UTF8ToUTF16("fr"),
+ child2_child2_accessible->GetInheritedString16Attribute(
+ ui::AX_ATTR_LANGUAGE));
+
+ // Test GetInheritedString16Attribute(attribute, out_value).
+ base::string16 value16;
+ EXPECT_TRUE(root_accessible->GetInheritedString16Attribute(
+ ui::AX_ATTR_LANGUAGE, &value16));
+ EXPECT_EQ(base::UTF8ToUTF16("en-US"), value16);
+ EXPECT_TRUE(child1_accessible->GetInheritedString16Attribute(
+ ui::AX_ATTR_LANGUAGE, &value16));
+ EXPECT_EQ(base::UTF8ToUTF16("en-US"), value16);
+ EXPECT_TRUE(child2_accessible->GetInheritedString16Attribute(
+ ui::AX_ATTR_LANGUAGE, &value16));
+ EXPECT_EQ(base::UTF8ToUTF16("fr"), value16);
+ EXPECT_TRUE(child2_child1_accessible->GetInheritedString16Attribute(
+ ui::AX_ATTR_LANGUAGE, &value16));
+ EXPECT_EQ(base::UTF8ToUTF16("fr"), value16);
+ EXPECT_TRUE(child2_child2_accessible->GetInheritedString16Attribute(
+ ui::AX_ATTR_LANGUAGE, &value16));
+ EXPECT_EQ(base::UTF8ToUTF16("fr"), value16);
+
+ // Test GetInheritedStringAttribute(attribute).
+ EXPECT_EQ("Helvetica", root_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY));
+ EXPECT_EQ("Helvetica", child1_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY));
+ EXPECT_EQ("Arial", child2_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY));
+ EXPECT_EQ("Arial", child2_child1_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY));
+ EXPECT_EQ("Arial", child2_child2_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY));
+
+ // Test GetInheritedStringAttribute(attribute, out_value).
+ std::string value;
+ EXPECT_TRUE(root_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY, &value));
+ EXPECT_EQ("Helvetica", value);
+ EXPECT_TRUE(child1_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY, &value));
+ EXPECT_EQ("Helvetica", value);
+ EXPECT_TRUE(child2_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY, &value));
+ EXPECT_EQ("Arial", value);
+ EXPECT_TRUE(child2_child1_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY, &value));
+ EXPECT_EQ("Arial", value);
+ EXPECT_TRUE(child2_child2_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY, &value));
+ EXPECT_EQ("Arial", value);
+}
+
TEST_F(BrowserAccessibilityTest, TestSanitizeStringAttributeForIA2) {
base::string16 input(L"\\:=,;");
base::string16 output;
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 68e9779..a89e48e 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -79,6 +79,17 @@ class DumpAccessibilityTreeTest : public DumpAccessibilityTestBase {
RunTest(aria_file, "accessibility/aria");
}
+ void RunCSSTest(const base::FilePath::CharType* file_path) {
+ base::FilePath dir_test_data;
+ ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &dir_test_data));
+ base::FilePath test_path(
+ dir_test_data.AppendASCII("accessibility").AppendASCII("css"));
+ ASSERT_TRUE(base::PathExists(test_path)) << test_path.LossyDisplayName();
+
+ base::FilePath css_file = test_path.Append(base::FilePath(file_path));
+ RunTest(css_file, "accessibility/css");
+ }
+
void RunHtmlTest(const base::FilePath::CharType* file_path) {
base::FilePath dir_test_data;
ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &dir_test_data));
@@ -107,6 +118,18 @@ class DumpAccessibilityTreeTest : public DumpAccessibilityTestBase {
}
};
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityCSSColor) {
+ RunCSSTest(FILE_PATH_LITERAL("color.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityCSSFontStyle) {
+ RunCSSTest(FILE_PATH_LITERAL("font-style.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityCSSLanguage) {
+ RunCSSTest(FILE_PATH_LITERAL("language.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityA) {
RunHtmlTest(FILE_PATH_LITERAL("a.html"));
}
diff --git a/content/renderer/accessibility/blink_ax_tree_source.cc b/content/renderer/accessibility/blink_ax_tree_source.cc
index b4094e0..858c3a0 100644
--- a/content/renderer/accessibility/blink_ax_tree_source.cc
+++ b/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -138,12 +138,12 @@ AXContentTreeData BlinkAXTreeSource::GetTreeData() const {
blink::WebDocument document = BlinkAXTreeSource::GetMainDocument();
const blink::WebAXObject& root = GetRoot();
- tree_data.title = document.title().utf8();
- tree_data.url = document.url().string().utf8();
- tree_data.mimetype = document.isXHTMLDocument() ? "text/xhtml" : "text/html";
+ tree_data.doctype = "html";
tree_data.loaded = root.isLoaded();
tree_data.loading_progress = root.estimatedLoadingProgress();
- tree_data.doctype = "html";
+ tree_data.mimetype = document.isXHTMLDocument() ? "text/xhtml" : "text/html";
+ tree_data.title = document.title().utf8();
+ tree_data.url = document.url().string().utf8();
WebAXObject focus = document.focusedAccessibilityObject();
if (!focus.isNull())
@@ -312,6 +312,12 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
if (src.color())
dst->AddIntAttribute(ui::AX_ATTR_COLOR, src.color());
+ if (src.fontFamily().length()) {
+ WebAXObject parent = src.parentObject();
+ if (parent.isNull() || parent.fontFamily() != src.fontFamily())
+ dst->AddStringAttribute(ui::AX_ATTR_FONT_FAMILY, src.fontFamily().utf8());
+ }
+
// Font size is in pixels.
if (src.fontSize())
dst->AddFloatAttribute(ui::AX_ATTR_FONT_SIZE, src.fontSize());
@@ -320,7 +326,8 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
dst->AddIntAttribute(ui::AX_ATTR_INVALID_STATE,
AXInvalidStateFromBlink(src.invalidState()));
}
- if (src.invalidState() == blink::WebAXInvalidStateOther) {
+ if (src.invalidState() == blink::WebAXInvalidStateOther &&
+ src.ariaInvalidValue().length()) {
dst->AddStringAttribute(
ui::AX_ATTR_ARIA_INVALID_VALUE, src.ariaInvalidValue().utf8());
}
@@ -367,25 +374,39 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
if (src.actionVerb().length()) {
dst->AddStringAttribute(ui::AX_ATTR_ACTION, src.actionVerb().utf8());
}
- if (src.ariaAutoComplete().length())
+
+ if (src.ariaAutoComplete().length()) {
dst->AddStringAttribute(
ui::AX_ATTR_AUTO_COMPLETE,
src.ariaAutoComplete().utf8());
+ }
+
if (src.isAriaReadOnly())
dst->AddBoolAttribute(ui::AX_ATTR_ARIA_READONLY, true);
+
if (src.isButtonStateMixed())
dst->AddBoolAttribute(ui::AX_ATTR_STATE_MIXED, true);
+
if (src.canSetValueAttribute())
dst->AddBoolAttribute(ui::AX_ATTR_CAN_SET_VALUE, true);
+
if (src.hasComputedStyle()) {
dst->AddStringAttribute(
ui::AX_ATTR_DISPLAY, src.computedStyleDisplay().utf8());
}
+
+ if (src.language().length()) {
+ WebAXObject parent = src.parentObject();
+ if (parent.isNull() || parent.language() != src.language())
+ dst->AddStringAttribute(ui::AX_ATTR_LANGUAGE, src.language().utf8());
+ }
+
if (src.keyboardShortcut().length()) {
dst->AddStringAttribute(
ui::AX_ATTR_SHORTCUT,
src.keyboardShortcut().utf8());
}
+
if (!src.ariaActiveDescendant().isDetached()) {
dst->AddIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID,
src.ariaActiveDescendant().axID());
diff --git a/content/test/data/accessibility/aria/aria-invalid-expected-win.txt b/content/test/data/accessibility/aria/aria-invalid-expected-win.txt
index 2fbe377..873bf49 100644
--- a/content/test/data/accessibility/aria/aria-invalid-expected-win.txt
+++ b/content/test/data/accessibility/aria/aria-invalid-expected-win.txt
@@ -1,17 +1,17 @@
-ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
-++IA2_ROLE_SECTION IA2_STATE_INVALID_ENTRY invalid:true
-++++ROLE_SYSTEM_STATICTEXT name='invalid=true'
-++IA2_ROLE_SECTION IA2_STATE_INVALID_ENTRY invalid:spelling
-++++ROLE_SYSTEM_STATICTEXT name='invalid=spelling'
-++IA2_ROLE_SECTION IA2_STATE_INVALID_ENTRY invalid:grammar
-++++ROLE_SYSTEM_STATICTEXT name='invalid=grammar'
+ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE invalid:true invalid:spelling invalid:grammar invalid:false invalid:unknown invalid:false
+++IA2_ROLE_SECTION IA2_STATE_INVALID_ENTRY invalid:false
+++++ROLE_SYSTEM_STATICTEXT name='invalid=true' invalid:false
+++IA2_ROLE_SECTION IA2_STATE_INVALID_ENTRY invalid:false
+++++ROLE_SYSTEM_STATICTEXT name='invalid=spelling' invalid:false
+++IA2_ROLE_SECTION IA2_STATE_INVALID_ENTRY invalid:false
+++++ROLE_SYSTEM_STATICTEXT name='invalid=grammar' invalid:false
++IA2_ROLE_SECTION invalid:false
-++++ROLE_SYSTEM_STATICTEXT name='invalid=false'
-++IA2_ROLE_SECTION
-++++ROLE_SYSTEM_STATICTEXT name='invalid=<empty>'
-++IA2_ROLE_SECTION
-++++ROLE_SYSTEM_STATICTEXT name='invalid=<default>'
-++IA2_ROLE_SECTION IA2_STATE_INVALID_ENTRY invalid:unknown
-++++ROLE_SYSTEM_STATICTEXT name='invalid=unknown'
-++IA2_ROLE_FORM
+++++ROLE_SYSTEM_STATICTEXT name='invalid=false' invalid:false
+++IA2_ROLE_SECTION invalid:false
+++++ROLE_SYSTEM_STATICTEXT name='invalid=<empty>' invalid:false
+++IA2_ROLE_SECTION invalid:false
+++++ROLE_SYSTEM_STATICTEXT name='invalid=<default>' invalid:false
+++IA2_ROLE_SECTION IA2_STATE_INVALID_ENTRY invalid:false
+++++ROLE_SYSTEM_STATICTEXT name='invalid=unknown' invalid:false
+++IA2_ROLE_FORM invalid:true
++++ROLE_SYSTEM_TEXT FOCUSABLE IA2_STATE_INVALID_ENTRY invalid:true
diff --git a/content/test/data/accessibility/css/color-expected-blink.txt b/content/test/data/accessibility/css/color-expected-blink.txt
new file mode 100644
index 0000000..79c5d80
--- /dev/null
+++ b/content/test/data/accessibility/css/color-expected-blink.txt
@@ -0,0 +1,11 @@
+rootWebArea color=-16777216
+++paragraph backgroundColor=-16776961 color=-65536
+++++staticText name='Red on blue.' backgroundColor=-16776961 color=-65536
+++++++inlineTextBox name='Red on blue.' color=-16777216
+++div color=-16777216
+++++staticText name='Default.' color=-16777216
+++++++inlineTextBox name='Default.' color=-16777216
+++++staticText name='Blue background.' backgroundColor=-16776961 color=-16777216
+++++++inlineTextBox name='Blue background.' color=-16777216
+++++staticText name='Green text.' color=-16711936
+++++++inlineTextBox name='Green text.' color=-16777216
diff --git a/content/test/data/accessibility/css/color-expected-win.txt b/content/test/data/accessibility/css/color-expected-win.txt
new file mode 100644
index 0000000..5fc6beb
--- /dev/null
+++ b/content/test/data/accessibility/css/color-expected-win.txt
@@ -0,0 +1,7 @@
+ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE background-color:rgb(0\,0\,255) color:rgb(255\,0\,0) background-color:transparent color:rgb(0\,0\,0) ia2_hypertext='<obj0><obj1>'
+++IA2_ROLE_PARAGRAPH background-color:rgb(0\,0\,255) color:rgb(255\,0\,0) ia2_hypertext='Red on blue.'
+++++ROLE_SYSTEM_STATICTEXT name='Red on blue.' background-color:rgb(0\,0\,255) color:rgb(255\,0\,0) ia2_hypertext='Red on blue.'
+++IA2_ROLE_SECTION FOCUSABLE background-color:transparent color:rgb(0\,0\,0) background-color:rgb(0\,0\,255) color:rgb(0\,0\,0) background-color:transparent color:rgb(0\,255\,0) ia2_hypertext='Default.Blue background.Green text.'
+++++ROLE_SYSTEM_STATICTEXT name='Default.' background-color:transparent color:rgb(0\,0\,0) ia2_hypertext='Default.'
+++++ROLE_SYSTEM_STATICTEXT name='Blue background.' background-color:rgb(0\,0\,255) color:rgb(0\,0\,0) ia2_hypertext='Blue background.'
+++++ROLE_SYSTEM_STATICTEXT name='Green text.' background-color:transparent color:rgb(0\,255\,0) ia2_hypertext='Green text.'
diff --git a/content/test/data/accessibility/css/color.html b/content/test/data/accessibility/css/color.html
new file mode 100644
index 0000000..b5db005
--- /dev/null
+++ b/content/test/data/accessibility/css/color.html
@@ -0,0 +1,17 @@
+<!--
+@BLINK-ALLOW:backgroundColor=*
+@BLINK-ALLOW:color=*
+@WIN-ALLOW:background-color:*
+@WIN-ALLOW:color:*
+@WIN-ALLOW:ia2_hypertext=*
+-->
+<!DOCTYPE html>
+<html>
+ <body>
+ <p style="background-color: #0000FF; color: #FF0000">Red on blue.</p>
+ <div contentEditable><span>Default.</span>
+ <span style="background-color: #0000FF;">Blue background.</span>
+ <span style="color: #00FF00;">Green text.</span>
+ </div>
+ </body>
+</html>
diff --git a/content/test/data/accessibility/css/font-style-expected-blink.txt b/content/test/data/accessibility/css/font-style-expected-blink.txt
new file mode 100644
index 0000000..0be2e0a
--- /dev/null
+++ b/content/test/data/accessibility/css/font-style-expected-blink.txt
@@ -0,0 +1,15 @@
+rootWebArea
+++paragraph
+++++staticText name='Normal '
+++++++inlineTextBox name='Normal '
+++++staticText name='bold' textStyle=1
+++++++inlineTextBox name='bold'
+++++staticText name='italic' textStyle=2
+++++++inlineTextBox name='italic'
+++div
+++++staticText name='Normal'
+++++++inlineTextBox name='Normal'
+++++staticText name='bold' textStyle=1
+++++++inlineTextBox name='bold'
+++++staticText name='italic' textStyle=2
+++++++inlineTextBox name='italic'
diff --git a/content/test/data/accessibility/css/font-style-expected-win.txt b/content/test/data/accessibility/css/font-style-expected-win.txt
new file mode 100644
index 0000000..5699609
--- /dev/null
+++ b/content/test/data/accessibility/css/font-style-expected-win.txt
@@ -0,0 +1,9 @@
+ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE font-style:normal font-weight:normal ia2_hypertext='<obj0><obj1>'
+++IA2_ROLE_PARAGRAPH font-style:normal font-weight:normal font-weight:bold font-style:underline font-style:italic,underline ia2_hypertext='Normal bolditalic'
+++++ROLE_SYSTEM_STATICTEXT name='Normal ' font-style:normal font-weight:normal ia2_hypertext='Normal '
+++++ROLE_SYSTEM_STATICTEXT name='bold' font-weight:bold font-style:underline ia2_hypertext='bold'
+++++ROLE_SYSTEM_STATICTEXT name='italic' font-style:italic,underline ia2_hypertext='italic'
+++IA2_ROLE_SECTION FOCUSABLE font-style:normal font-weight:normal font-weight:bold font-style:underline font-style:italic,underline ia2_hypertext='Normalbolditalic'
+++++ROLE_SYSTEM_STATICTEXT name='Normal' font-style:normal font-weight:normal ia2_hypertext='Normal'
+++++ROLE_SYSTEM_STATICTEXT name='bold' font-weight:bold font-style:underline ia2_hypertext='bold'
+++++ROLE_SYSTEM_STATICTEXT name='italic' font-style:italic,underline ia2_hypertext='italic'
diff --git a/content/test/data/accessibility/css/font-style.html b/content/test/data/accessibility/css/font-style.html
new file mode 100644
index 0000000..5df21b4
--- /dev/null
+++ b/content/test/data/accessibility/css/font-style.html
@@ -0,0 +1,16 @@
+<!--
+@BLINK-ALLOW:textStyle=*
+@WIN-ALLOW:font-weight:*
+@WIN-ALLOW:font-style:*
+@WIN-ALLOW:ia2_hypertext=*
+-->
+<!DOCTYPE html>
+<html>
+ <body>
+ <p>Normal <b>bold</b> <i>italic</i></p>
+ <div contentEditable><span>Normal</span>
+ <span style="font-weight: bold;">bold</span>
+ <span style="font-style: italic;">italic</span>
+ </div>
+ </body>
+</html>
diff --git a/content/test/data/accessibility/css/language-expected-blink.txt b/content/test/data/accessibility/css/language-expected-blink.txt
new file mode 100644
index 0000000..d6f6a81
--- /dev/null
+++ b/content/test/data/accessibility/css/language-expected-blink.txt
@@ -0,0 +1,7 @@
+rootWebArea
+++paragraph language='en-US'
+++++staticText name='How are you?'
+++++++inlineTextBox name='How are you?'
+++paragraph language='fr-FR'
+++++staticText name='Comment allez-vous?'
+++++++inlineTextBox name='Comment allez-vous?'
diff --git a/content/test/data/accessibility/css/language-expected-win.txt b/content/test/data/accessibility/css/language-expected-win.txt
new file mode 100644
index 0000000..51afa6a
--- /dev/null
+++ b/content/test/data/accessibility/css/language-expected-win.txt
@@ -0,0 +1,5 @@
+ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE language:en-US language:fr-FR ia2_hypertext='<obj0><obj1>'
+++IA2_ROLE_PARAGRAPH language:en-US ia2_hypertext='How are you?'
+++++ROLE_SYSTEM_STATICTEXT name='How are you?' language:en-US ia2_hypertext='How are you?'
+++IA2_ROLE_PARAGRAPH language:fr-FR ia2_hypertext='Comment allez-vous?'
+++++ROLE_SYSTEM_STATICTEXT name='Comment allez-vous?' language:fr-FR ia2_hypertext='Comment allez-vous?'
diff --git a/content/test/data/accessibility/css/language.html b/content/test/data/accessibility/css/language.html
new file mode 100644
index 0000000..3d46856
--- /dev/null
+++ b/content/test/data/accessibility/css/language.html
@@ -0,0 +1,12 @@
+<!--
+@BLINK-ALLOW:language=*
+@WIN-ALLOW:ia2_hypertext=*
+@WIN-ALLOW:language:*
+-->
+<!DOCTYPE html>
+<html>
+ <body>
+ <p lang="en-US">How are you?</p>
+ <p lang="fr-FR">Comment allez-vous?</p>
+ </body>
+</html>
diff --git a/content/test/data/accessibility/html/keygen-expected-win.txt b/content/test/data/accessibility/html/keygen-expected-win.txt
index 5f5869c..11e72f7 100644
--- a/content/test/data/accessibility/html/keygen-expected-win.txt
+++ b/content/test/data/accessibility/html/keygen-expected-win.txt
@@ -1,7 +1,7 @@
ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
++IA2_ROLE_SECTION role_name='body'
-++++IA2_ROLE_SECTION FOCUSABLE invalid:false role_name='keygen'
-++++++ROLE_SYSTEM_COMBOBOX COLLAPSED FOCUSABLE HASPOPUP invalid:false
+++++IA2_ROLE_SECTION FOCUSABLE role_name='keygen'
+++++++ROLE_SYSTEM_COMBOBOX COLLAPSED FOCUSABLE HASPOPUP
++++++++ROLE_SYSTEM_LIST INVISIBLE
++++++++++ROLE_SYSTEM_LISTITEM SELECTED FOCUSABLE SELECTABLE
++++++++++ROLE_SYSTEM_LISTITEM INVISIBLE FOCUSABLE SELECTABLE
diff --git a/content/test/data/accessibility/html/keygen.html b/content/test/data/accessibility/html/keygen.html
index 0e3d0a1..ce904c2 100644
--- a/content/test/data/accessibility/html/keygen.html
+++ b/content/test/data/accessibility/html/keygen.html
@@ -1,7 +1,6 @@
<!--
@WIN-ALLOW:SELECTED
@WIN-ALLOW:SELECTABLE
-@WIN-ALLOW:invalid*
@WIN-ALLOW:role_name*
@WIN-ALLOW:COLLAPSED
@WIN-ALLOW:INVISIBLE
diff --git a/content/test/data/accessibility/html/optgroup-expected-win.txt b/content/test/data/accessibility/html/optgroup-expected-win.txt
index 69ba92a..d3b393bd 100644
--- a/content/test/data/accessibility/html/optgroup-expected-win.txt
+++ b/content/test/data/accessibility/html/optgroup-expected-win.txt
@@ -1,6 +1,6 @@
ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
++IA2_ROLE_SECTION
-++++ROLE_SYSTEM_LIST FOCUSABLE IA2_STATE_VERTICAL invalid:false
+++++ROLE_SYSTEM_LIST FOCUSABLE IA2_STATE_VERTICAL
++++++ROLE_SYSTEM_GROUPING name='Enabled' xml-roles:group
++++++++ROLE_SYSTEM_STATICTEXT name='Enabled'
++++++ROLE_SYSTEM_LISTITEM name='One' FOCUSABLE SELECTABLE
diff --git a/content/test/data/accessibility/html/optgroup.html b/content/test/data/accessibility/html/optgroup.html
index bef8d42..2571670 100644
--- a/content/test/data/accessibility/html/optgroup.html
+++ b/content/test/data/accessibility/html/optgroup.html
@@ -3,7 +3,6 @@
@WIN-ALLOW:xml-roles*
@WIN-ALLOW:IA2_STATE_VERTICAL
@WIN-ALLOW:SELECTABLE
-@WIN-ALLOW:invalid*
-->
<!DOCTYPE html>
<html>
diff --git a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
index 409f370..bf68f5e 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
@@ -827,10 +827,10 @@ const AtomicString& AXLayoutObject::accessKey() const
RGBA32 AXLayoutObject::backgroundColor() const
{
- if (!m_layoutObject)
+ if (!getLayoutObject())
return AXNodeObject::backgroundColor();
- const ComputedStyle* style = m_layoutObject->style();
+ const ComputedStyle* style = getLayoutObject()->style();
if (!style || !style->hasBackground())
return AXNodeObject::backgroundColor();
@@ -840,10 +840,10 @@ RGBA32 AXLayoutObject::backgroundColor() const
RGBA32 AXLayoutObject::color() const
{
- if (!m_layoutObject || isColorWell())
+ if (!getLayoutObject() || isColorWell())
return AXNodeObject::color();
- const ComputedStyle* style = m_layoutObject->style();
+ const ComputedStyle* style = getLayoutObject()->style();
if (!style)
return AXNodeObject::color();
@@ -851,13 +851,26 @@ RGBA32 AXLayoutObject::color() const
return color.rgb();
}
+String AXLayoutObject::fontFamily() const
+{
+ if (!getLayoutObject())
+ return AXNodeObject::fontFamily();
+
+ const ComputedStyle* style = getLayoutObject()->style();
+ if (!style)
+ return AXNodeObject::fontFamily();
+
+ FontDescription& fontDescription = const_cast<FontDescription&>(style->getFontDescription());
+ return fontDescription.firstFamily().family();
+}
+
// Font size is in pixels.
float AXLayoutObject::fontSize() const
{
- if (!m_layoutObject)
+ if (!getLayoutObject())
return AXNodeObject::fontSize();
- const ComputedStyle* style = m_layoutObject->style();
+ const ComputedStyle* style = getLayoutObject()->style();
if (!style)
return AXNodeObject::fontSize();
@@ -867,10 +880,10 @@ float AXLayoutObject::fontSize() const
String AXLayoutObject::text() const
{
if (isPasswordFieldAndShouldHideValue()) {
- if (!m_layoutObject)
+ if (!getLayoutObject())
return String();
- const ComputedStyle* style = m_layoutObject->style();
+ const ComputedStyle* style = getLayoutObject()->style();
if (!style)
return String();
@@ -906,10 +919,10 @@ String AXLayoutObject::text() const
AccessibilityTextDirection AXLayoutObject::textDirection() const
{
- if (!m_layoutObject)
+ if (!getLayoutObject())
return AXNodeObject::textDirection();
- const ComputedStyle* style = m_layoutObject->style();
+ const ComputedStyle* style = getLayoutObject()->style();
if (!style)
return AXNodeObject::textDirection();
@@ -942,10 +955,10 @@ int AXLayoutObject::textLength() const
TextStyle AXLayoutObject::getTextStyle() const
{
- if (!m_layoutObject)
+ if (!getLayoutObject())
return AXNodeObject::getTextStyle();
- const ComputedStyle* style = m_layoutObject->style();
+ const ComputedStyle* style = getLayoutObject()->style();
if (!style)
return AXNodeObject::getTextStyle();
diff --git a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.h b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.h
index e43355a..4eab54b 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.h
+++ b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.h
@@ -101,6 +101,7 @@ protected:
const AtomicString& accessKey() const override;
RGBA32 backgroundColor() const final;
RGBA32 color() const final;
+ String fontFamily() const final;
// Font size is in pixels.
float fontSize() const final;
String text() const override;
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.h b/third_party/WebKit/Source/modules/accessibility/AXObject.h
index 0495800..bec65aa 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXObject.h
+++ b/third_party/WebKit/Source/modules/accessibility/AXObject.h
@@ -699,6 +699,7 @@ public:
// Used by objects of role ColorWellRole.
virtual RGBA32 colorValue() const { return Color::transparent; }
virtual bool canvasHasFallbackContent() const { return false; }
+ virtual String fontFamily() const { return nullAtom; }
// Font size is in pixels.
virtual float fontSize() const { return 0.0f; }
virtual int headingLevel() const { return 0; }
diff --git a/third_party/WebKit/Source/web/WebAXObject.cpp b/third_party/WebKit/Source/web/WebAXObject.cpp
index b892249..4445b63 100644
--- a/third_party/WebKit/Source/web/WebAXObject.cpp
+++ b/third_party/WebKit/Source/web/WebAXObject.cpp
@@ -636,6 +636,14 @@ WebRect WebAXObject::boundingBoxRect() const
return pixelSnappedIntRect(m_private->elementRect());
}
+WebString WebAXObject::fontFamily() const
+{
+ if (isDetached())
+ return WebString();
+
+ return m_private->fontFamily();
+}
+
float WebAXObject::fontSize() const
{
if (isDetached())
diff --git a/third_party/WebKit/public/web/WebAXObject.h b/third_party/WebKit/public/web/WebAXObject.h
index f0051c1..b591739 100644
--- a/third_party/WebKit/public/web/WebAXObject.h
+++ b/third_party/WebKit/public/web/WebAXObject.h
@@ -142,6 +142,7 @@ public:
BLINK_EXPORT bool isRichlyEditable() const;
BLINK_EXPORT bool ariaOwns(WebVector<WebAXObject>& ownsElements) const;
BLINK_EXPORT WebRect boundingBoxRect() const;
+ BLINK_EXPORT WebString fontFamily() const;
BLINK_EXPORT float fontSize() const;
BLINK_EXPORT bool canvasHasFallbackContent() const;
BLINK_EXPORT WebPoint clickPoint() const;
diff --git a/ui/accessibility/ax_enums.idl b/ui/accessibility/ax_enums.idl
index bad6a7a..be08a8a36 100644
--- a/ui/accessibility/ax_enums.idl
+++ b/ui/accessibility/ax_enums.idl
@@ -236,14 +236,18 @@
[cpp_enum_prefix_override="ax_attr"] enum AXStringAttribute {
access_key,
action,
+ // Only used when invalid_state == invalid_state_other.
+ aria_invalid_value,
auto_complete,
container_live_relevant,
container_live_status,
description,
display,
+ // Only present when different from parent.
+ font_family,
html_tag,
- // Only used when invalid_state == invalid_state_other.
- aria_invalid_value,
+ // Only present when different from parent.
+ language,
name,
live_relevant,
live_status,
diff --git a/ui/accessibility/ax_node_data.cc b/ui/accessibility/ax_node_data.cc
index be59c71..6c2be76 100644
--- a/ui/accessibility/ax_node_data.cc
+++ b/ui/accessibility/ax_node_data.cc
@@ -513,6 +513,9 @@ std::string AXNodeData::ToString() const {
case AX_ATTR_ACTION:
result += " action=" + value;
break;
+ case AX_ATTR_ARIA_INVALID_VALUE:
+ result += " aria_invalid_value=" + value;
+ break;
case AX_ATTR_AUTO_COMPLETE:
result += " autocomplete=" + value;
break;
@@ -522,11 +525,14 @@ std::string AXNodeData::ToString() const {
case AX_ATTR_DISPLAY:
result += " display=" + value;
break;
+ case AX_ATTR_FONT_FAMILY:
+ result += " font-family=" + value;
+ break;
case AX_ATTR_HTML_TAG:
result += " html_tag=" + value;
break;
- case AX_ATTR_ARIA_INVALID_VALUE:
- result += " aria_invalid_value=" + value;
+ case AX_ATTR_LANGUAGE:
+ result += " language=" + value;
break;
case AX_ATTR_LIVE_RELEVANT:
result += " relevant=" + value;
diff --git a/ui/accessibility/ax_tree_data.cc b/ui/accessibility/ax_tree_data.cc
index 274da85..4e434db 100644
--- a/ui/accessibility/ax_tree_data.cc
+++ b/ui/accessibility/ax_tree_data.cc
@@ -46,19 +46,18 @@ std::string AXTreeData::ToString() const {
if (focused_tree_id != -1)
result += " focused_tree_id=" + IntToString(focused_tree_id);
- if (!url.empty())
- result += " url=" + url;
- if (!title.empty())
- result += " title=" + title;
- if (!mimetype.empty())
- result += " mimetype=" + mimetype;
if (!doctype.empty())
result += " doctype=" + doctype;
-
if (loaded)
result += " loaded=true";
if (loading_progress != 0.0)
result += " loading_progress=" + DoubleToString(loading_progress);
+ if (!mimetype.empty())
+ result += " mimetype=" + mimetype;
+ if (!url.empty())
+ result += " url=" + url;
+ if (!title.empty())
+ result += " title=" + title;
if (focus_id != -1)
result += " focus_id=" + IntToString(focus_id);
@@ -79,13 +78,10 @@ bool operator==(const AXTreeData& lhs, const AXTreeData& rhs) {
return (lhs.tree_id == rhs.tree_id &&
lhs.parent_tree_id == rhs.parent_tree_id &&
lhs.focused_tree_id == rhs.focused_tree_id &&
- lhs.url == rhs.url &&
- lhs.title == rhs.title &&
- lhs.mimetype == rhs.mimetype &&
- lhs.doctype == rhs.doctype &&
- lhs.loaded == rhs.loaded &&
+ lhs.doctype == rhs.doctype && lhs.loaded == rhs.loaded &&
lhs.loading_progress == rhs.loading_progress &&
- lhs.focus_id == rhs.focus_id &&
+ lhs.mimetype == rhs.mimetype && lhs.title == rhs.title &&
+ lhs.url == rhs.url && lhs.focus_id == rhs.focus_id &&
lhs.sel_anchor_object_id == rhs.sel_anchor_object_id &&
lhs.sel_anchor_offset == rhs.sel_anchor_offset &&
lhs.sel_focus_object_id == rhs.sel_focus_object_id &&
diff --git a/ui/accessibility/ax_tree_data.h b/ui/accessibility/ax_tree_data.h
index f780415..83a1589 100644
--- a/ui/accessibility/ax_tree_data.h
+++ b/ui/accessibility/ax_tree_data.h
@@ -43,12 +43,12 @@ struct AX_EXPORT AXTreeData {
int32_t focused_tree_id;
// Attributes specific to trees that are web frames.
- std::string url;
- std::string title;
- std::string mimetype;
std::string doctype;
bool loaded;
float loading_progress;
+ std::string mimetype;
+ std::string title;
+ std::string url;
// The node with keyboard focus within this tree, if any, or -1 if no node
// in this tree has focus.