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 |