Commit f232bf32 authored by Dana Fried's avatar Dana Fried Committed by Commit Bot

Add screen reader support for 'New' feature badging.

See go/newlabel for more information.

This CL adds "this is a new feature" to
the text read by the screen reader, after the hotkey but before the
"item M of N" description.

So for example, a tab context menu item might look like this:
  ...
  Add tab to Read Later [New]     CTRL+SHIFT+Z
  Move tab to new group [New]
  ...

As you scroll through, you will hear:
  "Add tab to read later, control plus shift plus Z, this is a new
   feature, item 4 of 7"
  "Move tab to new group, this is a new feature, item 5 of 7"

Note: The screenshot in the associated png file is of the visual presentation
of the badge, as the actual text read does not appear on-screen.

Bug: 1114082
Change-Id: I758d0b6cb92856e62bde87f9cd55553feb281b3d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2343008Reviewed-by: default avatarPeter Boström <pbos@chromium.org>
Commit-Queue: Dana Fried <dfried@chromium.org>
Cr-Commit-Position: refs/heads/master@{#796157}
parent 2e8f2b9d
......@@ -115,7 +115,7 @@ bool IsRecentTabsCommand(int command_id) {
class FullscreenButton : public ImageButton {
public:
explicit FullscreenButton(views::ButtonListener* listener)
: ImageButton(listener) { }
: ImageButton(listener) {}
FullscreenButton(const FullscreenButton&) = delete;
FullscreenButton& operator=(const FullscreenButton&) = delete;
......@@ -219,13 +219,13 @@ base::string16 GetAccessibleNameForAppMenuItem(ButtonMenuItemModel* model,
ui::Accelerator menu_accelerator;
if (add_accelerator_text &&
model->GetAcceleratorAt(item_index, &menu_accelerator)) {
accelerator_text =
ui::Accelerator(menu_accelerator.key_code(),
menu_accelerator.modifiers()).GetShortcutText();
accelerator_text = ui::Accelerator(menu_accelerator.key_code(),
menu_accelerator.modifiers())
.GetShortcutText();
}
return MenuItemView::GetAccessibleNameForMenuItem(
accessible_name, accelerator_text);
return MenuItemView::GetAccessibleNameForMenuItem(accessible_name,
accelerator_text, false);
}
// A button that lives inside a menu item.
......@@ -402,7 +402,6 @@ class AppMenu::CutCopyPasteView : public AppMenuView {
// ZoomView --------------------------------------------------------------------
// ZoomView contains the various zoom controls: two buttons to increase/decrease
// the zoom, a label showing the current zoom percent, and a button to go
// full-screen.
......@@ -556,9 +555,8 @@ class AppMenu::ZoomView : public AppMenuView {
private:
content::WebContents* GetActiveWebContents() const {
return menu() ?
menu()->browser_->tab_strip_model()->GetActiveWebContents() :
nullptr;
return menu() ? menu()->browser_->tab_strip_model()->GetActiveWebContents()
: nullptr;
}
void OnZoomLevelChanged(const content::HostZoomMap::ZoomLevelChange& change) {
......@@ -572,10 +570,8 @@ class AppMenu::ZoomView : public AppMenuView {
auto* zoom_controller = zoom::ZoomController::FromWebContents(contents);
if (zoom_controller)
zoom = zoom_controller->GetZoomPercent();
increment_button_->SetEnabled(zoom <
contents->GetMaximumZoomPercent());
decrement_button_->SetEnabled(zoom >
contents->GetMinimumZoomPercent());
increment_button_->SetEnabled(zoom < contents->GetMaximumZoomPercent());
decrement_button_->SetEnabled(zoom > contents->GetMinimumZoomPercent());
}
zoom_label_->SetText(base::FormatPercent(zoom));
// An alert notification will ensure that the zoom label is always announced
......@@ -790,15 +786,16 @@ void AppMenu::GetLabelStyle(int command_id, LabelStyle* style) const {
base::string16 AppMenu::GetTooltipText(int command_id,
const gfx::Point& p) const {
return IsBookmarkCommand(command_id) ?
bookmark_menu_delegate_->GetTooltipText(command_id, p) : base::string16();
return IsBookmarkCommand(command_id)
? bookmark_menu_delegate_->GetTooltipText(command_id, p)
: base::string16();
}
bool AppMenu::IsTriggerableEvent(views::MenuItemView* menu,
const ui::Event& e) {
return IsBookmarkCommand(menu->GetCommand()) ?
bookmark_menu_delegate_->IsTriggerableEvent(menu, e) :
MenuDelegate::IsTriggerableEvent(menu, e);
return IsBookmarkCommand(menu->GetCommand())
? bookmark_menu_delegate_->IsTriggerableEvent(menu, e)
: MenuDelegate::IsTriggerableEvent(menu, e);
}
bool AppMenu::GetDropFormats(MenuItemView* menu,
......@@ -806,27 +803,27 @@ bool AppMenu::GetDropFormats(MenuItemView* menu,
std::set<ui::ClipboardFormatType>* format_types) {
CreateBookmarkMenu();
return bookmark_menu_delegate_.get() &&
bookmark_menu_delegate_->GetDropFormats(menu, formats, format_types);
bookmark_menu_delegate_->GetDropFormats(menu, formats, format_types);
}
bool AppMenu::AreDropTypesRequired(MenuItemView* menu) {
CreateBookmarkMenu();
return bookmark_menu_delegate_.get() &&
bookmark_menu_delegate_->AreDropTypesRequired(menu);
bookmark_menu_delegate_->AreDropTypesRequired(menu);
}
bool AppMenu::CanDrop(MenuItemView* menu, const ui::OSExchangeData& data) {
CreateBookmarkMenu();
return bookmark_menu_delegate_.get() &&
bookmark_menu_delegate_->CanDrop(menu, data);
bookmark_menu_delegate_->CanDrop(menu, data);
}
int AppMenu::GetDropOperation(MenuItemView* item,
const ui::DropTargetEvent& event,
DropPosition* position) {
return IsBookmarkCommand(item->GetCommand()) ?
bookmark_menu_delegate_->GetDropOperation(item, event, position) :
ui::DragDropTypes::DRAG_NONE;
return IsBookmarkCommand(item->GetCommand())
? bookmark_menu_delegate_->GetDropOperation(item, event, position)
: ui::DragDropTypes::DRAG_NONE;
}
int AppMenu::OnPerformDrop(MenuItemView* menu,
......@@ -843,15 +840,16 @@ bool AppMenu::ShowContextMenu(MenuItemView* source,
int command_id,
const gfx::Point& p,
ui::MenuSourceType source_type) {
return IsBookmarkCommand(command_id) ?
bookmark_menu_delegate_->ShowContextMenu(source, command_id, p,
source_type) :
false;
return IsBookmarkCommand(command_id)
? bookmark_menu_delegate_->ShowContextMenu(source, command_id, p,
source_type)
: false;
}
bool AppMenu::CanDrag(MenuItemView* menu) {
return IsBookmarkCommand(menu->GetCommand()) ?
bookmark_menu_delegate_->CanDrag(menu) : false;
return IsBookmarkCommand(menu->GetCommand())
? bookmark_menu_delegate_->CanDrag(menu)
: false;
}
void AppMenu::WriteDragData(MenuItemView* sender, ui::OSExchangeData* data) {
......@@ -860,9 +858,9 @@ void AppMenu::WriteDragData(MenuItemView* sender, ui::OSExchangeData* data) {
}
int AppMenu::GetDragOperations(MenuItemView* sender) {
return IsBookmarkCommand(sender->GetCommand()) ?
bookmark_menu_delegate_->GetDragOperations(sender) :
MenuDelegate::GetDragOperations(sender);
return IsBookmarkCommand(sender->GetCommand())
? bookmark_menu_delegate_->GetDragOperations(sender)
: MenuDelegate::GetDragOperations(sender);
}
int AppMenu::GetMaxWidthForMenu(MenuItemView* menu) {
......@@ -905,7 +903,7 @@ bool AppMenu::IsCommandEnabled(int command_id) const {
void AppMenu::ExecuteCommand(int command_id, int mouse_event_flags) {
if (IsBookmarkCommand(command_id)) {
UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.OpenBookmark",
menu_opened_timer_.Elapsed());
menu_opened_timer_.Elapsed());
UMA_HISTOGRAM_ENUMERATION("WrenchMenu.MenuAction",
MENU_ACTION_BOOKMARK_OPEN, LIMIT_MENU_ACTION);
bookmark_menu_delegate_->ExecuteCommand(command_id, mouse_event_flags);
......@@ -963,8 +961,8 @@ void AppMenu::WillHideMenu(MenuItemView* menu) {
// It's okay to just turn off the animation and not turn it back on because
// the menu widget will be recreated next time it's opened. See
// ToolbarView::RunMenu() and Init() of this class.
menu->GetSubmenu()->GetWidget()->
SetVisibilityChangedAnimationsEnabled(false);
menu->GetSubmenu()->GetWidget()->SetVisibilityChangedAnimationsEnabled(
false);
}
}
......@@ -1080,9 +1078,8 @@ void AppMenu::PopulateMenu(MenuItemView* parent, MenuModel* model) {
case IDC_RECENT_TABS_MENU:
DCHECK(!recent_tabs_menu_model_delegate_.get());
recent_tabs_menu_model_delegate_.reset(
new RecentTabsMenuModelDelegate(this, model->GetSubmenuModelAt(i),
item));
recent_tabs_menu_model_delegate_.reset(new RecentTabsMenuModelDelegate(
this, model->GetSubmenuModelAt(i), item));
break;
default:
......@@ -1164,10 +1161,8 @@ void AppMenu::CreateBookmarkMenu() {
browser_->window()->GetNativeWindow());
bookmark_menu_delegate_.reset(
new BookmarkMenuDelegate(browser_, browser_, parent));
bookmark_menu_delegate_->Init(this,
bookmark_menu_,
model->bookmark_bar_node(),
0,
bookmark_menu_delegate_->Init(this, bookmark_menu_,
model->bookmark_bar_node(), 0,
BookmarkMenuDelegate::SHOW_PERMANENT_FOLDERS,
BOOKMARK_LAUNCH_LOCATION_APP_MENU);
}
......
......@@ -384,6 +384,10 @@ need to be translated for each locale.-->
<message name="IDS_MENU_ITEM_NEW_BADGE" desc="Appears as a badge on menu items denoting new features">
New
</message>
<message name="IDS_MENU_ITEM_NEW_BADGE_SCREEN_READER_MESSAGE"
desc="Message appended to screen reader description of menu items which have the 'New' badge">
This is a new feature
</message>
<!-- General application strings -->
<message name="IDS_SENTENCE_END" desc="The symbol that is used to end a sentence.">
......
c88f3adea4b633341c30b3220292ae3cfa4dd50f
\ No newline at end of file
......@@ -219,7 +219,8 @@ void MenuItemView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
} else {
item_text = title_;
}
node_data->SetName(GetAccessibleNameForMenuItem(item_text, GetMinorText()));
node_data->SetName(GetAccessibleNameForMenuItem(item_text, GetMinorText(),
ShouldShowNewBadge()));
switch (type_) {
case Type::kSubMenu:
......@@ -276,7 +277,8 @@ bool MenuItemView::IsBubble(MenuAnchorPosition anchor) {
// static
base::string16 MenuItemView::GetAccessibleNameForMenuItem(
const base::string16& item_text,
const base::string16& minor_text) {
const base::string16& minor_text,
bool is_new_feature) {
base::string16 accessible_name = item_text;
// Filter out the "&" for accessibility clients.
......@@ -298,6 +300,12 @@ base::string16 MenuItemView::GetAccessibleNameForMenuItem(
accessible_name.append(minor_text);
}
if (is_new_feature) {
accessible_name.push_back(' ');
accessible_name.append(l10n_util::GetStringUTF16(
IDS_MENU_ITEM_NEW_BADGE_SCREEN_READER_MESSAGE));
}
return accessible_name;
}
......@@ -762,6 +770,12 @@ void MenuItemView::SetAlerted() {
SchedulePaint();
}
bool MenuItemView::ShouldShowNewBadge() const {
static const bool feature_enabled =
base::FeatureList::IsEnabled(features::kEnableNewBadgeOnMenuItems);
return feature_enabled && is_new_;
}
MenuItemView::MenuItemView(MenuItemView* parent,
int command,
MenuItemView::Type type) {
......@@ -1454,12 +1468,6 @@ bool MenuItemView::HasChecksOrRadioButtons() const {
[](const auto* item) { return item->HasChecksOrRadioButtons(); });
}
bool MenuItemView::ShouldShowNewBadge() const {
static const bool feature_enabled =
base::FeatureList::IsEnabled(features::kEnableNewBadgeOnMenuItems);
return feature_enabled && is_new_;
}
BEGIN_METADATA(MenuItemView)
METADATA_PARENT_CLASS(View)
END_METADATA()
......
......@@ -138,7 +138,8 @@ class VIEWS_EXPORT MenuItemView : public View {
// removed and the menu item accelerator text is appended.
static base::string16 GetAccessibleNameForMenuItem(
const base::string16& item_text,
const base::string16& accelerator_text);
const base::string16& accelerator_text,
bool is_new_feature);
// Hides and cancels the menu. This does nothing if the menu is not open.
void Cancel();
......@@ -353,6 +354,10 @@ class VIEWS_EXPORT MenuItemView : public View {
void SetAlerted();
bool is_alerted() const { return is_alerted_; }
// Returns whether or not a "new" badge should be shown on this menu item.
// Takes into account whether the badging feature is enabled.
bool ShouldShowNewBadge() const;
protected:
// Creates a MenuItemView. This is used by the various AddXXX methods.
MenuItemView(MenuItemView* parent, int command, Type type);
......@@ -491,10 +496,6 @@ class VIEWS_EXPORT MenuItemView : public View {
// Returns true if the menu has items with a checkbox or a radio button.
bool HasChecksOrRadioButtons() const;
// Returns whether or not a "new" badge should be shown on this menu item.
// Takes into account whether the badging feature is enabled.
bool ShouldShowNewBadge() const;
void invalidate_dimensions() { dimensions_.height = 0; }
bool is_dimensions_valid() const { return dimensions_.height > 0; }
......
......@@ -373,8 +373,9 @@ void SubmenuView::SetSelectedRow(int row) {
}
base::string16 SubmenuView::GetTextForRow(int row) {
return MenuItemView::GetAccessibleNameForMenuItem(GetMenuItemAt(row)->title(),
base::string16());
return MenuItemView::GetAccessibleNameForMenuItem(
GetMenuItemAt(row)->title(), base::string16(),
GetMenuItemAt(row)->ShouldShowNewBadge());
}
bool SubmenuView::IsShowing() const {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment