| 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; | 
|  |