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

Side by Side Diff: ui/accessibility/platform/ax_platform_node_win.cc

Issue 2975413002: Move ia2_attributes handling to AXPlatformNodeWin. (Closed)
Patch Set: Initial Created 3 years, 5 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 <atlbase.h> 5 #include <atlbase.h>
6 #include <atlcom.h> 6 #include <atlcom.h>
7 #include <limits.h> 7 #include <limits.h>
8 #include <oleacc.h> 8 #include <oleacc.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 10
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 // 197 //
198 // AXPlatformNodeWin 198 // AXPlatformNodeWin
199 // 199 //
200 200
201 AXPlatformNodeWin::AXPlatformNodeWin() { 201 AXPlatformNodeWin::AXPlatformNodeWin() {
202 } 202 }
203 203
204 AXPlatformNodeWin::~AXPlatformNodeWin() { 204 AXPlatformNodeWin::~AXPlatformNodeWin() {
205 } 205 }
206 206
207 // Static
208 void AXPlatformNodeWin::SanitizeStringAttributeForIA2(
209 const base::string16& input,
210 base::string16* output) {
211 DCHECK(output);
212 // According to the IA2 Spec, these characters need to be escaped with a
213 // backslash: backslash, colon, comma, equals and semicolon.
214 // Note that backslash must be replaced first.
215 base::ReplaceChars(input, L"\\", L"\\\\", output);
216 base::ReplaceChars(*output, L":", L"\\:", output);
217 base::ReplaceChars(*output, L",", L"\\,", output);
218 base::ReplaceChars(*output, L"=", L"\\=", output);
219 base::ReplaceChars(*output, L";", L"\\;", output);
220 }
221
222 void AXPlatformNodeWin::StringAttributeToIA2(ui::AXStringAttribute attribute,
223 const char* ia2_attr) {
224 base::string16 value;
225 if (GetString16Attribute(attribute, &value)) {
226 SanitizeStringAttributeForIA2(value, &value);
227 ia2_attributes_.push_back(base::ASCIIToUTF16(ia2_attr) + L":" + value);
228 }
229 }
230
231 void AXPlatformNodeWin::BoolAttributeToIA2(ui::AXBoolAttribute attribute,
232 const char* ia2_attr) {
233 bool value;
234 if (GetBoolAttribute(attribute, &value)) {
235 ia2_attributes_.push_back((base::ASCIIToUTF16(ia2_attr) + L":") +
236 (value ? L"true" : L"false"));
237 }
238 }
239
240 void AXPlatformNodeWin::IntAttributeToIA2(ui::AXIntAttribute attribute,
241 const char* ia2_attr) {
242 int value;
243 if (GetIntAttribute(attribute, &value)) {
244 ia2_attributes_.push_back(base::ASCIIToUTF16(ia2_attr) + L":" +
245 base::IntToString16(value));
246 }
247 }
248
207 // 249 //
208 // AXPlatformNodeBase implementation. 250 // AXPlatformNodeBase implementation.
209 // 251 //
210 252
211 void AXPlatformNodeWin::Dispose() { 253 void AXPlatformNodeWin::Dispose() {
212 Release(); 254 Release();
213 } 255 }
214 256
215 void AXPlatformNodeWin::Destroy() { 257 void AXPlatformNodeWin::Destroy() {
216 RemoveAlertTarget(); 258 RemoveAlertTarget();
(...skipping 2202 matching lines...) Expand 10 before | Expand all | Expand 10 after
2419 case ui::AX_ROLE_ABBR: 2461 case ui::AX_ROLE_ABBR:
2420 case ui::AX_ROLE_TIME: 2462 case ui::AX_ROLE_TIME:
2421 ia2_role = IA2_ROLE_TEXT_FRAME; 2463 ia2_role = IA2_ROLE_TEXT_FRAME;
2422 break; 2464 break;
2423 default: 2465 default:
2424 break; 2466 break;
2425 } 2467 }
2426 return ia2_role; 2468 return ia2_role;
2427 } 2469 }
2428 2470
2471 std::vector<base::string16> AXPlatformNodeWin::IA2Attributes() {
2472 // maybe use a cache?
2473 ia2_attributes_.clear();
dmazzoni 2017/07/17 08:27:18 It doesn't seem to make sense to store ia2_attribu
dougt 2017/07/17 19:28:27 Done.
2474
2475 // Expose some HTLM and ARIA attributes in the IAccessible2 attributes string.
2476 // "display", "tag", and "xml-roles" have somewhat unusual names for
2477 // historical reasons. Aside from that virtually every ARIA attribute
2478 // is exposed in a really straightforward way, i.e. "aria-foo" is exposed
2479 // as "foo".
2480 StringAttributeToIA2(ui::AX_ATTR_DISPLAY, "display");
2481 StringAttributeToIA2(ui::AX_ATTR_HTML_TAG, "tag");
2482 StringAttributeToIA2(ui::AX_ATTR_ROLE, "xml-roles");
2483 StringAttributeToIA2(ui::AX_ATTR_PLACEHOLDER, "placeholder");
2484
2485 StringAttributeToIA2(ui::AX_ATTR_AUTO_COMPLETE, "autocomplete");
2486 StringAttributeToIA2(ui::AX_ATTR_ROLE_DESCRIPTION, "roledescription");
2487 StringAttributeToIA2(ui::AX_ATTR_KEY_SHORTCUTS, "keyshortcuts");
2488
2489 IntAttributeToIA2(ui::AX_ATTR_HIERARCHICAL_LEVEL, "level");
2490 IntAttributeToIA2(ui::AX_ATTR_SET_SIZE, "setsize");
2491 IntAttributeToIA2(ui::AX_ATTR_POS_IN_SET, "posinset");
2492
2493 if (HasIntAttribute(ui::AX_ATTR_CHECKED_STATE))
2494 ia2_attributes_.push_back(L"checkable:true");
2495
2496 // Expose live region attributes.
2497 StringAttributeToIA2(ui::AX_ATTR_LIVE_STATUS, "live");
2498 StringAttributeToIA2(ui::AX_ATTR_LIVE_RELEVANT, "relevant");
2499 BoolAttributeToIA2(ui::AX_ATTR_LIVE_ATOMIC, "atomic");
2500 BoolAttributeToIA2(ui::AX_ATTR_LIVE_BUSY, "busy");
2501
2502 // Expose container live region attributes.
2503 StringAttributeToIA2(ui::AX_ATTR_CONTAINER_LIVE_STATUS, "container-live");
2504 StringAttributeToIA2(ui::AX_ATTR_CONTAINER_LIVE_RELEVANT,
2505 "container-relevant");
2506 BoolAttributeToIA2(ui::AX_ATTR_CONTAINER_LIVE_ATOMIC, "container-atomic");
2507 BoolAttributeToIA2(ui::AX_ATTR_CONTAINER_LIVE_BUSY, "container-busy");
2508
2509 // Expose the non-standard explicit-name IA2 attribute.
2510 int name_from;
2511 if (GetIntAttribute(ui::AX_ATTR_NAME_FROM, &name_from) &&
2512 name_from != ui::AX_NAME_FROM_CONTENTS) {
2513 ia2_attributes_.push_back(L"explicit-name:true");
2514 }
2515
2516 // Expose the aria-current attribute.
2517 int32_t aria_current_state;
2518 if (GetIntAttribute(ui::AX_ATTR_ARIA_CURRENT_STATE, &aria_current_state)) {
2519 switch (static_cast<ui::AXAriaCurrentState>(aria_current_state)) {
2520 case ui::AX_ARIA_CURRENT_STATE_NONE:
2521 break;
2522 case ui::AX_ARIA_CURRENT_STATE_FALSE:
2523 ia2_attributes_.push_back(L"current:false");
2524 break;
2525 case ui::AX_ARIA_CURRENT_STATE_TRUE:
2526 ia2_attributes_.push_back(L"current:true");
2527 break;
2528 case ui::AX_ARIA_CURRENT_STATE_PAGE:
2529 ia2_attributes_.push_back(L"current:page");
2530 break;
2531 case ui::AX_ARIA_CURRENT_STATE_STEP:
2532 ia2_attributes_.push_back(L"current:step");
2533 break;
2534 case ui::AX_ARIA_CURRENT_STATE_LOCATION:
2535 ia2_attributes_.push_back(L"current:location");
2536 break;
2537 case ui::AX_ARIA_CURRENT_STATE_DATE:
2538 ia2_attributes_.push_back(L"current:date");
2539 break;
2540 case ui::AX_ARIA_CURRENT_STATE_TIME:
2541 ia2_attributes_.push_back(L"current:time");
2542 break;
2543 }
2544 }
2545
2546 // Expose table cell index.
2547 if (ui::IsCellOrTableHeaderRole(GetData().role)) {
2548 AXPlatformNodeBase* table = FromNativeViewAccessible(GetParent());
2549
2550 while (table && !ui::IsTableLikeRole(table->GetData().role))
2551 table = FromNativeViewAccessible(table->GetParent());
2552
2553 if (table) {
2554 const std::vector<int32_t>& unique_cell_ids =
2555 table->GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS);
2556 for (size_t i = 0; i < unique_cell_ids.size(); ++i) {
2557 if (unique_cell_ids[i] == GetData().id) {
2558 ia2_attributes_.push_back(base::string16(L"table-cell-index:") +
2559 base::IntToString16(static_cast<int>(i)));
2560 }
2561 }
2562 }
2563 }
2564
2565 // Expose aria-colcount and aria-rowcount in a table, grid or treegrid.
2566 if (ui::IsTableLikeRole(GetData().role)) {
2567 IntAttributeToIA2(ui::AX_ATTR_ARIA_COLUMN_COUNT, "colcount");
2568 IntAttributeToIA2(ui::AX_ATTR_ARIA_ROW_COUNT, "rowcount");
2569 }
2570
2571 // Expose aria-colindex and aria-rowindex in a cell or row.
2572 if (ui::IsCellOrTableHeaderRole(GetData().role) ||
2573 GetData().role == ui::AX_ROLE_ROW) {
2574 if (GetData().role != ui::AX_ROLE_ROW)
2575 IntAttributeToIA2(ui::AX_ATTR_ARIA_CELL_COLUMN_INDEX, "colindex");
2576 IntAttributeToIA2(ui::AX_ATTR_ARIA_CELL_ROW_INDEX, "rowindex");
2577 }
2578
2579 // Expose row or column header sort direction.
2580 int32_t sort_direction;
2581 if ((MSAARole() == ROLE_SYSTEM_COLUMNHEADER ||
2582 MSAARole() == ROLE_SYSTEM_ROWHEADER) &&
2583 GetIntAttribute(ui::AX_ATTR_SORT_DIRECTION, &sort_direction)) {
2584 switch (static_cast<ui::AXSortDirection>(sort_direction)) {
2585 case ui::AX_SORT_DIRECTION_NONE:
2586 break;
2587 case ui::AX_SORT_DIRECTION_UNSORTED:
2588 ia2_attributes_.push_back(L"sort:none");
2589 break;
2590 case ui::AX_SORT_DIRECTION_ASCENDING:
2591 ia2_attributes_.push_back(L"sort:ascending");
2592 break;
2593 case ui::AX_SORT_DIRECTION_DESCENDING:
2594 ia2_attributes_.push_back(L"sort:descending");
2595 break;
2596 case ui::AX_SORT_DIRECTION_OTHER:
2597 ia2_attributes_.push_back(L"sort:other");
2598 break;
2599 }
2600 }
2601
2602 if (ui::IsCellOrTableHeaderRole(GetData().role)) {
2603 // Expose colspan attribute.
2604 base::string16 colspan;
2605 if (GetData().GetHtmlAttribute("aria-colspan", &colspan)) {
2606 SanitizeStringAttributeForIA2(colspan, &colspan);
2607 ia2_attributes_.push_back(L"colspan:" + colspan);
2608 }
2609 // Expose rowspan attribute.
2610 base::string16 rowspan;
2611 if (GetData().GetHtmlAttribute("aria-rowspan", &rowspan)) {
2612 SanitizeStringAttributeForIA2(rowspan, &rowspan);
2613 ia2_attributes_.push_back(L"rowspan:" + rowspan);
2614 }
2615 }
2616
2617 // Expose slider value.
2618 if (IsRangeValueSupported()) {
2619 base::string16 value = GetRangeValueText();
2620 SanitizeStringAttributeForIA2(value, &value);
2621 ia2_attributes_.push_back(L"valuetext:" + value);
2622 }
2623
2624 // Expose dropeffect attribute.
2625 base::string16 drop_effect;
2626 if (GetData().GetHtmlAttribute("aria-dropeffect", &drop_effect)) {
2627 SanitizeStringAttributeForIA2(drop_effect, &drop_effect);
2628 ia2_attributes_.push_back(L"dropeffect:" + drop_effect);
2629 }
2630
2631 // Expose grabbed attribute.
2632 base::string16 grabbed;
2633 if (GetData().GetHtmlAttribute("aria-grabbed", &grabbed)) {
2634 SanitizeStringAttributeForIA2(grabbed, &grabbed);
2635 ia2_attributes_.push_back(L"grabbed:" + grabbed);
2636 }
2637
2638 // Expose class attribute.
2639 base::string16 class_attr;
2640 if (GetData().GetHtmlAttribute("class", &class_attr)) {
2641 SanitizeStringAttributeForIA2(class_attr, &class_attr);
2642 ia2_attributes_.push_back(L"class:" + class_attr);
2643 }
2644
2645 // Expose datetime attribute.
2646 base::string16 datetime;
2647 if (GetData().role == ui::AX_ROLE_TIME &&
2648 GetData().GetHtmlAttribute("datetime", &datetime)) {
2649 SanitizeStringAttributeForIA2(datetime, &datetime);
2650 ia2_attributes_.push_back(L"datetime:" + datetime);
2651 }
2652
2653 // Expose id attribute.
2654 base::string16 id;
2655 if (GetData().GetHtmlAttribute("id", &id)) {
2656 SanitizeStringAttributeForIA2(id, &id);
2657 ia2_attributes_.push_back(L"id:" + id);
2658 }
2659
2660 // Expose src attribute.
2661 base::string16 src;
2662 if (GetData().role == ui::AX_ROLE_IMAGE &&
2663 GetData().GetHtmlAttribute("src", &src)) {
2664 SanitizeStringAttributeForIA2(src, &src);
2665 ia2_attributes_.push_back(L"src:" + src);
2666 }
2667
2668 // Expose input-text type attribute.
2669 base::string16 type;
2670 base::string16 html_tag = GetString16Attribute(ui::AX_ATTR_HTML_TAG);
2671 if (IsSimpleTextControl() && html_tag == L"input" &&
2672 GetData().GetHtmlAttribute("type", &type)) {
2673 SanitizeStringAttributeForIA2(type, &type);
2674 ia2_attributes_.push_back(L"text-input-type:" + type);
2675 }
2676
2677 return ia2_attributes_;
2678 }
2679
2429 bool AXPlatformNodeWin::ShouldNodeHaveReadonlyState( 2680 bool AXPlatformNodeWin::ShouldNodeHaveReadonlyState(
2430 const AXNodeData& data) const { 2681 const AXNodeData& data) const {
2431 if (data.GetBoolAttribute(ui::AX_ATTR_ARIA_READONLY)) 2682 if (data.GetBoolAttribute(ui::AX_ATTR_ARIA_READONLY))
2432 return true; 2683 return true;
2433 2684
2434 if (!data.HasState(ui::AX_STATE_READ_ONLY)) 2685 if (!data.HasState(ui::AX_STATE_READ_ONLY))
2435 return false; 2686 return false;
2436 2687
2437 switch (data.role) { 2688 switch (data.role) {
2438 case ui::AX_ROLE_ARTICLE: 2689 case ui::AX_ROLE_ARTICLE:
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
2760 if (container && container->GetData().role == ui::AX_ROLE_GROUP) 3011 if (container && container->GetData().role == ui::AX_ROLE_GROUP)
2761 container = FromNativeViewAccessible(container->GetParent()); 3012 container = FromNativeViewAccessible(container->GetParent());
2762 3013
2763 if (!container) 3014 if (!container)
2764 return false; 3015 return false;
2765 3016
2766 return container->GetData().role == ui::AX_ROLE_TREE_GRID; 3017 return container->GetData().role == ui::AX_ROLE_TREE_GRID;
2767 } 3018 }
2768 3019
2769 } // namespace ui 3020 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698