Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(435)

Side by Side Diff: content/browser/accessibility/browser_accessibility_win.cc

Issue 1768753003: Implemented the reporting of text style and language information on Windows. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Updated to using HashTable from base and GetInheritedStringAttribute instead of specialized methods… Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698