Skip to content

Commit

Permalink
[M112][PaymentRequest] Fix payments view accessibility visibility
Browse files Browse the repository at this point in the history
(cherry picked from commit a73e70d)

This ensures that invisible payments views are ignored in accessibility
contexts such as a screen reader. See the bug for more context, in
summary we used to rely on screen readers ignoring invisible elements,
which is no longer the case.

- Behind the PaymentHandlerMinimalHeaderUX feature, the finished
  progress bar which is used as a separator is set to ignored once it's
  done loading. The origin label is also set to accessibility focusable.
- The processing spinner, present and invisible on most payment sheets,
  is set to ignored when invisible.
- Hidden payment sheets, made invisible within a stack of payment sheet
  views used for animation, are set to ignored when invisible.

Bug: 1418659, 1420720
Change-Id: I54d43bf3de29b84941c6a0a906c41139df0e4cf6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4294863
Reviewed-by: Peter Kotwicz <pkotwicz@chromium.org>
Commit-Queue: Nick Burris <nburris@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1112179}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4304359
Cr-Commit-Position: refs/branch-heads/5615@{chromium#188}
Cr-Branched-From: 9c6408e-refs/heads/main@{#1109224}
  • Loading branch information
nickburris authored and Chromium LUCI CQ committed Mar 3, 2023
1 parent 012a3ba commit 32a741a
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 0 deletions.
Expand Up @@ -43,6 +43,7 @@
#include "ui/gfx/color_utils.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/button/image_button.h"
Expand Down Expand Up @@ -393,6 +394,7 @@ void PaymentHandlerWebFlowViewController::PopulateSheetHeaderView(
origin, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC)));
origin_label->SetElideBehavior(gfx::ELIDE_HEAD);
origin_label->SetID(static_cast<int>(DialogViewID::SHEET_TITLE));
origin_label->SetFocusBehavior(views::View::FocusBehavior::ACCESSIBLE_ONLY);
// Turn off autoreadability because the computed foreground color takes
// contrast into account.
SkColor background_color = container->background()->get_color();
Expand Down Expand Up @@ -567,6 +569,11 @@ void PaymentHandlerWebFlowViewController::LoadProgressChanged(double progress) {
// The progress bar reflects the load progress until it reaches 1.0, at
// which point it's reset to 0 to just show the separator color.
progress_bar_->SetValue(progress < 1.0 ? progress : 0);

// The progress bar is accessibility-visible while loading, and then ignored
// once it just serves as a separator.
progress_bar_->GetViewAccessibility().OverrideIsIgnored(progress == 1.0);
progress_bar_->GetViewAccessibility().OverrideIsLeaf(progress == 1.0);
} else {
progress_bar_->SetValue(progress);
const bool show_progress = progress < 1.0;
Expand Down
10 changes: 10 additions & 0 deletions chrome/browser/ui/views/payments/payment_request_dialog_view.cc
Expand Up @@ -36,6 +36,7 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/color/color_id.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/background.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
Expand Down Expand Up @@ -136,6 +137,8 @@ void PaymentRequestDialogView::ShowErrorMessage() {
void PaymentRequestDialogView::ShowProcessingSpinner() {
throbber_->Start();
throbber_overlay_->SetVisible(true);
throbber_overlay_->GetViewAccessibility().OverrideIsIgnored(false);
throbber_overlay_->GetViewAccessibility().OverrideIsLeaf(false);
if (observer_for_testing_)
observer_for_testing_->OnProcessingSpinnerShown();
}
Expand Down Expand Up @@ -417,7 +420,14 @@ void PaymentRequestDialogView::EditorViewUpdated() {

void PaymentRequestDialogView::HideProcessingSpinner() {
throbber_->Stop();
// TODO(crbug.com/1418659): Instead of setting the throbber to invisible, can
// we destroy and remove it from the view when it's not being used?
throbber_overlay_->SetVisible(false);
// Screen readers do not ignore invisible elements, so force the screen
// reader to skip the invisible throbber by making it an ignored leaf node in
// the accessibility tree.
throbber_overlay_->GetViewAccessibility().OverrideIsIgnored(true);
throbber_overlay_->GetViewAccessibility().OverrideIsLeaf(true);
if (observer_for_testing_)
observer_for_testing_->OnProcessingSpinnerHidden();
}
Expand Down
Expand Up @@ -23,6 +23,7 @@
#include "ui/compositor/layer.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/button/image_button.h"
Expand Down Expand Up @@ -127,6 +128,16 @@ class SheetView : public views::BoxLayoutView, public views::FocusTraversable {
first_focusable_ = nullptr;
}

void SetVisible(bool visible) override {
views::View::SetVisible(visible);

// Screen readers do not ignore invisible elements, so force the screen
// reader to skip invisible sheet views by making it an ignored leaf node in
// the accessibility tree.
GetViewAccessibility().OverrideIsIgnored(!visible);
GetViewAccessibility().OverrideIsLeaf(!visible);
}

raw_ptr<views::View> first_focusable_ = nullptr;
std::unique_ptr<views::FocusSearch> focus_search_ =
std::make_unique<views::FocusSearch>(/*root=*/this,
Expand Down
@@ -0,0 +1,119 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/payments/payment_request_browsertest_base.h"
#include "chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "content/public/test/browser_test.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/views/accessibility/view_accessibility.h"

namespace payments {

class PaymentRequestSheetControllerTest : public PaymentRequestBrowserTestBase {
public:
PaymentRequestSheetControllerTest() = default;
~PaymentRequestSheetControllerTest() override = default;
};

IN_PROC_BROWSER_TEST_F(PaymentRequestSheetControllerTest,
ProcessingSpinnerViewAccessibility) {
// Installs two apps so that the Payment Request UI will be shown.
std::string a_method_name;
InstallPaymentApp("a.com", "/payment_request_success_responder.js",
&a_method_name);
std::string b_method_name;
InstallPaymentApp("b.com", "/payment_request_success_responder.js",
&b_method_name);

NavigateTo("/payment_request_retry_with_payer_errors.html");
autofill::AutofillProfile contact = autofill::test::GetFullProfile();
AddAutofillProfile(contact);

InvokePaymentRequestUIWithJs(
content::JsReplace("buyWithMethods([{supportedMethods:$1}"
", {supportedMethods:$2}]);",
a_method_name, b_method_name));

// Click on pay.
EXPECT_TRUE(IsPayButtonEnabled());
ResetEventWaiterForSequence({DialogEvent::PROCESSING_SPINNER_SHOWN});
ClickOnDialogViewAndWait(DialogViewID::PAY_BUTTON, dialog_view());

EXPECT_TRUE(dialog_view()->throbber_overlay_for_testing()->GetVisible());
EXPECT_FALSE(dialog_view()
->throbber_overlay_for_testing()
->GetViewAccessibility()
.IsIgnored());
EXPECT_FALSE(dialog_view()
->throbber_overlay_for_testing()
->GetViewAccessibility()
.IsLeaf());

// Wait for the response to settle.
ASSERT_TRUE(
content::ExecJs(GetActiveWebContents(), "processShowResponse();"));

// Call retry to finish the dialog loading state and hide the spinner.
ResetEventWaiterForSequence({DialogEvent::PROCESSING_SPINNER_HIDDEN,
DialogEvent::SPEC_DONE_UPDATING,
DialogEvent::PROCESSING_SPINNER_HIDDEN,
DialogEvent::BACK_TO_PAYMENT_SHEET_NAVIGATION,
DialogEvent::CONTACT_INFO_EDITOR_OPENED});
ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(),
"retry({"
" payer: {"
" email: 'EMAIL ERROR',"
" name: 'NAME ERROR',"
" phone: 'PHONE ERROR'"
" }"
"});"));
WaitForObservedEvent();

EXPECT_FALSE(dialog_view()->throbber_overlay_for_testing()->GetVisible());
EXPECT_TRUE(dialog_view()
->throbber_overlay_for_testing()
->GetViewAccessibility()
.IsIgnored());
EXPECT_TRUE(dialog_view()
->throbber_overlay_for_testing()
->GetViewAccessibility()
.IsLeaf());
}

IN_PROC_BROWSER_TEST_F(PaymentRequestSheetControllerTest,
HiddenSheetViewAccessibility) {
// Installs two apps so that the Payment Request UI will be shown.
std::string a_method_name;
InstallPaymentApp("a.com", "/payment_request_success_responder.js",
&a_method_name);
std::string b_method_name;
InstallPaymentApp("b.com", "/payment_request_success_responder.js",
&b_method_name);

NavigateTo("/payment_request_contact_details_test.html");
InvokePaymentRequestUIWithJs(
content::JsReplace("buyWithMethods([{supportedMethods:$1}"
", {supportedMethods:$2}]);",
a_method_name, b_method_name));

// Expect that the payment request view is accessibility visible.
views::View* payment_request_view =
GetByDialogViewID(DialogViewID::PAYMENT_REQUEST_SHEET);
EXPECT_FALSE(payment_request_view->GetViewAccessibility().IsIgnored());
EXPECT_FALSE(payment_request_view->GetViewAccessibility().IsLeaf());

OpenContactInfoEditorScreen();

// Expect that the now hidden payment request view is not accessibility
// visible, and that the contact info view is.
EXPECT_TRUE(payment_request_view->GetViewAccessibility().IsIgnored());
EXPECT_TRUE(payment_request_view->GetViewAccessibility().IsLeaf());
views::View* contact_info_view =
GetByDialogViewID(DialogViewID::CONTACT_INFO_EDITOR_SHEET);
EXPECT_FALSE(contact_info_view->GetViewAccessibility().IsIgnored());
EXPECT_FALSE(contact_info_view->GetViewAccessibility().IsLeaf());
}

} // namespace payments
1 change: 1 addition & 0 deletions chrome/test/BUILD.gn
Expand Up @@ -3515,6 +3515,7 @@ if (!is_android) {
"../browser/ui/views/payments/payment_request_payment_app_browsertest.cc",
"../browser/ui/views/payments/payment_request_payment_response_browsertest.cc",
"../browser/ui/views/payments/payment_request_retry_browsertest.cc",
"../browser/ui/views/payments/payment_request_sheet_controller_browsertest.cc",
"../browser/ui/views/payments/payment_request_shipping_address_instance_browsertest.cc",
"../browser/ui/views/payments/payment_request_show_promise_browsertest.cc",
"../browser/ui/views/payments/payment_request_update_with_browsertest.cc",
Expand Down

0 comments on commit 32a741a

Please sign in to comment.