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

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: Fixed test expectations. 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>
11 11
12 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_split.h" 13 #include "base/strings/string_split.h"
14 #include "base/strings/string_util.h" 14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
16 #include "base/win/enum_variant.h" 16 #include "base/win/enum_variant.h"
17 #include "base/win/scoped_comptr.h" 17 #include "base/win/scoped_comptr.h"
18 #include "base/win/windows_version.h" 18 #include "base/win/windows_version.h"
19 #include "content/browser/accessibility/browser_accessibility_manager_win.h" 19 #include "content/browser/accessibility/browser_accessibility_manager_win.h"
20 #include "content/browser/accessibility/browser_accessibility_state_impl.h" 20 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
21 #include "content/common/accessibility_messages.h" 21 #include "content/common/accessibility_messages.h"
22 #include "content/public/common/content_client.h" 22 #include "content/public/common/content_client.h"
23 #include "third_party/skia/include/core/SkColor.h"
23 #include "ui/accessibility/ax_text_utils.h" 24 #include "ui/accessibility/ax_text_utils.h"
24 #include "ui/base/win/accessibility_ids_win.h" 25 #include "ui/base/win/accessibility_ids_win.h"
25 #include "ui/base/win/accessibility_misc_utils.h" 26 #include "ui/base/win/accessibility_misc_utils.h"
26 #include "ui/base/win/atl_module.h" 27 #include "ui/base/win/atl_module.h"
27 28
28 namespace content { 29 namespace content {
29 30
30 // These nonstandard GUIDs are taken directly from the Mozilla sources 31 // These nonstandard GUIDs are taken directly from the Mozilla sources
31 // (accessible/src/msaa/nsAccessNodeWrap.cpp); some documentation is here: 32 // (accessible/src/msaa/nsAccessNodeWrap.cpp); some documentation is here:
32 // http://developer.mozilla.org/en/Accessibility/AT-APIs/ImplementationFeatures/ MSAA 33 // http://developer.mozilla.org/en/Accessibility/AT-APIs/ImplementationFeatures/ MSAA
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 109
109 STDMETHODIMP BrowserAccessibilityRelation::get_nTargets(long* n_targets) { 110 STDMETHODIMP BrowserAccessibilityRelation::get_nTargets(long* n_targets) {
110 if (!n_targets) 111 if (!n_targets)
111 return E_INVALIDARG; 112 return E_INVALIDARG;
112 113
113 if (!owner_->instance_active()) 114 if (!owner_->instance_active())
114 return E_FAIL; 115 return E_FAIL;
115 116
116 *n_targets = static_cast<long>(target_ids_.size()); 117 *n_targets = static_cast<long>(target_ids_.size());
117 118
118 BrowserAccessibilityManager* manager = owner_->manager();
119 for (long i = *n_targets - 1; i >= 0; --i) { 119 for (long i = *n_targets - 1; i >= 0; --i) {
120 BrowserAccessibility* result = manager->GetFromID(target_ids_[i]); 120 BrowserAccessibilityWin* result = owner_->GetFromID(target_ids_[i]);
121 if (!result || !result->instance_active()) { 121 if (!result || !result->instance_active()) {
122 *n_targets = 0; 122 *n_targets = 0;
123 break; 123 break;
124 } 124 }
125 } 125 }
126 return S_OK; 126 return S_OK;
127 } 127 }
128 128
129 STDMETHODIMP BrowserAccessibilityRelation::get_target(long target_index, 129 STDMETHODIMP BrowserAccessibilityRelation::get_target(long target_index,
130 IUnknown** target) { 130 IUnknown** target) {
131 if (!target) 131 if (!target)
132 return E_INVALIDARG; 132 return E_INVALIDARG;
133 133
134 if (!owner_->instance_active()) 134 if (!owner_->instance_active())
135 return E_FAIL; 135 return E_FAIL;
136 136
137 if (target_index < 0 || 137 if (target_index < 0 ||
138 target_index >= static_cast<long>(target_ids_.size())) { 138 target_index >= static_cast<long>(target_ids_.size())) {
139 return E_INVALIDARG; 139 return E_INVALIDARG;
140 } 140 }
141 141
142 BrowserAccessibilityManager* manager = owner_->manager(); 142 BrowserAccessibility* result = owner_->GetFromID(target_ids_[target_index]);
143 BrowserAccessibility* result =
144 manager->GetFromID(target_ids_[target_index]);
145 if (!result || !result->instance_active()) 143 if (!result || !result->instance_active())
146 return E_FAIL; 144 return E_FAIL;
147 145
148 *target = static_cast<IAccessible*>( 146 *target = static_cast<IAccessible*>(
149 ToBrowserAccessibilityWin(result)->NewReference()); 147 ToBrowserAccessibilityWin(result)->NewReference());
150 return S_OK; 148 return S_OK;
151 } 149 }
152 150
153 STDMETHODIMP BrowserAccessibilityRelation::get_targets(long max_targets, 151 STDMETHODIMP BrowserAccessibilityRelation::get_targets(long max_targets,
154 IUnknown** targets, 152 IUnknown** targets,
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 target->ia_role() == ROLE_SYSTEM_SCROLLBAR || 567 target->ia_role() == ROLE_SYSTEM_SCROLLBAR ||
570 target->ia_role() == ROLE_SYSTEM_SLIDER) { 568 target->ia_role() == ROLE_SYSTEM_SLIDER) {
571 base::string16 value_text = target->GetValueText(); 569 base::string16 value_text = target->GetValueText();
572 *value = SysAllocString(value_text.c_str()); 570 *value = SysAllocString(value_text.c_str());
573 DCHECK(*value); 571 DCHECK(*value);
574 return S_OK; 572 return S_OK;
575 } 573 }
576 574
577 // Expose color well value. 575 // Expose color well value.
578 if (target->ia2_role() == IA2_ROLE_COLOR_CHOOSER) { 576 if (target->ia2_role() == IA2_ROLE_COLOR_CHOOSER) {
579 int color = target->GetIntAttribute(ui::AX_ATTR_COLOR_VALUE); 577 unsigned int color = static_cast<unsigned int>(
580 int red = (color >> 16) & 0xFF; 578 target->GetIntAttribute(ui::AX_ATTR_COLOR_VALUE));
581 int green = (color >> 8) & 0xFF; 579 unsigned int red = SkColorGetR(color);
582 int blue = color & 0xFF; 580 unsigned int green = SkColorGetG(color);
581 unsigned int blue = SkColorGetB(color);
583 base::string16 value_text; 582 base::string16 value_text;
584 value_text = base::IntToString16((red * 100) / 255) + L"% red " + 583 value_text = base::UintToString16(red * 100 / 255) + L"% red " +
585 base::IntToString16((green * 100) / 255) + L"% green " + 584 base::UintToString16(green * 100 / 255) + L"% green " +
586 base::IntToString16((blue * 100) / 255) + L"% blue"; 585 base::UintToString16(blue * 100 / 255) + L"% blue";
587 *value = SysAllocString(value_text.c_str()); 586 *value = SysAllocString(value_text.c_str());
588 DCHECK(*value); 587 DCHECK(*value);
589 return S_OK; 588 return S_OK;
590 } 589 }
591 590
592 *value = SysAllocString(target->value().c_str()); 591 *value = SysAllocString(target->value().c_str());
593 DCHECK(*value); 592 DCHECK(*value);
594 return S_OK; 593 return S_OK;
595 } 594 }
596 595
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
680 679
681 if (!role) 680 if (!role)
682 return E_INVALIDARG; 681 return E_INVALIDARG;
683 682
684 *role = ia2_role(); 683 *role = ia2_role();
685 684
686 return S_OK; 685 return S_OK;
687 } 686 }
688 687
689 STDMETHODIMP BrowserAccessibilityWin::get_attributes(BSTR* attributes) { 688 STDMETHODIMP BrowserAccessibilityWin::get_attributes(BSTR* attributes) {
689 if (!attributes)
690 return E_INVALIDARG;
691 *attributes = nullptr;
692
690 if (!instance_active()) 693 if (!instance_active())
691 return E_FAIL; 694 return E_FAIL;
692 695
693 if (!attributes)
694 return E_INVALIDARG;
695
696 // The iaccessible2 attributes are a set of key-value pairs
697 // separated by semicolons, with a colon between the key and the value.
698 base::string16 str; 696 base::string16 str;
699 const std::vector<base::string16>& attributes_list = ia2_attributes(); 697 for (const base::string16& attribute : ia2_attributes())
700 for (unsigned int i = 0; i < attributes_list.size(); ++i) { 698 str += attribute + L';';
701 str += attributes_list[i] + L';';
702 }
703 699
704 if (str.empty()) 700 if (str.empty())
705 return S_FALSE; 701 return S_FALSE;
706 702
707 *attributes = SysAllocString(str.c_str()); 703 *attributes = SysAllocString(str.c_str());
708 DCHECK(*attributes); 704 DCHECK(*attributes);
709 return S_OK; 705 return S_OK;
710 } 706 }
711 707
712 STDMETHODIMP BrowserAccessibilityWin::get_states(AccessibleStates* states) { 708 STDMETHODIMP BrowserAccessibilityWin::get_states(AccessibleStates* states) {
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 manager()->ScrollToMakeVisible( 836 manager()->ScrollToMakeVisible(
841 *this, gfx::Rect(r.right(), r.y(), 0, r.height())); 837 *this, gfx::Rect(r.right(), r.y(), 0, r.height()));
842 break; 838 break;
843 case IA2_SCROLL_TYPE_ANYWHERE: 839 case IA2_SCROLL_TYPE_ANYWHERE:
844 default: 840 default:
845 manager()->ScrollToMakeVisible(*this, r); 841 manager()->ScrollToMakeVisible(*this, r);
846 break; 842 break;
847 } 843 }
848 844
849 manager()->ToBrowserAccessibilityManagerWin()->TrackScrollingObject(this); 845 manager()->ToBrowserAccessibilityManagerWin()->TrackScrollingObject(this);
850
851 return S_OK; 846 return S_OK;
852 } 847 }
853 848
854 STDMETHODIMP BrowserAccessibilityWin::scrollToPoint( 849 STDMETHODIMP BrowserAccessibilityWin::scrollToPoint(
855 IA2CoordinateType coordinate_type, 850 IA2CoordinateType coordinate_type,
856 LONG x, 851 LONG x,
857 LONG y) { 852 LONG y) {
858 if (!instance_active()) 853 if (!instance_active())
859 return E_FAIL; 854 return E_FAIL;
860 855
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
1174 return S_FALSE; 1169 return S_FALSE;
1175 } 1170 }
1176 1171
1177 if (column < 0 || column >= columns) 1172 if (column < 0 || column >= columns)
1178 return E_INVALIDARG; 1173 return E_INVALIDARG;
1179 1174
1180 const std::vector<int32_t>& cell_ids = 1175 const std::vector<int32_t>& cell_ids =
1181 GetIntListAttribute(ui::AX_ATTR_CELL_IDS); 1176 GetIntListAttribute(ui::AX_ATTR_CELL_IDS);
1182 for (int i = 0; i < rows; ++i) { 1177 for (int i = 0; i < rows; ++i) {
1183 int cell_id = cell_ids[i * columns + column]; 1178 int cell_id = cell_ids[i * columns + column];
1184 BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>( 1179 BrowserAccessibilityWin* cell = GetFromID(cell_id);
1185 manager()->GetFromID(cell_id));
1186 if (cell && cell->GetRole() == ui::AX_ROLE_COLUMN_HEADER) { 1180 if (cell && cell->GetRole() == ui::AX_ROLE_COLUMN_HEADER) {
1187 base::string16 cell_name = cell->GetString16Attribute( 1181 base::string16 cell_name = cell->GetString16Attribute(
1188 ui::AX_ATTR_NAME); 1182 ui::AX_ATTR_NAME);
1189 if (cell_name.size() > 0) { 1183 if (cell_name.size() > 0) {
1190 *description = SysAllocString(cell_name.c_str()); 1184 *description = SysAllocString(cell_name.c_str());
1191 return S_OK; 1185 return S_OK;
1192 } 1186 }
1193 1187
1194 if (cell->description().size() > 0) { 1188 if (cell->description().size() > 0) {
1195 *description = SysAllocString(cell->description().c_str()); 1189 *description = SysAllocString(cell->description().c_str());
(...skipping 24 matching lines...) Expand all
1220 rows <= 0) { 1214 rows <= 0) {
1221 return S_FALSE; 1215 return S_FALSE;
1222 } 1216 }
1223 1217
1224 if (row < 0 || row >= rows || column < 0 || column >= columns) 1218 if (row < 0 || row >= rows || column < 0 || column >= columns)
1225 return E_INVALIDARG; 1219 return E_INVALIDARG;
1226 1220
1227 const std::vector<int32_t>& cell_ids = 1221 const std::vector<int32_t>& cell_ids =
1228 GetIntListAttribute(ui::AX_ATTR_CELL_IDS); 1222 GetIntListAttribute(ui::AX_ATTR_CELL_IDS);
1229 int cell_id = cell_ids[row * columns + column]; 1223 int cell_id = cell_ids[row * columns + column];
1230 BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>( 1224 BrowserAccessibilityWin* cell = GetFromID(cell_id);
1231 manager()->GetFromID(cell_id));
1232 int colspan; 1225 int colspan;
1233 if (cell && 1226 if (cell &&
1234 cell->GetIntAttribute( 1227 cell->GetIntAttribute(
1235 ui::AX_ATTR_TABLE_CELL_COLUMN_SPAN, &colspan) && 1228 ui::AX_ATTR_TABLE_CELL_COLUMN_SPAN, &colspan) &&
1236 colspan >= 1) { 1229 colspan >= 1) {
1237 *n_columns_spanned = colspan; 1230 *n_columns_spanned = colspan;
1238 return S_OK; 1231 return S_OK;
1239 } 1232 }
1240 1233
1241 return S_FALSE; 1234 return S_FALSE;
(...skipping 16 matching lines...) Expand all
1258 1251
1259 const std::vector<int32_t>& unique_cell_ids = 1252 const std::vector<int32_t>& unique_cell_ids =
1260 GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS); 1253 GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS);
1261 int cell_id_count = static_cast<int>(unique_cell_ids.size()); 1254 int cell_id_count = static_cast<int>(unique_cell_ids.size());
1262 if (cell_index < 0) 1255 if (cell_index < 0)
1263 return E_INVALIDARG; 1256 return E_INVALIDARG;
1264 if (cell_index >= cell_id_count) 1257 if (cell_index >= cell_id_count)
1265 return S_FALSE; 1258 return S_FALSE;
1266 1259
1267 int cell_id = unique_cell_ids[cell_index]; 1260 int cell_id = unique_cell_ids[cell_index];
1268 BrowserAccessibilityWin* cell = 1261 BrowserAccessibilityWin* cell = GetFromID(cell_id);
1269 ToBrowserAccessibilityWin(manager()->GetFromID(cell_id));
1270 int col_index; 1262 int col_index;
1271 if (cell && 1263 if (cell &&
1272 cell->GetIntAttribute( 1264 cell->GetIntAttribute(
1273 ui::AX_ATTR_TABLE_CELL_COLUMN_INDEX, &col_index)) { 1265 ui::AX_ATTR_TABLE_CELL_COLUMN_INDEX, &col_index)) {
1274 *column_index = col_index; 1266 *column_index = col_index;
1275 return S_OK; 1267 return S_OK;
1276 } 1268 }
1277 1269
1278 return S_FALSE; 1270 return S_FALSE;
1279 } 1271 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1363 return S_FALSE; 1355 return S_FALSE;
1364 } 1356 }
1365 1357
1366 if (row < 0 || row >= rows) 1358 if (row < 0 || row >= rows)
1367 return E_INVALIDARG; 1359 return E_INVALIDARG;
1368 1360
1369 const std::vector<int32_t>& cell_ids = 1361 const std::vector<int32_t>& cell_ids =
1370 GetIntListAttribute(ui::AX_ATTR_CELL_IDS); 1362 GetIntListAttribute(ui::AX_ATTR_CELL_IDS);
1371 for (int i = 0; i < columns; ++i) { 1363 for (int i = 0; i < columns; ++i) {
1372 int cell_id = cell_ids[row * columns + i]; 1364 int cell_id = cell_ids[row * columns + i];
1373 BrowserAccessibilityWin* cell = 1365 BrowserAccessibilityWin* cell = GetFromID(cell_id);
1374 ToBrowserAccessibilityWin(manager()->GetFromID(cell_id));
1375 if (cell && cell->GetRole() == ui::AX_ROLE_ROW_HEADER) { 1366 if (cell && cell->GetRole() == ui::AX_ROLE_ROW_HEADER) {
1376 base::string16 cell_name = cell->GetString16Attribute( 1367 base::string16 cell_name = cell->GetString16Attribute(
1377 ui::AX_ATTR_NAME); 1368 ui::AX_ATTR_NAME);
1378 if (cell_name.size() > 0) { 1369 if (cell_name.size() > 0) {
1379 *description = SysAllocString(cell_name.c_str()); 1370 *description = SysAllocString(cell_name.c_str());
1380 return S_OK; 1371 return S_OK;
1381 } 1372 }
1382 1373
1383 if (cell->description().size() > 0) { 1374 if (cell->description().size() > 0) {
1384 *description = SysAllocString(cell->description().c_str()); 1375 *description = SysAllocString(cell->description().c_str());
(...skipping 23 matching lines...) Expand all
1408 rows <= 0) { 1399 rows <= 0) {
1409 return S_FALSE; 1400 return S_FALSE;
1410 } 1401 }
1411 1402
1412 if (row < 0 || row >= rows || column < 0 || column >= columns) 1403 if (row < 0 || row >= rows || column < 0 || column >= columns)
1413 return E_INVALIDARG; 1404 return E_INVALIDARG;
1414 1405
1415 const std::vector<int32_t>& cell_ids = 1406 const std::vector<int32_t>& cell_ids =
1416 GetIntListAttribute(ui::AX_ATTR_CELL_IDS); 1407 GetIntListAttribute(ui::AX_ATTR_CELL_IDS);
1417 int cell_id = cell_ids[row * columns + column]; 1408 int cell_id = cell_ids[row * columns + column];
1418 BrowserAccessibilityWin* cell = 1409 BrowserAccessibilityWin* cell = GetFromID(cell_id);
1419 ToBrowserAccessibilityWin(manager()->GetFromID(cell_id));
1420 int rowspan; 1410 int rowspan;
1421 if (cell && 1411 if (cell &&
1422 cell->GetIntAttribute( 1412 cell->GetIntAttribute(
1423 ui::AX_ATTR_TABLE_CELL_ROW_SPAN, &rowspan) && 1413 ui::AX_ATTR_TABLE_CELL_ROW_SPAN, &rowspan) &&
1424 rowspan >= 1) { 1414 rowspan >= 1) {
1425 *n_rows_spanned = rowspan; 1415 *n_rows_spanned = rowspan;
1426 return S_OK; 1416 return S_OK;
1427 } 1417 }
1428 1418
1429 return S_FALSE; 1419 return S_FALSE;
(...skipping 16 matching lines...) Expand all
1446 1436
1447 const std::vector<int32_t>& unique_cell_ids = 1437 const std::vector<int32_t>& unique_cell_ids =
1448 GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS); 1438 GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS);
1449 int cell_id_count = static_cast<int>(unique_cell_ids.size()); 1439 int cell_id_count = static_cast<int>(unique_cell_ids.size());
1450 if (cell_index < 0) 1440 if (cell_index < 0)
1451 return E_INVALIDARG; 1441 return E_INVALIDARG;
1452 if (cell_index >= cell_id_count) 1442 if (cell_index >= cell_id_count)
1453 return S_FALSE; 1443 return S_FALSE;
1454 1444
1455 int cell_id = unique_cell_ids[cell_index]; 1445 int cell_id = unique_cell_ids[cell_index];
1456 BrowserAccessibilityWin* cell = 1446 BrowserAccessibilityWin* cell = GetFromID(cell_id);
1457 ToBrowserAccessibilityWin(manager()->GetFromID(cell_id));
1458 int cell_row_index; 1447 int cell_row_index;
1459 if (cell && 1448 if (cell &&
1460 cell->GetIntAttribute( 1449 cell->GetIntAttribute(
1461 ui::AX_ATTR_TABLE_CELL_ROW_INDEX, &cell_row_index)) { 1450 ui::AX_ATTR_TABLE_CELL_ROW_INDEX, &cell_row_index)) {
1462 *row_index = cell_row_index; 1451 *row_index = cell_row_index;
1463 return S_OK; 1452 return S_OK;
1464 } 1453 }
1465 1454
1466 return S_FALSE; 1455 return S_FALSE;
1467 } 1456 }
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1575 1564
1576 const std::vector<int32_t>& unique_cell_ids = 1565 const std::vector<int32_t>& unique_cell_ids =
1577 GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS); 1566 GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS);
1578 int cell_id_count = static_cast<int>(unique_cell_ids.size()); 1567 int cell_id_count = static_cast<int>(unique_cell_ids.size());
1579 if (index < 0) 1568 if (index < 0)
1580 return E_INVALIDARG; 1569 return E_INVALIDARG;
1581 if (index >= cell_id_count) 1570 if (index >= cell_id_count)
1582 return S_FALSE; 1571 return S_FALSE;
1583 1572
1584 int cell_id = unique_cell_ids[index]; 1573 int cell_id = unique_cell_ids[index];
1585 BrowserAccessibilityWin* cell = 1574 BrowserAccessibilityWin* cell = GetFromID(cell_id);
1586 ToBrowserAccessibilityWin(manager()->GetFromID(cell_id));
1587 int rowspan; 1575 int rowspan;
1588 int colspan; 1576 int colspan;
1589 if (cell && 1577 if (cell &&
1590 cell->GetIntAttribute( 1578 cell->GetIntAttribute(
1591 ui::AX_ATTR_TABLE_CELL_ROW_SPAN, &rowspan) && 1579 ui::AX_ATTR_TABLE_CELL_ROW_SPAN, &rowspan) &&
1592 cell->GetIntAttribute( 1580 cell->GetIntAttribute(
1593 ui::AX_ATTR_TABLE_CELL_COLUMN_SPAN, &colspan) && 1581 ui::AX_ATTR_TABLE_CELL_COLUMN_SPAN, &colspan) &&
1594 rowspan >= 1 && 1582 rowspan >= 1 &&
1595 colspan >= 1) { 1583 colspan >= 1) {
1596 *row_extents = rowspan; 1584 *row_extents = rowspan;
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
1734 return S_FALSE; 1722 return S_FALSE;
1735 } 1723 }
1736 if (columns <= 0 || rows <= 0 || column < 0 || column >= columns) 1724 if (columns <= 0 || rows <= 0 || column < 0 || column >= columns)
1737 return S_FALSE; 1725 return S_FALSE;
1738 1726
1739 const std::vector<int32_t>& cell_ids = 1727 const std::vector<int32_t>& cell_ids =
1740 table->GetIntListAttribute(ui::AX_ATTR_CELL_IDS); 1728 table->GetIntListAttribute(ui::AX_ATTR_CELL_IDS);
1741 1729
1742 for (int i = 0; i < rows; ++i) { 1730 for (int i = 0; i < rows; ++i) {
1743 int cell_id = cell_ids[i * columns + column]; 1731 int cell_id = cell_ids[i * columns + column];
1744 BrowserAccessibilityWin* cell = 1732 BrowserAccessibilityWin* cell = GetFromID(cell_id);
1745 ToBrowserAccessibilityWin(manager()->GetFromID(cell_id));
1746 if (cell && cell->GetRole() == ui::AX_ROLE_COLUMN_HEADER) 1733 if (cell && cell->GetRole() == ui::AX_ROLE_COLUMN_HEADER)
1747 (*n_column_header_cells)++; 1734 (*n_column_header_cells)++;
1748 } 1735 }
1749 1736
1750 *cell_accessibles = static_cast<IUnknown**>(CoTaskMemAlloc( 1737 *cell_accessibles = static_cast<IUnknown**>(CoTaskMemAlloc(
1751 (*n_column_header_cells) * sizeof(cell_accessibles[0]))); 1738 (*n_column_header_cells) * sizeof(cell_accessibles[0])));
1752 int index = 0; 1739 int index = 0;
1753 for (int i = 0; i < rows; ++i) { 1740 for (int i = 0; i < rows; ++i) {
1754 int cell_id = cell_ids[i * columns + column]; 1741 int cell_id = cell_ids[i * columns + column];
1755 BrowserAccessibility* cell = manager()->GetFromID(cell_id); 1742 BrowserAccessibility* cell = manager()->GetFromID(cell_id);
(...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after
2342 return E_INVALIDARG; 2329 return E_INVALIDARG;
2343 2330
2344 const base::string16& text_str = GetText(); 2331 const base::string16& text_str = GetText();
2345 HandleSpecialTextOffset(text_str, &start_offset); 2332 HandleSpecialTextOffset(text_str, &start_offset);
2346 HandleSpecialTextOffset(text_str, &end_offset); 2333 HandleSpecialTextOffset(text_str, &end_offset);
2347 2334
2348 manager()->SetTextSelection(*this, start_offset, end_offset); 2335 manager()->SetTextSelection(*this, start_offset, end_offset);
2349 return S_OK; 2336 return S_OK;
2350 } 2337 }
2351 2338
2352 //
2353 // IAccessibleText methods not implemented.
2354 //
2355
2356 STDMETHODIMP BrowserAccessibilityWin::get_attributes(LONG offset, 2339 STDMETHODIMP BrowserAccessibilityWin::get_attributes(LONG offset,
2357 LONG* start_offset, 2340 LONG* start_offset,
2358 LONG* end_offset, 2341 LONG* end_offset,
2359 BSTR* text_attributes) { 2342 BSTR* text_attributes) {
2360 return E_NOTIMPL; 2343 if (!start_offset || !end_offset || !text_attributes)
2344 return E_INVALIDARG;
2345
2346 *start_offset = *end_offset = 0;
2347 *text_attributes = nullptr;
2348 if (!instance_active())
2349 return E_FAIL;
2350
2351 const base::string16& text = GetText();
2352 HandleSpecialTextOffset(text, &offset);
2353 if (offset < 0 || offset > static_cast<LONG>(text.size()))
2354 return E_INVALIDARG;
2355
2356 ComputeStylesIfNeeded();
2357 *start_offset = FindStartOfStyle(offset, ui::BACKWARDS_DIRECTION);
2358 *end_offset = FindStartOfStyle(offset, ui::FORWARDS_DIRECTION);
2359
2360 base::string16 attributes_str;
2361 const std::vector<base::string16>& attributes =
2362 offset_to_text_attributes().find(*start_offset)->second;
2363 for (const base::string16& attribute : attributes) {
2364 attributes_str += attribute + L';';
2365 }
2366
2367 if (attributes.empty())
2368 return S_FALSE;
2369
2370 *text_attributes = SysAllocString(attributes_str.c_str());
2371 DCHECK(*text_attributes);
2372 return S_OK;
2361 } 2373 }
2362 2374
2363 // 2375 //
2364 // IAccessibleHypertext methods. 2376 // IAccessibleHypertext methods.
2365 // 2377 //
2366 2378
2367 STDMETHODIMP BrowserAccessibilityWin::get_nHyperlinks(long* hyperlink_count) { 2379 STDMETHODIMP BrowserAccessibilityWin::get_nHyperlinks(long* hyperlink_count) {
2368 if (!instance_active()) 2380 if (!instance_active())
2369 return E_FAIL; 2381 return E_FAIL;
2370 2382
(...skipping 10 matching lines...) Expand all
2381 if (!instance_active()) 2393 if (!instance_active())
2382 return E_FAIL; 2394 return E_FAIL;
2383 2395
2384 if (!hyperlink || 2396 if (!hyperlink ||
2385 index < 0 || 2397 index < 0 ||
2386 index >= static_cast<long>(hyperlinks().size())) { 2398 index >= static_cast<long>(hyperlinks().size())) {
2387 return E_INVALIDARG; 2399 return E_INVALIDARG;
2388 } 2400 }
2389 2401
2390 int32_t id = hyperlinks()[index]; 2402 int32_t id = hyperlinks()[index];
2391 BrowserAccessibilityWin* child = 2403 BrowserAccessibilityWin* link = GetFromID(id);
2392 ToBrowserAccessibilityWin(manager()->GetFromID(id)); 2404 if (!link)
2393 if (child) { 2405 return E_FAIL;
2394 *hyperlink = static_cast<IAccessibleHyperlink*>(child->NewReference());
2395 return S_OK;
2396 }
2397 2406
2398 return E_FAIL; 2407 *hyperlink = static_cast<IAccessibleHyperlink*>(link->NewReference());
2408 return S_OK;
2399 } 2409 }
2400 2410
2401 STDMETHODIMP BrowserAccessibilityWin::get_hyperlinkIndex( 2411 STDMETHODIMP BrowserAccessibilityWin::get_hyperlinkIndex(
2402 long char_index, 2412 long char_index,
2403 long* hyperlink_index) { 2413 long* hyperlink_index) {
2404 if (!instance_active()) 2414 if (!instance_active())
2405 return E_FAIL; 2415 return E_FAIL;
2406 2416
2407 if (!hyperlink_index) 2417 if (!hyperlink_index)
2408 return E_INVALIDARG; 2418 return E_INVALIDARG;
(...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after
2966 STDMETHODIMP BrowserAccessibilityWin::get_innerHTML(BSTR* innerHTML) { 2976 STDMETHODIMP BrowserAccessibilityWin::get_innerHTML(BSTR* innerHTML) {
2967 return E_NOTIMPL; 2977 return E_NOTIMPL;
2968 } 2978 }
2969 2979
2970 STDMETHODIMP 2980 STDMETHODIMP
2971 BrowserAccessibilityWin::get_localInterface(void** local_interface) { 2981 BrowserAccessibilityWin::get_localInterface(void** local_interface) {
2972 return E_NOTIMPL; 2982 return E_NOTIMPL;
2973 } 2983 }
2974 2984
2975 STDMETHODIMP BrowserAccessibilityWin::get_language(BSTR* language) { 2985 STDMETHODIMP BrowserAccessibilityWin::get_language(BSTR* language) {
2976 return E_NOTIMPL; 2986 if (!language)
2987 return E_INVALIDARG;
2988 *language = nullptr;
2989
2990 if (!instance_active())
2991 return E_FAIL;
2992
2993 base::string16 lang = GetInheritedString16Attribute(ui::AX_ATTR_LANGUAGE);
2994 if (lang.empty())
2995 lang = L"en-US";
2996
2997 *language = SysAllocString(lang.c_str());
2998 DCHECK(*language);
2999 return S_OK;
2977 } 3000 }
2978 3001
2979 // 3002 //
2980 // ISimpleDOMText methods. 3003 // ISimpleDOMText methods.
2981 // 3004 //
2982 3005
2983 STDMETHODIMP BrowserAccessibilityWin::get_domText(BSTR* dom_text) { 3006 STDMETHODIMP BrowserAccessibilityWin::get_domText(BSTR* dom_text) {
2984 if (!instance_active()) 3007 if (!instance_active())
2985 return E_FAIL; 3008 return E_FAIL;
2986 3009
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
3045 } 3068 }
3046 3069
3047 manager()->ScrollToMakeVisible(*this, GetLocalBoundsForRange( 3070 manager()->ScrollToMakeVisible(*this, GetLocalBoundsForRange(
3048 start_index, end_index - start_index)); 3071 start_index, end_index - start_index));
3049 manager()->ToBrowserAccessibilityManagerWin()->TrackScrollingObject(this); 3072 manager()->ToBrowserAccessibilityManagerWin()->TrackScrollingObject(this);
3050 3073
3051 return S_OK; 3074 return S_OK;
3052 } 3075 }
3053 3076
3054 STDMETHODIMP BrowserAccessibilityWin::get_fontFamily(BSTR* font_family) { 3077 STDMETHODIMP BrowserAccessibilityWin::get_fontFamily(BSTR* font_family) {
3055 return E_NOTIMPL; 3078 if (!font_family)
3079 return E_INVALIDARG;
3080 *font_family = nullptr;
3081
3082 if (!instance_active())
3083 return E_FAIL;
3084
3085 base::string16 family =
3086 GetInheritedString16Attribute(ui::AX_ATTR_FONT_FAMILY);
3087 if (family.empty())
3088 return S_FALSE;
3089
3090 *font_family = SysAllocString(family.c_str());
3091 DCHECK(*font_family);
3092 return S_OK;
3056 } 3093 }
3057 3094
3058 // 3095 //
3059 // IServiceProvider methods. 3096 // IServiceProvider methods.
3060 // 3097 //
3061 3098
3062 STDMETHODIMP BrowserAccessibilityWin::QueryService(REFGUID guid_service, 3099 STDMETHODIMP BrowserAccessibilityWin::QueryService(REFGUID guid_service,
3063 REFIID riid, 3100 REFIID riid,
3064 void** object) { 3101 void** object) {
3065 if (!instance_active()) 3102 if (!instance_active())
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
3226 if (!ax_object || !ax_object->IsHyperlink()) { 3263 if (!ax_object || !ax_object->IsHyperlink()) {
3227 *object = nullptr; 3264 *object = nullptr;
3228 return E_NOINTERFACE; 3265 return E_NOINTERFACE;
3229 } 3266 }
3230 } 3267 }
3231 3268
3232 return CComObjectRootBase::InternalQueryInterface( 3269 return CComObjectRootBase::InternalQueryInterface(
3233 this_ptr, entries, iid, object); 3270 this_ptr, entries, iid, object);
3234 } 3271 }
3235 3272
3273 void BrowserAccessibilityWin::ComputeStylesIfNeeded() {
3274 if (!offset_to_text_attributes().empty())
3275 return;
3276
3277 std::map<int, std::vector<base::string16>> attributes_map;
3278 if (PlatformIsLeaf()) {
3279 attributes_map[0] = ComputeTextAttributes();
3280 win_attributes_->offset_to_text_attributes.swap(attributes_map);
3281 return;
3282 }
3283
3284 int start_offset = 0;
3285 for (size_t i = 0; i < PlatformChildCount(); ++i) {
3286 const auto child = ToBrowserAccessibilityWin(PlatformGetChild(i));
3287 DCHECK(child);
3288 std::vector<base::string16> attributes(child->ComputeTextAttributes());
3289
3290 if (attributes_map.empty()) {
3291 attributes_map[start_offset] = attributes;
3292 } else {
3293 // Only add the attributes for this child if we are at the start of a new
3294 // style span.
3295 std::vector<base::string16> previous_attributes =
3296 attributes_map.rbegin()->second;
3297 if (!std::equal(attributes.begin(), attributes.end(),
3298 previous_attributes.begin())) {
3299 attributes_map[start_offset] = attributes;
3300 }
3301 }
3302
3303 if (child->IsTextOnlyObject())
3304 start_offset += child->GetText().length();
3305 else
3306 start_offset += 1;
3307 }
3308
3309 win_attributes_->offset_to_text_attributes.swap(attributes_map);
3310 }
3311
3236 base::string16 BrowserAccessibilityWin::GetText() const { 3312 base::string16 BrowserAccessibilityWin::GetText() const {
3237 if (PlatformIsChildOfLeaf()) 3313 if (PlatformIsChildOfLeaf())
3238 return BrowserAccessibility::GetText(); 3314 return BrowserAccessibility::GetText();
3239 return win_attributes_->hypertext; 3315 return win_attributes_->hypertext;
3240 } 3316 }
3241 3317
3242 // 3318 //
3243 // Private methods. 3319 // Private methods.
3244 // 3320 //
3245 3321
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
3310 table->GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS); 3386 table->GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS);
3311 for (size_t i = 0; i < unique_cell_ids.size(); ++i) { 3387 for (size_t i = 0; i < unique_cell_ids.size(); ++i) {
3312 if (unique_cell_ids[i] == GetId()) { 3388 if (unique_cell_ids[i] == GetId()) {
3313 win_attributes_->ia2_attributes.push_back( 3389 win_attributes_->ia2_attributes.push_back(
3314 base::string16(L"table-cell-index:") + base::IntToString16(i)); 3390 base::string16(L"table-cell-index:") + base::IntToString16(i));
3315 } 3391 }
3316 } 3392 }
3317 } 3393 }
3318 } 3394 }
3319 3395
3320 // Expose invalid state for form controls and elements with aria-invalid.
3321 int invalid_state;
3322 if (GetIntAttribute(ui::AX_ATTR_INVALID_STATE, &invalid_state)) {
3323 // TODO(nektar): Handle the possibility of having multiple aria-invalid
3324 // attributes defined, e.g., "invalid:spelling,grammar".
3325 switch (invalid_state) {
3326 case ui::AX_INVALID_STATE_FALSE:
3327 win_attributes_->ia2_attributes.push_back(L"invalid:false");
3328 break;
3329 case ui::AX_INVALID_STATE_TRUE:
3330 win_attributes_->ia2_attributes.push_back(L"invalid:true");
3331 break;
3332 case ui::AX_INVALID_STATE_SPELLING:
3333 win_attributes_->ia2_attributes.push_back(L"invalid:spelling");
3334 break;
3335 case ui::AX_INVALID_STATE_GRAMMAR:
3336 win_attributes_->ia2_attributes.push_back(L"invalid:grammar");
3337 break;
3338 case ui::AX_INVALID_STATE_OTHER:
3339 {
3340 base::string16 aria_invalid_value;
3341 if (GetString16Attribute(ui::AX_ATTR_ARIA_INVALID_VALUE,
3342 &aria_invalid_value)) {
3343 SanitizeStringAttributeForIA2(aria_invalid_value,
3344 &aria_invalid_value);
3345 win_attributes_->ia2_attributes.push_back(
3346 L"invalid:" + aria_invalid_value);
3347 } else {
3348 // Set the attribute to L"true", since we cannot be more specific.
3349 win_attributes_->ia2_attributes.push_back(L"invalid:true");
3350 }
3351 }
3352 break;
3353 default:
3354 NOTREACHED();
3355 }
3356 }
3357
3358 // Expose row or column header sort direction. 3396 // Expose row or column header sort direction.
3359 int32_t sort_direction; 3397 int32_t sort_direction;
3360 if ((ia_role() == ROLE_SYSTEM_COLUMNHEADER || 3398 if ((ia_role() == ROLE_SYSTEM_COLUMNHEADER ||
3361 ia_role() == ROLE_SYSTEM_ROWHEADER) && 3399 ia_role() == ROLE_SYSTEM_ROWHEADER) &&
3362 GetIntAttribute(ui::AX_ATTR_SORT_DIRECTION, &sort_direction)) { 3400 GetIntAttribute(ui::AX_ATTR_SORT_DIRECTION, &sort_direction)) {
3363 switch (sort_direction) { 3401 switch (sort_direction) {
3364 case ui::AX_SORT_DIRECTION_UNSORTED: 3402 case ui::AX_SORT_DIRECTION_UNSORTED:
3365 win_attributes_->ia2_attributes.push_back(L"sort:none"); 3403 win_attributes_->ia2_attributes.push_back(L"sort:none");
3366 break; 3404 break;
3367 case ui::AX_SORT_DIRECTION_ASCENDING: 3405 case ui::AX_SORT_DIRECTION_ASCENDING:
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
3427 3465
3428 return; 3466 return;
3429 } 3467 }
3430 3468
3431 // Construct the hypertext for this node, which contains the concatenation 3469 // Construct the hypertext for this node, which contains the concatenation
3432 // of all of the static text and widespace of this node's children and an 3470 // of all of the static text and widespace of this node's children and an
3433 // embedded object character for all the other children. Build up a map from 3471 // embedded object character for all the other children. Build up a map from
3434 // the character index of each embedded object character to the id of the 3472 // the character index of each embedded object character to the id of the
3435 // child object it points to. 3473 // child object it points to.
3436 for (unsigned int i = 0; i < PlatformChildCount(); ++i) { 3474 for (unsigned int i = 0; i < PlatformChildCount(); ++i) {
3437 BrowserAccessibilityWin* child = 3475 const auto child = ToBrowserAccessibilityWin(PlatformGetChild(i));
3438 ToBrowserAccessibilityWin(PlatformGetChild(i));
3439 DCHECK(child); 3476 DCHECK(child);
3440 // Similar to Firefox, we don't expose text-only objects in IA2 hypertext. 3477 // Similar to Firefox, we don't expose text-only objects in IA2 hypertext.
3441 if (child->IsTextOnlyObject()) { 3478 if (child->IsTextOnlyObject()) {
3442 win_attributes_->hypertext += child->name(); 3479 win_attributes_->hypertext += child->name();
3443 } else { 3480 } else {
3444 int32_t char_offset = static_cast<int32_t>(GetText().size()); 3481 int32_t char_offset = static_cast<int32_t>(GetText().size());
3445 int32_t child_id = child->GetId(); 3482 int32_t child_id = child->GetId();
3446 int32_t index = hyperlinks().size(); 3483 int32_t index = hyperlinks().size();
3447 win_attributes_->hyperlink_offset_to_index[char_offset] = index; 3484 win_attributes_->hyperlink_offset_to_index[char_offset] = index;
3448 win_attributes_->hyperlinks.push_back(child_id); 3485 win_attributes_->hyperlinks.push_back(child_id);
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
3566 3603
3567 bool BrowserAccessibilityWin::IsNative() const { 3604 bool BrowserAccessibilityWin::IsNative() const {
3568 return true; 3605 return true;
3569 } 3606 }
3570 3607
3571 void BrowserAccessibilityWin::OnLocationChanged() { 3608 void BrowserAccessibilityWin::OnLocationChanged() {
3572 manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent( 3609 manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent(
3573 EVENT_OBJECT_LOCATIONCHANGE, this); 3610 EVENT_OBJECT_LOCATIONCHANGE, this);
3574 } 3611 }
3575 3612
3613 std::vector<base::string16> BrowserAccessibilityWin::ComputeTextAttributes()
3614 const {
3615 std::vector<base::string16> attributes;
3616
3617 // We include list markers for now, but there might be other objects that are
3618 // auto generated.
3619 // TODO(nektar): Compute what objects are auto-generated in Blink.
3620 if (GetRole() == ui::AX_ROLE_LIST_MARKER)
3621 attributes.push_back(L"auto-generated:true");
3622 else
3623 attributes.push_back(L"auto-generated:false");
3624
3625 int color;
3626 base::string16 color_value(L"transparent");
3627 if (GetIntAttribute(ui::AX_ATTR_BACKGROUND_COLOR, &color)) {
3628 unsigned int alpha = SkColorGetA(color);
3629 unsigned int red = SkColorGetR(color);
3630 unsigned int green = SkColorGetG(color);
3631 unsigned int blue = SkColorGetB(color);
3632 if (alpha) {
3633 color_value = L"rgb(" + base::UintToString16(red) + L',' +
3634 base::UintToString16(green) + L',' +
3635 base::UintToString16(blue) + L')';
3636 }
3637 }
3638 SanitizeStringAttributeForIA2(color_value, &color_value);
3639 attributes.push_back(L"background-color:" + color_value);
3640
3641 if (GetIntAttribute(ui::AX_ATTR_COLOR, &color)) {
3642 unsigned int red = SkColorGetR(color);
3643 unsigned int green = SkColorGetG(color);
3644 unsigned int blue = SkColorGetB(color);
3645 color_value = L"rgb(" + base::UintToString16(red) + L',' +
3646 base::UintToString16(green) + L',' +
3647 base::UintToString16(blue) + L')';
3648 } else {
3649 color_value = L"rgb(0,0,0)";
3650 }
3651 SanitizeStringAttributeForIA2(color_value, &color_value);
3652 attributes.push_back(L"color:" + color_value);
3653
3654 base::string16 font_family(
3655 GetInheritedString16Attribute(ui::AX_ATTR_FONT_FAMILY));
3656 // Attribute has no default value.
3657 if (!font_family.empty()) {
3658 SanitizeStringAttributeForIA2(font_family, &font_family);
3659 attributes.push_back(L"font-family:" + font_family);
3660 }
3661
3662 float font_size;
3663 // Attribute has no default value.
3664 if (GetFloatAttribute(ui::AX_ATTR_FONT_SIZE, &font_size)) {
3665 // The IA2 Spec requires the value to be in pt, not in pixels.
3666 // There are 72 points per inch.
3667 // We assume that there are 96 pixels per inch on a standard display.
3668 // TODO(nektar): Figure out the current value of pixels per inch.
3669 float points = font_size * 72.0 / 96.0;
3670 attributes.push_back(L"font-size:" +
3671 base::UTF8ToUTF16(base::DoubleToString(points)) +
3672 L"pt");
3673 }
3674
3675 auto text_style =
3676 static_cast<ui::AXTextStyle>(GetIntAttribute(ui::AX_ATTR_TEXT_STYLE));
3677 if (text_style == ui::AX_TEXT_STYLE_NONE) {
3678 attributes.push_back(L"font-style:normal");
3679 attributes.push_back(L"font-weight:normal");
3680 } else {
3681 if (text_style & ui::AX_TEXT_STYLE_BOLD)
3682 attributes.push_back(L"font-weight:bold");
3683
3684 base::string16 font_style;
3685 if (text_style & ui::AX_TEXT_STYLE_ITALIC)
3686 font_style += L",italic";
3687 if (text_style & ui::AX_TEXT_STYLE_UNDERLINE)
3688 font_style += L",underline";
3689 if (text_style & ui::AX_TEXT_STYLE_LINE_THROUGH)
3690 font_style += L",line-through";
3691 // TODO(nektar): Support more font style attributes in Blink.
3692
3693 if (font_style.empty()) {
3694 font_style = L"normal";
3695 } else {
3696 // Remove the leading comma.
3697 font_style.erase(0, 1);
3698 }
3699 attributes.push_back(L"font-style:" + font_style);
3700 }
3701
3702 auto invalid_state = static_cast<ui::AXInvalidState>(
3703 GetIntAttribute(ui::AX_ATTR_INVALID_STATE));
3704 switch (invalid_state) {
3705 case ui::AX_INVALID_STATE_NONE:
3706 case ui::AX_INVALID_STATE_FALSE:
3707 attributes.push_back(L"invalid:false");
3708 break;
3709 case ui::AX_INVALID_STATE_TRUE:
3710 attributes.push_back(L"invalid:true");
3711 break;
3712 case ui::AX_INVALID_STATE_SPELLING:
3713 case ui::AX_INVALID_STATE_GRAMMAR: {
3714 base::string16 spelling_grammar_value;
3715 if (invalid_state & ui::AX_INVALID_STATE_SPELLING)
3716 spelling_grammar_value = L"spelling";
3717 else if (invalid_state & ui::AX_INVALID_STATE_GRAMMAR)
3718 spelling_grammar_value = L"grammar";
3719 else
3720 spelling_grammar_value = L"spelling,grammar";
3721 attributes.push_back(L"invalid:" + spelling_grammar_value);
3722 break;
3723 }
3724 case ui::AX_INVALID_STATE_OTHER: {
3725 base::string16 aria_invalid_value;
3726 if (GetString16Attribute(ui::AX_ATTR_ARIA_INVALID_VALUE,
3727 &aria_invalid_value)) {
3728 SanitizeStringAttributeForIA2(aria_invalid_value, &aria_invalid_value);
3729 attributes.push_back(L"invalid:" + aria_invalid_value);
3730 } else {
3731 // Set the attribute to L"true", since we cannot be more specific.
3732 attributes.push_back(L"invalid:true");
3733 }
3734 break;
3735 }
3736 default:
3737 NOTREACHED();
3738 }
3739
3740 base::string16 language(GetInheritedString16Attribute(ui::AX_ATTR_LANGUAGE));
3741 // Default value should be L"en-US".
3742 if (language.empty()) {
3743 attributes.push_back(L"language:en-US");
3744 } else {
3745 SanitizeStringAttributeForIA2(language, &language);
3746 attributes.push_back(L"language:" + language);
3747 }
3748
3749 // TODO(nektar): Add Blink support for the following attributes.
3750 // Currently set to their default values as dictated by the IA2 Spec.
3751 attributes.push_back(L"text-line-through-mode:continuous");
3752 attributes.push_back(L"text-line-through-style:none");
3753 // Default value must be the empty string.
3754 attributes.push_back(L"text-line-through-text:");
3755 attributes.push_back(L"text-line-through-type:none");
3756 attributes.push_back(L"text-line-through-width:auto");
3757 attributes.push_back(L"text-outline:false");
3758 attributes.push_back(L"text-position:baseline");
3759 attributes.push_back(L"text-shadow:none");
3760 attributes.push_back(L"text-underline-mode:continuous");
3761 attributes.push_back(L"text-underline-style:none");
3762 attributes.push_back(L"text-underline-type:none");
3763 attributes.push_back(L"text-underline-width:auto");
3764
3765 auto text_direction = static_cast<ui::AXTextDirection>(
3766 GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION));
3767 switch (text_direction) {
3768 case ui::AX_TEXT_DIRECTION_NONE:
3769 case ui::AX_TEXT_DIRECTION_LTR:
3770 attributes.push_back(L"writing-mode:lr");
3771 break;
3772 case ui::AX_TEXT_DIRECTION_RTL:
3773 attributes.push_back(L"writing-mode:rl");
3774 break;
3775 case ui::AX_TEXT_DIRECTION_TTB:
3776 attributes.push_back(L"writing-mode:tb");
3777 break;
3778 case ui::AX_TEXT_DIRECTION_BTT:
3779 // Not listed in the IA2 Spec.
3780 attributes.push_back(L"writing-mode:bt");
3781 break;
3782 default:
3783 NOTREACHED();
3784 }
3785
3786 return attributes;
3787 }
3788
3576 BrowserAccessibilityWin* BrowserAccessibilityWin::NewReference() { 3789 BrowserAccessibilityWin* BrowserAccessibilityWin::NewReference() {
3577 AddRef(); 3790 AddRef();
3578 return this; 3791 return this;
3579 } 3792 }
3580 3793
3581 BrowserAccessibilityWin* BrowserAccessibilityWin::GetTargetFromChildID( 3794 BrowserAccessibilityWin* BrowserAccessibilityWin::GetTargetFromChildID(
3582 const VARIANT& var_id) { 3795 const VARIANT& var_id) {
3583 if (var_id.vt != VT_I4) 3796 if (var_id.vt != VT_I4)
3584 return NULL; 3797 return NULL;
3585 3798
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
3665 if (parent) { 3878 if (parent) {
3666 hyperlink_index = 3879 hyperlink_index =
3667 ToBrowserAccessibilityWin(parent)->GetHyperlinkIndexFromChild(*this); 3880 ToBrowserAccessibilityWin(parent)->GetHyperlinkIndexFromChild(*this);
3668 } 3881 }
3669 3882
3670 if (hyperlink_index >= 0) 3883 if (hyperlink_index >= 0)
3671 return true; 3884 return true;
3672 return false; 3885 return false;
3673 } 3886 }
3674 3887
3888 BrowserAccessibilityWin*
3889 BrowserAccessibilityWin::GetHyperlinkFromHypertextOffset(int offset) const {
3890 std::map<int32_t, int32_t>::iterator iterator =
3891 hyperlink_offset_to_index().find(offset);
3892 if (iterator == hyperlink_offset_to_index().end())
3893 return nullptr;
3894
3895 int32_t index = iterator->second;
3896 DCHECK_GE(index, 0);
3897 DCHECK_LT(index, static_cast<int32_t>(hyperlinks().size()));
3898 int32_t id = hyperlinks()[index];
3899 BrowserAccessibilityWin* hyperlink = GetFromID(id);
3900 if (!hyperlink)
3901 return nullptr;
3902 return hyperlink;
3903 }
3904
3675 int32_t BrowserAccessibilityWin::GetHyperlinkIndexFromChild( 3905 int32_t BrowserAccessibilityWin::GetHyperlinkIndexFromChild(
3676 const BrowserAccessibilityWin& child) const { 3906 const BrowserAccessibilityWin& child) const {
3677 if (hyperlinks().empty()) 3907 if (hyperlinks().empty())
3678 return -1; 3908 return -1;
3679 3909
3680 auto iterator = std::find( 3910 auto iterator = std::find(
3681 hyperlinks().begin(), hyperlinks().end(), child.GetId()); 3911 hyperlinks().begin(), hyperlinks().end(), child.GetId());
3682 if (iterator == hyperlinks().end()) 3912 if (iterator == hyperlinks().end())
3683 return -1; 3913 return -1;
3684 3914
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
3808 return 0; 4038 return 0;
3809 if (endpoint_index_in_common_parent > index_in_common_parent) 4039 if (endpoint_index_in_common_parent > index_in_common_parent)
3810 return GetText().size(); 4040 return GetText().size();
3811 4041
3812 NOTREACHED(); 4042 NOTREACHED();
3813 return -1; 4043 return -1;
3814 } 4044 }
3815 4045
3816 int BrowserAccessibilityWin::GetSelectionAnchor() const { 4046 int BrowserAccessibilityWin::GetSelectionAnchor() const {
3817 int32_t anchor_id = manager()->GetTreeData().sel_anchor_object_id; 4047 int32_t anchor_id = manager()->GetTreeData().sel_anchor_object_id;
3818 const auto anchor_object = 4048 const BrowserAccessibilityWin* anchor_object = GetFromID(anchor_id);
3819 ToBrowserAccessibilityWin(manager()->GetFromID(anchor_id));
3820 if (!anchor_object) 4049 if (!anchor_object)
3821 return -1; 4050 return -1;
3822 4051
3823 int anchor_offset = manager()->GetTreeData().sel_anchor_offset; 4052 int anchor_offset = manager()->GetTreeData().sel_anchor_offset;
3824 return GetHypertextOffsetFromEndpoint(*anchor_object, anchor_offset); 4053 return GetHypertextOffsetFromEndpoint(*anchor_object, anchor_offset);
3825 } 4054 }
3826 4055
3827 int BrowserAccessibilityWin::GetSelectionFocus() const { 4056 int BrowserAccessibilityWin::GetSelectionFocus() const {
3828 int32_t focus_id = manager()->GetTreeData().sel_focus_object_id; 4057 int32_t focus_id = manager()->GetTreeData().sel_focus_object_id;
3829 const auto focus_object = 4058 const BrowserAccessibilityWin* focus_object = GetFromID(focus_id);
3830 ToBrowserAccessibilityWin(manager()->GetFromID(focus_id));
3831 if (!focus_object) 4059 if (!focus_object)
3832 return -1; 4060 return -1;
3833 4061
3834 int focus_offset = manager()->GetTreeData().sel_focus_offset; 4062 int focus_offset = manager()->GetTreeData().sel_focus_offset;
3835 return GetHypertextOffsetFromEndpoint(*focus_object, focus_offset); 4063 return GetHypertextOffsetFromEndpoint(*focus_object, focus_offset);
3836 } 4064 }
3837 4065
3838 void BrowserAccessibilityWin::GetSelectionOffsets( 4066 void BrowserAccessibilityWin::GetSelectionOffsets(
3839 int* selection_start, int* selection_end) const { 4067 int* selection_start, int* selection_end) const {
3840 DCHECK(selection_start && selection_end); 4068 DCHECK(selection_start && selection_end);
(...skipping 29 matching lines...) Expand all
3870 } 4098 }
3871 4099
3872 // The IA2 Spec says that if the largest of the two offsets falls on an 4100 // The IA2 Spec says that if the largest of the two offsets falls on an
3873 // embedded object character and if there is a selection in that embedded 4101 // embedded object character and if there is a selection in that embedded
3874 // object, it should be incremented by one so that it points after the 4102 // object, it should be incremented by one so that it points after the
3875 // embedded object character. 4103 // embedded object character.
3876 // This is a signal to AT software that the embedded object is also part of 4104 // This is a signal to AT software that the embedded object is also part of
3877 // the selection. 4105 // the selection.
3878 int* largest_offset = 4106 int* largest_offset =
3879 (*selection_start <= *selection_end) ? selection_end : selection_start; 4107 (*selection_start <= *selection_end) ? selection_end : selection_start;
3880 auto current_object = const_cast<BrowserAccessibilityWin*>(this); 4108 BrowserAccessibilityWin* hyperlink =
3881 LONG hyperlink_index; 4109 GetHyperlinkFromHypertextOffset(*largest_offset);
3882 HRESULT hr = 4110 if (!hyperlink)
3883 current_object->get_hyperlinkIndex(*largest_offset, &hyperlink_index);
3884 if (hr != S_OK)
3885 return; 4111 return;
3886 4112
3887 DCHECK_GE(hyperlink_index, 0);
3888 base::win::ScopedComPtr<IAccessibleHyperlink> hyperlink;
3889 hr = current_object->get_hyperlink(hyperlink_index, hyperlink.Receive());
3890 DCHECK(SUCCEEDED(hr));
3891 base::win::ScopedComPtr<IAccessibleText> hyperlink_text;
3892 hr = hyperlink.QueryInterface(hyperlink_text.Receive());
3893 DCHECK(SUCCEEDED(hr));
3894 LONG n_selections = 0; 4113 LONG n_selections = 0;
3895 hr = hyperlink_text->get_nSelections(&n_selections); 4114 HRESULT hr = hyperlink->get_nSelections(&n_selections);
3896 DCHECK(SUCCEEDED(hr)); 4115 DCHECK(SUCCEEDED(hr));
3897 if (n_selections > 0) 4116 if (n_selections > 0)
3898 ++(*largest_offset); 4117 ++(*largest_offset);
3899 } 4118 }
3900 4119
3901 base::string16 BrowserAccessibilityWin::GetValueText() { 4120 base::string16 BrowserAccessibilityWin::GetValueText() {
3902 float fval; 4121 float fval;
3903 base::string16 value = this->value(); 4122 base::string16 value = this->value();
3904 4123
3905 if (value.empty() && 4124 if (value.empty() &&
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
4017 if (ia2_boundary == IA2_TEXT_BOUNDARY_WORD) 4236 if (ia2_boundary == IA2_TEXT_BOUNDARY_WORD)
4018 return GetWordStartBoundary(static_cast<int>(start_offset), direction); 4237 return GetWordStartBoundary(static_cast<int>(start_offset), direction);
4019 4238
4020 ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary); 4239 ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary);
4021 const std::vector<int32_t>& line_breaks = 4240 const std::vector<int32_t>& line_breaks =
4022 GetIntListAttribute(ui::AX_ATTR_LINE_BREAKS); 4241 GetIntListAttribute(ui::AX_ATTR_LINE_BREAKS);
4023 return ui::FindAccessibleTextBoundary( 4242 return ui::FindAccessibleTextBoundary(
4024 text, line_breaks, boundary, start_offset, direction); 4243 text, line_breaks, boundary, start_offset, direction);
4025 } 4244 }
4026 4245
4027 BrowserAccessibilityWin* BrowserAccessibilityWin::GetFromID(int32_t id) { 4246 LONG BrowserAccessibilityWin::FindStartOfStyle(
4247 LONG start_offset,
4248 ui::TextBoundaryDirection direction) const {
4249 LONG text_length = static_cast<LONG>(GetText().length());
4250 DCHECK_GE(start_offset, 0);
4251 DCHECK_LE(start_offset, text_length);
4252
4253 switch (direction) {
4254 case ui::BACKWARDS_DIRECTION: {
4255 if (offset_to_text_attributes().empty())
4256 return 0;
4257
4258 auto iterator = offset_to_text_attributes().upper_bound(start_offset);
4259 --iterator;
4260 return static_cast<LONG>(iterator->first);
4261 }
4262 case ui::FORWARDS_DIRECTION: {
4263 const auto iterator =
4264 offset_to_text_attributes().upper_bound(start_offset);
4265 if (iterator == offset_to_text_attributes().end())
4266 return text_length;
4267 return static_cast<LONG>(iterator->first);
4268 }
4269 default:
4270 NOTREACHED();
4271 }
4272
4273 return start_offset;
4274 }
4275
4276 BrowserAccessibilityWin* BrowserAccessibilityWin::GetFromID(int32_t id) const {
4277 if (!instance_active())
4278 return nullptr;
4028 return ToBrowserAccessibilityWin(manager()->GetFromID(id)); 4279 return ToBrowserAccessibilityWin(manager()->GetFromID(id));
4029 } 4280 }
4030 4281
4031 bool BrowserAccessibilityWin::IsListBoxOptionOrMenuListOption() { 4282 bool BrowserAccessibilityWin::IsListBoxOptionOrMenuListOption() {
4032 if (!GetParent()) 4283 if (!GetParent())
4033 return false; 4284 return false;
4034 4285
4035 int32_t role = GetRole(); 4286 int32_t role = GetRole();
4036 int32_t parent_role = GetParent()->GetRole(); 4287 int32_t parent_role = GetParent()->GetRole();
4037 4288
4038 if (role == ui::AX_ROLE_LIST_BOX_OPTION && 4289 if (role == ui::AX_ROLE_LIST_BOX_OPTION &&
4039 parent_role == ui::AX_ROLE_LIST_BOX) { 4290 parent_role == ui::AX_ROLE_LIST_BOX) {
4040 return true; 4291 return true;
4041 } 4292 }
4042 4293
4043 if (role == ui::AX_ROLE_MENU_LIST_OPTION && 4294 if (role == ui::AX_ROLE_MENU_LIST_OPTION &&
4044 parent_role == ui::AX_ROLE_MENU_LIST_POPUP) { 4295 parent_role == ui::AX_ROLE_MENU_LIST_POPUP) {
4045 return true; 4296 return true;
4046 } 4297 }
4047 4298
4048 return false; 4299 return false;
4049 } 4300 }
4050 4301
4302 void BrowserAccessibilityWin::AddRelations(
4303 ui::AXIntListAttribute src_attr,
4304 const base::string16& iaccessiblerelation_type) {
4305 if (!HasIntListAttribute(src_attr))
4306 return;
4307
4308 const std::vector<int32_t>& ids = GetIntListAttribute(src_attr);
4309 for (size_t i = 0; i < ids.size(); ++i) {
4310 CComObject<BrowserAccessibilityRelation>* relation;
4311 HRESULT hr =
4312 CComObject<BrowserAccessibilityRelation>::CreateInstance(&relation);
4313 DCHECK(SUCCEEDED(hr));
4314 relation->AddRef();
4315 relation->Initialize(this, iaccessiblerelation_type);
4316 relation->AddTarget(ids[i]);
4317 relations_.push_back(relation);
4318 }
4319 }
4320
4051 void BrowserAccessibilityWin::UpdateRequiredAttributes() { 4321 void BrowserAccessibilityWin::UpdateRequiredAttributes() {
4052 // Expose slider value. 4322 // Expose slider value.
4053 if (ia_role() == ROLE_SYSTEM_PROGRESSBAR || 4323 if (ia_role() == ROLE_SYSTEM_PROGRESSBAR ||
4054 ia_role() == ROLE_SYSTEM_SCROLLBAR || 4324 ia_role() == ROLE_SYSTEM_SCROLLBAR ||
4055 ia_role() == ROLE_SYSTEM_SLIDER) { 4325 ia_role() == ROLE_SYSTEM_SLIDER) {
4056 base::string16 value_text = GetValueText(); 4326 base::string16 value_text = GetValueText();
4057 SanitizeStringAttributeForIA2(value_text, &value_text); 4327 SanitizeStringAttributeForIA2(value_text, &value_text);
4058 win_attributes_->ia2_attributes.push_back(L"valuetext:" + value_text); 4328 win_attributes_->ia2_attributes.push_back(L"valuetext:" + value_text);
4059 } 4329 }
4060 4330
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
4104 // Expose input-text type attribute. 4374 // Expose input-text type attribute.
4105 base::string16 type; 4375 base::string16 type;
4106 base::string16 html_tag = GetString16Attribute(ui::AX_ATTR_HTML_TAG); 4376 base::string16 html_tag = GetString16Attribute(ui::AX_ATTR_HTML_TAG);
4107 if (IsSimpleTextControl() && html_tag == L"input" && 4377 if (IsSimpleTextControl() && html_tag == L"input" &&
4108 GetHtmlAttribute("type", &type)) { 4378 GetHtmlAttribute("type", &type)) {
4109 SanitizeStringAttributeForIA2(type, &type); 4379 SanitizeStringAttributeForIA2(type, &type);
4110 win_attributes_->ia2_attributes.push_back(L"text-input-type:" + type); 4380 win_attributes_->ia2_attributes.push_back(L"text-input-type:" + type);
4111 } 4381 }
4112 } 4382 }
4113 4383
4114 void BrowserAccessibilityWin::AddRelations(
4115 ui::AXIntListAttribute src_attr,
4116 const base::string16& iaccessiblerelation_type) {
4117 if (!HasIntListAttribute(src_attr))
4118 return;
4119
4120 const std::vector<int32_t>& ids = GetIntListAttribute(src_attr);
4121 for (size_t i = 0; i < ids.size(); ++i) {
4122 CComObject<BrowserAccessibilityRelation>* relation;
4123 HRESULT hr = CComObject<BrowserAccessibilityRelation>::CreateInstance(
4124 &relation);
4125 DCHECK(SUCCEEDED(hr));
4126 relation->AddRef();
4127 relation->Initialize(this, iaccessiblerelation_type);
4128 relation->AddTarget(ids[i]);
4129 relations_.push_back(relation);
4130 }
4131 }
4132
4133 void BrowserAccessibilityWin::InitRoleAndState() { 4384 void BrowserAccessibilityWin::InitRoleAndState() {
4134 int32_t ia_role = 0; 4385 int32_t ia_role = 0;
4135 int32_t ia_state = 0; 4386 int32_t ia_state = 0;
4136 base::string16 role_name; 4387 base::string16 role_name;
4137 int32_t ia2_role = 0; 4388 int32_t ia2_role = 0;
4138 int32_t ia2_state = IA2_STATE_OPAQUE; 4389 int32_t ia2_state = IA2_STATE_OPAQUE;
4139 4390
4140 if (HasState(ui::AX_STATE_BUSY)) 4391 if (HasState(ui::AX_STATE_BUSY))
4141 ia_state |= STATE_SYSTEM_BUSY; 4392 ia_state |= STATE_SYSTEM_BUSY;
4142 if (HasState(ui::AX_STATE_CHECKED)) 4393 if (HasState(ui::AX_STATE_CHECKED))
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after
4685 return static_cast<BrowserAccessibilityWin*>(obj); 4936 return static_cast<BrowserAccessibilityWin*>(obj);
4686 } 4937 }
4687 4938
4688 const BrowserAccessibilityWin* 4939 const BrowserAccessibilityWin*
4689 ToBrowserAccessibilityWin(const BrowserAccessibility* obj) { 4940 ToBrowserAccessibilityWin(const BrowserAccessibility* obj) {
4690 DCHECK(!obj || obj->IsNative()); 4941 DCHECK(!obj || obj->IsNative());
4691 return static_cast<const BrowserAccessibilityWin*>(obj); 4942 return static_cast<const BrowserAccessibilityWin*>(obj);
4692 } 4943 }
4693 4944
4694 } // namespace content 4945 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698