Commit 17172936 authored by Rachel Wong's avatar Rachel Wong Committed by Commit Bot

[privacy view] Fix a11y bugs in the launcher notice.

This CL does the following:
- Remove the default focus action. This allows ChromeVox to immediately
  select and read out the notice when the search box is opened.
- Make all of the text behave as one entity for ChromeVox, which can
  also activate it as the link.
- Use the AppListColorProvider to get the correct shading color when
  the close button is focused. This ensures that the color will still
  contrast with the background in dark mode.

Bug: 1112714
Change-Id: I798d532a030a0f331845ab440b8f6aabced46af0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2463024
Commit-Queue: Rachel Wong <wrong@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#815885}
parent 5c3231cd
...@@ -43,22 +43,26 @@ constexpr int kRightPaddingDip = 4; ...@@ -43,22 +43,26 @@ constexpr int kRightPaddingDip = 4;
constexpr int kCellSpacingDip = 18; constexpr int kCellSpacingDip = 18;
constexpr int kIconSizeDip = 20; constexpr int kIconSizeDip = 20;
// Link view used inside the privacy notice. // Text view used inside the privacy notice.
class PrivacyLinkView : public views::Link { class PrivacyTextView : public views::StyledLabel {
public: public:
explicit PrivacyLinkView(const base::string16& title) : Link(title) {} explicit PrivacyTextView(PrivacyInfoView* privacy_view)
: StyledLabel(), privacy_view_(privacy_view) {}
// views::View: // views::View:
bool HandleAccessibleAction(const ui::AXActionData& action_data) override { bool HandleAccessibleAction(const ui::AXActionData& action_data) override {
switch (action_data.action) { switch (action_data.action) {
case ax::mojom::Action::kFocus: case ax::mojom::Action::kDoDefault:
// Do nothing because the search box needs to keep focus. privacy_view_->LinkClicked();
return true; return true;
default: default:
break; break;
} }
return views::Link::HandleAccessibleAction(action_data); return views::StyledLabel::HandleAccessibleAction(action_data);
} }
private:
PrivacyInfoView* const privacy_view_; // Not owned.
}; };
} // namespace } // namespace
...@@ -97,7 +101,9 @@ void PrivacyInfoView::OnPaintBackground(gfx::Canvas* canvas) { ...@@ -97,7 +101,9 @@ void PrivacyInfoView::OnPaintBackground(gfx::Canvas* canvas) {
if (selected_action_ == Action::kCloseButton) { if (selected_action_ == Action::kCloseButton) {
cc::PaintFlags flags; cc::PaintFlags flags;
flags.setAntiAlias(true); flags.setAntiAlias(true);
flags.setColor(SkColorSetA(gfx::kGoogleGrey900, 0x14)); flags.setColor(SkColorSetA(
AppListColorProvider::Get()->GetSearchResultViewHighlightColor(),
0x14));
flags.setStyle(cc::PaintFlags::kFill_Style); flags.setStyle(cc::PaintFlags::kFill_Style);
canvas->DrawCircle(close_button_->bounds().CenterPoint(), canvas->DrawCircle(close_button_->bounds().CenterPoint(),
close_button_->width() / 2, flags); close_button_->width() / 2, flags);
...@@ -147,7 +153,6 @@ void PrivacyInfoView::OnKeyEvent(ui::KeyEvent* event) { ...@@ -147,7 +153,6 @@ void PrivacyInfoView::OnKeyEvent(ui::KeyEvent* event) {
CloseButtonPressed(); CloseButtonPressed();
break; break;
case Action::kNone: case Action::kNone:
case Action::kDefault:
break; break;
} }
} }
...@@ -155,14 +160,8 @@ void PrivacyInfoView::OnKeyEvent(ui::KeyEvent* event) { ...@@ -155,14 +160,8 @@ void PrivacyInfoView::OnKeyEvent(ui::KeyEvent* event) {
void PrivacyInfoView::SelectInitialResultAction(bool reverse_tab_order) { void PrivacyInfoView::SelectInitialResultAction(bool reverse_tab_order) {
if (!reverse_tab_order) { if (!reverse_tab_order) {
if (is_default_result()) { selected_action_ = Action::kTextLink;
// Hold the selection but do nothing. This is so that the text view is not text_view_->NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true);
// selected immediately after the launcher opens.
selected_action_ = Action::kDefault;
} else {
selected_action_ = Action::kTextLink;
text_view_->NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true);
}
} else { } else {
selected_action_ = Action::kCloseButton; selected_action_ = Action::kCloseButton;
close_button_->NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true); close_button_->NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true);
...@@ -174,48 +173,20 @@ void PrivacyInfoView::SelectInitialResultAction(bool reverse_tab_order) { ...@@ -174,48 +173,20 @@ void PrivacyInfoView::SelectInitialResultAction(bool reverse_tab_order) {
} }
bool PrivacyInfoView::SelectNextResultAction(bool reverse_tab_order) { bool PrivacyInfoView::SelectNextResultAction(bool reverse_tab_order) {
// There are three selection elements: default -> text view -> close button.
// The default selection is not traversed if selection is caused by user
// action.
bool action_changed = false; bool action_changed = false;
if (!reverse_tab_order) { // There are two traversal elements, the text view and close button.
switch (selected_action_) { if (!reverse_tab_order && selected_action_ == Action::kTextLink) {
case Action::kDefault: // Move selection forward from the text view to the close button.
// Move selection forward from default to the text view. selected_action_ = Action::kCloseButton;
selected_action_ = Action::kTextLink; close_button_->NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true);
text_view_->NotifyAccessibilityEvent(ax::mojom::Event::kSelection, action_changed = true;
true); } else if (reverse_tab_order && selected_action_ == Action::kCloseButton) {
action_changed = true; // Move selection backward from the close button to the text view.
break; selected_action_ = Action::kTextLink;
case Action::kTextLink: text_view_->NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true);
// Move selection forward from the text view to the close button. action_changed = true;
selected_action_ = Action::kCloseButton;
close_button_->NotifyAccessibilityEvent(ax::mojom::Event::kSelection,
true);
action_changed = true;
break;
case Action::kNone:
case Action::kCloseButton:
break;
}
} else { } else {
switch (selected_action_) {
case Action::kCloseButton:
// Move selection backward from the close button to the text view.
selected_action_ = Action::kTextLink;
text_view_->NotifyAccessibilityEvent(ax::mojom::Event::kSelection,
true);
action_changed = true;
break;
case Action::kNone:
case Action::kDefault:
case Action::kTextLink:
break;
}
}
if (!action_changed) {
selected_action_ = Action::kNone; selected_action_ = Action::kNone;
} }
...@@ -226,9 +197,17 @@ bool PrivacyInfoView::SelectNextResultAction(bool reverse_tab_order) { ...@@ -226,9 +197,17 @@ bool PrivacyInfoView::SelectNextResultAction(bool reverse_tab_order) {
} }
void PrivacyInfoView::NotifyA11yResultSelected() { void PrivacyInfoView::NotifyA11yResultSelected() {
// Do not notify when this view is selected by default. Notifications for the switch (selected_action_) {
// child views are handled by SelectInitialResultAction and case Action::kTextLink:
// SelectNextResultAction. text_view_->NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true);
break;
case Action::kCloseButton:
close_button_->NotifyAccessibilityEvent(ax::mojom::Event::kSelection,
true);
break;
case Action::kNone:
break;
}
} }
void PrivacyInfoView::ButtonPressed(views::Button* sender, void PrivacyInfoView::ButtonPressed(views::Button* sender,
...@@ -277,13 +256,12 @@ void PrivacyInfoView::InitText() { ...@@ -277,13 +256,12 @@ void PrivacyInfoView::InitText() {
size_t offset; size_t offset;
const base::string16 text = const base::string16 text =
l10n_util::GetStringFUTF16(info_string_id_, link, &offset); l10n_util::GetStringFUTF16(info_string_id_, link, &offset);
text_view_ = AddChildView(std::make_unique<views::StyledLabel>()); text_view_ = AddChildView(std::make_unique<PrivacyTextView>(this));
text_view_->SetText(text); text_view_->SetText(text);
text_view_->SetAutoColorReadabilityEnabled(false); text_view_->SetAutoColorReadabilityEnabled(false);
// Assign a container role to the text view so that ChromeVox focuses on text_view_->SetFocusBehavior(FocusBehavior::ALWAYS);
// the inner text elements individually. // Make the whole text view behave as a link for accessibility.
text_view_->GetViewAccessibility().OverrideRole( text_view_->GetViewAccessibility().OverrideRole(ax::mojom::Role::kLink);
ax::mojom::Role::kGenericContainer);
views::StyledLabel::RangeStyleInfo style; views::StyledLabel::RangeStyleInfo style;
style.override_color = AppListColorProvider::Get()->GetSearchBoxTextColor(); style.override_color = AppListColorProvider::Get()->GetSearchBoxTextColor();
...@@ -294,7 +272,7 @@ void PrivacyInfoView::InitText() { ...@@ -294,7 +272,7 @@ void PrivacyInfoView::InitText() {
// manually because default focus handling remains on the search box. // manually because default focus handling remains on the search box.
views::StyledLabel::RangeStyleInfo link_style; views::StyledLabel::RangeStyleInfo link_style;
link_style.disable_line_wrapping = true; link_style.disable_line_wrapping = true;
auto custom_view = std::make_unique<PrivacyLinkView>(link); auto custom_view = std::make_unique<views::Link>(link);
custom_view->set_callback(base::BindRepeating(&PrivacyInfoView::LinkClicked, custom_view->set_callback(base::BindRepeating(&PrivacyInfoView::LinkClicked,
base::Unretained(this))); base::Unretained(this)));
custom_view->SetEnabledColor(gfx::kGoogleBlue700); custom_view->SetEnabledColor(gfx::kGoogleBlue700);
......
...@@ -50,7 +50,7 @@ class PrivacyInfoView : public SearchResultBaseView { ...@@ -50,7 +50,7 @@ class PrivacyInfoView : public SearchResultBaseView {
PrivacyInfoView(int info_string_id, int link_string_id); PrivacyInfoView(int info_string_id, int link_string_id);
private: private:
enum class Action { kNone, kDefault, kTextLink, kCloseButton }; enum class Action { kNone, kTextLink, kCloseButton };
void InitLayout(); void InitLayout();
void InitInfoIcon(); void InitInfoIcon();
......
...@@ -667,30 +667,7 @@ TEST_F(SearchBoxViewTest, NavigatePrivacyNotice) { ...@@ -667,30 +667,7 @@ TEST_F(SearchBoxViewTest, NavigatePrivacyNotice) {
EXPECT_TRUE(selection->is_default_result()); EXPECT_TRUE(selection->is_default_result());
EXPECT_EQ(selection, privacy_container_view->GetResultViewAt(0)); EXPECT_EQ(selection, privacy_container_view->GetResultViewAt(0));
// The privacy view should have two additional non-default actions. // The privacy view should have one additional action.
KeyPress(ui::VKEY_TAB);
selection = selection_controller->selected_result();
EXPECT_EQ(selection, privacy_container_view->GetResultViewAt(0));
KeyPress(ui::VKEY_TAB);
selection = selection_controller->selected_result();
EXPECT_EQ(selection, privacy_container_view->GetResultViewAt(0));
KeyPress(ui::VKEY_TAB);
selection = selection_controller->selected_result();
ASSERT_TRUE(selection->result());
EXPECT_EQ(selection->result()->title(), base::ASCIIToUTF16("test"));
// Move focus forward to the close button and then the privacy view again.
// The privacy view should now have only two actions.
KeyPress(ui::VKEY_TAB);
selection = selection_controller->selected_result();
EXPECT_FALSE(selection);
KeyPress(ui::VKEY_TAB);
selection = selection_controller->selected_result();
EXPECT_EQ(selection, privacy_container_view->GetResultViewAt(0));
KeyPress(ui::VKEY_TAB); KeyPress(ui::VKEY_TAB);
selection = selection_controller->selected_result(); selection = selection_controller->selected_result();
EXPECT_EQ(selection, privacy_container_view->GetResultViewAt(0)); EXPECT_EQ(selection, privacy_container_view->GetResultViewAt(0));
...@@ -700,7 +677,7 @@ TEST_F(SearchBoxViewTest, NavigatePrivacyNotice) { ...@@ -700,7 +677,7 @@ TEST_F(SearchBoxViewTest, NavigatePrivacyNotice) {
ASSERT_TRUE(selection->result()); ASSERT_TRUE(selection->result());
EXPECT_EQ(selection->result()->title(), base::ASCIIToUTF16("test")); EXPECT_EQ(selection->result()->title(), base::ASCIIToUTF16("test"));
// When navigating backwards, the privacy notice should have two actions. // The privacy notice should also have two actions when navigating backwards.
KeyPress(ui::VKEY_TAB, /*is_shift_down=*/true); KeyPress(ui::VKEY_TAB, /*is_shift_down=*/true);
selection = selection_controller->selected_result(); selection = selection_controller->selected_result();
EXPECT_EQ(selection, privacy_container_view->GetResultViewAt(0)); EXPECT_EQ(selection, privacy_container_view->GetResultViewAt(0));
...@@ -740,7 +717,6 @@ TEST_F(SearchBoxViewTest, KeyboardEventClosesPrivacyNotice) { ...@@ -740,7 +717,6 @@ TEST_F(SearchBoxViewTest, KeyboardEventClosesPrivacyNotice) {
// Navigate to the close button and press enter. The privacy info should no // Navigate to the close button and press enter. The privacy info should no
// longer be shown. // longer be shown.
KeyPress(ui::VKEY_TAB); KeyPress(ui::VKEY_TAB);
KeyPress(ui::VKEY_TAB);
KeyPress(ui::VKEY_RETURN); KeyPress(ui::VKEY_RETURN);
EXPECT_FALSE(view_delegate()->ShouldShowAssistantPrivacyInfo()); EXPECT_FALSE(view_delegate()->ShouldShowAssistantPrivacyInfo());
} }
...@@ -769,22 +745,18 @@ TEST_F(SearchBoxViewTest, PrivacyViewActionNotOverriddenByNewResults) { ...@@ -769,22 +745,18 @@ TEST_F(SearchBoxViewTest, PrivacyViewActionNotOverriddenByNewResults) {
selection_controller->selected_result(); selection_controller->selected_result();
EXPECT_EQ(selection, privacy_container_view->GetResultViewAt(0)); EXPECT_EQ(selection, privacy_container_view->GetResultViewAt(0));
// The privacy view should have two additional actions. Tab to the next // The privacy view should have one additional action. Tab to the next privacy
// privacy view action. // view action.
KeyPress(ui::VKEY_TAB); KeyPress(ui::VKEY_TAB);
selection = selection_controller->selected_result(); selection = selection_controller->selected_result();
EXPECT_EQ(selection, privacy_container_view->GetResultViewAt(0)); EXPECT_EQ(selection, privacy_container_view->GetResultViewAt(0));
// Create a new search result. The privacy view should only have one action // Create a new search result. The privacy view should have no actions
// remaining. // remaining.
CreateSearchResult(ash::SearchResultDisplayType::kList, 0.5, CreateSearchResult(ash::SearchResultDisplayType::kList, 0.5,
base::ASCIIToUTF16("testing"), base::string16()); base::ASCIIToUTF16("testing"), base::string16());
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
KeyPress(ui::VKEY_TAB);
selection = selection_controller->selected_result();
EXPECT_EQ(selection, privacy_container_view->GetResultViewAt(0));
KeyPress(ui::VKEY_TAB); KeyPress(ui::VKEY_TAB);
selection = selection_controller->selected_result(); selection = selection_controller->selected_result();
ASSERT_TRUE(selection); ASSERT_TRUE(selection);
......
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