Index: content/browser/accessibility/browser_accessibility_win.cc |
=================================================================== |
--- content/browser/accessibility/browser_accessibility_win.cc (revision 98956) |
+++ content/browser/accessibility/browser_accessibility_win.cc (working copy) |
@@ -8,6 +8,7 @@ |
#include "base/string_util.h" |
#include "base/utf_string_conversions.h" |
#include "content/browser/accessibility/browser_accessibility_manager_win.h" |
+#include "content/common/view_messages.h" |
#include "net/base/escape.h" |
using webkit_glue::WebAccessibility; |
@@ -37,7 +38,8 @@ |
: ia_role_(0), |
ia_state_(0), |
ia2_role_(0), |
- ia2_state_(0) { |
+ ia2_state_(0), |
+ first_time_(true) { |
} |
BrowserAccessibilityWin::~BrowserAccessibilityWin() { |
@@ -421,15 +423,13 @@ |
if (!attributes) |
return E_INVALIDARG; |
- // Follow Firefox's convention, which is to return a set of key-value pairs |
+ // The iaccessible2 attributes are a set of key-value pairs |
// separated by semicolons, with a colon between the key and the value. |
string16 str; |
- for (unsigned int i = 0; i < html_attributes_.size(); i++) { |
+ for (unsigned int i = 0; i < ia2_attributes_.size(); ++i) { |
if (i != 0) |
str += L';'; |
- str += Escape(html_attributes_[i].first); |
- str += L':'; |
- str += Escape(html_attributes_[i].second); |
+ str += ia2_attributes_[i]; |
} |
if (str.empty()) |
@@ -574,7 +574,8 @@ |
return S_OK; |
} |
- return S_FALSE; |
+ *accessible = NULL; |
+ return E_INVALIDARG; |
} |
STDMETHODIMP BrowserAccessibilityWin::get_caption(IUnknown** accessible) { |
@@ -610,9 +611,16 @@ |
if (row < 0 || row >= rows || column < 0 || column >= columns) |
return E_INVALIDARG; |
- *cell_index = row * columns + column; |
+ 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; |
+ } |
+ } |
- return S_OK; |
+ return S_FALSE; |
} |
STDMETHODIMP BrowserAccessibilityWin::get_columnDescription( |
@@ -636,7 +644,7 @@ |
if (column < 0 || column >= columns) |
return E_INVALIDARG; |
- for (int i = 0; i < rows; i++) { |
+ for (int i = 0; i < rows; ++i) { |
int cell_id = cell_ids_[i * columns + column]; |
BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>( |
manager_->GetFromRendererID(cell_id)); |
@@ -707,21 +715,24 @@ |
if (!column_index) |
return E_INVALIDARG; |
- int columns; |
- int rows; |
- if (!GetIntAttribute(WebAccessibility::ATTR_TABLE_COLUMN_COUNT, &columns) || |
- !GetIntAttribute(WebAccessibility::ATTR_TABLE_ROW_COUNT, &rows) || |
- columns <= 0 || |
- rows <= 0) { |
+ 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]; |
+ BrowserAccessibilityWin* cell = |
+ manager_->GetFromRendererID(cell_id)->toBrowserAccessibilityWin(); |
+ int col_index; |
+ if (cell && |
+ cell->GetIntAttribute( |
+ WebAccessibility::ATTR_TABLE_CELL_COLUMN_INDEX, &col_index)) { |
+ *column_index = col_index; |
+ return S_OK; |
} |
- if (cell_index < 0 || cell_index >= columns * rows) |
- return E_INVALIDARG; |
- |
- *column_index = cell_index % columns; |
- |
- return S_OK; |
+ return S_FALSE; |
} |
STDMETHODIMP BrowserAccessibilityWin::get_nColumns( |
@@ -816,10 +827,10 @@ |
if (row < 0 || row >= rows) |
return E_INVALIDARG; |
- for (int i = 0; i < columns; i++) { |
+ for (int i = 0; i < columns; ++i) { |
int cell_id = cell_ids_[row * columns + i]; |
- BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>( |
- manager_->GetFromRendererID(cell_id)); |
+ BrowserAccessibilityWin* cell = |
+ manager_->GetFromRendererID(cell_id)->toBrowserAccessibilityWin(); |
if (cell && cell->role_ == WebAccessibility::ROLE_ROW_HEADER) { |
if (cell->name_.size() > 0) { |
*description = SysAllocString(cell->name_.c_str()); |
@@ -857,8 +868,8 @@ |
return E_INVALIDARG; |
int cell_id = cell_ids_[row * columns + column]; |
- BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>( |
- manager_->GetFromRendererID(cell_id)); |
+ BrowserAccessibilityWin* cell = |
+ manager_->GetFromRendererID(cell_id)->toBrowserAccessibilityWin(); |
int rowspan; |
if (cell && |
cell->GetIntAttribute( |
@@ -887,21 +898,24 @@ |
if (!row_index) |
return E_INVALIDARG; |
- int columns; |
- int rows; |
- if (!GetIntAttribute(WebAccessibility::ATTR_TABLE_COLUMN_COUNT, &columns) || |
- !GetIntAttribute(WebAccessibility::ATTR_TABLE_ROW_COUNT, &rows) || |
- columns <= 0 || |
- rows <= 0) { |
+ 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]; |
+ BrowserAccessibilityWin* cell = |
+ manager_->GetFromRendererID(cell_id)->toBrowserAccessibilityWin(); |
+ int cell_row_index; |
+ if (cell && |
+ cell->GetIntAttribute( |
+ WebAccessibility::ATTR_TABLE_CELL_ROW_INDEX, &cell_row_index)) { |
+ *row_index = cell_row_index; |
+ return S_OK; |
} |
- if (cell_index < 0 || cell_index >= columns * rows) |
- return E_INVALIDARG; |
- |
- *row_index = cell_index / columns; |
- |
- return S_OK; |
+ return S_FALSE; |
} |
STDMETHODIMP BrowserAccessibilityWin::get_selectedChildren( |
@@ -914,6 +928,7 @@ |
if (!children || !n_children) |
return E_INVALIDARG; |
+ // TODO(dmazzoni): Implement this. |
*n_children = 0; |
return S_OK; |
} |
@@ -928,6 +943,7 @@ |
if (!columns || !n_columns) |
return E_INVALIDARG; |
+ // TODO(dmazzoni): Implement this. |
*n_columns = 0; |
return S_OK; |
} |
@@ -942,6 +958,7 @@ |
if (!rows || !n_rows) |
return E_INVALIDARG; |
+ // TODO(dmazzoni): Implement this. |
*n_rows = 0; |
return S_OK; |
} |
@@ -967,6 +984,7 @@ |
if (!is_selected) |
return E_INVALIDARG; |
+ // TODO(dmazzoni): Implement this. |
*is_selected = false; |
return S_OK; |
} |
@@ -980,6 +998,7 @@ |
if (!is_selected) |
return E_INVALIDARG; |
+ // TODO(dmazzoni): Implement this. |
*is_selected = false; |
return S_OK; |
} |
@@ -994,6 +1013,7 @@ |
if (!is_selected) |
return E_INVALIDARG; |
+ // TODO(dmazzoni): Implement this. |
*is_selected = false; |
return S_OK; |
} |
@@ -1011,23 +1031,15 @@ |
if (!row || !column || !row_extents || !column_extents || !is_selected) |
return E_INVALIDARG; |
- int columns; |
- int rows; |
- if (!GetIntAttribute(WebAccessibility::ATTR_TABLE_COLUMN_COUNT, &columns) || |
- !GetIntAttribute(WebAccessibility::ATTR_TABLE_ROW_COUNT, &rows) || |
- columns <= 0 || |
- rows <= 0) { |
+ 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; |
- } |
- if (index < 0 || index >= columns * rows) |
- return E_INVALIDARG; |
- |
- *column = index % columns; |
- *row = index / columns; |
- int cell_id = cell_ids_[index]; |
- BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>( |
- manager_->GetFromRendererID(cell_id)); |
+ int cell_id = unique_cell_ids_[index]; |
+ BrowserAccessibilityWin* cell = |
+ manager_->GetFromRendererID(cell_id)->toBrowserAccessibilityWin(); |
int rowspan; |
int colspan; |
if (cell && |
@@ -1046,6 +1058,64 @@ |
} |
// |
+// IAccessibleTable2 methods. |
+// |
+ |
+STDMETHODIMP BrowserAccessibilityWin::get_cellAt( |
+ long row, |
+ long column, |
+ IUnknown** cell) { |
+ return get_accessibleAt(row, column, cell); |
+} |
+ |
+STDMETHODIMP BrowserAccessibilityWin::get_nSelectedCells(long* cell_count) { |
+ return get_nSelectedChildren(cell_count); |
+} |
+ |
+STDMETHODIMP BrowserAccessibilityWin::get_selectedCells( |
+ IUnknown*** cells, |
+ long* n_selected_cells) { |
+ if (!instance_active_) |
+ return E_FAIL; |
+ |
+ if (!cells || !n_selected_cells) |
+ return E_INVALIDARG; |
+ |
+ // TODO(dmazzoni): Implement this. |
+ *n_selected_cells = 0; |
+ return S_OK; |
+} |
+ |
+STDMETHODIMP BrowserAccessibilityWin::get_selectedColumns( |
+ long** columns, |
+ long* n_columns) { |
+ if (!instance_active_) |
+ return E_FAIL; |
+ |
+ if (!columns || !n_columns) |
+ return E_INVALIDARG; |
+ |
+ // TODO(dmazzoni): Implement this. |
+ *n_columns = 0; |
+ return S_OK; |
+} |
+ |
+STDMETHODIMP BrowserAccessibilityWin::get_selectedRows( |
+ long** rows, |
+ long* n_rows) { |
+ if (!instance_active_) |
+ return E_FAIL; |
+ |
+ if (!rows || !n_rows) |
+ return E_INVALIDARG; |
+ |
+ // TODO(dmazzoni): Implement this. |
+ *n_rows = 0; |
+ return S_OK; |
+} |
+ |
+ |
+// |
// IAccessibleTableCell methods. |
// |
@@ -1088,8 +1158,10 @@ |
BrowserAccessibility* table = parent(); |
while (table && table->role() != WebAccessibility::ROLE_TABLE) |
table = table->parent(); |
- if (!table) |
+ if (!table) { |
+ NOTREACHED(); |
return S_FALSE; |
+ } |
int columns; |
int rows; |
@@ -1102,10 +1174,10 @@ |
if (columns <= 0 || rows <= 0 || column < 0 || column >= columns) |
return S_FALSE; |
- for (int i = 0; i < rows; i++) { |
+ for (int i = 0; i < rows; ++i) { |
int cell_id = table->cell_ids()[i * columns + column]; |
- BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>( |
- manager_->GetFromRendererID(cell_id)); |
+ BrowserAccessibilityWin* cell = |
+ manager_->GetFromRendererID(cell_id)->toBrowserAccessibilityWin(); |
if (cell && cell->role_ == WebAccessibility::ROLE_COLUMN_HEADER) |
(*n_column_header_cells)++; |
} |
@@ -1113,14 +1185,14 @@ |
*cell_accessibles = static_cast<IUnknown**>(CoTaskMemAlloc( |
(*n_column_header_cells) * sizeof(cell_accessibles[0]))); |
int index = 0; |
- for (int i = 0; i < rows; i++) { |
+ for (int i = 0; i < rows; ++i) { |
int cell_id = table->cell_ids()[i * columns + column]; |
- BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>( |
- manager_->GetFromRendererID(cell_id)); |
+ BrowserAccessibilityWin* cell = |
+ manager_->GetFromRendererID(cell_id)->toBrowserAccessibilityWin(); |
if (cell && cell->role_ == WebAccessibility::ROLE_COLUMN_HEADER) { |
(*cell_accessibles)[index] = |
static_cast<IAccessible*>(cell->NewReference()); |
- index++; |
+ ++index; |
} |
} |
@@ -1184,8 +1256,10 @@ |
BrowserAccessibility* table = parent(); |
while (table && table->role() != WebAccessibility::ROLE_TABLE) |
table = table->parent(); |
- if (!table) |
+ if (!table) { |
+ NOTREACHED(); |
return S_FALSE; |
+ } |
int columns; |
int rows; |
@@ -1198,10 +1272,10 @@ |
if (columns <= 0 || rows <= 0 || row < 0 || row >= rows) |
return S_FALSE; |
- for (int i = 0; i < columns; i++) { |
+ for (int i = 0; i < columns; ++i) { |
int cell_id = table->cell_ids()[row * columns + i]; |
- BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>( |
- manager_->GetFromRendererID(cell_id)); |
+ BrowserAccessibilityWin* cell = |
+ manager_->GetFromRendererID(cell_id)->toBrowserAccessibilityWin(); |
if (cell && cell->role_ == WebAccessibility::ROLE_ROW_HEADER) |
(*n_row_header_cells)++; |
} |
@@ -1209,14 +1283,14 @@ |
*cell_accessibles = static_cast<IUnknown**>(CoTaskMemAlloc( |
(*n_row_header_cells) * sizeof(cell_accessibles[0]))); |
int index = 0; |
- for (int i = 0; i < columns; i++) { |
+ for (int i = 0; i < columns; ++i) { |
int cell_id = table->cell_ids()[row * columns + i]; |
- BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>( |
- manager_->GetFromRendererID(cell_id)); |
+ BrowserAccessibilityWin* cell = |
+ manager_->GetFromRendererID(cell_id)->toBrowserAccessibilityWin(); |
if (cell && cell->role_ == WebAccessibility::ROLE_ROW_HEADER) { |
(*cell_accessibles)[index] = |
static_cast<IAccessible*>(cell->NewReference()); |
- index++; |
+ ++index; |
} |
} |
@@ -1298,14 +1372,22 @@ |
if (!table) |
return E_INVALIDARG; |
+ |
+ int row; |
+ int column; |
+ GetIntAttribute(WebAccessibility::ATTR_TABLE_CELL_ROW_INDEX, &row); |
+ GetIntAttribute(WebAccessibility::ATTR_TABLE_CELL_COLUMN_INDEX, &column); |
+ |
BrowserAccessibility* find_table = parent(); |
while (find_table && find_table->role() != WebAccessibility::ROLE_TABLE) |
find_table = find_table->parent(); |
- if (!find_table) |
+ if (!find_table) { |
+ NOTREACHED(); |
return S_FALSE; |
+ } |
- *table = static_cast<IAccessible*>( |
- static_cast<BrowserAccessibilityWin*>(find_table)->NewReference()); |
+ *table = static_cast<IAccessibleTable*>( |
+ find_table->toBrowserAccessibilityWin()->NewReference()); |
return S_OK; |
} |
@@ -1526,7 +1608,115 @@ |
return get_text(*start_offset, *end_offset, text); |
} |
+STDMETHODIMP BrowserAccessibilityWin::get_newText(IA2TextSegment* new_text) { |
+ if (!instance_active_) |
+ return E_FAIL; |
+ |
+ if (!new_text) |
+ return E_INVALIDARG; |
+ |
+ string16 text = TextForIAccessibleText(); |
+ |
+ new_text->text = SysAllocString(text.c_str()); |
+ new_text->start = 0; |
+ new_text->end = static_cast<long>(text.size()); |
+ return S_OK; |
+} |
+ |
+STDMETHODIMP BrowserAccessibilityWin::get_oldText(IA2TextSegment* old_text) { |
+ if (!instance_active_) |
+ return E_FAIL; |
+ |
+ if (!old_text) |
+ return E_INVALIDARG; |
+ |
+ old_text->text = SysAllocString(old_text_.c_str()); |
+ old_text->start = 0; |
+ old_text->end = static_cast<long>(old_text_.size()); |
+ return S_OK; |
+} |
+ |
+STDMETHODIMP BrowserAccessibilityWin::get_offsetAtPoint( |
+ LONG x, LONG y, enum IA2CoordinateType coord_type, LONG* offset) { |
+ if (!instance_active_) |
+ return E_FAIL; |
+ |
+ if (!offset) |
+ return E_INVALIDARG; |
+ |
+ // TODO(dmazzoni): implement this. We're returning S_OK for now so that |
+ // screen readers still return partially accurate results rather than |
+ // completely failing. |
+ *offset = 0; |
+ return S_OK; |
+} |
+ |
// |
+// IAccessibleValue methods. |
+// |
+ |
+STDMETHODIMP BrowserAccessibilityWin::get_currentValue(VARIANT* value) { |
+ if (!instance_active_) |
+ return E_FAIL; |
+ |
+ if (!value) |
+ return E_INVALIDARG; |
+ |
+ float float_val; |
+ if (GetFloatAttribute(WebAccessibility::ATTR_VALUE_FOR_RANGE, &float_val)) { |
+ value->vt = VT_R8; |
+ value->dblVal = float_val; |
+ return S_OK; |
+ } |
+ |
+ value->vt = VT_EMPTY; |
+ return S_FALSE; |
+} |
+ |
+STDMETHODIMP BrowserAccessibilityWin::get_minimumValue(VARIANT* value) { |
+ if (!instance_active_) |
+ return E_FAIL; |
+ |
+ if (!value) |
+ return E_INVALIDARG; |
+ |
+ float float_val; |
+ if (GetFloatAttribute(WebAccessibility::ATTR_MIN_VALUE_FOR_RANGE, |
+ &float_val)) { |
+ value->vt = VT_R8; |
+ value->dblVal = float_val; |
+ return S_OK; |
+ } |
+ |
+ value->vt = VT_EMPTY; |
+ return S_FALSE; |
+} |
+ |
+STDMETHODIMP BrowserAccessibilityWin::get_maximumValue(VARIANT* value) { |
+ if (!instance_active_) |
+ return E_FAIL; |
+ |
+ if (!value) |
+ return E_INVALIDARG; |
+ |
+ float float_val; |
+ if (GetFloatAttribute(WebAccessibility::ATTR_MAX_VALUE_FOR_RANGE, |
+ &float_val)) { |
+ value->vt = VT_R8; |
+ value->dblVal = float_val; |
+ return S_OK; |
+ } |
+ |
+ value->vt = VT_EMPTY; |
+ return S_FALSE; |
+} |
+ |
+STDMETHODIMP BrowserAccessibilityWin::setCurrentValue(VARIANT new_value) { |
+ // TODO(dmazzoni): Implement this. |
+ return E_NOTIMPL; |
+} |
+ |
+// |
// ISimpleDOMDocument methods. |
// |
@@ -1707,7 +1897,7 @@ |
// We only cache a single style property for now: DISPLAY |
- for (unsigned short i = 0; i < num_style_properties; i++) { |
+ for (unsigned short i = 0; i < num_style_properties; ++i) { |
string16 name = (LPCWSTR)style_properties[i]; |
StringToLowerASCII(&name); |
if (name == L"display") { |
@@ -1853,19 +2043,14 @@ |
if (!instance_active_) |
return E_FAIL; |
- if (guidService == IID_IAccessibleTable) { |
- printf("iatable"); |
- } |
- if (guidService == IID_IAccessibleTableCell) { |
- printf("iatable"); |
- } |
- |
if (guidService == IID_IAccessible || |
guidService == IID_IAccessible2 || |
guidService == IID_IAccessibleImage || |
guidService == IID_IAccessibleTable || |
+ guidService == IID_IAccessibleTable2 || |
guidService == IID_IAccessibleTableCell || |
guidService == IID_IAccessibleText || |
+ guidService == IID_IAccessibleValue || |
guidService == IID_ISimpleDOMDocument || |
guidService == IID_ISimpleDOMNode || |
guidService == IID_ISimpleDOMText || |
@@ -1896,7 +2081,7 @@ |
*object = NULL; |
return E_NOINTERFACE; |
} |
- } else if (iid == IID_IAccessibleTable) { |
+ } else if (iid == IID_IAccessibleTable || iid == IID_IAccessibleTable2) { |
if (ia_role_ != ROLE_SYSTEM_TABLE) { |
*object = NULL; |
return E_NOINTERFACE; |
@@ -1906,6 +2091,13 @@ |
*object = NULL; |
return E_NOINTERFACE; |
} |
+ } else if (iid == IID_IAccessibleValue) { |
+ if (ia_role_ != ROLE_SYSTEM_PROGRESSBAR && |
+ ia_role_ != ROLE_SYSTEM_SCROLLBAR && |
+ ia_role_ != ROLE_SYSTEM_SLIDER) { |
+ *object = NULL; |
+ return E_NOINTERFACE; |
+ } |
} else if (iid == IID_ISimpleDOMDocument) { |
if (ia_role_ != ROLE_SYSTEM_DOCUMENT) { |
*object = NULL; |
@@ -1927,17 +2119,72 @@ |
InitRoleAndState(); |
- // Expose headings levels to NVDA with the "level" object attribute. |
+ // Expose headings levels with the "level" attribute. |
if (role_ == WebAccessibility::ROLE_HEADING && role_name_.size() == 2 && |
IsAsciiDigit(role_name_[1])) { |
- html_attributes_.push_back(std::make_pair(L"level", role_name_.substr(1))); |
+ ia2_attributes_.push_back(string16(L"level:") + role_name_.substr(1)); |
} |
- // Expose the "display" object attribute. |
- string16 display; |
- if (GetStringAttribute(WebAccessibility::ATTR_DISPLAY, &display)) |
- html_attributes_.push_back(std::make_pair(L"display", display)); |
+ // Expose the "display" and "tag" attributes. |
+ StringAttributeToIA2(WebAccessibility::ATTR_DISPLAY, "display"); |
+ StringAttributeToIA2(WebAccessibility::ATTR_HTML_TAG, "tag"); |
+ StringAttributeToIA2(WebAccessibility::ATTR_ROLE, "xml-roles"); |
+ // Expose "level" attribute for tree nodes. |
+ IntAttributeToIA2(WebAccessibility::ATTR_HIERARCHICAL_LEVEL, "level"); |
+ |
+ // Expose live region attributes. |
+ StringAttributeToIA2(WebAccessibility::ATTR_LIVE_STATUS, "live"); |
+ StringAttributeToIA2(WebAccessibility::ATTR_LIVE_RELEVANT, "relevant"); |
+ BoolAttributeToIA2(WebAccessibility::ATTR_LIVE_ATOMIC, "atomic"); |
+ BoolAttributeToIA2(WebAccessibility::ATTR_LIVE_BUSY, "busy"); |
+ |
+ // Expose container live region attributes. |
+ StringAttributeToIA2(WebAccessibility::ATTR_CONTAINER_LIVE_STATUS, |
+ "container-live"); |
+ StringAttributeToIA2(WebAccessibility::ATTR_CONTAINER_LIVE_RELEVANT, |
+ "container-relevant"); |
+ BoolAttributeToIA2(WebAccessibility::ATTR_CONTAINER_LIVE_ATOMIC, |
+ "container-atomic"); |
+ BoolAttributeToIA2(WebAccessibility::ATTR_CONTAINER_LIVE_BUSY, |
+ "container-busy"); |
+ |
+ // Expose slider value. |
+ if (ia_role_ == ROLE_SYSTEM_PROGRESSBAR || |
+ ia_role_ == ROLE_SYSTEM_SCROLLBAR || |
+ ia_role_ == ROLE_SYSTEM_SLIDER) { |
+ float fval; |
+ if (value_.empty() && |
+ GetFloatAttribute(WebAccessibility::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 table cell index. |
+ if (ia_role_ == ROLE_SYSTEM_CELL) { |
+ BrowserAccessibility* table = parent(); |
+ while (table && table->role() != WebAccessibility::ROLE_TABLE) |
+ table = table->parent(); |
+ if (table) { |
+ const std::vector<int32>& unique_cell_ids = table->unique_cell_ids(); |
+ int index = -1; |
+ for (size_t i = 0; i < unique_cell_ids.size(); ++i) { |
+ if (unique_cell_ids[i] == renderer_id_) { |
+ index = static_cast<int>(i); |
+ break; |
+ } |
+ } |
+ if (index >= 0) { |
+ ia2_attributes_.push_back(string16(L"table-cell-index:") + |
+ base::IntToString16(index)); |
+ } |
+ } else { |
+ NOTREACHED(); |
+ } |
+ } |
+ |
// If this is static text, put the text in the name rather than the value. |
if (role_ == WebAccessibility::ROLE_STATIC_TEXT && name_.empty()) |
name_.swap(value_); |
@@ -1955,6 +2202,28 @@ |
GetStringAttribute(WebAccessibility::ATTR_URL, &value_); |
} |
+void BrowserAccessibilityWin::SendNodeUpdateEvents() { |
+ // Fire an event when an alert first appears. |
+ if (role_ == WebAccessibility::ROLE_ALERT && first_time_) |
+ manager_->NotifyAccessibilityEvent(ViewHostMsg_AccEvent::ALERT, this); |
+ |
+ // Fire events if text has changed. |
+ string16 text = TextForIAccessibleText(); |
+ if (previous_text_ != text) { |
+ if (!previous_text_.empty() && !text.empty()) { |
+ manager_->NotifyAccessibilityEvent( |
+ ViewHostMsg_AccEvent::OBJECT_SHOW, this); |
+ } |
+ |
+ // TODO(dmazzoni): Look into HIDE events, too. |
+ |
+ old_text_ = previous_text_; |
+ previous_text_ = text; |
+ } |
+ |
+ first_time_ = false; |
+} |
+ |
void BrowserAccessibilityWin::NativeAddReference() { |
AddRef(); |
} |
@@ -1999,13 +2268,36 @@ |
return S_OK; |
} |
+void BrowserAccessibilityWin::StringAttributeToIA2( |
+ WebAccessibility::StringAttribute attribute, const char* ia2_attr) { |
+ string16 value; |
+ if (GetStringAttribute(attribute, &value)) |
+ ia2_attributes_.push_back(ASCIIToUTF16(ia2_attr) + L":" + value); |
+} |
+ |
+void BrowserAccessibilityWin::BoolAttributeToIA2( |
+ WebAccessibility::BoolAttribute attribute, const char* ia2_attr) { |
+ bool value; |
+ if (GetBoolAttribute(attribute, &value)) { |
+ ia2_attributes_.push_back((ASCIIToUTF16(ia2_attr) + L":") + |
+ (value ? L"true" : L"false")); |
+ } |
+} |
+ |
+void BrowserAccessibilityWin::IntAttributeToIA2( |
+ WebAccessibility::IntAttribute attribute, const char* ia2_attr) { |
+ int value; |
+ if (GetIntAttribute(attribute, &value)) |
+ ia2_attributes_.push_back(ASCIIToUTF16(ia2_attr) + L":" + |
+ base::IntToString16(value)); |
+} |
+ |
string16 BrowserAccessibilityWin::Escape(const string16& str) { |
return EscapeQueryParamValueUTF8(str, false); |
} |
const string16& BrowserAccessibilityWin::TextForIAccessibleText() { |
- if (role_ == WebAccessibility::ROLE_TEXT_FIELD || |
- role_ == WebAccessibility::ROLE_TEXTAREA) { |
+ if (IsEditableText()) { |
return value_; |
} else { |
return name_; |
@@ -2041,7 +2333,7 @@ |
return start_offset; |
} else if (boundary == IA2_TEXT_BOUNDARY_LINE) { |
if (direction == 1) { |
- for (int j = 0; j < static_cast<int>(line_breaks_.size()); j++) { |
+ for (int j = 0; j < static_cast<int>(line_breaks_.size()); ++j) { |
if (line_breaks_[j] > start_offset) |
return line_breaks_[j]; |
} |
@@ -2112,7 +2404,10 @@ |
void BrowserAccessibilityWin::InitRoleAndState() { |
ia_state_ = 0; |
ia2_state_ = IA2_STATE_OPAQUE; |
+ ia2_attributes_.clear(); |
+ if ((state_ >> WebAccessibility::STATE_BUSY) & 1) |
+ ia_state_|= STATE_SYSTEM_BUSY; |
if ((state_ >> WebAccessibility::STATE_CHECKED) & 1) |
ia_state_ |= STATE_SYSTEM_CHECKED; |
if ((state_ >> WebAccessibility::STATE_COLLAPSED) & 1) |
@@ -2140,37 +2435,57 @@ |
ia_state_|= STATE_SYSTEM_PRESSED; |
if ((state_ >> WebAccessibility::STATE_PROTECTED) & 1) |
ia_state_|= STATE_SYSTEM_PROTECTED; |
+ if ((state_ >> WebAccessibility::STATE_READONLY) & 1) |
+ ia_state_|= STATE_SYSTEM_READONLY; |
+ if ((state_ >> WebAccessibility::STATE_REQUIRED) & 1) |
+ ia2_state_|= IA2_STATE_REQUIRED; |
if ((state_ >> WebAccessibility::STATE_SELECTABLE) & 1) |
ia_state_|= STATE_SYSTEM_SELECTABLE; |
if ((state_ >> WebAccessibility::STATE_SELECTED) & 1) |
ia_state_|= STATE_SYSTEM_SELECTED; |
- if ((state_ >> WebAccessibility::STATE_READONLY) & 1) |
- ia_state_|= STATE_SYSTEM_READONLY; |
if ((state_ >> WebAccessibility::STATE_TRAVERSED) & 1) |
ia_state_|= STATE_SYSTEM_TRAVERSED; |
- if ((state_ >> WebAccessibility::STATE_BUSY) & 1) |
- ia_state_|= STATE_SYSTEM_BUSY; |
if ((state_ >> WebAccessibility::STATE_UNAVAILABLE) & 1) |
ia_state_|= STATE_SYSTEM_UNAVAILABLE; |
+ if ((state_ >> WebAccessibility::STATE_VERTICAL) & 1) { |
+ ia2_state_|= IA2_STATE_VERTICAL; |
+ } else { |
+ ia2_state_|= IA2_STATE_HORIZONTAL; |
+ } |
+ if ((state_ >> WebAccessibility::STATE_VISITED) & 1) |
+ ia_state_|= STATE_SYSTEM_TRAVERSED; |
+ string16 invalid; |
+ if (GetHtmlAttribute("aria-invalid", &invalid)) |
+ ia2_state_|= IA2_STATE_INVALID_ENTRY; |
+ |
+ bool mixed = false; |
+ GetBoolAttribute(WebAccessibility::ATTR_BUTTON_MIXED, &mixed); |
+ if (mixed) |
+ ia_state_|= STATE_SYSTEM_MIXED; |
+ |
string16 html_tag; |
GetStringAttribute(WebAccessibility::ATTR_HTML_TAG, &html_tag); |
ia_role_ = 0; |
ia2_role_ = 0; |
switch (role_) { |
case WebAccessibility::ROLE_ALERT: |
- case WebAccessibility::ROLE_ALERT_DIALOG: |
ia_role_ = ROLE_SYSTEM_ALERT; |
break; |
+ case WebAccessibility::ROLE_ALERT_DIALOG: |
+ ia_role_ = ROLE_SYSTEM_DIALOG; |
+ break; |
case WebAccessibility::ROLE_APPLICATION: |
ia_role_ = ROLE_SYSTEM_APPLICATION; |
break; |
case WebAccessibility::ROLE_ARTICLE: |
ia_role_ = ROLE_SYSTEM_GROUPING; |
ia2_role_ = IA2_ROLE_SECTION; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_BUSY_INDICATOR: |
ia_role_ = ROLE_SYSTEM_ANIMATION; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_BUTTON: |
ia_role_ = ROLE_SYSTEM_PUSHBUTTON; |
@@ -2187,9 +2502,11 @@ |
break; |
case WebAccessibility::ROLE_COLUMN: |
ia_role_ = ROLE_SYSTEM_COLUMN; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_COLUMN_HEADER: |
ia_role_ = ROLE_SYSTEM_COLUMNHEADER; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_COMBO_BOX: |
ia_role_ = ROLE_SYSTEM_COMBOBOX; |
@@ -2197,15 +2514,19 @@ |
case WebAccessibility::ROLE_DEFINITION_LIST_DEFINITION: |
role_name_ = html_tag; |
ia2_role_ = IA2_ROLE_PARAGRAPH; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_DEFINITION_LIST_TERM: |
ia_role_ = ROLE_SYSTEM_LISTITEM; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_DIALOG: |
ia_role_ = ROLE_SYSTEM_DIALOG; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_DISCLOSURE_TRIANGLE: |
ia_role_ = ROLE_SYSTEM_OUTLINEBUTTON; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_DOCUMENT: |
case WebAccessibility::ROLE_WEB_AREA: |
@@ -2220,10 +2541,17 @@ |
break; |
case WebAccessibility::ROLE_GRID: |
ia_role_ = ROLE_SYSTEM_TABLE; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_GROUP: |
if (html_tag == L"li") { |
ia_role_ = ROLE_SYSTEM_LISTITEM; |
+ } else if (html_tag == L"form") { |
+ role_name_ = html_tag; |
+ ia2_role_ = IA2_ROLE_FORM; |
+ } else if (html_tag == L"p") { |
+ role_name_ = html_tag; |
+ ia2_role_ = IA2_ROLE_PARAGRAPH; |
} else { |
if (html_tag.empty()) |
role_name_ = L"div"; |
@@ -2231,24 +2559,30 @@ |
role_name_ = html_tag; |
ia2_role_ = IA2_ROLE_SECTION; |
} |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_GROW_AREA: |
ia_role_ = ROLE_SYSTEM_GRIP; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_HEADING: |
role_name_ = html_tag; |
ia2_role_ = IA2_ROLE_HEADING; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_IMAGE: |
ia_role_ = ROLE_SYSTEM_GRAPHIC; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_IMAGE_MAP: |
role_name_ = html_tag; |
ia2_role_ = IA2_ROLE_IMAGE_MAP; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_IMAGE_MAP_LINK: |
ia_role_ = ROLE_SYSTEM_LINK; |
ia_state_|= STATE_SYSTEM_LINKED; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_LANDMARK_APPLICATION: |
case WebAccessibility::ROLE_LANDMARK_BANNER: |
@@ -2259,6 +2593,7 @@ |
case WebAccessibility::ROLE_LANDMARK_SEARCH: |
ia_role_ = ROLE_SYSTEM_GROUPING; |
ia2_role_ = IA2_ROLE_SECTION; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_LINK: |
case WebAccessibility::ROLE_WEBCORE_LINK: |
@@ -2267,17 +2602,25 @@ |
break; |
case WebAccessibility::ROLE_LIST: |
ia_role_ = ROLE_SYSTEM_LIST; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_LISTBOX: |
ia_role_ = ROLE_SYSTEM_LIST; |
break; |
case WebAccessibility::ROLE_LISTBOX_OPTION: |
+ ia_role_ = ROLE_SYSTEM_LISTITEM; |
+ break; |
case WebAccessibility::ROLE_LIST_ITEM: |
- case WebAccessibility::ROLE_LIST_MARKER: |
ia_role_ = ROLE_SYSTEM_LISTITEM; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
+ case WebAccessibility::ROLE_LIST_MARKER: |
+ ia_role_ = ROLE_SYSTEM_TEXT; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
+ break; |
case WebAccessibility::ROLE_MATH: |
ia_role_ = ROLE_SYSTEM_EQUATION; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_MENU: |
case WebAccessibility::ROLE_MENU_BUTTON: |
@@ -2296,15 +2639,22 @@ |
case WebAccessibility::ROLE_NOTE: |
ia_role_ = ROLE_SYSTEM_GROUPING; |
ia2_role_ = IA2_ROLE_NOTE; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_OUTLINE: |
ia_role_ = ROLE_SYSTEM_OUTLINE; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_POPUP_BUTTON: |
- ia_role_ = ROLE_SYSTEM_COMBOBOX; |
+ if (html_tag == L"select") { |
+ ia_role_ = ROLE_SYSTEM_COMBOBOX; |
+ } else { |
+ ia_role_ = ROLE_SYSTEM_BUTTONMENU; |
+ } |
break; |
case WebAccessibility::ROLE_PROGRESS_INDICATOR: |
ia_role_ = ROLE_SYSTEM_PROGRESSBAR; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_RADIO_BUTTON: |
ia_role_ = ROLE_SYSTEM_RADIOBUTTON; |
@@ -2316,20 +2666,25 @@ |
case WebAccessibility::ROLE_REGION: |
ia_role_ = ROLE_SYSTEM_GROUPING; |
ia2_role_ = IA2_ROLE_SECTION; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_ROW: |
ia_role_ = ROLE_SYSTEM_ROW; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_ROW_HEADER: |
ia_role_ = ROLE_SYSTEM_ROWHEADER; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_RULER: |
ia_role_ = ROLE_SYSTEM_CLIENT; |
ia2_role_ = IA2_ROLE_RULER; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_SCROLLAREA: |
ia_role_ = ROLE_SYSTEM_CLIENT; |
ia2_role_ = IA2_ROLE_SCROLL_PANE; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_SCROLLBAR: |
ia_role_ = ROLE_SYSTEM_SCROLLBAR; |
@@ -2340,13 +2695,16 @@ |
case WebAccessibility::ROLE_SPLIT_GROUP: |
ia_role_ = ROLE_SYSTEM_CLIENT; |
ia2_role_ = IA2_ROLE_SPLIT_PANE; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_ANNOTATION: |
case WebAccessibility::ROLE_STATIC_TEXT: |
ia_role_ = ROLE_SYSTEM_TEXT; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_STATUS: |
ia_role_ = ROLE_SYSTEM_STATUSBAR; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_SPLITTER: |
ia_role_ = ROLE_SYSTEM_SEPARATOR; |
@@ -2356,10 +2714,12 @@ |
break; |
case WebAccessibility::ROLE_TABLE: |
ia_role_ = ROLE_SYSTEM_TABLE; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_TABLE_HEADER_CONTAINER: |
ia_role_ = ROLE_SYSTEM_GROUPING; |
ia2_role_ = IA2_ROLE_SECTION; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_TAB_GROUP: |
case WebAccessibility::ROLE_TAB_LIST: |
@@ -2380,21 +2740,27 @@ |
break; |
case WebAccessibility::ROLE_TIMER: |
ia_role_ = ROLE_SYSTEM_CLOCK; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_TOOLBAR: |
ia_role_ = ROLE_SYSTEM_TOOLBAR; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_TOOLTIP: |
ia_role_ = ROLE_SYSTEM_TOOLTIP; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_TREE: |
ia_role_ = ROLE_SYSTEM_OUTLINE; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_TREE_GRID: |
ia_role_ = ROLE_SYSTEM_OUTLINE; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_TREE_ITEM: |
ia_role_ = ROLE_SYSTEM_OUTLINEITEM; |
+ ia_state_|= STATE_SYSTEM_READONLY; |
break; |
case WebAccessibility::ROLE_WINDOW: |
ia_role_ = ROLE_SYSTEM_WINDOW; |