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

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

Issue 790003003: Exposed the invalid state of form controls to the accessibility APIs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Tried fixing Android unit tests. Created 5 years, 11 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 "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
(...skipping 2962 matching lines...) Expand 10 before | Expand all | Expand 10 after
2973 ui::AX_ATTR_UNIQUE_CELL_IDS); 2973 ui::AX_ATTR_UNIQUE_CELL_IDS);
2974 for (size_t i = 0; i < unique_cell_ids.size(); ++i) { 2974 for (size_t i = 0; i < unique_cell_ids.size(); ++i) {
2975 if (unique_cell_ids[i] == GetId()) { 2975 if (unique_cell_ids[i] == GetId()) {
2976 ia2_attributes_.push_back( 2976 ia2_attributes_.push_back(
2977 base::string16(L"table-cell-index:") + base::IntToString16(i)); 2977 base::string16(L"table-cell-index:") + base::IntToString16(i));
2978 } 2978 }
2979 } 2979 }
2980 } 2980 }
2981 } 2981 }
2982 2982
2983 // Expose invalid state for form controls and elements with aria-invalid.
2984 int invalid_state;
2985 if (GetIntAttribute(ui::AX_ATTR_INVALID_STATE, &invalid_state)) {
2986 // TODO(nektar): Handle the possibility of having multiple aria-invalid
2987 // attributes defined, e.g., "invalid:spelling,grammar".
2988 switch (invalid_state) {
2989 case ui::AX_INVALID_STATE_NONE:
2990 break;
2991 case ui::AX_INVALID_STATE_FALSE:
2992 ia2_attributes_.push_back(L"invalid:false");
2993 break;
2994 case ui::AX_INVALID_STATE_TRUE:
2995 ia2_attributes_.push_back(L"invalid:true");
2996 break;
2997 case ui::AX_INVALID_STATE_SPELLING:
2998 ia2_attributes_.push_back(L"invalid:spelling");
2999 break;
3000 case ui::AX_INVALID_STATE_GRAMMAR:
3001 ia2_attributes_.push_back(L"invalid:grammar");
3002 break;
3003 case ui::AX_INVALID_STATE_OTHER:
3004 {
3005 base::string16 aria_invalid_value;
3006 if (GetString16Attribute(ui::AX_ATTR_ARIA_INVALID_VALUE,
3007 &aria_invalid_value)) {
3008 ia2_attributes_.push_back(L"invalid:" + aria_invalid_value);
3009 } else {
3010 // Set the attribute to L"true", since we cannot be more specific.
3011 ia2_attributes_.push_back(L"invalid:true");
3012 }
3013 }
3014 break;
3015 default:
3016 NOTREACHED();
3017 }
3018 }
3019
2983 // The calculation of the accessible name of an element has been 3020 // The calculation of the accessible name of an element has been
2984 // standardized in the HTML to Platform Accessibility APIs Implementation 3021 // standardized in the HTML to Platform Accessibility APIs Implementation
2985 // Guide (http://www.w3.org/TR/html-aapi/). In order to return the 3022 // Guide (http://www.w3.org/TR/html-aapi/). In order to return the
2986 // appropriate accessible name on Windows, we need to apply some logic 3023 // appropriate accessible name on Windows, we need to apply some logic
2987 // to the fields we get from WebKit. 3024 // to the fields we get from WebKit.
2988 // 3025 //
2989 // TODO(dmazzoni): move most of this logic into WebKit. 3026 // TODO(dmazzoni): move most of this logic into WebKit.
2990 // 3027 //
2991 // WebKit gives us: 3028 // WebKit gives us:
2992 // 3029 //
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
3287 LONG* offset) { 3324 LONG* offset) {
3288 if (*offset == IA2_TEXT_OFFSET_LENGTH) 3325 if (*offset == IA2_TEXT_OFFSET_LENGTH)
3289 *offset = static_cast<LONG>(text.size()); 3326 *offset = static_cast<LONG>(text.size());
3290 else if (*offset == IA2_TEXT_OFFSET_CARET) 3327 else if (*offset == IA2_TEXT_OFFSET_CARET)
3291 get_caretOffset(offset); 3328 get_caretOffset(offset);
3292 } 3329 }
3293 3330
3294 ui::TextBoundaryType BrowserAccessibilityWin::IA2TextBoundaryToTextBoundary( 3331 ui::TextBoundaryType BrowserAccessibilityWin::IA2TextBoundaryToTextBoundary(
3295 IA2TextBoundaryType ia2_boundary) { 3332 IA2TextBoundaryType ia2_boundary) {
3296 switch(ia2_boundary) { 3333 switch(ia2_boundary) {
3297 case IA2_TEXT_BOUNDARY_CHAR: return ui::CHAR_BOUNDARY; 3334 case IA2_TEXT_BOUNDARY_CHAR:
3298 case IA2_TEXT_BOUNDARY_WORD: return ui::WORD_BOUNDARY; 3335 return ui::CHAR_BOUNDARY;
3299 case IA2_TEXT_BOUNDARY_LINE: return ui::LINE_BOUNDARY; 3336 case IA2_TEXT_BOUNDARY_WORD:
3300 case IA2_TEXT_BOUNDARY_SENTENCE: return ui::SENTENCE_BOUNDARY; 3337 return ui::WORD_BOUNDARY;
3301 case IA2_TEXT_BOUNDARY_PARAGRAPH: return ui::PARAGRAPH_BOUNDARY; 3338 case IA2_TEXT_BOUNDARY_LINE:
3302 case IA2_TEXT_BOUNDARY_ALL: return ui::ALL_BOUNDARY; 3339 return ui::LINE_BOUNDARY;
3340 case IA2_TEXT_BOUNDARY_SENTENCE:
3341 return ui::SENTENCE_BOUNDARY;
3342 case IA2_TEXT_BOUNDARY_PARAGRAPH:
3343 return ui::PARAGRAPH_BOUNDARY;
3344 case IA2_TEXT_BOUNDARY_ALL:
3345 return ui::ALL_BOUNDARY;
3303 default: 3346 default:
3304 NOTREACHED(); 3347 NOTREACHED();
3305 return ui::CHAR_BOUNDARY;
3306 } 3348 }
3349 return ui::CHAR_BOUNDARY;
3307 } 3350 }
3308 3351
3309 LONG BrowserAccessibilityWin::FindBoundary( 3352 LONG BrowserAccessibilityWin::FindBoundary(
3310 const base::string16& text, 3353 const base::string16& text,
3311 IA2TextBoundaryType ia2_boundary, 3354 IA2TextBoundaryType ia2_boundary,
3312 LONG start_offset, 3355 LONG start_offset,
3313 ui::TextBoundaryDirection direction) { 3356 ui::TextBoundaryDirection direction) {
3314 HandleSpecialTextOffset(text, &start_offset); 3357 HandleSpecialTextOffset(text, &start_offset);
3315 ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary); 3358 ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary);
3316 const std::vector<int32>& line_breaks = GetIntListAttribute( 3359 const std::vector<int32>& line_breaks = GetIntListAttribute(
(...skipping 20 matching lines...) Expand all
3337 if (HasState(ui::AX_STATE_EXPANDED)) 3380 if (HasState(ui::AX_STATE_EXPANDED))
3338 ia_state_ |= STATE_SYSTEM_EXPANDED; 3381 ia_state_ |= STATE_SYSTEM_EXPANDED;
3339 if (HasState(ui::AX_STATE_FOCUSABLE)) 3382 if (HasState(ui::AX_STATE_FOCUSABLE))
3340 ia_state_ |= STATE_SYSTEM_FOCUSABLE; 3383 ia_state_ |= STATE_SYSTEM_FOCUSABLE;
3341 if (HasState(ui::AX_STATE_HASPOPUP)) 3384 if (HasState(ui::AX_STATE_HASPOPUP))
3342 ia_state_ |= STATE_SYSTEM_HASPOPUP; 3385 ia_state_ |= STATE_SYSTEM_HASPOPUP;
3343 if (HasState(ui::AX_STATE_HOVERED)) 3386 if (HasState(ui::AX_STATE_HOVERED))
3344 ia_state_ |= STATE_SYSTEM_HOTTRACKED; 3387 ia_state_ |= STATE_SYSTEM_HOTTRACKED;
3345 if (HasState(ui::AX_STATE_INDETERMINATE)) 3388 if (HasState(ui::AX_STATE_INDETERMINATE))
3346 ia_state_ |= STATE_SYSTEM_INDETERMINATE; 3389 ia_state_ |= STATE_SYSTEM_INDETERMINATE;
3390 if (HasIntAttribute(ui::AX_ATTR_INVALID_STATE) &&
3391 GetIntAttribute(ui::AX_ATTR_INVALID_STATE) != ui::AX_INVALID_STATE_FALSE)
3392 ia2_state_ |= IA2_STATE_INVALID_ENTRY;
3347 if (HasState(ui::AX_STATE_INVISIBLE)) 3393 if (HasState(ui::AX_STATE_INVISIBLE))
3348 ia_state_ |= STATE_SYSTEM_INVISIBLE; 3394 ia_state_ |= STATE_SYSTEM_INVISIBLE;
3349 if (HasState(ui::AX_STATE_LINKED)) 3395 if (HasState(ui::AX_STATE_LINKED))
3350 ia_state_ |= STATE_SYSTEM_LINKED; 3396 ia_state_ |= STATE_SYSTEM_LINKED;
3351 if (HasState(ui::AX_STATE_MULTISELECTABLE)) { 3397 if (HasState(ui::AX_STATE_MULTISELECTABLE)) {
3352 ia_state_ |= STATE_SYSTEM_EXTSELECTABLE; 3398 ia_state_ |= STATE_SYSTEM_EXTSELECTABLE;
3353 ia_state_ |= STATE_SYSTEM_MULTISELECTABLE; 3399 ia_state_ |= STATE_SYSTEM_MULTISELECTABLE;
3354 } 3400 }
3355 // TODO(ctguil): Support STATE_SYSTEM_EXTSELECTABLE/accSelect. 3401 // TODO(ctguil): Support STATE_SYSTEM_EXTSELECTABLE/accSelect.
3356 if (HasState(ui::AX_STATE_OFFSCREEN)) 3402 if (HasState(ui::AX_STATE_OFFSCREEN))
(...skipping 18 matching lines...) Expand all
3375 ia2_state_ |= IA2_STATE_HORIZONTAL; 3421 ia2_state_ |= IA2_STATE_HORIZONTAL;
3376 if (HasState(ui::AX_STATE_VISITED)) 3422 if (HasState(ui::AX_STATE_VISITED))
3377 ia_state_ |= STATE_SYSTEM_TRAVERSED; 3423 ia_state_ |= STATE_SYSTEM_TRAVERSED;
3378 3424
3379 // WebKit marks everything as readonly unless it's editable text, so if it's 3425 // WebKit marks everything as readonly unless it's editable text, so if it's
3380 // not readonly, mark it as editable now. The final computation of the 3426 // not readonly, mark it as editable now. The final computation of the
3381 // READONLY state for MSAA is below, after the switch. 3427 // READONLY state for MSAA is below, after the switch.
3382 if (!HasState(ui::AX_STATE_READ_ONLY)) 3428 if (!HasState(ui::AX_STATE_READ_ONLY))
3383 ia2_state_ |= IA2_STATE_EDITABLE; 3429 ia2_state_ |= IA2_STATE_EDITABLE;
3384 3430
3385 base::string16 invalid;
3386 if (GetHtmlAttribute("aria-invalid", &invalid))
3387 ia2_state_ |= IA2_STATE_INVALID_ENTRY;
3388
3389 if (GetBoolAttribute(ui::AX_ATTR_BUTTON_MIXED)) 3431 if (GetBoolAttribute(ui::AX_ATTR_BUTTON_MIXED))
3390 ia_state_ |= STATE_SYSTEM_MIXED; 3432 ia_state_ |= STATE_SYSTEM_MIXED;
3391 3433
3392 if (GetBoolAttribute(ui::AX_ATTR_CAN_SET_VALUE)) 3434 if (GetBoolAttribute(ui::AX_ATTR_CAN_SET_VALUE))
3393 ia2_state_ |= IA2_STATE_EDITABLE; 3435 ia2_state_ |= IA2_STATE_EDITABLE;
3394 3436
3395 if (!GetStringAttribute(ui::AX_ATTR_AUTO_COMPLETE).empty()) 3437 if (!GetStringAttribute(ui::AX_ATTR_AUTO_COMPLETE).empty())
3396 ia2_state_ |= IA2_STATE_SUPPORTS_AUTOCOMPLETION; 3438 ia2_state_ |= IA2_STATE_SUPPORTS_AUTOCOMPLETION;
3397 3439
3398 base::string16 html_tag = GetString16Attribute( 3440 base::string16 html_tag = GetString16Attribute(
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
3851 // The role should always be set. 3893 // The role should always be set.
3852 DCHECK(!role_name_.empty() || ia_role_); 3894 DCHECK(!role_name_.empty() || ia_role_);
3853 3895
3854 // If we didn't explicitly set the IAccessible2 role, make it the same 3896 // If we didn't explicitly set the IAccessible2 role, make it the same
3855 // as the MSAA role. 3897 // as the MSAA role.
3856 if (!ia2_role_) 3898 if (!ia2_role_)
3857 ia2_role_ = ia_role_; 3899 ia2_role_ = ia_role_;
3858 } 3900 }
3859 3901
3860 } // namespace content 3902 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698