Commit a28187dc authored by Olesia Marukhno's avatar Olesia Marukhno Committed by Chromium LUCI CQ

Implement a11y support for permission chip UI

Announce to screenreaders that a permission has requested if chip UI is
used. For prompt UI, the bubble is shown and it takes over the focus.
Chip UI is less intrusive so it must be explicitly annouced for screen
reader users. To avoid users not hearing the announcement, it would be
reannouced after 2 minutes.

Chip UI is now one of the panes (users can cycle through panes with F6). This way users can easily access it with keyboard which is very important for screenreader users.

Also to make sure that users don't miss pending permission request, added message about having pending permission request to tab announcement.

Bug: 1150836

Change-Id: I7118abcf0bed9702cf17d15a9bb59f9a1d8783b6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2578843
Commit-Queue: Olesia Marukhno <olesiamarukhno@google.com>
Reviewed-by: default avatarBret Sepulveda <bsep@chromium.org>
Cr-Commit-Position: refs/heads/master@{#836198}
parent 81d167c5
......@@ -367,6 +367,21 @@ are declared in tools/grit/grit_rule.gni.
</message>
</if>
<if expr="chromeos">
<message name="IDS_PERMISSIONS_REQUESTED_SCREENREADER_ANNOUNCEMENT" desc="Announcement to screen readers on ChromeOS when permission is requested to inform users of how to focus the permission UI.">
Permission requested, press Ctrl + Forward to respond
</message>
</if>
<if expr="is_macosx">
<message name="IDS_PERMISSIONS_REQUESTED_SCREENREADER_ANNOUNCEMENT" desc="Announcement to screen readers on MacOS when permission is requested to inform users of how to focus the permission UI.">
Permission requested, press ⌘ + Option + Up arrow to respond
</message>
</if>
<if expr="is_win or desktop_linux">
<message name="IDS_PERMISSIONS_REQUESTED_SCREENREADER_ANNOUNCEMENT" desc="Announcement to screen readers on Windows or Linux when permission is requested to inform users of how to focus the permission UI.">
Permission requested, press F6 to respond
</message>
</if>
<message name="IDS_PERMISSIONS_BUBBLE_PROMPT" desc="The label that is used to introduce permission request details to the user in a popup.">
<ph name="SITE_NAME">$1<ex>google.com</ex></ph> wants to
</message>
......@@ -9900,6 +9915,21 @@ Please help our engineers fix this problem. Tell us what happened right before y
<message name="IDS_TAB_AX_LABEL_NAMED_GROUP_FORMAT" desc="Accessibility label text for a tab, when it is in a group that has been named by the user. Example: 'Google Search - Part of group MyGroupName'">
<ph name="WINDOW_TITLE">$1<ex>Google Search</ex></ph> - Part of group <ph name="GROUP_NAME">$2</ph>
</message>
<if expr="chromeos">
<message name="IDS_TAB_AX_LABEL_PERMISSION_REQUESTED_FORMAT" desc="Accessibility label text for ChromeOS, when a tab has a pending request. Example: 'Google Search - Permission requested, press F6 to respond'.">
<ph name="WINDOW_TITLE">$1<ex>Google Search</ex></ph> - Permission requested, press Ctrl + Forward to respond
</message>
</if>
<if expr="is_macosx">
<message name="IDS_TAB_AX_LABEL_PERMISSION_REQUESTED_FORMAT" desc="Accessibility label text for MacOS, when a tab has a pending request. Example: 'Google Search - Permission requested, press F6 to respond'.">
<ph name="WINDOW_TITLE">$1<ex>Google Search</ex></ph> - Permission requested, press ⌘ + Option + Up arrow to respond
</message>
</if>
<if expr="is_win or desktop_linux">
<message name="IDS_TAB_AX_LABEL_PERMISSION_REQUESTED_FORMAT" desc="Accessibility label text for Windows or Linux, when a tab has a pending request. Example: 'Google Search - Permission requested, press F6 to respond'.">
<ph name="WINDOW_TITLE">$1<ex>Google Search</ex></ph> - Permission requested, press F6 to respond
</message>
</if>
<message name="IDS_GROUP_AX_LABEL_UNNAMED_GROUP_FORMAT" desc="Spoken by screen readers when a tab group header that has not been named by the user gets focused but is not visually rendered. Example: 'Unnamed group - Google Search and 3 other tabs - Expanded'">
Unnamed group - <ph name="GROUP_CONTENTS">$2<ex>Google Search and 3 other tabs</ex></ph> - <ph name="COLLAPSED_STATE">$1</ph>
</message>
......
28cb556942ba8d8ee5f13b748e024cef038b40fd
\ No newline at end of file
6622e95ade1803f260b2a5b930f235ec9c155787
\ No newline at end of file
......@@ -2300,6 +2300,13 @@ base::string16 BrowserView::GetAccessibleTabLabel(bool include_app_name,
title);
}
// Tab has a pending permission request.
if (toolbar_ && toolbar_->location_bar() &&
toolbar_->location_bar()->permission_chip()->GetVisible()) {
return l10n_util::GetStringFUTF16(
IDS_TAB_AX_LABEL_PERMISSION_REQUESTED_FORMAT, title);
}
// Alert tab states.
base::Optional<TabAlertState> alert = tabstrip_->GetTabAlertState(index);
if (!alert.has_value())
......@@ -2721,6 +2728,11 @@ void BrowserView::GetAccessiblePanes(std::vector<views::View*>* panes) {
if (webui_tab_strip_)
panes->push_back(webui_tab_strip_);
#endif
// When permission is requested, permission chip must be first pane in the
// pane traversal order to be easily accessible for keyboard users.
if (toolbar_ && toolbar_->location_bar()) {
panes->push_back(toolbar_->location_bar()->permission_chip());
}
panes->push_back(toolbar_button_provider_->GetAsAccessiblePaneView());
if (tab_strip_region_view_)
panes->push_back(tab_strip_region_view_);
......
......@@ -14,6 +14,7 @@
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.h"
#include "chrome/browser/ui/views/permission_bubble/permission_prompt_style.h"
#include "chrome/grit/generated_resources.h"
#include "components/permissions/permission_request.h"
#include "components/strings/grit/components_strings.h"
#include "components/vector_icons/vector_icons.h"
......@@ -24,6 +25,7 @@
#include "ui/gfx/color_utils.h"
#include "ui/gfx/favicon_size.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/background.h"
#include "ui/views/controls/button/button_controller.h"
#include "ui/views/controls/image_view.h"
......@@ -140,11 +142,20 @@ void PermissionChip::DisplayRequest(
}
requested_time_ = base::TimeTicks::Now();
PreferredSizeChanged();
AnnouncePermissionRequested();
// In case the user didn't hear the initial alert, reannounce permission again
// with a 2 minute delay.
constexpr auto kDelayBeforeReannouncingRequest =
base::TimeDelta::FromMinutes(2);
announce_timer_.Start(FROM_HERE, kDelayBeforeReannouncingRequest, this,
&PermissionChip::AnnouncePermissionRequested);
}
void PermissionChip::FinalizeRequest() {
SetVisible(false);
timer_.AbandonAndStop();
announce_timer_.AbandonAndStop();
delegate_ = nullptr;
if (prompt_bubble_)
prompt_bubble_->GetWidget()->Close();
......@@ -228,6 +239,9 @@ void PermissionChip::OpenBubble() {
// deactivation.
DCHECK(!prompt_bubble_);
// If the user opens the bubble, they must know about the pending request so
// we don't need to announce it again later.
announce_timer_.AbandonAndStop();
prompt_bubble_ = new PermissionPromptBubbleView(
browser_, delegate_, requested_time_, PermissionPromptStyle::kChip);
prompt_bubble_->Show();
......@@ -304,3 +318,8 @@ base::string16 PermissionChip::GetPermissionMessage() {
: l10n_util::GetStringUTF16(
IDS_MEDIA_CAPTURE_VIDEO_AND_AUDIO_PERMISSION_CHIP);
}
void PermissionChip::AnnouncePermissionRequested() {
GetViewAccessibility().AnnounceText(l10n_util::GetStringUTF16(
IDS_PERMISSIONS_REQUESTED_SCREENREADER_ANNOUNCEMENT));
}
......@@ -10,6 +10,7 @@
#include "components/permissions/permission_request.h"
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/gfx/animation/slide_animation.h"
#include "ui/views/accessible_pane_view.h"
#include "ui/views/animation/animation_delegate_views.h"
#include "ui/views/controls/button/md_text_button.h"
#include "ui/views/widget/widget_observer.h"
......@@ -28,7 +29,7 @@ class BubbleOwnerDelegate {
// A chip view shown in the location bar to notify user about a permission
// request. Shows a permission bubble on click.
class PermissionChip : public views::View,
class PermissionChip : public views::AccessiblePaneView,
public views::AnimationDelegateViews,
public views::WidgetObserver,
public BubbleOwnerDelegate {
......@@ -76,6 +77,7 @@ class PermissionChip : public views::View,
void UpdatePermissionIconAndTextColor();
base::string16 GetPermissionMessage();
const gfx::VectorIcon& GetPermissionIconId();
void AnnouncePermissionRequested();
void AnimateCollapse();
void AnimateExpand();
......@@ -90,6 +92,8 @@ class PermissionChip : public views::View,
// A timer used to collapse the chip after a delay.
base::OneShotTimer timer_;
base::OneShotTimer announce_timer_;
// The button that displays the icon and text.
views::MdTextButton* chip_button_;
......
......@@ -191,7 +191,15 @@ IN_PROC_BROWSER_TEST_P(PermissionPromptBubbleViewBrowserTest,
views::test::AXEventCounter counter(views::AXEventManager::Get());
EXPECT_EQ(0, counter.GetCount(ax::mojom::Event::kAlert));
ShowUi("geolocation");
EXPECT_EQ(1, counter.GetCount(ax::mojom::Event::kAlert));
PermissionChip* permission_chip = GetPermissionChipView();
// If chip UI is used, two notifications will be announced: one that
// permission was requested and second when bubble is opened.
if (permission_chip->GetVisible()) {
EXPECT_EQ(2, counter.GetCount(ax::mojom::Event::kAlert));
} else {
EXPECT_EQ(1, counter.GetCount(ax::mojom::Event::kAlert));
}
}
// Test bubbles showing when tabs move between windows. Simulates a situation
......
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