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

Side by Side Diff: ui/accessibility/platform/ax_platform_node_mac.mm

Issue 2706743002: MacViews/a11y: Disable most text-specific attributes for protected textfields. (Closed)
Patch Set: Review comments. Created 3 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 #import "ui/accessibility/platform/ax_platform_node_mac.h" 5 #import "ui/accessibility/platform/ax_platform_node_mac.h"
6 6
7 #import <Cocoa/Cocoa.h> 7 #import <Cocoa/Cocoa.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #include "base/macros.h" 10 #include "base/macros.h"
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 NSAccessibilityEnabledAttribute, 348 NSAccessibilityEnabledAttribute,
349 NSAccessibilityFocusedAttribute, 349 NSAccessibilityFocusedAttribute,
350 NSAccessibilityHelpAttribute, 350 NSAccessibilityHelpAttribute,
351 NSAccessibilityTopLevelUIElementAttribute, 351 NSAccessibilityTopLevelUIElementAttribute,
352 NSAccessibilityWindowAttribute, 352 NSAccessibilityWindowAttribute,
353 ]; 353 ];
354 354
355 // Attributes required for user-editable controls. 355 // Attributes required for user-editable controls.
356 NSArray* const kValueAttributes = @[ NSAccessibilityValueAttribute ]; 356 NSArray* const kValueAttributes = @[ NSAccessibilityValueAttribute ];
357 357
358 // Attributes required for textfields. 358 // Attributes required for unprotected textfields.
359 NSArray* const kTextfieldAttributes = @[ 359 NSArray* const kUnprotectedTextfieldAttributes = @[
360 NSAccessibilityInsertionPointLineNumberAttribute, 360 NSAccessibilityInsertionPointLineNumberAttribute,
361 NSAccessibilityNumberOfCharactersAttribute, 361 NSAccessibilityNumberOfCharactersAttribute,
362 NSAccessibilityPlaceholderValueAttribute,
363 NSAccessibilitySelectedTextAttribute, 362 NSAccessibilitySelectedTextAttribute,
364 NSAccessibilitySelectedTextRangeAttribute, 363 NSAccessibilitySelectedTextRangeAttribute,
365 NSAccessibilityVisibleCharacterRangeAttribute, 364 NSAccessibilityVisibleCharacterRangeAttribute,
366 ]; 365 ];
367 366
367 // Required for all textfields, including protected ones.
368 NSString* const kTextfieldAttributes =
369 NSAccessibilityPlaceholderValueAttribute;
370
368 base::scoped_nsobject<NSMutableArray> axAttributes( 371 base::scoped_nsobject<NSMutableArray> axAttributes(
369 [[NSMutableArray alloc] init]); 372 [[NSMutableArray alloc] init]);
370 373
371 [axAttributes addObjectsFromArray:kAllRoleAttributes]; 374 [axAttributes addObjectsFromArray:kAllRoleAttributes];
372 switch (node_->GetData().role) { 375 switch (node_->GetData().role) {
373 case ui::AX_ROLE_TEXT_FIELD: 376 case ui::AX_ROLE_TEXT_FIELD:
374 [axAttributes addObjectsFromArray:kTextfieldAttributes]; 377 [axAttributes addObject:kTextfieldAttributes];
378 if (!ui::AXNodeData::IsFlagSet(node_->GetData().state,
379 ui::AX_STATE_PROTECTED)) {
380 [axAttributes addObjectsFromArray:kUnprotectedTextfieldAttributes];
381 }
375 // Fallthrough. 382 // Fallthrough.
376 case ui::AX_ROLE_CHECK_BOX: 383 case ui::AX_ROLE_CHECK_BOX:
377 case ui::AX_ROLE_COMBO_BOX: 384 case ui::AX_ROLE_COMBO_BOX:
378 case ui::AX_ROLE_MENU_ITEM_CHECK_BOX: 385 case ui::AX_ROLE_MENU_ITEM_CHECK_BOX:
379 case ui::AX_ROLE_MENU_ITEM_RADIO: 386 case ui::AX_ROLE_MENU_ITEM_RADIO:
380 case ui::AX_ROLE_RADIO_BUTTON: 387 case ui::AX_ROLE_RADIO_BUTTON:
381 case ui::AX_ROLE_SEARCH_BOX: 388 case ui::AX_ROLE_SEARCH_BOX:
382 case ui::AX_ROLE_SLIDER: 389 case ui::AX_ROLE_SLIDER:
383 case ui::AX_ROLE_SLIDER_THUMB: 390 case ui::AX_ROLE_SLIDER_THUMB:
384 case ui::AX_ROLE_TOGGLE_BUTTON: 391 case ui::AX_ROLE_TOGGLE_BUTTON:
(...skipping 13 matching lines...) Expand all
398 // Allow certain attributes to be written via an accessibility client. A 405 // Allow certain attributes to be written via an accessibility client. A
399 // writable attribute will only appear as such if the accessibility element 406 // writable attribute will only appear as such if the accessibility element
400 // has a value set for that attribute. 407 // has a value set for that attribute.
401 if ([attributeName 408 if ([attributeName
402 isEqualToString:NSAccessibilitySelectedChildrenAttribute] || 409 isEqualToString:NSAccessibilitySelectedChildrenAttribute] ||
403 [attributeName 410 [attributeName
404 isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) { 411 isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) {
405 return NO; 412 return NO;
406 } 413 }
407 414
408 // Since tabs use the Radio Button role on Mac, the standard way to set them 415 if ([attributeName isEqualToString:NSAccessibilityValueAttribute]) {
409 // is via the value attribute rather than the selected attribute. 416 if (node_->GetData().HasStateFlag(ui::AX_STATE_PROTECTED)) {
410 if ([attributeName isEqualToString:NSAccessibilityValueAttribute] && 417 // NSSecureTextField doesn't allow values to be edited (despite showing up
411 node_->GetData().role == ui::AX_ROLE_TAB) { 418 // as editable), match its behavior.
412 return !node_->GetData().HasStateFlag(ui::AX_STATE_SELECTED); 419 return NO;
420 }
421 // Since tabs use the Radio Button role on Mac, the standard way to set
422 // them is via the value attribute rather than the selected attribute.
423 else if (node_->GetData().role == ui::AX_ROLE_TAB) {
tapted 2017/02/24 05:23:42 nit: remove "else" (since the prior `if` always re
Patti Lor 2017/02/26 23:16:37 Done.
424 return !node_->GetData().HasStateFlag(ui::AX_STATE_SELECTED);
425 }
413 } 426 }
414 427
415 if ([attributeName isEqualToString:NSAccessibilityValueAttribute] || 428 if ([attributeName isEqualToString:NSAccessibilityValueAttribute] ||
416 [attributeName isEqualToString:NSAccessibilitySelectedTextAttribute] || 429 [attributeName isEqualToString:NSAccessibilitySelectedTextAttribute] ||
417 [attributeName 430 [attributeName
418 isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) { 431 isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
419 return !ui::AXNodeData::IsFlagSet(node_->GetData().state, 432 return !ui::AXNodeData::IsFlagSet(node_->GetData().state,
420 ui::AX_STATE_READ_ONLY); 433 ui::AX_STATE_READ_ONLY);
421 } 434 }
422 435
423 if ([attributeName isEqualToString:NSAccessibilityFocusedAttribute]) { 436 if ([attributeName isEqualToString:NSAccessibilityFocusedAttribute]) {
424 return ui::AXNodeData::IsFlagSet(node_->GetData().state, 437 return ui::AXNodeData::IsFlagSet(node_->GetData().state,
425 ui::AX_STATE_FOCUSABLE); 438 ui::AX_STATE_FOCUSABLE);
426 } 439 }
427 440
428 // TODO(patricialor): Add callbacks for updating the above attributes except 441 // TODO(patricialor): Add callbacks for updating the above attributes except
429 // NSAccessibilityValueAttribute and return YES. 442 // NSAccessibilityValueAttribute and return YES.
430 return NO; 443 return NO;
431 } 444 }
432 445
433 - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute { 446 - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute {
434 ui::AXActionData data; 447 ui::AXActionData data;
435 448
436 // Check for attributes first. Only the |data.action| should be set here - any 449 // Check for attributes first. Only the |data.action| should be set here - any
437 // type-specific information, if needed, should be set below. 450 // type-specific information, if needed, should be set below.
438 if ([attribute isEqualToString:NSAccessibilityValueAttribute]) { 451 if ([attribute isEqualToString:NSAccessibilityValueAttribute] &&
452 !node_->GetData().HasStateFlag(ui::AX_STATE_PROTECTED)) {
439 data.action = node_->GetData().role == ui::AX_ROLE_TAB 453 data.action = node_->GetData().role == ui::AX_ROLE_TAB
440 ? ui::AX_ACTION_SET_SELECTION 454 ? ui::AX_ACTION_SET_SELECTION
441 : ui::AX_ACTION_SET_VALUE; 455 : ui::AX_ACTION_SET_VALUE;
442 } else if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) { 456 } else if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) {
443 data.action = ui::AX_ACTION_REPLACE_SELECTED_TEXT; 457 data.action = ui::AX_ACTION_REPLACE_SELECTED_TEXT;
444 } else if ([attribute 458 } else if ([attribute
445 isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) { 459 isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
446 data.action = ui::AX_ACTION_SET_SELECTION; 460 data.action = ui::AX_ACTION_SET_SELECTION;
447 } else if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { 461 } else if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
448 if ([value isKindOfClass:[NSNumber class]]) { 462 if ([value isKindOfClass:[NSNumber class]]) {
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 return @(node_->GetData().HasStateFlag(ui::AX_STATE_SELECTED)); 590 return @(node_->GetData().HasStateFlag(ui::AX_STATE_SELECTED));
577 } 591 }
578 592
579 - (NSString*)AXPlaceholderValue { 593 - (NSString*)AXPlaceholderValue {
580 return [self getStringAttribute:ui::AX_ATTR_PLACEHOLDER]; 594 return [self getStringAttribute:ui::AX_ATTR_PLACEHOLDER];
581 } 595 }
582 596
583 // Text-specific attributes. 597 // Text-specific attributes.
584 598
585 - (NSString*)AXSelectedText { 599 - (NSString*)AXSelectedText {
600 if (ui::AXNodeData::IsFlagSet(node_->GetData().state, ui::AX_STATE_PROTECTED))
601 return nil;
602
586 NSRange selectedTextRange; 603 NSRange selectedTextRange;
587 [[self AXSelectedTextRange] getValue:&selectedTextRange]; 604 [[self AXSelectedTextRange] getValue:&selectedTextRange];
588 return [[self AXValue] substringWithRange:selectedTextRange]; 605 return [[self AXValue] substringWithRange:selectedTextRange];
589 } 606 }
590 607
591 - (NSValue*)AXSelectedTextRange { 608 - (NSValue*)AXSelectedTextRange {
609 if (ui::AXNodeData::IsFlagSet(node_->GetData().state, ui::AX_STATE_PROTECTED))
610 return nil;
611
592 int textDir, start, end; 612 int textDir, start, end;
593 node_->GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION, &textDir); 613 node_->GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION, &textDir);
594 node_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, &start); 614 node_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, &start);
595 node_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, &end); 615 node_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, &end);
596 // NSRange cannot represent the direction the text was selected in, so make 616 // NSRange cannot represent the direction the text was selected in, so make
597 // sure the correct selection index is used when creating a new range, taking 617 // sure the correct selection index is used when creating a new range, taking
598 // into account the textfield text direction as well. 618 // into account the textfield text direction as well.
599 bool isReversed = (textDir == ui::AX_TEXT_DIRECTION_RTL) || 619 bool isReversed = (textDir == ui::AX_TEXT_DIRECTION_RTL) ||
600 (textDir == ui::AX_TEXT_DIRECTION_BTT); 620 (textDir == ui::AX_TEXT_DIRECTION_BTT);
601 int beginSelectionIndex = (end > start && !isReversed) ? start : end; 621 int beginSelectionIndex = (end > start && !isReversed) ? start : end;
602 return [NSValue valueWithRange:{beginSelectionIndex, abs(end - start)}]; 622 return [NSValue valueWithRange:{beginSelectionIndex, abs(end - start)}];
603 } 623 }
604 624
605 - (NSNumber*)AXNumberOfCharacters { 625 - (NSNumber*)AXNumberOfCharacters {
626 if (ui::AXNodeData::IsFlagSet(node_->GetData().state, ui::AX_STATE_PROTECTED))
627 return nil;
606 return @([[self AXValue] length]); 628 return @([[self AXValue] length]);
607 } 629 }
608 630
609 - (NSValue*)AXVisibleCharacterRange { 631 - (NSValue*)AXVisibleCharacterRange {
632 if (ui::AXNodeData::IsFlagSet(node_->GetData().state, ui::AX_STATE_PROTECTED))
633 return nil;
610 return [NSValue valueWithRange:{0, [[self AXNumberOfCharacters] intValue]}]; 634 return [NSValue valueWithRange:{0, [[self AXNumberOfCharacters] intValue]}];
611 } 635 }
612 636
613 - (NSNumber*)AXInsertionPointLineNumber { 637 - (NSNumber*)AXInsertionPointLineNumber {
638 if (ui::AXNodeData::IsFlagSet(node_->GetData().state, ui::AX_STATE_PROTECTED))
639 return nil;
614 // Multiline is not supported on views. 640 // Multiline is not supported on views.
615 return @0; 641 return @0;
616 } 642 }
617 643
618 @end 644 @end
619 645
620 namespace ui { 646 namespace ui {
621 647
622 // static 648 // static
623 AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) { 649 AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 } 687 }
662 NotifyMacEvent(native_node_, event_type); 688 NotifyMacEvent(native_node_, event_type);
663 } 689 }
664 690
665 int AXPlatformNodeMac::GetIndexInParent() { 691 int AXPlatformNodeMac::GetIndexInParent() {
666 // TODO(dmazzoni): implement this. http://crbug.com/396137 692 // TODO(dmazzoni): implement this. http://crbug.com/396137
667 return -1; 693 return -1;
668 } 694 }
669 695
670 } // namespace ui 696 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698