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

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: Fixed BrowserAccessibilityCocoa::AXInvalid. Created 6 years 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 2961 matching lines...) Expand 10 before | Expand all | Expand 10 after
2972 ui::AX_ATTR_UNIQUE_CELL_IDS); 2972 ui::AX_ATTR_UNIQUE_CELL_IDS);
2973 for (size_t i = 0; i < unique_cell_ids.size(); ++i) { 2973 for (size_t i = 0; i < unique_cell_ids.size(); ++i) {
2974 if (unique_cell_ids[i] == GetId()) { 2974 if (unique_cell_ids[i] == GetId()) {
2975 ia2_attributes_.push_back( 2975 ia2_attributes_.push_back(
2976 base::string16(L"table-cell-index:") + base::IntToString16(i)); 2976 base::string16(L"table-cell-index:") + base::IntToString16(i));
2977 } 2977 }
2978 } 2978 }
2979 } 2979 }
2980 } 2980 }
2981 2981
2982 // Expose invalid state for form controls and elements with aria-invalid.
2983 int invalidState;
dmazzoni 2014/12/19 17:30:33 nit: invalid_state (c++ files in Chromium are like
2984 if (GetIntAttribute(ui::AX_ATTR_INVALID_STATE, &invalidState)) {
2985 // TODO(nektar): Handle the possibility of having multiple aria-invalid
2986 // attributes defined, e.g., "invalid:spelling,grammar".
2987 switch (invalidState) {
2988 case ui::AX_INVALID_STATE_NONE:
2989 break;
2990 case ui::AX_INVALID_STATE_FALSE:
2991 ia2_attributes_.push_back(L"invalid:false");
2992 break;
2993 case ui::AX_INVALID_STATE_TRUE:
2994 ia2_attributes_.push_back(L"invalid:true");
2995 break;
2996 case ui::AX_INVALID_STATE_SPELLING:
2997 ia2_attributes_.push_back(L"invalid:spelling");
2998 break;
2999 case ui::AX_INVALID_STATE_GRAMMAR:
3000 ia2_attributes_.push_back(L"invalid:grammar");
3001 break;
3002 case ui::AX_INVALID_STATE_OTHER:
3003 {
3004 base::string16 ariaInvalidValue;
3005 if (GetString16Attribute(ui::AX_ATTR_ARIA_INVALID_VALUE,
dmazzoni 2014/12/19 17:30:33 nit: you need braces for both the "if" and "else"
3006 &ariaInvalidValue))
3007 ia2_attributes_.push_back(L"invalid:" + ariaInvalidValue);
dmazzoni 2014/12/19 17:30:33 nit: indent 2 less
3008 else
3009 // Set the attribute to L"true", since we cannot be more specific.
3010 ia2_attributes_.push_back(L"invalid:true");
dmazzoni 2014/12/19 17:30:33 nit: indent 2 less
3011 }
3012 break;
3013 default:
3014 NOTREACHED();
3015 }
3016 }
3017
2982 // The calculation of the accessible name of an element has been 3018 // The calculation of the accessible name of an element has been
2983 // standardized in the HTML to Platform Accessibility APIs Implementation 3019 // standardized in the HTML to Platform Accessibility APIs Implementation
2984 // Guide (http://www.w3.org/TR/html-aapi/). In order to return the 3020 // Guide (http://www.w3.org/TR/html-aapi/). In order to return the
2985 // appropriate accessible name on Windows, we need to apply some logic 3021 // appropriate accessible name on Windows, we need to apply some logic
2986 // to the fields we get from WebKit. 3022 // to the fields we get from WebKit.
2987 // 3023 //
2988 // TODO(dmazzoni): move most of this logic into WebKit. 3024 // TODO(dmazzoni): move most of this logic into WebKit.
2989 // 3025 //
2990 // WebKit gives us: 3026 // WebKit gives us:
2991 // 3027 //
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
3278 LONG* offset) { 3314 LONG* offset) {
3279 if (*offset == IA2_TEXT_OFFSET_LENGTH) 3315 if (*offset == IA2_TEXT_OFFSET_LENGTH)
3280 *offset = static_cast<LONG>(text.size()); 3316 *offset = static_cast<LONG>(text.size());
3281 else if (*offset == IA2_TEXT_OFFSET_CARET) 3317 else if (*offset == IA2_TEXT_OFFSET_CARET)
3282 get_caretOffset(offset); 3318 get_caretOffset(offset);
3283 } 3319 }
3284 3320
3285 ui::TextBoundaryType BrowserAccessibilityWin::IA2TextBoundaryToTextBoundary( 3321 ui::TextBoundaryType BrowserAccessibilityWin::IA2TextBoundaryToTextBoundary(
3286 IA2TextBoundaryType ia2_boundary) { 3322 IA2TextBoundaryType ia2_boundary) {
3287 switch(ia2_boundary) { 3323 switch(ia2_boundary) {
3288 case IA2_TEXT_BOUNDARY_CHAR: return ui::CHAR_BOUNDARY; 3324 case IA2_TEXT_BOUNDARY_CHAR:
3289 case IA2_TEXT_BOUNDARY_WORD: return ui::WORD_BOUNDARY; 3325 return ui::CHAR_BOUNDARY;
3290 case IA2_TEXT_BOUNDARY_LINE: return ui::LINE_BOUNDARY; 3326 case IA2_TEXT_BOUNDARY_WORD:
3291 case IA2_TEXT_BOUNDARY_SENTENCE: return ui::SENTENCE_BOUNDARY; 3327 return ui::WORD_BOUNDARY;
3292 case IA2_TEXT_BOUNDARY_PARAGRAPH: return ui::PARAGRAPH_BOUNDARY; 3328 case IA2_TEXT_BOUNDARY_LINE:
3293 case IA2_TEXT_BOUNDARY_ALL: return ui::ALL_BOUNDARY; 3329 return ui::LINE_BOUNDARY;
3330 case IA2_TEXT_BOUNDARY_SENTENCE:
3331 return ui::SENTENCE_BOUNDARY;
3332 case IA2_TEXT_BOUNDARY_PARAGRAPH:
3333 return ui::PARAGRAPH_BOUNDARY;
3334 case IA2_TEXT_BOUNDARY_ALL:
3335 return ui::ALL_BOUNDARY;
3294 default: 3336 default:
3295 NOTREACHED(); 3337 NOTREACHED();
3296 return ui::CHAR_BOUNDARY;
3297 } 3338 }
3339 return ui::CHAR_BOUNDARY;
3298 } 3340 }
3299 3341
3300 LONG BrowserAccessibilityWin::FindBoundary( 3342 LONG BrowserAccessibilityWin::FindBoundary(
3301 const base::string16& text, 3343 const base::string16& text,
3302 IA2TextBoundaryType ia2_boundary, 3344 IA2TextBoundaryType ia2_boundary,
3303 LONG start_offset, 3345 LONG start_offset,
3304 ui::TextBoundaryDirection direction) { 3346 ui::TextBoundaryDirection direction) {
3305 HandleSpecialTextOffset(text, &start_offset); 3347 HandleSpecialTextOffset(text, &start_offset);
3306 ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary); 3348 ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary);
3307 const std::vector<int32>& line_breaks = GetIntListAttribute( 3349 const std::vector<int32>& line_breaks = GetIntListAttribute(
(...skipping 20 matching lines...) Expand all
3328 if (HasState(ui::AX_STATE_EXPANDED)) 3370 if (HasState(ui::AX_STATE_EXPANDED))
3329 ia_state_ |= STATE_SYSTEM_EXPANDED; 3371 ia_state_ |= STATE_SYSTEM_EXPANDED;
3330 if (HasState(ui::AX_STATE_FOCUSABLE)) 3372 if (HasState(ui::AX_STATE_FOCUSABLE))
3331 ia_state_ |= STATE_SYSTEM_FOCUSABLE; 3373 ia_state_ |= STATE_SYSTEM_FOCUSABLE;
3332 if (HasState(ui::AX_STATE_HASPOPUP)) 3374 if (HasState(ui::AX_STATE_HASPOPUP))
3333 ia_state_ |= STATE_SYSTEM_HASPOPUP; 3375 ia_state_ |= STATE_SYSTEM_HASPOPUP;
3334 if (HasState(ui::AX_STATE_HOVERED)) 3376 if (HasState(ui::AX_STATE_HOVERED))
3335 ia_state_ |= STATE_SYSTEM_HOTTRACKED; 3377 ia_state_ |= STATE_SYSTEM_HOTTRACKED;
3336 if (HasState(ui::AX_STATE_INDETERMINATE)) 3378 if (HasState(ui::AX_STATE_INDETERMINATE))
3337 ia_state_ |= STATE_SYSTEM_INDETERMINATE; 3379 ia_state_ |= STATE_SYSTEM_INDETERMINATE;
3380 if (HasIntAttribute(ui::AX_ATTR_INVALID_STATE) &&
3381 GetIntAttribute(ui::AX_ATTR_INVALID_STATE) != ui::AX_INVALID_STATE_FALSE)
3382 ia2_state_ |= IA2_STATE_INVALID_ENTRY;
dmazzoni 2014/12/19 17:30:34 nit: indent 2 less
3338 if (HasState(ui::AX_STATE_INVISIBLE)) 3383 if (HasState(ui::AX_STATE_INVISIBLE))
3339 ia_state_ |= STATE_SYSTEM_INVISIBLE; 3384 ia_state_ |= STATE_SYSTEM_INVISIBLE;
3340 if (HasState(ui::AX_STATE_LINKED)) 3385 if (HasState(ui::AX_STATE_LINKED))
3341 ia_state_ |= STATE_SYSTEM_LINKED; 3386 ia_state_ |= STATE_SYSTEM_LINKED;
3342 if (HasState(ui::AX_STATE_MULTISELECTABLE)) { 3387 if (HasState(ui::AX_STATE_MULTISELECTABLE)) {
3343 ia_state_ |= STATE_SYSTEM_EXTSELECTABLE; 3388 ia_state_ |= STATE_SYSTEM_EXTSELECTABLE;
3344 ia_state_ |= STATE_SYSTEM_MULTISELECTABLE; 3389 ia_state_ |= STATE_SYSTEM_MULTISELECTABLE;
3345 } 3390 }
3346 // TODO(ctguil): Support STATE_SYSTEM_EXTSELECTABLE/accSelect. 3391 // TODO(ctguil): Support STATE_SYSTEM_EXTSELECTABLE/accSelect.
3347 if (HasState(ui::AX_STATE_OFFSCREEN)) 3392 if (HasState(ui::AX_STATE_OFFSCREEN))
(...skipping 18 matching lines...) Expand all
3366 ia2_state_ |= IA2_STATE_HORIZONTAL; 3411 ia2_state_ |= IA2_STATE_HORIZONTAL;
3367 if (HasState(ui::AX_STATE_VISITED)) 3412 if (HasState(ui::AX_STATE_VISITED))
3368 ia_state_ |= STATE_SYSTEM_TRAVERSED; 3413 ia_state_ |= STATE_SYSTEM_TRAVERSED;
3369 3414
3370 // WebKit marks everything as readonly unless it's editable text, so if it's 3415 // WebKit marks everything as readonly unless it's editable text, so if it's
3371 // not readonly, mark it as editable now. The final computation of the 3416 // not readonly, mark it as editable now. The final computation of the
3372 // READONLY state for MSAA is below, after the switch. 3417 // READONLY state for MSAA is below, after the switch.
3373 if (!HasState(ui::AX_STATE_READ_ONLY)) 3418 if (!HasState(ui::AX_STATE_READ_ONLY))
3374 ia2_state_ |= IA2_STATE_EDITABLE; 3419 ia2_state_ |= IA2_STATE_EDITABLE;
3375 3420
3376 base::string16 invalid;
3377 if (GetHtmlAttribute("aria-invalid", &invalid))
3378 ia2_state_ |= IA2_STATE_INVALID_ENTRY;
3379
3380 if (GetBoolAttribute(ui::AX_ATTR_BUTTON_MIXED)) 3421 if (GetBoolAttribute(ui::AX_ATTR_BUTTON_MIXED))
3381 ia_state_ |= STATE_SYSTEM_MIXED; 3422 ia_state_ |= STATE_SYSTEM_MIXED;
3382 3423
3383 if (GetBoolAttribute(ui::AX_ATTR_CAN_SET_VALUE)) 3424 if (GetBoolAttribute(ui::AX_ATTR_CAN_SET_VALUE))
3384 ia2_state_ |= IA2_STATE_EDITABLE; 3425 ia2_state_ |= IA2_STATE_EDITABLE;
3385 3426
3386 if (!GetStringAttribute(ui::AX_ATTR_AUTO_COMPLETE).empty()) 3427 if (!GetStringAttribute(ui::AX_ATTR_AUTO_COMPLETE).empty())
3387 ia2_state_ |= IA2_STATE_SUPPORTS_AUTOCOMPLETION; 3428 ia2_state_ |= IA2_STATE_SUPPORTS_AUTOCOMPLETION;
3388 3429
3389 base::string16 html_tag = GetString16Attribute( 3430 base::string16 html_tag = GetString16Attribute(
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
3831 // The role should always be set. 3872 // The role should always be set.
3832 DCHECK(!role_name_.empty() || ia_role_); 3873 DCHECK(!role_name_.empty() || ia_role_);
3833 3874
3834 // If we didn't explicitly set the IAccessible2 role, make it the same 3875 // If we didn't explicitly set the IAccessible2 role, make it the same
3835 // as the MSAA role. 3876 // as the MSAA role.
3836 if (!ia2_role_) 3877 if (!ia2_role_)
3837 ia2_role_ = ia_role_; 3878 ia2_role_ = ia_role_;
3838 } 3879 }
3839 3880
3840 } // namespace content 3881 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698