Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/accessibility/browser_accessibility_win.h" | 5 #include "content/browser/accessibility/browser_accessibility_win.h" |
| 6 | 6 |
| 7 #include <UIAutomationClient.h> | 7 #include <UIAutomationClient.h> |
| 8 #include <UIAutomationCoreApi.h> | 8 #include <UIAutomationCoreApi.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 112 | 112 |
| 113 STDMETHODIMP BrowserAccessibilityRelation::get_nTargets(long* n_targets) { | 113 STDMETHODIMP BrowserAccessibilityRelation::get_nTargets(long* n_targets) { |
| 114 if (!n_targets) | 114 if (!n_targets) |
| 115 return E_INVALIDARG; | 115 return E_INVALIDARG; |
| 116 | 116 |
| 117 if (!owner_->instance_active()) | 117 if (!owner_->instance_active()) |
| 118 return E_FAIL; | 118 return E_FAIL; |
| 119 | 119 |
| 120 *n_targets = static_cast<long>(target_ids_.size()); | 120 *n_targets = static_cast<long>(target_ids_.size()); |
| 121 | 121 |
| 122 BrowserAccessibilityManager* manager = owner_->manager(); | |
| 123 for (long i = *n_targets - 1; i >= 0; --i) { | 122 for (long i = *n_targets - 1; i >= 0; --i) { |
| 124 BrowserAccessibility* result = manager->GetFromID(target_ids_[i]); | 123 BrowserAccessibilityWin* result = owner_->GetFromID(target_ids_[i]); |
| 125 if (!result || !result->instance_active()) { | 124 if (!result || !result->instance_active()) { |
| 126 *n_targets = 0; | 125 *n_targets = 0; |
| 127 break; | 126 break; |
| 128 } | 127 } |
| 129 } | 128 } |
| 130 return S_OK; | 129 return S_OK; |
| 131 } | 130 } |
| 132 | 131 |
| 133 STDMETHODIMP BrowserAccessibilityRelation::get_target(long target_index, | 132 STDMETHODIMP BrowserAccessibilityRelation::get_target(long target_index, |
| 134 IUnknown** target) { | 133 IUnknown** target) { |
| 135 if (!target) | 134 if (!target) |
| 136 return E_INVALIDARG; | 135 return E_INVALIDARG; |
| 137 | 136 |
| 138 if (!owner_->instance_active()) | 137 if (!owner_->instance_active()) |
| 139 return E_FAIL; | 138 return E_FAIL; |
| 140 | 139 |
| 141 if (target_index < 0 || | 140 if (target_index < 0 || |
| 142 target_index >= static_cast<long>(target_ids_.size())) { | 141 target_index >= static_cast<long>(target_ids_.size())) { |
| 143 return E_INVALIDARG; | 142 return E_INVALIDARG; |
| 144 } | 143 } |
| 145 | 144 |
| 146 BrowserAccessibilityManager* manager = owner_->manager(); | 145 BrowserAccessibility* result = owner_->GetFromID(target_ids_[target_index]); |
| 147 BrowserAccessibility* result = | |
| 148 manager->GetFromID(target_ids_[target_index]); | |
| 149 if (!result || !result->instance_active()) | 146 if (!result || !result->instance_active()) |
| 150 return E_FAIL; | 147 return E_FAIL; |
| 151 | 148 |
| 152 *target = static_cast<IAccessible*>( | 149 *target = static_cast<IAccessible*>( |
| 153 result->ToBrowserAccessibilityWin()->NewReference()); | 150 result->ToBrowserAccessibilityWin()->NewReference()); |
| 154 return S_OK; | 151 return S_OK; |
| 155 } | 152 } |
| 156 | 153 |
| 157 STDMETHODIMP BrowserAccessibilityRelation::get_targets(long max_targets, | 154 STDMETHODIMP BrowserAccessibilityRelation::get_targets(long max_targets, |
| 158 IUnknown** targets, | 155 IUnknown** targets, |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 592 target->ia_role() == ROLE_SYSTEM_SCROLLBAR || | 589 target->ia_role() == ROLE_SYSTEM_SCROLLBAR || |
| 593 target->ia_role() == ROLE_SYSTEM_SLIDER) { | 590 target->ia_role() == ROLE_SYSTEM_SLIDER) { |
| 594 base::string16 value_text = target->GetValueText(); | 591 base::string16 value_text = target->GetValueText(); |
| 595 *value = SysAllocString(value_text.c_str()); | 592 *value = SysAllocString(value_text.c_str()); |
| 596 DCHECK(*value); | 593 DCHECK(*value); |
| 597 return S_OK; | 594 return S_OK; |
| 598 } | 595 } |
| 599 | 596 |
| 600 // Expose color well value. | 597 // Expose color well value. |
| 601 if (target->ia2_role() == IA2_ROLE_COLOR_CHOOSER) { | 598 if (target->ia2_role() == IA2_ROLE_COLOR_CHOOSER) { |
| 602 int color = target->GetIntAttribute(ui::AX_ATTR_COLOR_VALUE); | 599 unsigned int color = static_cast<unsigned int>( |
| 603 int red = (color >> 16) & 0xFF; | 600 target->GetIntAttribute(ui::AX_ATTR_COLOR_VALUE)); |
| 604 int green = (color >> 8) & 0xFF; | 601 unsigned int red, green, blue, alpha; |
| 605 int blue = color & 0xFF; | 602 RGBAToColorValues(color, &red, &green, &blue, &alpha); |
| 606 base::string16 value_text; | 603 base::string16 value_text; |
| 607 value_text = base::IntToString16((red * 100) / 255) + L"% red " + | 604 value_text = base::UintToString16(red * 100 / 255) + L"% red " + |
| 608 base::IntToString16((green * 100) / 255) + L"% green " + | 605 base::UintToString16(green * 100 / 255) + L"% green " + |
| 609 base::IntToString16((blue * 100) / 255) + L"% blue"; | 606 base::UintToString16(blue * 100 / 255) + L"% blue"; |
| 610 *value = SysAllocString(value_text.c_str()); | 607 *value = SysAllocString(value_text.c_str()); |
| 611 DCHECK(*value); | 608 DCHECK(*value); |
| 612 return S_OK; | 609 return S_OK; |
| 613 } | 610 } |
| 614 | 611 |
| 615 *value = SysAllocString(target->value().c_str()); | 612 *value = SysAllocString(target->value().c_str()); |
| 616 DCHECK(*value); | 613 DCHECK(*value); |
| 617 return S_OK; | 614 return S_OK; |
| 618 } | 615 } |
| 619 | 616 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 703 | 700 |
| 704 if (!role) | 701 if (!role) |
| 705 return E_INVALIDARG; | 702 return E_INVALIDARG; |
| 706 | 703 |
| 707 *role = ia2_role(); | 704 *role = ia2_role(); |
| 708 | 705 |
| 709 return S_OK; | 706 return S_OK; |
| 710 } | 707 } |
| 711 | 708 |
| 712 STDMETHODIMP BrowserAccessibilityWin::get_attributes(BSTR* attributes) { | 709 STDMETHODIMP BrowserAccessibilityWin::get_attributes(BSTR* attributes) { |
| 710 if (!attributes) | |
| 711 return E_INVALIDARG; | |
| 712 *attributes = nullptr; | |
| 713 | |
| 713 if (!instance_active()) | 714 if (!instance_active()) |
| 714 return E_FAIL; | 715 return E_FAIL; |
| 715 | 716 |
| 716 if (!attributes) | |
| 717 return E_INVALIDARG; | |
| 718 | |
| 719 // The iaccessible2 attributes are a set of key-value pairs | |
| 720 // separated by semicolons, with a colon between the key and the value. | |
| 721 base::string16 str; | 717 base::string16 str; |
| 722 const std::vector<base::string16>& attributes_list = ia2_attributes(); | 718 for (const base::string16& attribute : ia2_attributes()) |
| 723 for (unsigned int i = 0; i < attributes_list.size(); ++i) { | 719 str += attribute + L';'; |
| 724 str += attributes_list[i] + L';'; | |
| 725 } | |
| 726 | 720 |
| 727 if (str.empty()) | 721 if (str.empty()) |
| 728 return S_FALSE; | 722 return S_FALSE; |
| 729 | 723 |
| 730 *attributes = SysAllocString(str.c_str()); | 724 *attributes = SysAllocString(str.c_str()); |
| 731 DCHECK(*attributes); | 725 DCHECK(*attributes); |
| 732 return S_OK; | 726 return S_OK; |
| 733 } | 727 } |
| 734 | 728 |
| 735 STDMETHODIMP BrowserAccessibilityWin::get_states(AccessibleStates* states) { | 729 STDMETHODIMP BrowserAccessibilityWin::get_states(AccessibleStates* states) { |
| (...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1197 return S_FALSE; | 1191 return S_FALSE; |
| 1198 } | 1192 } |
| 1199 | 1193 |
| 1200 if (column < 0 || column >= columns) | 1194 if (column < 0 || column >= columns) |
| 1201 return E_INVALIDARG; | 1195 return E_INVALIDARG; |
| 1202 | 1196 |
| 1203 const std::vector<int32_t>& cell_ids = | 1197 const std::vector<int32_t>& cell_ids = |
| 1204 GetIntListAttribute(ui::AX_ATTR_CELL_IDS); | 1198 GetIntListAttribute(ui::AX_ATTR_CELL_IDS); |
| 1205 for (int i = 0; i < rows; ++i) { | 1199 for (int i = 0; i < rows; ++i) { |
| 1206 int cell_id = cell_ids[i * columns + column]; | 1200 int cell_id = cell_ids[i * columns + column]; |
| 1207 BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>( | 1201 BrowserAccessibilityWin* cell = GetFromID(cell_id); |
| 1208 manager()->GetFromID(cell_id)); | |
| 1209 if (cell && cell->GetRole() == ui::AX_ROLE_COLUMN_HEADER) { | 1202 if (cell && cell->GetRole() == ui::AX_ROLE_COLUMN_HEADER) { |
| 1210 base::string16 cell_name = cell->GetString16Attribute( | 1203 base::string16 cell_name = cell->GetString16Attribute( |
| 1211 ui::AX_ATTR_NAME); | 1204 ui::AX_ATTR_NAME); |
| 1212 if (cell_name.size() > 0) { | 1205 if (cell_name.size() > 0) { |
| 1213 *description = SysAllocString(cell_name.c_str()); | 1206 *description = SysAllocString(cell_name.c_str()); |
| 1214 return S_OK; | 1207 return S_OK; |
| 1215 } | 1208 } |
| 1216 | 1209 |
| 1217 if (cell->description().size() > 0) { | 1210 if (cell->description().size() > 0) { |
| 1218 *description = SysAllocString(cell->description().c_str()); | 1211 *description = SysAllocString(cell->description().c_str()); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 1243 rows <= 0) { | 1236 rows <= 0) { |
| 1244 return S_FALSE; | 1237 return S_FALSE; |
| 1245 } | 1238 } |
| 1246 | 1239 |
| 1247 if (row < 0 || row >= rows || column < 0 || column >= columns) | 1240 if (row < 0 || row >= rows || column < 0 || column >= columns) |
| 1248 return E_INVALIDARG; | 1241 return E_INVALIDARG; |
| 1249 | 1242 |
| 1250 const std::vector<int32_t>& cell_ids = | 1243 const std::vector<int32_t>& cell_ids = |
| 1251 GetIntListAttribute(ui::AX_ATTR_CELL_IDS); | 1244 GetIntListAttribute(ui::AX_ATTR_CELL_IDS); |
| 1252 int cell_id = cell_ids[row * columns + column]; | 1245 int cell_id = cell_ids[row * columns + column]; |
| 1253 BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>( | 1246 BrowserAccessibilityWin* cell = GetFromID(cell_id); |
| 1254 manager()->GetFromID(cell_id)); | |
| 1255 int colspan; | 1247 int colspan; |
| 1256 if (cell && | 1248 if (cell && |
| 1257 cell->GetIntAttribute( | 1249 cell->GetIntAttribute( |
| 1258 ui::AX_ATTR_TABLE_CELL_COLUMN_SPAN, &colspan) && | 1250 ui::AX_ATTR_TABLE_CELL_COLUMN_SPAN, &colspan) && |
| 1259 colspan >= 1) { | 1251 colspan >= 1) { |
| 1260 *n_columns_spanned = colspan; | 1252 *n_columns_spanned = colspan; |
| 1261 return S_OK; | 1253 return S_OK; |
| 1262 } | 1254 } |
| 1263 | 1255 |
| 1264 return S_FALSE; | 1256 return S_FALSE; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1281 | 1273 |
| 1282 const std::vector<int32_t>& unique_cell_ids = | 1274 const std::vector<int32_t>& unique_cell_ids = |
| 1283 GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS); | 1275 GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS); |
| 1284 int cell_id_count = static_cast<int>(unique_cell_ids.size()); | 1276 int cell_id_count = static_cast<int>(unique_cell_ids.size()); |
| 1285 if (cell_index < 0) | 1277 if (cell_index < 0) |
| 1286 return E_INVALIDARG; | 1278 return E_INVALIDARG; |
| 1287 if (cell_index >= cell_id_count) | 1279 if (cell_index >= cell_id_count) |
| 1288 return S_FALSE; | 1280 return S_FALSE; |
| 1289 | 1281 |
| 1290 int cell_id = unique_cell_ids[cell_index]; | 1282 int cell_id = unique_cell_ids[cell_index]; |
| 1291 BrowserAccessibilityWin* cell = | 1283 BrowserAccessibilityWin* cell = GetFromID(cell_id); |
| 1292 manager()->GetFromID(cell_id)->ToBrowserAccessibilityWin(); | |
| 1293 int col_index; | 1284 int col_index; |
| 1294 if (cell && | 1285 if (cell && |
| 1295 cell->GetIntAttribute( | 1286 cell->GetIntAttribute( |
| 1296 ui::AX_ATTR_TABLE_CELL_COLUMN_INDEX, &col_index)) { | 1287 ui::AX_ATTR_TABLE_CELL_COLUMN_INDEX, &col_index)) { |
| 1297 *column_index = col_index; | 1288 *column_index = col_index; |
| 1298 return S_OK; | 1289 return S_OK; |
| 1299 } | 1290 } |
| 1300 | 1291 |
| 1301 return S_FALSE; | 1292 return S_FALSE; |
| 1302 } | 1293 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1386 return S_FALSE; | 1377 return S_FALSE; |
| 1387 } | 1378 } |
| 1388 | 1379 |
| 1389 if (row < 0 || row >= rows) | 1380 if (row < 0 || row >= rows) |
| 1390 return E_INVALIDARG; | 1381 return E_INVALIDARG; |
| 1391 | 1382 |
| 1392 const std::vector<int32_t>& cell_ids = | 1383 const std::vector<int32_t>& cell_ids = |
| 1393 GetIntListAttribute(ui::AX_ATTR_CELL_IDS); | 1384 GetIntListAttribute(ui::AX_ATTR_CELL_IDS); |
| 1394 for (int i = 0; i < columns; ++i) { | 1385 for (int i = 0; i < columns; ++i) { |
| 1395 int cell_id = cell_ids[row * columns + i]; | 1386 int cell_id = cell_ids[row * columns + i]; |
| 1396 BrowserAccessibilityWin* cell = | 1387 BrowserAccessibilityWin* cell = GetFromID(cell_id); |
| 1397 manager()->GetFromID(cell_id)->ToBrowserAccessibilityWin(); | |
| 1398 if (cell && cell->GetRole() == ui::AX_ROLE_ROW_HEADER) { | 1388 if (cell && cell->GetRole() == ui::AX_ROLE_ROW_HEADER) { |
| 1399 base::string16 cell_name = cell->GetString16Attribute( | 1389 base::string16 cell_name = cell->GetString16Attribute( |
| 1400 ui::AX_ATTR_NAME); | 1390 ui::AX_ATTR_NAME); |
| 1401 if (cell_name.size() > 0) { | 1391 if (cell_name.size() > 0) { |
| 1402 *description = SysAllocString(cell_name.c_str()); | 1392 *description = SysAllocString(cell_name.c_str()); |
| 1403 return S_OK; | 1393 return S_OK; |
| 1404 } | 1394 } |
| 1405 | 1395 |
| 1406 if (cell->description().size() > 0) { | 1396 if (cell->description().size() > 0) { |
| 1407 *description = SysAllocString(cell->description().c_str()); | 1397 *description = SysAllocString(cell->description().c_str()); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1431 rows <= 0) { | 1421 rows <= 0) { |
| 1432 return S_FALSE; | 1422 return S_FALSE; |
| 1433 } | 1423 } |
| 1434 | 1424 |
| 1435 if (row < 0 || row >= rows || column < 0 || column >= columns) | 1425 if (row < 0 || row >= rows || column < 0 || column >= columns) |
| 1436 return E_INVALIDARG; | 1426 return E_INVALIDARG; |
| 1437 | 1427 |
| 1438 const std::vector<int32_t>& cell_ids = | 1428 const std::vector<int32_t>& cell_ids = |
| 1439 GetIntListAttribute(ui::AX_ATTR_CELL_IDS); | 1429 GetIntListAttribute(ui::AX_ATTR_CELL_IDS); |
| 1440 int cell_id = cell_ids[row * columns + column]; | 1430 int cell_id = cell_ids[row * columns + column]; |
| 1441 BrowserAccessibilityWin* cell = | 1431 BrowserAccessibilityWin* cell = GetFromID(cell_id); |
| 1442 manager()->GetFromID(cell_id)->ToBrowserAccessibilityWin(); | |
| 1443 int rowspan; | 1432 int rowspan; |
| 1444 if (cell && | 1433 if (cell && |
| 1445 cell->GetIntAttribute( | 1434 cell->GetIntAttribute( |
| 1446 ui::AX_ATTR_TABLE_CELL_ROW_SPAN, &rowspan) && | 1435 ui::AX_ATTR_TABLE_CELL_ROW_SPAN, &rowspan) && |
| 1447 rowspan >= 1) { | 1436 rowspan >= 1) { |
| 1448 *n_rows_spanned = rowspan; | 1437 *n_rows_spanned = rowspan; |
| 1449 return S_OK; | 1438 return S_OK; |
| 1450 } | 1439 } |
| 1451 | 1440 |
| 1452 return S_FALSE; | 1441 return S_FALSE; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1469 | 1458 |
| 1470 const std::vector<int32_t>& unique_cell_ids = | 1459 const std::vector<int32_t>& unique_cell_ids = |
| 1471 GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS); | 1460 GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS); |
| 1472 int cell_id_count = static_cast<int>(unique_cell_ids.size()); | 1461 int cell_id_count = static_cast<int>(unique_cell_ids.size()); |
| 1473 if (cell_index < 0) | 1462 if (cell_index < 0) |
| 1474 return E_INVALIDARG; | 1463 return E_INVALIDARG; |
| 1475 if (cell_index >= cell_id_count) | 1464 if (cell_index >= cell_id_count) |
| 1476 return S_FALSE; | 1465 return S_FALSE; |
| 1477 | 1466 |
| 1478 int cell_id = unique_cell_ids[cell_index]; | 1467 int cell_id = unique_cell_ids[cell_index]; |
| 1479 BrowserAccessibilityWin* cell = | 1468 BrowserAccessibilityWin* cell = GetFromID(cell_id); |
| 1480 manager()->GetFromID(cell_id)->ToBrowserAccessibilityWin(); | |
| 1481 int cell_row_index; | 1469 int cell_row_index; |
| 1482 if (cell && | 1470 if (cell && |
| 1483 cell->GetIntAttribute( | 1471 cell->GetIntAttribute( |
| 1484 ui::AX_ATTR_TABLE_CELL_ROW_INDEX, &cell_row_index)) { | 1472 ui::AX_ATTR_TABLE_CELL_ROW_INDEX, &cell_row_index)) { |
| 1485 *row_index = cell_row_index; | 1473 *row_index = cell_row_index; |
| 1486 return S_OK; | 1474 return S_OK; |
| 1487 } | 1475 } |
| 1488 | 1476 |
| 1489 return S_FALSE; | 1477 return S_FALSE; |
| 1490 } | 1478 } |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1598 | 1586 |
| 1599 const std::vector<int32_t>& unique_cell_ids = | 1587 const std::vector<int32_t>& unique_cell_ids = |
| 1600 GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS); | 1588 GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS); |
| 1601 int cell_id_count = static_cast<int>(unique_cell_ids.size()); | 1589 int cell_id_count = static_cast<int>(unique_cell_ids.size()); |
| 1602 if (index < 0) | 1590 if (index < 0) |
| 1603 return E_INVALIDARG; | 1591 return E_INVALIDARG; |
| 1604 if (index >= cell_id_count) | 1592 if (index >= cell_id_count) |
| 1605 return S_FALSE; | 1593 return S_FALSE; |
| 1606 | 1594 |
| 1607 int cell_id = unique_cell_ids[index]; | 1595 int cell_id = unique_cell_ids[index]; |
| 1608 BrowserAccessibilityWin* cell = | 1596 BrowserAccessibilityWin* cell = GetFromID(cell_id); |
| 1609 manager()->GetFromID(cell_id)->ToBrowserAccessibilityWin(); | |
| 1610 int rowspan; | 1597 int rowspan; |
| 1611 int colspan; | 1598 int colspan; |
| 1612 if (cell && | 1599 if (cell && |
| 1613 cell->GetIntAttribute( | 1600 cell->GetIntAttribute( |
| 1614 ui::AX_ATTR_TABLE_CELL_ROW_SPAN, &rowspan) && | 1601 ui::AX_ATTR_TABLE_CELL_ROW_SPAN, &rowspan) && |
| 1615 cell->GetIntAttribute( | 1602 cell->GetIntAttribute( |
| 1616 ui::AX_ATTR_TABLE_CELL_COLUMN_SPAN, &colspan) && | 1603 ui::AX_ATTR_TABLE_CELL_COLUMN_SPAN, &colspan) && |
| 1617 rowspan >= 1 && | 1604 rowspan >= 1 && |
| 1618 colspan >= 1) { | 1605 colspan >= 1) { |
| 1619 *row_extents = rowspan; | 1606 *row_extents = rowspan; |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1757 return S_FALSE; | 1744 return S_FALSE; |
| 1758 } | 1745 } |
| 1759 if (columns <= 0 || rows <= 0 || column < 0 || column >= columns) | 1746 if (columns <= 0 || rows <= 0 || column < 0 || column >= columns) |
| 1760 return S_FALSE; | 1747 return S_FALSE; |
| 1761 | 1748 |
| 1762 const std::vector<int32_t>& cell_ids = | 1749 const std::vector<int32_t>& cell_ids = |
| 1763 table->GetIntListAttribute(ui::AX_ATTR_CELL_IDS); | 1750 table->GetIntListAttribute(ui::AX_ATTR_CELL_IDS); |
| 1764 | 1751 |
| 1765 for (int i = 0; i < rows; ++i) { | 1752 for (int i = 0; i < rows; ++i) { |
| 1766 int cell_id = cell_ids[i * columns + column]; | 1753 int cell_id = cell_ids[i * columns + column]; |
| 1767 BrowserAccessibilityWin* cell = | 1754 BrowserAccessibilityWin* cell = GetFromID(cell_id); |
| 1768 manager()->GetFromID(cell_id)->ToBrowserAccessibilityWin(); | |
| 1769 if (cell && cell->GetRole() == ui::AX_ROLE_COLUMN_HEADER) | 1755 if (cell && cell->GetRole() == ui::AX_ROLE_COLUMN_HEADER) |
| 1770 (*n_column_header_cells)++; | 1756 (*n_column_header_cells)++; |
| 1771 } | 1757 } |
| 1772 | 1758 |
| 1773 *cell_accessibles = static_cast<IUnknown**>(CoTaskMemAlloc( | 1759 *cell_accessibles = static_cast<IUnknown**>(CoTaskMemAlloc( |
| 1774 (*n_column_header_cells) * sizeof(cell_accessibles[0]))); | 1760 (*n_column_header_cells) * sizeof(cell_accessibles[0]))); |
| 1775 int index = 0; | 1761 int index = 0; |
| 1776 for (int i = 0; i < rows; ++i) { | 1762 for (int i = 0; i < rows; ++i) { |
| 1777 int cell_id = cell_ids[i * columns + column]; | 1763 int cell_id = cell_ids[i * columns + column]; |
| 1778 BrowserAccessibility* cell = manager()->GetFromID(cell_id); | 1764 BrowserAccessibility* cell = manager()->GetFromID(cell_id); |
| (...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2365 return E_INVALIDARG; | 2351 return E_INVALIDARG; |
| 2366 | 2352 |
| 2367 const base::string16& text_str = GetText(); | 2353 const base::string16& text_str = GetText(); |
| 2368 HandleSpecialTextOffset(text_str, &start_offset); | 2354 HandleSpecialTextOffset(text_str, &start_offset); |
| 2369 HandleSpecialTextOffset(text_str, &end_offset); | 2355 HandleSpecialTextOffset(text_str, &end_offset); |
| 2370 | 2356 |
| 2371 manager()->SetTextSelection(*this, start_offset, end_offset); | 2357 manager()->SetTextSelection(*this, start_offset, end_offset); |
| 2372 return S_OK; | 2358 return S_OK; |
| 2373 } | 2359 } |
| 2374 | 2360 |
| 2375 // | |
| 2376 // IAccessibleText methods not implemented. | |
| 2377 // | |
| 2378 | |
| 2379 STDMETHODIMP BrowserAccessibilityWin::get_attributes(LONG offset, | 2361 STDMETHODIMP BrowserAccessibilityWin::get_attributes(LONG offset, |
| 2380 LONG* start_offset, | 2362 LONG* start_offset, |
| 2381 LONG* end_offset, | 2363 LONG* end_offset, |
| 2382 BSTR* text_attributes) { | 2364 BSTR* text_attributes) { |
| 2383 return E_NOTIMPL; | 2365 if (!start_offset || !end_offset || !text_attributes) |
| 2366 return E_INVALIDARG; | |
| 2367 | |
| 2368 *start_offset = *end_offset = 0; | |
| 2369 *text_attributes = nullptr; | |
| 2370 if (!instance_active()) | |
| 2371 return E_FAIL; | |
| 2372 | |
| 2373 const base::string16& text = GetText(); | |
| 2374 HandleSpecialTextOffset(text, &offset); | |
| 2375 if (offset < 0 || offset > static_cast<LONG>(text.size())) | |
| 2376 return E_INVALIDARG; | |
| 2377 | |
| 2378 ComputeTextAttributes(); | |
|
dmazzoni
2016/03/07 23:38:11
We shouldn't compute them from scratch every time
| |
| 2379 *start_offset = FindStartOfStyle(offset, ui::BACKWARDS_DIRECTION); | |
| 2380 *end_offset = FindStartOfStyle(offset, ui::FORWARDS_DIRECTION); | |
| 2381 | |
| 2382 base::string16 attributes; | |
| 2383 for (base::string16& attribute : offset_to_text_attributes()[*start_offset]) { | |
| 2384 attributes += attribute + L';'; | |
| 2385 } | |
| 2386 | |
| 2387 if (attributes.empty()) | |
| 2388 return S_FALSE; | |
| 2389 | |
| 2390 *text_attributes = SysAllocString(attributes.c_str()); | |
| 2391 DCHECK(*text_attributes); | |
| 2392 return S_OK; | |
| 2384 } | 2393 } |
| 2385 | 2394 |
| 2386 // | 2395 // |
| 2387 // IAccessibleHypertext methods. | 2396 // IAccessibleHypertext methods. |
| 2388 // | 2397 // |
| 2389 | 2398 |
| 2390 STDMETHODIMP BrowserAccessibilityWin::get_nHyperlinks(long* hyperlink_count) { | 2399 STDMETHODIMP BrowserAccessibilityWin::get_nHyperlinks(long* hyperlink_count) { |
| 2391 if (!instance_active()) | 2400 if (!instance_active()) |
| 2392 return E_FAIL; | 2401 return E_FAIL; |
| 2393 | 2402 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 2404 if (!instance_active()) | 2413 if (!instance_active()) |
| 2405 return E_FAIL; | 2414 return E_FAIL; |
| 2406 | 2415 |
| 2407 if (!hyperlink || | 2416 if (!hyperlink || |
| 2408 index < 0 || | 2417 index < 0 || |
| 2409 index >= static_cast<long>(hyperlinks().size())) { | 2418 index >= static_cast<long>(hyperlinks().size())) { |
| 2410 return E_INVALIDARG; | 2419 return E_INVALIDARG; |
| 2411 } | 2420 } |
| 2412 | 2421 |
| 2413 int32_t id = hyperlinks()[index]; | 2422 int32_t id = hyperlinks()[index]; |
| 2414 BrowserAccessibilityWin* child = | 2423 BrowserAccessibilityWin* link = GetFromID(id); |
| 2415 manager()->GetFromID(id)->ToBrowserAccessibilityWin(); | 2424 if (link) { |
| 2416 if (child) { | 2425 *hyperlink = static_cast<IAccessibleHyperlink*>(link->NewReference()); |
| 2417 *hyperlink = static_cast<IAccessibleHyperlink*>(child->NewReference()); | |
| 2418 return S_OK; | 2426 return S_OK; |
| 2419 } | 2427 } |
| 2420 | 2428 |
| 2421 return E_FAIL; | 2429 return E_FAIL; |
| 2422 } | 2430 } |
| 2423 | 2431 |
| 2424 STDMETHODIMP BrowserAccessibilityWin::get_hyperlinkIndex( | 2432 STDMETHODIMP BrowserAccessibilityWin::get_hyperlinkIndex( |
| 2425 long char_index, | 2433 long char_index, |
| 2426 long* hyperlink_index) { | 2434 long* hyperlink_index) { |
| 2427 if (!instance_active()) | 2435 if (!instance_active()) |
| (...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2989 STDMETHODIMP BrowserAccessibilityWin::get_innerHTML(BSTR* innerHTML) { | 2997 STDMETHODIMP BrowserAccessibilityWin::get_innerHTML(BSTR* innerHTML) { |
| 2990 return E_NOTIMPL; | 2998 return E_NOTIMPL; |
| 2991 } | 2999 } |
| 2992 | 3000 |
| 2993 STDMETHODIMP | 3001 STDMETHODIMP |
| 2994 BrowserAccessibilityWin::get_localInterface(void** local_interface) { | 3002 BrowserAccessibilityWin::get_localInterface(void** local_interface) { |
| 2995 return E_NOTIMPL; | 3003 return E_NOTIMPL; |
| 2996 } | 3004 } |
| 2997 | 3005 |
| 2998 STDMETHODIMP BrowserAccessibilityWin::get_language(BSTR* language) { | 3006 STDMETHODIMP BrowserAccessibilityWin::get_language(BSTR* language) { |
| 2999 return E_NOTIMPL; | 3007 if (!language) |
| 3008 return E_INVALIDARG; | |
| 3009 *language = nullptr; | |
| 3010 | |
| 3011 if (!instance_active()) | |
| 3012 return E_FAIL; | |
| 3013 | |
| 3014 base::string16 lang = GetInheritedString16Attribute(ui::AX_ATTR_LANGUAGE); | |
| 3015 if (lang.empty()) | |
| 3016 lang = L"en-US"; | |
| 3017 | |
| 3018 *language = SysAllocString(lang.c_str()); | |
| 3019 DCHECK(*language); | |
| 3020 return S_OK; | |
| 3000 } | 3021 } |
| 3001 | 3022 |
| 3002 // | 3023 // |
| 3003 // ISimpleDOMText methods. | 3024 // ISimpleDOMText methods. |
| 3004 // | 3025 // |
| 3005 | 3026 |
| 3006 STDMETHODIMP BrowserAccessibilityWin::get_domText(BSTR* dom_text) { | 3027 STDMETHODIMP BrowserAccessibilityWin::get_domText(BSTR* dom_text) { |
| 3007 if (!instance_active()) | 3028 if (!instance_active()) |
| 3008 return E_FAIL; | 3029 return E_FAIL; |
| 3009 | 3030 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3068 } | 3089 } |
| 3069 | 3090 |
| 3070 manager()->ScrollToMakeVisible(*this, GetLocalBoundsForRange( | 3091 manager()->ScrollToMakeVisible(*this, GetLocalBoundsForRange( |
| 3071 start_index, end_index - start_index)); | 3092 start_index, end_index - start_index)); |
| 3072 manager()->ToBrowserAccessibilityManagerWin()->TrackScrollingObject(this); | 3093 manager()->ToBrowserAccessibilityManagerWin()->TrackScrollingObject(this); |
| 3073 | 3094 |
| 3074 return S_OK; | 3095 return S_OK; |
| 3075 } | 3096 } |
| 3076 | 3097 |
| 3077 STDMETHODIMP BrowserAccessibilityWin::get_fontFamily(BSTR* font_family) { | 3098 STDMETHODIMP BrowserAccessibilityWin::get_fontFamily(BSTR* font_family) { |
| 3078 return E_NOTIMPL; | 3099 if (!font_family) |
| 3100 return E_INVALIDARG; | |
| 3101 *font_family = nullptr; | |
| 3102 | |
| 3103 if (!instance_active()) | |
| 3104 return E_FAIL; | |
| 3105 | |
| 3106 base::string16 family = | |
| 3107 GetInheritedString16Attribute(ui::AX_ATTR_FONT_FAMILY); | |
| 3108 if (family.empty()) | |
| 3109 return S_FALSE; | |
| 3110 | |
| 3111 *font_family = SysAllocString(family.c_str()); | |
| 3112 DCHECK(*font_family); | |
| 3113 return S_OK; | |
| 3079 } | 3114 } |
| 3080 | 3115 |
| 3081 // | 3116 // |
| 3082 // IServiceProvider methods. | 3117 // IServiceProvider methods. |
| 3083 // | 3118 // |
| 3084 | 3119 |
| 3085 STDMETHODIMP BrowserAccessibilityWin::QueryService(REFGUID guid_service, | 3120 STDMETHODIMP BrowserAccessibilityWin::QueryService(REFGUID guid_service, |
| 3086 REFIID riid, | 3121 REFIID riid, |
| 3087 void** object) { | 3122 void** object) { |
| 3088 if (!instance_active()) | 3123 if (!instance_active()) |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3333 table->GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS); | 3368 table->GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS); |
| 3334 for (size_t i = 0; i < unique_cell_ids.size(); ++i) { | 3369 for (size_t i = 0; i < unique_cell_ids.size(); ++i) { |
| 3335 if (unique_cell_ids[i] == GetId()) { | 3370 if (unique_cell_ids[i] == GetId()) { |
| 3336 win_attributes_->ia2_attributes.push_back( | 3371 win_attributes_->ia2_attributes.push_back( |
| 3337 base::string16(L"table-cell-index:") + base::IntToString16(i)); | 3372 base::string16(L"table-cell-index:") + base::IntToString16(i)); |
| 3338 } | 3373 } |
| 3339 } | 3374 } |
| 3340 } | 3375 } |
| 3341 } | 3376 } |
| 3342 | 3377 |
| 3343 // Expose invalid state for form controls and elements with aria-invalid. | |
| 3344 int invalid_state; | |
| 3345 if (GetIntAttribute(ui::AX_ATTR_INVALID_STATE, &invalid_state)) { | |
| 3346 // TODO(nektar): Handle the possibility of having multiple aria-invalid | |
| 3347 // attributes defined, e.g., "invalid:spelling,grammar". | |
| 3348 switch (invalid_state) { | |
| 3349 case ui::AX_INVALID_STATE_FALSE: | |
| 3350 win_attributes_->ia2_attributes.push_back(L"invalid:false"); | |
| 3351 break; | |
| 3352 case ui::AX_INVALID_STATE_TRUE: | |
| 3353 win_attributes_->ia2_attributes.push_back(L"invalid:true"); | |
| 3354 break; | |
| 3355 case ui::AX_INVALID_STATE_SPELLING: | |
| 3356 win_attributes_->ia2_attributes.push_back(L"invalid:spelling"); | |
| 3357 break; | |
| 3358 case ui::AX_INVALID_STATE_GRAMMAR: | |
| 3359 win_attributes_->ia2_attributes.push_back(L"invalid:grammar"); | |
| 3360 break; | |
| 3361 case ui::AX_INVALID_STATE_OTHER: | |
| 3362 { | |
| 3363 base::string16 aria_invalid_value; | |
| 3364 if (GetString16Attribute(ui::AX_ATTR_ARIA_INVALID_VALUE, | |
| 3365 &aria_invalid_value)) { | |
| 3366 SanitizeStringAttributeForIA2(aria_invalid_value, | |
| 3367 &aria_invalid_value); | |
| 3368 win_attributes_->ia2_attributes.push_back( | |
| 3369 L"invalid:" + aria_invalid_value); | |
| 3370 } else { | |
| 3371 // Set the attribute to L"true", since we cannot be more specific. | |
| 3372 win_attributes_->ia2_attributes.push_back(L"invalid:true"); | |
| 3373 } | |
| 3374 } | |
| 3375 break; | |
| 3376 default: | |
| 3377 NOTREACHED(); | |
| 3378 } | |
| 3379 } | |
| 3380 | |
| 3381 // Expose row or column header sort direction. | 3378 // Expose row or column header sort direction. |
| 3382 int32_t sort_direction; | 3379 int32_t sort_direction; |
| 3383 if ((ia_role() == ROLE_SYSTEM_COLUMNHEADER || | 3380 if ((ia_role() == ROLE_SYSTEM_COLUMNHEADER || |
| 3384 ia_role() == ROLE_SYSTEM_ROWHEADER) && | 3381 ia_role() == ROLE_SYSTEM_ROWHEADER) && |
| 3385 GetIntAttribute(ui::AX_ATTR_SORT_DIRECTION, &sort_direction)) { | 3382 GetIntAttribute(ui::AX_ATTR_SORT_DIRECTION, &sort_direction)) { |
| 3386 switch (sort_direction) { | 3383 switch (sort_direction) { |
| 3387 case ui::AX_SORT_DIRECTION_UNSORTED: | 3384 case ui::AX_SORT_DIRECTION_UNSORTED: |
| 3388 win_attributes_->ia2_attributes.push_back(L"sort:none"); | 3385 win_attributes_->ia2_attributes.push_back(L"sort:none"); |
| 3389 break; | 3386 break; |
| 3390 case ui::AX_SORT_DIRECTION_ASCENDING: | 3387 case ui::AX_SORT_DIRECTION_ASCENDING: |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3688 if (parent) { | 3685 if (parent) { |
| 3689 hyperlink_index = | 3686 hyperlink_index = |
| 3690 parent->ToBrowserAccessibilityWin()->GetHyperlinkIndexFromChild(*this); | 3687 parent->ToBrowserAccessibilityWin()->GetHyperlinkIndexFromChild(*this); |
| 3691 } | 3688 } |
| 3692 | 3689 |
| 3693 if (hyperlink_index >= 0) | 3690 if (hyperlink_index >= 0) |
| 3694 return true; | 3691 return true; |
| 3695 return false; | 3692 return false; |
| 3696 } | 3693 } |
| 3697 | 3694 |
| 3695 BrowserAccessibilityWin* | |
| 3696 BrowserAccessibilityWin::GetHyperlinkFromHypertextOffset(int offset) const { | |
| 3697 std::map<int32_t, int32_t>::iterator iterator = | |
| 3698 hyperlink_offset_to_index().find(offset); | |
| 3699 if (iterator == hyperlink_offset_to_index().end()) | |
| 3700 return nullptr; | |
| 3701 | |
| 3702 int32_t index = iterator->second; | |
| 3703 DCHECK_GE(index, 0); | |
| 3704 DCHECK_LT(index, static_cast<int32_t>(hyperlinks().size())); | |
| 3705 int32_t id = hyperlinks()[index]; | |
| 3706 BrowserAccessibilityWin* hyperlink = GetFromID(id); | |
| 3707 if (!hyperlink) | |
| 3708 return nullptr; | |
| 3709 return hyperlink; | |
| 3710 } | |
| 3711 | |
| 3698 int32_t BrowserAccessibilityWin::GetHyperlinkIndexFromChild( | 3712 int32_t BrowserAccessibilityWin::GetHyperlinkIndexFromChild( |
| 3699 const BrowserAccessibilityWin& child) const { | 3713 const BrowserAccessibilityWin& child) const { |
| 3700 if (hyperlinks().empty()) | 3714 if (hyperlinks().empty()) |
| 3701 return -1; | 3715 return -1; |
| 3702 | 3716 |
| 3703 auto iterator = std::find( | 3717 auto iterator = std::find( |
| 3704 hyperlinks().begin(), hyperlinks().end(), child.GetId()); | 3718 hyperlinks().begin(), hyperlinks().end(), child.GetId()); |
| 3705 if (iterator == hyperlinks().end()) | 3719 if (iterator == hyperlinks().end()) |
| 3706 return -1; | 3720 return -1; |
| 3707 | 3721 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3831 return 0; | 3845 return 0; |
| 3832 if (endpoint_index_in_common_parent > index_in_common_parent) | 3846 if (endpoint_index_in_common_parent > index_in_common_parent) |
| 3833 return GetText().size(); | 3847 return GetText().size(); |
| 3834 | 3848 |
| 3835 NOTREACHED(); | 3849 NOTREACHED(); |
| 3836 return -1; | 3850 return -1; |
| 3837 } | 3851 } |
| 3838 | 3852 |
| 3839 int BrowserAccessibilityWin::GetSelectionAnchor() const { | 3853 int BrowserAccessibilityWin::GetSelectionAnchor() const { |
| 3840 int32_t anchor_id = manager()->GetTreeData().sel_anchor_object_id; | 3854 int32_t anchor_id = manager()->GetTreeData().sel_anchor_object_id; |
| 3841 const auto anchor_object = | 3855 const BrowserAccessibilityWin* anchor_object = GetFromID(anchor_id); |
| 3842 manager()->GetFromID(anchor_id)->ToBrowserAccessibilityWin(); | |
| 3843 if (!anchor_object) | 3856 if (!anchor_object) |
| 3844 return -1; | 3857 return -1; |
| 3845 | 3858 |
| 3846 int anchor_offset = manager()->GetTreeData().sel_anchor_offset; | 3859 int anchor_offset = manager()->GetTreeData().sel_anchor_offset; |
| 3847 return GetHypertextOffsetFromEndpoint(*anchor_object, anchor_offset); | 3860 return GetHypertextOffsetFromEndpoint(*anchor_object, anchor_offset); |
| 3848 } | 3861 } |
| 3849 | 3862 |
| 3850 int BrowserAccessibilityWin::GetSelectionFocus() const { | 3863 int BrowserAccessibilityWin::GetSelectionFocus() const { |
| 3851 int32_t focus_id = manager()->GetTreeData().sel_focus_object_id; | 3864 int32_t focus_id = manager()->GetTreeData().sel_focus_object_id; |
| 3852 const auto focus_object = | 3865 const BrowserAccessibilityWin* focus_object = GetFromID(focus_id); |
| 3853 manager()->GetFromID(focus_id)->ToBrowserAccessibilityWin(); | |
| 3854 if (!focus_object) | 3866 if (!focus_object) |
| 3855 return -1; | 3867 return -1; |
| 3856 | 3868 |
| 3857 int focus_offset = manager()->GetTreeData().sel_focus_offset; | 3869 int focus_offset = manager()->GetTreeData().sel_focus_offset; |
| 3858 return GetHypertextOffsetFromEndpoint(*focus_object, focus_offset); | 3870 return GetHypertextOffsetFromEndpoint(*focus_object, focus_offset); |
| 3859 } | 3871 } |
| 3860 | 3872 |
| 3861 void BrowserAccessibilityWin::GetSelectionOffsets( | 3873 void BrowserAccessibilityWin::GetSelectionOffsets( |
| 3862 int* selection_start, int* selection_end) const { | 3874 int* selection_start, int* selection_end) const { |
| 3863 DCHECK(selection_start && selection_end); | 3875 DCHECK(selection_start && selection_end); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 3893 } | 3905 } |
| 3894 | 3906 |
| 3895 // The IA2 Spec says that if the largest of the two offsets falls on an | 3907 // The IA2 Spec says that if the largest of the two offsets falls on an |
| 3896 // embedded object character and if there is a selection in that embedded | 3908 // embedded object character and if there is a selection in that embedded |
| 3897 // object, it should be incremented by one so that it points after the | 3909 // object, it should be incremented by one so that it points after the |
| 3898 // embedded object character. | 3910 // embedded object character. |
| 3899 // This is a signal to AT software that the embedded object is also part of | 3911 // This is a signal to AT software that the embedded object is also part of |
| 3900 // the selection. | 3912 // the selection. |
| 3901 int* largest_offset = | 3913 int* largest_offset = |
| 3902 (*selection_start <= *selection_end) ? selection_end : selection_start; | 3914 (*selection_start <= *selection_end) ? selection_end : selection_start; |
| 3903 auto current_object = const_cast<BrowserAccessibilityWin*>(this); | 3915 BrowserAccessibilityWin* hyperlink = |
| 3904 LONG hyperlink_index; | 3916 GetHyperlinkFromHypertextOffset(*largest_offset); |
| 3905 HRESULT hr = | 3917 if (!hyperlink) |
| 3906 current_object->get_hyperlinkIndex(*largest_offset, &hyperlink_index); | |
| 3907 if (hr != S_OK) | |
| 3908 return; | 3918 return; |
| 3909 | 3919 |
| 3910 DCHECK_GE(hyperlink_index, 0); | |
| 3911 base::win::ScopedComPtr<IAccessibleHyperlink> hyperlink; | |
| 3912 hr = current_object->get_hyperlink(hyperlink_index, hyperlink.Receive()); | |
| 3913 DCHECK(SUCCEEDED(hr)); | |
| 3914 base::win::ScopedComPtr<IAccessibleText> hyperlink_text; | |
| 3915 hr = hyperlink.QueryInterface(hyperlink_text.Receive()); | |
| 3916 DCHECK(SUCCEEDED(hr)); | |
| 3917 LONG n_selections = 0; | 3920 LONG n_selections = 0; |
| 3918 hr = hyperlink_text->get_nSelections(&n_selections); | 3921 HRESULT hr = hyperlink->get_nSelections(&n_selections); |
| 3919 DCHECK(SUCCEEDED(hr)); | 3922 DCHECK(SUCCEEDED(hr)); |
| 3920 if (n_selections > 0) | 3923 if (n_selections > 0) |
| 3921 ++(*largest_offset); | 3924 ++(*largest_offset); |
| 3922 } | 3925 } |
| 3923 | 3926 |
| 3924 base::string16 BrowserAccessibilityWin::GetValueText() { | 3927 base::string16 BrowserAccessibilityWin::GetValueText() { |
| 3925 float fval; | 3928 float fval; |
| 3926 base::string16 value = this->value(); | 3929 base::string16 value = this->value(); |
| 3927 | 3930 |
| 3928 if (value.empty() && | 3931 if (value.empty() && |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3994 old_text.size() - common_suffix - 1, | 3997 old_text.size() - common_suffix - 1, |
| 3995 new_text.size() - common_suffix - 1)) { | 3998 new_text.size() - common_suffix - 1)) { |
| 3996 ++common_suffix; | 3999 ++common_suffix; |
| 3997 } | 4000 } |
| 3998 | 4001 |
| 3999 *start = common_prefix; | 4002 *start = common_prefix; |
| 4000 *old_len = old_text.size() - common_prefix - common_suffix; | 4003 *old_len = old_text.size() - common_prefix - common_suffix; |
| 4001 *new_len = new_text.size() - common_prefix - common_suffix; | 4004 *new_len = new_text.size() - common_prefix - common_suffix; |
| 4002 } | 4005 } |
| 4003 | 4006 |
| 4007 void BrowserAccessibilityWin::ComputeTextAttributes() { | |
| 4008 base::hash_map<int, std::vector<base::string16>> attributes_map; | |
| 4009 int start_offset = 0; | |
| 4010 for (size_t i = 0; i < PlatformChildCount(); ++i) { | |
|
dmazzoni
2016/03/07 23:38:11
Why does this loop over children, but not recursiv
| |
| 4011 const auto child = PlatformGetChild(i)->ToBrowserAccessibilityWin(); | |
| 4012 DCHECK(child); | |
| 4013 std::vector<base::string16> attributes; | |
| 4014 | |
| 4015 if (child->ia_role() == ui::AX_ROLE_LIST_MARKER) | |
|
dmazzoni
2016/03/07 23:38:11
The LHS is an IAccessible role but the RHS is a Ch
| |
| 4016 attributes.push_back(L"auto-generated:true"); | |
| 4017 else | |
| 4018 attributes.push_back(L"auto-generated:false"); | |
| 4019 | |
| 4020 int color; | |
| 4021 base::string16 color_value(L"transparent"); | |
| 4022 if (child->GetIntAttribute(ui::AX_ATTR_BACKGROUND_COLOR, &color)) { | |
| 4023 unsigned int red, green, blue, alpha; | |
| 4024 RGBAToColorValues(static_cast<unsigned int>(color), &red, &green, &blue, | |
| 4025 &alpha); | |
| 4026 if (alpha) { | |
| 4027 color_value = L"rgb(" + base::UintToString16(red) + L',' + | |
| 4028 base::UintToString16(blue) + L',' + | |
| 4029 base::UintToString16(green) + L')'; | |
| 4030 } | |
| 4031 } | |
| 4032 attributes.push_back(L"background-color:" + color_value); | |
| 4033 | |
| 4034 if (child->GetIntAttribute(ui::AX_ATTR_COLOR, &color)) { | |
| 4035 unsigned int red, green, blue, alpha; | |
| 4036 RGBAToColorValues(static_cast<unsigned int>(color), &red, &green, &blue, | |
| 4037 &alpha); | |
| 4038 color_value = L"rgb(" + base::UintToString16(red) + L',' + | |
| 4039 base::UintToString16(blue) + L',' + | |
| 4040 base::UintToString16(green) + L')'; | |
| 4041 } else { | |
| 4042 color_value = L"rgb(0,0,0)"; | |
| 4043 } | |
| 4044 attributes.push_back(L"color:" + color_value); | |
| 4045 | |
| 4046 base::string16 font_family = | |
| 4047 child->GetInheritedString16Attribute(ui::AX_ATTR_FONT_FAMILY); | |
| 4048 // Attribute has no default value. | |
| 4049 if (!font_family.empty()) { | |
| 4050 SanitizeStringAttributeForIA2(font_family, &font_family); | |
| 4051 attributes.push_back(L"font-family:" + font_family); | |
| 4052 } | |
| 4053 | |
| 4054 float font_size; | |
| 4055 // Attribute has no default value. | |
| 4056 if (child->GetFloatAttribute(ui::AX_ATTR_FONT_SIZE, &font_size)) { | |
| 4057 // The IA2 Spec requires the value to be in pt, not in pixels. | |
| 4058 // There are 72 points per inch. | |
| 4059 // We assume that there are 96 pixels per inch on a standard display. | |
| 4060 // TODO(nektar): Figure out the current value of pixels per inch. | |
| 4061 float points = font_size * 72.0 / 96.0; | |
| 4062 attributes.push_back(L"font-size:" + | |
| 4063 base::UTF8ToUTF16(base::DoubleToString(points))); | |
| 4064 } | |
| 4065 | |
| 4066 auto text_style = | |
| 4067 static_cast<ui::AXTextStyle>(GetIntAttribute(ui::AX_ATTR_TEXT_STYLE)); | |
| 4068 if (text_style == ui::AX_TEXT_STYLE_NONE) { | |
| 4069 attributes.push_back(L"font-style:normal"); | |
| 4070 attributes.push_back(L"font-weight:normal"); | |
| 4071 } else { | |
| 4072 if (text_style & ui::AX_TEXT_STYLE_BOLD) | |
| 4073 attributes.push_back(L"font-weight:bold"); | |
| 4074 | |
| 4075 base::string16 font_style; | |
| 4076 if (text_style & ui::AX_TEXT_STYLE_ITALIC) | |
| 4077 font_style += L",italic"; | |
| 4078 if (text_style & ui::AX_TEXT_STYLE_UNDERLINE) | |
| 4079 font_style += L",underline"; | |
| 4080 if (text_style & ui::AX_TEXT_STYLE_LINE_THROUGH) | |
| 4081 font_style += L",line-through"; | |
| 4082 // TODO(nektar): Support more font style attributes in Blink. | |
| 4083 | |
| 4084 if (font_style.empty()) { | |
| 4085 font_style = L"normal"; | |
| 4086 } else { | |
| 4087 // Remove the leading comma. | |
| 4088 font_style.erase(0, 1); | |
| 4089 } | |
| 4090 attributes.push_back(L"font-style:" + font_style); | |
| 4091 } | |
| 4092 | |
| 4093 auto invalid_state = static_cast<ui::AXInvalidState>( | |
| 4094 child->GetIntAttribute(ui::AX_ATTR_INVALID_STATE)); | |
| 4095 switch (invalid_state) { | |
| 4096 case ui::AX_INVALID_STATE_NONE: | |
| 4097 case ui::AX_INVALID_STATE_FALSE: | |
| 4098 attributes.push_back(L"invalid:false"); | |
| 4099 break; | |
| 4100 case ui::AX_INVALID_STATE_TRUE: | |
| 4101 attributes.push_back(L"invalid:true"); | |
| 4102 break; | |
| 4103 case ui::AX_INVALID_STATE_SPELLING: | |
| 4104 case ui::AX_INVALID_STATE_GRAMMAR: { | |
| 4105 base::string16 spelling_grammar_value; | |
| 4106 if (invalid_state & ui::AX_INVALID_STATE_SPELLING) | |
| 4107 spelling_grammar_value = L"spelling"; | |
| 4108 else if (invalid_state & ui::AX_INVALID_STATE_GRAMMAR) | |
| 4109 spelling_grammar_value = L"grammar"; | |
| 4110 else | |
| 4111 spelling_grammar_value = L"spelling,grammar"; | |
| 4112 attributes.push_back(L"invalid:" + spelling_grammar_value); | |
| 4113 break; | |
| 4114 } | |
| 4115 case ui::AX_INVALID_STATE_OTHER: { | |
| 4116 base::string16 aria_invalid_value; | |
| 4117 if (GetString16Attribute(ui::AX_ATTR_ARIA_INVALID_VALUE, | |
| 4118 &aria_invalid_value)) { | |
| 4119 SanitizeStringAttributeForIA2(aria_invalid_value, | |
| 4120 &aria_invalid_value); | |
| 4121 attributes.push_back(L"invalid:" + aria_invalid_value); | |
| 4122 } else { | |
| 4123 // Set the attribute to L"true", since we cannot be more specific. | |
| 4124 attributes.push_back(L"invalid:true"); | |
| 4125 } | |
| 4126 break; | |
| 4127 } | |
| 4128 default: | |
| 4129 NOTREACHED(); | |
| 4130 } | |
| 4131 | |
| 4132 base::string16 language = | |
| 4133 child->GetInheritedString16Attribute(ui::AX_ATTR_LANGUAGE); | |
| 4134 // Default value should be L"en-US". | |
| 4135 if (language.empty()) { | |
| 4136 attributes.push_back(L"language:en-US"); | |
| 4137 } else { | |
| 4138 SanitizeStringAttributeForIA2(language, &language); | |
| 4139 attributes.push_back(L"language:" + language); | |
| 4140 } | |
| 4141 | |
| 4142 // TODO(nektar): Add Blink support for the following attributes. | |
| 4143 // Currently set to their default values as dictated by the IA2 Spec. | |
| 4144 attributes.push_back(L"text-line-through-mode:continuous"); | |
| 4145 attributes.push_back(L"text-line-through-style:none"); | |
| 4146 // Default value must be the empty string. | |
| 4147 attributes.push_back(L"text-line-through-text:"); | |
| 4148 attributes.push_back(L"text-line-through-type:none"); | |
| 4149 attributes.push_back(L"text-line-through-width:auto"); | |
| 4150 attributes.push_back(L"text-outline:false"); | |
| 4151 attributes.push_back(L"text-position:baseline"); | |
| 4152 attributes.push_back(L"text-shadow:none"); | |
| 4153 attributes.push_back(L"text-underline-mode:continuous"); | |
| 4154 attributes.push_back(L"text-underline-style:none"); | |
| 4155 attributes.push_back(L"text-underline-type:none"); | |
| 4156 attributes.push_back(L"text-underline-width:auto"); | |
| 4157 | |
| 4158 auto text_direction = static_cast<ui::AXTextDirection>( | |
| 4159 child->GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION)); | |
| 4160 switch (text_direction) { | |
| 4161 case ui::AX_TEXT_DIRECTION_NONE: | |
| 4162 case ui::AX_TEXT_DIRECTION_LTR: | |
| 4163 attributes.push_back(L"writing-mode:lr"); | |
| 4164 break; | |
| 4165 case ui::AX_TEXT_DIRECTION_RTL: | |
| 4166 attributes.push_back(L"writing-mode:rl"); | |
| 4167 break; | |
| 4168 case ui::AX_TEXT_DIRECTION_TTB: | |
| 4169 attributes.push_back(L"writing-mode:tb"); | |
| 4170 break; | |
| 4171 case ui::AX_TEXT_DIRECTION_BTT: | |
| 4172 // Not listed in the IA2 Spec. | |
| 4173 attributes.push_back(L"writing-mode:bt"); | |
| 4174 break; | |
| 4175 default: | |
| 4176 NOTREACHED(); | |
| 4177 } | |
| 4178 | |
| 4179 if (attributes_map.empty()) { | |
| 4180 attributes_map[start_offset] = attributes; | |
| 4181 } else { | |
| 4182 // Only add the attributes for this child if we are at the start of a new | |
| 4183 // style span. | |
| 4184 std::vector<base::string16> previous_attributes = | |
| 4185 attributes_map.rbegin()->second; | |
| 4186 if (!std::equal(attributes.begin(), attributes.end(), | |
| 4187 previous_attributes.begin())) { | |
| 4188 attributes_map[start_offset] = attributes; | |
| 4189 } | |
| 4190 } | |
| 4191 | |
| 4192 if (child->IsTextOnlyObject()) | |
| 4193 start_offset += child->GetText().length(); | |
| 4194 else | |
| 4195 start_offset += 1; | |
| 4196 } | |
| 4197 | |
| 4198 win_attributes_->offset_to_text_attributes = attributes_map; | |
| 4199 } | |
| 4200 | |
| 4004 void BrowserAccessibilityWin::HandleSpecialTextOffset( | 4201 void BrowserAccessibilityWin::HandleSpecialTextOffset( |
| 4005 const base::string16& text, | 4202 const base::string16& text, |
| 4006 LONG* offset) { | 4203 LONG* offset) { |
| 4007 if (*offset == IA2_TEXT_OFFSET_LENGTH) | 4204 if (*offset == IA2_TEXT_OFFSET_LENGTH) |
| 4008 *offset = static_cast<LONG>(text.size()); | 4205 *offset = static_cast<LONG>(text.size()); |
| 4009 else if (*offset == IA2_TEXT_OFFSET_CARET) | 4206 else if (*offset == IA2_TEXT_OFFSET_CARET) |
| 4010 get_caretOffset(offset); | 4207 get_caretOffset(offset); |
| 4011 } | 4208 } |
| 4012 | 4209 |
| 4013 ui::TextBoundaryType BrowserAccessibilityWin::IA2TextBoundaryToTextBoundary( | 4210 ui::TextBoundaryType BrowserAccessibilityWin::IA2TextBoundaryToTextBoundary( |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 4040 if (ia2_boundary == IA2_TEXT_BOUNDARY_WORD) | 4237 if (ia2_boundary == IA2_TEXT_BOUNDARY_WORD) |
| 4041 return GetWordStartBoundary(static_cast<int>(start_offset), direction); | 4238 return GetWordStartBoundary(static_cast<int>(start_offset), direction); |
| 4042 | 4239 |
| 4043 ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary); | 4240 ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary); |
| 4044 const std::vector<int32_t>& line_breaks = | 4241 const std::vector<int32_t>& line_breaks = |
| 4045 GetIntListAttribute(ui::AX_ATTR_LINE_BREAKS); | 4242 GetIntListAttribute(ui::AX_ATTR_LINE_BREAKS); |
| 4046 return ui::FindAccessibleTextBoundary( | 4243 return ui::FindAccessibleTextBoundary( |
| 4047 text, line_breaks, boundary, start_offset, direction); | 4244 text, line_breaks, boundary, start_offset, direction); |
| 4048 } | 4245 } |
| 4049 | 4246 |
| 4050 BrowserAccessibilityWin* BrowserAccessibilityWin::GetFromID(int32_t id) { | 4247 LONG BrowserAccessibilityWin::FindStartOfStyle( |
| 4051 return manager()->GetFromID(id)->ToBrowserAccessibilityWin(); | 4248 LONG start_offset, |
| 4249 ui::TextBoundaryDirection direction) const { | |
| 4250 LONG text_length = static_cast<LONG>(GetText().length()); | |
| 4251 DCHECK_GE(start_offset, 0); | |
| 4252 DCHECK_LE(start_offset, text_length); | |
| 4253 | |
| 4254 switch (direction) { | |
| 4255 case ui::BACKWARDS_DIRECTION: { | |
| 4256 if (offset_to_text_attributes().empty()) | |
| 4257 return 0; | |
| 4258 | |
| 4259 auto iterator = offset_to_text_attributes().upper_bound(start_offset); | |
| 4260 --iterator; | |
| 4261 return static_cast<LONG>(iterator->first); | |
| 4262 } | |
| 4263 case ui::FORWARDS_DIRECTION: { | |
| 4264 const auto iterator = | |
| 4265 offset_to_text_attributes().upper_bound(start_offset); | |
| 4266 if (iterator == offset_to_text_attributes().end()) | |
| 4267 return text_length; | |
| 4268 return static_cast<LONG>(iterator->first); | |
| 4269 } | |
| 4270 default: | |
| 4271 NOTREACHED(); | |
| 4272 } | |
| 4273 | |
| 4274 return start_offset; | |
| 4275 } | |
| 4276 | |
| 4277 BrowserAccessibilityWin* BrowserAccessibilityWin::GetFromID(int32_t id) const { | |
| 4278 BrowserAccessibility* object = manager()->GetFromID(id); | |
| 4279 if (!object) | |
| 4280 return nullptr; | |
| 4281 return object->ToBrowserAccessibilityWin(); | |
| 4052 } | 4282 } |
| 4053 | 4283 |
| 4054 bool BrowserAccessibilityWin::IsListBoxOptionOrMenuListOption() { | 4284 bool BrowserAccessibilityWin::IsListBoxOptionOrMenuListOption() { |
| 4055 if (!GetParent()) | 4285 if (!GetParent()) |
| 4056 return false; | 4286 return false; |
| 4057 | 4287 |
| 4058 int32_t role = GetRole(); | 4288 int32_t role = GetRole(); |
| 4059 int32_t parent_role = GetParent()->GetRole(); | 4289 int32_t parent_role = GetParent()->GetRole(); |
| 4060 | 4290 |
| 4061 if (role == ui::AX_ROLE_LIST_BOX_OPTION && | 4291 if (role == ui::AX_ROLE_LIST_BOX_OPTION && |
| 4062 parent_role == ui::AX_ROLE_LIST_BOX) { | 4292 parent_role == ui::AX_ROLE_LIST_BOX) { |
| 4063 return true; | 4293 return true; |
| 4064 } | 4294 } |
| 4065 | 4295 |
| 4066 if (role == ui::AX_ROLE_MENU_LIST_OPTION && | 4296 if (role == ui::AX_ROLE_MENU_LIST_OPTION && |
| 4067 parent_role == ui::AX_ROLE_MENU_LIST_POPUP) { | 4297 parent_role == ui::AX_ROLE_MENU_LIST_POPUP) { |
| 4068 return true; | 4298 return true; |
| 4069 } | 4299 } |
| 4070 | 4300 |
| 4071 return false; | 4301 return false; |
| 4072 } | 4302 } |
| 4073 | 4303 |
| 4304 void BrowserAccessibilityWin::AddRelations( | |
| 4305 ui::AXIntListAttribute src_attr, | |
| 4306 const base::string16& iaccessiblerelation_type) { | |
| 4307 if (!HasIntListAttribute(src_attr)) | |
| 4308 return; | |
| 4309 | |
| 4310 const std::vector<int32_t>& ids = GetIntListAttribute(src_attr); | |
| 4311 for (size_t i = 0; i < ids.size(); ++i) { | |
| 4312 CComObject<BrowserAccessibilityRelation>* relation; | |
| 4313 HRESULT hr = | |
| 4314 CComObject<BrowserAccessibilityRelation>::CreateInstance(&relation); | |
| 4315 DCHECK(SUCCEEDED(hr)); | |
| 4316 relation->AddRef(); | |
| 4317 relation->Initialize(this, iaccessiblerelation_type); | |
| 4318 relation->AddTarget(ids[i]); | |
| 4319 relations_.push_back(relation); | |
| 4320 } | |
| 4321 } | |
| 4322 | |
| 4074 void BrowserAccessibilityWin::UpdateRequiredAttributes() { | 4323 void BrowserAccessibilityWin::UpdateRequiredAttributes() { |
| 4075 // Expose slider value. | 4324 // Expose slider value. |
| 4076 if (ia_role() == ROLE_SYSTEM_PROGRESSBAR || | 4325 if (ia_role() == ROLE_SYSTEM_PROGRESSBAR || |
| 4077 ia_role() == ROLE_SYSTEM_SCROLLBAR || | 4326 ia_role() == ROLE_SYSTEM_SCROLLBAR || |
| 4078 ia_role() == ROLE_SYSTEM_SLIDER) { | 4327 ia_role() == ROLE_SYSTEM_SLIDER) { |
| 4079 base::string16 value_text = GetValueText(); | 4328 base::string16 value_text = GetValueText(); |
| 4080 SanitizeStringAttributeForIA2(value_text, &value_text); | 4329 SanitizeStringAttributeForIA2(value_text, &value_text); |
| 4081 win_attributes_->ia2_attributes.push_back(L"valuetext:" + value_text); | 4330 win_attributes_->ia2_attributes.push_back(L"valuetext:" + value_text); |
| 4082 } | 4331 } |
| 4083 | 4332 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4127 // Expose input-text type attribute. | 4376 // Expose input-text type attribute. |
| 4128 base::string16 type; | 4377 base::string16 type; |
| 4129 base::string16 html_tag = GetString16Attribute(ui::AX_ATTR_HTML_TAG); | 4378 base::string16 html_tag = GetString16Attribute(ui::AX_ATTR_HTML_TAG); |
| 4130 if (IsSimpleTextControl() && html_tag == L"input" && | 4379 if (IsSimpleTextControl() && html_tag == L"input" && |
| 4131 GetHtmlAttribute("type", &type)) { | 4380 GetHtmlAttribute("type", &type)) { |
| 4132 SanitizeStringAttributeForIA2(type, &type); | 4381 SanitizeStringAttributeForIA2(type, &type); |
| 4133 win_attributes_->ia2_attributes.push_back(L"text-input-type:" + type); | 4382 win_attributes_->ia2_attributes.push_back(L"text-input-type:" + type); |
| 4134 } | 4383 } |
| 4135 } | 4384 } |
| 4136 | 4385 |
| 4137 void BrowserAccessibilityWin::AddRelations( | |
| 4138 ui::AXIntListAttribute src_attr, | |
| 4139 const base::string16& iaccessiblerelation_type) { | |
| 4140 if (!HasIntListAttribute(src_attr)) | |
| 4141 return; | |
| 4142 | |
| 4143 const std::vector<int32_t>& ids = GetIntListAttribute(src_attr); | |
| 4144 for (size_t i = 0; i < ids.size(); ++i) { | |
| 4145 CComObject<BrowserAccessibilityRelation>* relation; | |
| 4146 HRESULT hr = CComObject<BrowserAccessibilityRelation>::CreateInstance( | |
| 4147 &relation); | |
| 4148 DCHECK(SUCCEEDED(hr)); | |
| 4149 relation->AddRef(); | |
| 4150 relation->Initialize(this, iaccessiblerelation_type); | |
| 4151 relation->AddTarget(ids[i]); | |
| 4152 relations_.push_back(relation); | |
| 4153 } | |
| 4154 } | |
| 4155 | |
| 4156 void BrowserAccessibilityWin::InitRoleAndState() { | 4386 void BrowserAccessibilityWin::InitRoleAndState() { |
| 4157 int32_t ia_role = 0; | 4387 int32_t ia_role = 0; |
| 4158 int32_t ia_state = 0; | 4388 int32_t ia_state = 0; |
| 4159 base::string16 role_name; | 4389 base::string16 role_name; |
| 4160 int32_t ia2_role = 0; | 4390 int32_t ia2_role = 0; |
| 4161 int32_t ia2_state = IA2_STATE_OPAQUE; | 4391 int32_t ia2_state = IA2_STATE_OPAQUE; |
| 4162 | 4392 |
| 4163 if (HasState(ui::AX_STATE_BUSY)) | 4393 if (HasState(ui::AX_STATE_BUSY)) |
| 4164 ia_state |= STATE_SYSTEM_BUSY; | 4394 ia_state |= STATE_SYSTEM_BUSY; |
| 4165 if (HasState(ui::AX_STATE_CHECKED)) | 4395 if (HasState(ui::AX_STATE_CHECKED)) |
| (...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4697 ia2_role = ia_role; | 4927 ia2_role = ia_role; |
| 4698 | 4928 |
| 4699 win_attributes_->ia_role = ia_role; | 4929 win_attributes_->ia_role = ia_role; |
| 4700 win_attributes_->ia_state = ia_state; | 4930 win_attributes_->ia_state = ia_state; |
| 4701 win_attributes_->role_name = role_name; | 4931 win_attributes_->role_name = role_name; |
| 4702 win_attributes_->ia2_role = ia2_role; | 4932 win_attributes_->ia2_role = ia2_role; |
| 4703 win_attributes_->ia2_state = ia2_state; | 4933 win_attributes_->ia2_state = ia2_state; |
| 4704 } | 4934 } |
| 4705 | 4935 |
| 4706 } // namespace content | 4936 } // namespace content |
| OLD | NEW |