[go: nahoru, domu]

ChromeOS: Remove Guest button when Reset screen is displayed.

This Cl adds ScopedGuestButtonBlocker to temporarily hide Guest login button,
and blocks this button while Reset screen is shown.


Bug: 962398
TBR=oshima@chromium.org

Change-Id: I799d5723b4aea2a999a383c8635c790a2f510047
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1672629
Reviewed-by: Alexander Alekseev <alemate@chromium.org>
Reviewed-by: Ahmed Fakhry <afakhry@chromium.org>
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
Commit-Queue: Alexander Alekseev <alemate@chromium.org>
Cr-Commit-Position: refs/heads/master@{#680731}
diff --git a/ash/login/login_screen_controller.cc b/ash/login/login_screen_controller.cc
index 0a87a9ffe..f75b7b1 100644
--- a/ash/login/login_screen_controller.cc
+++ b/ash/login/login_screen_controller.cc
@@ -364,6 +364,14 @@
       ->SetAllowLoginAsGuest(allow_guest);
 }
 
+std::unique_ptr<ScopedGuestButtonBlocker>
+LoginScreenController::GetScopedGuestButtonBlocker() {
+  return Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow())
+      ->shelf_widget()
+      ->login_shelf_view()
+      ->GetScopedGuestButtonBlocker();
+}
+
 void LoginScreenController::ShowLockScreen() {
   OnShow();
   LockScreen::Show(LockScreen::ScreenType::kLock);
diff --git a/ash/login/login_screen_controller.h b/ash/login/login_screen_controller.h
index 3d19628..15b15d3 100644
--- a/ash/login/login_screen_controller.h
+++ b/ash/login/login_screen_controller.h
@@ -120,6 +120,8 @@
       ParentAccessRequestReason reason,
       bool extra_dimmer) override;
   void SetAllowLoginAsGuest(bool allow_guest) override;
+  std::unique_ptr<ScopedGuestButtonBlocker> GetScopedGuestButtonBlocker()
+      override;
 
   // KioskAppMenu:
   void SetKioskApps(
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn
index 12e2e478..caff4388 100644
--- a/ash/public/cpp/BUILD.gn
+++ b/ash/public/cpp/BUILD.gn
@@ -155,6 +155,7 @@
     "rounded_corner_decorator.h",
     "scale_utility.cc",
     "scale_utility.h",
+    "scoped_guest_button_blocker.h",
     "select_to_speak_event_handler_delegate.h",
     "session/session_activation_observer.h",
     "session/session_controller.cc",
diff --git a/ash/public/cpp/login_screen.h b/ash/public/cpp/login_screen.h
index 28db3c1e..cc112734 100644
--- a/ash/public/cpp/login_screen.h
+++ b/ash/public/cpp/login_screen.h
@@ -16,6 +16,7 @@
 
 class LoginScreenClient;
 class LoginScreenModel;
+class ScopedGuestButtonBlocker;
 
 enum class ParentAccessRequestReason;
 
@@ -79,6 +80,10 @@
   // true the button may still not be visible.
   virtual void SetAllowLoginAsGuest(bool allow_guest) = 0;
 
+  // Returns scoped object to temporarily disable Browse as Guest button.
+  virtual std::unique_ptr<ScopedGuestButtonBlocker>
+  GetScopedGuestButtonBlocker() = 0;
+
  protected:
   LoginScreen();
   virtual ~LoginScreen();
diff --git a/ash/public/cpp/scoped_guest_button_blocker.h b/ash/public/cpp/scoped_guest_button_blocker.h
new file mode 100644
index 0000000..dfb32a8
--- /dev/null
+++ b/ash/public/cpp/scoped_guest_button_blocker.h
@@ -0,0 +1,26 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_PUBLIC_CPP_SCOPED_GUEST_BUTTON_BLOCKER_H_
+#define ASH_PUBLIC_CPP_SCOPED_GUEST_BUTTON_BLOCKER_H_
+
+#include "base/macros.h"
+
+namespace ash {
+
+// Class that temporarily disables the Browse as Guest login button on shelf.
+class ScopedGuestButtonBlocker {
+ public:
+  virtual ~ScopedGuestButtonBlocker() = default;
+
+ protected:
+  ScopedGuestButtonBlocker() = default;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ScopedGuestButtonBlocker);
+};
+
+}  // namespace ash
+
+#endif  // ASH_PUBLIC_CPP_SCOPED_GUEST_BUTTON_BLOCKER_H_
diff --git a/ash/shelf/login_shelf_view.cc b/ash/shelf/login_shelf_view.cc
index 87e1d7b..41e861f 100644
--- a/ash/shelf/login_shelf_view.cc
+++ b/ash/shelf/login_shelf_view.cc
@@ -33,6 +33,7 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/metrics/user_metrics.h"
+#include "base/sequence_checker.h"
 #include "chromeos/strings/grit/chromeos_strings.h"
 #include "skia/ext/image_operations.h"
 #include "ui/accessibility/ax_node_data.h"
@@ -399,6 +400,36 @@
   DISALLOW_COPY_AND_ASSIGN(KioskAppsButton);
 };
 
+// Class that temporarily disables Guest login buttin on shelf.
+class LoginShelfView::ScopedGuestButtonBlockerImpl
+    : public ScopedGuestButtonBlocker {
+ public:
+  ScopedGuestButtonBlockerImpl(base::WeakPtr<LoginShelfView> shelf_view)
+      : shelf_view_(shelf_view) {
+    ++(shelf_view_->scoped_guest_button_blockers_);
+    if (shelf_view_->scoped_guest_button_blockers_ == 1)
+      shelf_view_->UpdateUi();
+  }
+
+  ~ScopedGuestButtonBlockerImpl() override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    if (!shelf_view_)
+      return;
+
+    DCHECK_GT(shelf_view_->scoped_guest_button_blockers_, 0);
+    --(shelf_view_->scoped_guest_button_blockers_);
+    if (!shelf_view_->scoped_guest_button_blockers_)
+      shelf_view_->UpdateUi();
+  }
+
+ private:
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  // ScopedGuestButtonBlockerImpl is not owned by the LoginShelfView,
+  // so they could be independently destroyed.
+  base::WeakPtr<LoginShelfView> shelf_view_;
+};
+
 LoginShelfView::TestUiUpdateDelegate::~TestUiUpdateDelegate() = default;
 
 LoginShelfView::LoginShelfView(
@@ -590,6 +621,12 @@
   GetViewByID(kShutdown)->SetEnabled(enable_shutdown_button);
 }
 
+std::unique_ptr<ScopedGuestButtonBlocker>
+LoginShelfView::GetScopedGuestButtonBlocker() {
+  return std::make_unique<LoginShelfView::ScopedGuestButtonBlockerImpl>(
+      weak_ptr_factory_.GetWeakPtr());
+}
+
 void LoginShelfView::OnLockScreenNoteStateChanged(
     mojom::TrayActionState state) {
   UpdateUi();
@@ -743,10 +780,14 @@
 // are no user views available. If there are no user pods (i.e. Gaia is the
 // only signin option), the guest button should be shown if allowed by policy
 // and OOBE.
+// 6. There are no scoped guest buttons blockers active.
 bool LoginShelfView::ShouldShowGuestButton() const {
   if (!allow_guest_)
     return false;
 
+  if (scoped_guest_button_blockers_ > 0)
+    return false;
+
   if (!DialogStateGuestAllowed(dialog_state_))
     return false;
 
diff --git a/ash/shelf/login_shelf_view.h b/ash/shelf/login_shelf_view.h
index 3ed0d1ec..267a26a 100644
--- a/ash/shelf/login_shelf_view.h
+++ b/ash/shelf/login_shelf_view.h
@@ -14,9 +14,11 @@
 #include "ash/login/ui/login_data_dispatcher.h"
 #include "ash/public/cpp/kiosk_app_menu.h"
 #include "ash/public/cpp/login_types.h"
+#include "ash/public/cpp/scoped_guest_button_blocker.h"
 #include "ash/shutdown_controller_impl.h"
 #include "ash/system/locale/locale_update_controller_impl.h"
 #include "ash/tray_action/tray_action_observer.h"
+#include "base/memory/weak_ptr.h"
 #include "base/scoped_observer.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/view.h"
@@ -66,6 +68,7 @@
     virtual void OnUiUpdate() = 0;
   };
 
+ public:
   explicit LoginShelfView(
       LockScreenActionBackgroundController* lock_screen_action_background);
   ~LoginShelfView() override;
@@ -126,6 +129,9 @@
     return test_ui_update_delegate_.get();
   }
 
+  // Returns scoped object to temporarily block Browse as Guest login button.
+  std::unique_ptr<ScopedGuestButtonBlocker> GetScopedGuestButtonBlocker();
+
  protected:
   // TrayActionObserver:
   void OnLockScreenNoteStateChanged(mojom::TrayActionState state) override;
@@ -145,6 +151,8 @@
   void OnLocaleChanged() override;
 
  private:
+  class ScopedGuestButtonBlockerImpl;
+
   bool LockScreenActionBackgroundAnimating() const;
 
   // Updates the visibility of buttons based on state changes, e.g. shutdown
@@ -197,6 +205,11 @@
   // coordinates are local to the view.
   gfx::Rect button_union_bounds_;
 
+  // Number of active scoped Guest button blockers.
+  int scoped_guest_button_blockers_ = 0;
+
+  base::WeakPtrFactory<LoginShelfView> weak_ptr_factory_{this};
+
   DISALLOW_COPY_AND_ASSIGN(LoginShelfView);
 };
 
diff --git a/chrome/browser/chromeos/login/reset_browsertest.cc b/chrome/browser/chromeos/login/reset_browsertest.cc
index 41c7e498..5c27c74e 100644
--- a/chrome/browser/chromeos/login/reset_browsertest.cc
+++ b/chrome/browser/chromeos/login/reset_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include <string>
 
+#include "ash/public/cpp/login_screen_test_api.h"
 #include "base/command_line.h"
 #include "base/scoped_observer.h"
 #include "chrome/browser/browser_process.h"
@@ -264,20 +265,25 @@
 };
 
 IN_PROC_BROWSER_TEST_F(ResetTest, ShowAndCancel) {
+  EXPECT_TRUE(ash::LoginScreenTestApi::IsGuestButtonShown());
   InvokeResetScreen();
   EXPECT_TRUE(login_prompt_visible_observer_->signal_emitted());
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown());
 
   test::OobeJS().ExpectVisible("reset");
 
   CloseResetScreen();
   test::OobeJS().CreateVisibilityWaiter(false, {"reset"})->Wait();
+  EXPECT_TRUE(ash::LoginScreenTestApi::IsGuestButtonShown());
 }
 
 IN_PROC_BROWSER_TEST_F(ResetTest, RestartBeforePowerwash) {
+  EXPECT_TRUE(ash::LoginScreenTestApi::IsGuestButtonShown());
   PrefService* prefs = g_browser_process->local_state();
 
   InvokeResetScreen();
   EXPECT_TRUE(login_prompt_visible_observer_->signal_emitted());
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown());
 
   EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls());
   EXPECT_EQ(0, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
@@ -286,14 +292,17 @@
   ASSERT_EQ(0, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
 
   EXPECT_TRUE(prefs->GetBoolean(prefs::kFactoryResetRequested));
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown());
 }
 
 IN_PROC_BROWSER_TEST_F(ResetOobeTest, ResetOnWelcomeScreen) {
   OobeScreenWaiter(WelcomeView::kScreenId).Wait();
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown());
   InvokeResetScreen();
 
   OobeScreenWaiter(ResetView::kScreenId).Wait();
   test::OobeJS().ExpectVisible("reset");
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown());
 
   ClickResetButton();
   EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls());
@@ -303,14 +312,17 @@
 
 IN_PROC_BROWSER_TEST_F(ResetOobeTest, RequestAndCancleResetOnWelcomeScreen) {
   OobeScreenWaiter(WelcomeView::kScreenId).Wait();
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown());
   InvokeResetScreen();
 
   OobeScreenWaiter(ResetView::kScreenId).Wait();
   test::OobeJS().ExpectVisible("reset");
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown());
 
   CloseResetScreen();
   OobeScreenWaiter(WelcomeView::kScreenId).Wait();
   test::OobeJS().ExpectHidden("reset");
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown());
 
   EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls());
   EXPECT_EQ(0, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
@@ -330,23 +342,28 @@
   update_engine_client_->set_can_rollback_check_result(false);
   InvokeResetScreen();
   EXPECT_TRUE(login_prompt_visible_observer_->signal_emitted());
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown());
 
   test::OobeJS().CreateVisibilityWaiter(true, {"reset"})->Wait();
   test::OobeJS().ExpectHidden("overlay-reset");
   CloseResetScreen();
   test::OobeJS().CreateVisibilityWaiter(false, {"reset"})->Wait();
+  EXPECT_TRUE(ash::LoginScreenTestApi::IsGuestButtonShown());
 
   // Go to confirmation phase, cancel from there in 2 steps.
   prefs->SetBoolean(prefs::kFactoryResetRequested, true);
   InvokeResetScreen();
   test::OobeJS().CreateVisibilityWaiter(false, {"overlay-reset"})->Wait();
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown());
   ClickToConfirmButton();
   test::OobeJS().CreateVisibilityWaiter(true, {"overlay-reset"})->Wait();
   ClickDismissConfirmationButton();
   test::OobeJS().CreateVisibilityWaiter(false, {"overlay-reset"})->Wait();
   test::OobeJS().CreateVisibilityWaiter(true, {"reset"})->Wait();
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown());
   CloseResetScreen();
   test::OobeJS().CreateVisibilityWaiter(false, {"reset"})->Wait();
+  EXPECT_TRUE(ash::LoginScreenTestApi::IsGuestButtonShown());
 
   // Rollback available. Show and cancel from confirmation screen.
   update_engine_client_->set_can_rollback_check_result(true);
@@ -371,10 +388,13 @@
 IN_PROC_BROWSER_TEST_F(ResetFirstAfterBootTest, ShowAfterBootIfRequested) {
   OobeScreenWaiter(ResetView::kScreenId).Wait();
   EXPECT_TRUE(login_prompt_visible_observer_->signal_emitted());
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown());
 
   test::OobeJS().CreateVisibilityWaiter(true, {"reset"})->Wait();
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown());
   CloseResetScreen();
   test::OobeJS().CreateVisibilityWaiter(false, {"reset"})->Wait();
+  EXPECT_TRUE(ash::LoginScreenTestApi::IsGuestButtonShown());
 }
 
 IN_PROC_BROWSER_TEST_F(ResetFirstAfterBootTest, PRE_RollbackUnavailable) {
@@ -385,6 +405,7 @@
 IN_PROC_BROWSER_TEST_F(ResetFirstAfterBootTest, RollbackUnavailable) {
   InvokeResetScreen();
   EXPECT_TRUE(login_prompt_visible_observer_->signal_emitted());
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown());
 
   EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls());
   EXPECT_EQ(0, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
@@ -397,6 +418,7 @@
   EXPECT_EQ(0, update_engine_client_->rollback_call_count());
   CloseResetScreen();
   OobeScreenExitWaiter(ResetView::kScreenId).Wait();
+  EXPECT_TRUE(ash::LoginScreenTestApi::IsGuestButtonShown());
 
   // Next invocation leads to rollback view.
   PrefService* prefs = g_browser_process->local_state();
@@ -419,8 +441,12 @@
 IN_PROC_BROWSER_TEST_F(ResetFirstAfterBootTestWithRollback, RollbackAvailable) {
   PrefService* prefs = g_browser_process->local_state();
 
-  InvokeResetScreen();
+  // PRE test triggers start with Reset screen.
+  OobeScreenWaiter(ResetView::kScreenId).Wait();
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown());
+
   EXPECT_TRUE(login_prompt_visible_observer_->signal_emitted());
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown());
 
   EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls());
   EXPECT_EQ(0, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
@@ -432,14 +458,19 @@
   EXPECT_EQ(0, update_engine_client_->rollback_call_count());
   CloseResetScreen();
   OobeScreenExitWaiter(ResetView::kScreenId).Wait();
+  EXPECT_TRUE(ash::LoginScreenTestApi::IsGuestButtonShown());
 
   // Next invocation leads to simple reset, not rollback view.
   prefs->SetBoolean(prefs::kFactoryResetRequested, true);
   InvokeResetScreen();
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown());
   InvokeRollbackOption();  // Shows rollback.
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown());
   ClickDismissConfirmationButton();
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown());
   CloseResetScreen();
   OobeScreenExitWaiter(ResetView::kScreenId).Wait();
+  EXPECT_TRUE(ash::LoginScreenTestApi::IsGuestButtonShown());
 
   InvokeResetScreen();
   ClickToConfirmButton();
@@ -449,6 +480,7 @@
   EXPECT_EQ(0, update_engine_client_->rollback_call_count());
   CloseResetScreen();
   OobeScreenExitWaiter(ResetView::kScreenId).Wait();
+  EXPECT_TRUE(ash::LoginScreenTestApi::IsGuestButtonShown());
 
   prefs->SetBoolean(prefs::kFactoryResetRequested, true);
   InvokeResetScreen();
diff --git a/chrome/browser/chromeos/login/screens/reset_screen.cc b/chrome/browser/chromeos/login/screens/reset_screen.cc
index 3f60cd48..14338f3 100644
--- a/chrome/browser/chromeos/login/screens/reset_screen.cc
+++ b/chrome/browser/chromeos/login/screens/reset_screen.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/chromeos/login/screens/reset_screen.h"
 
+#include "ash/public/cpp/login_screen.h"
+#include "ash/public/cpp/scoped_guest_button_blocker.h"
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/metrics/histogram_macros.h"
@@ -191,6 +193,13 @@
   if (view_)
     view_->Show();
 
+  // Guest sugn-in button should be disabled as sign-in is not possible while
+  // reset screen is shown.
+  if (!scoped_guest_button_blocker_) {
+    scoped_guest_button_blocker_ =
+        ash::LoginScreen::Get()->GetScopedGuestButtonBlocker();
+  }
+
   reset::DialogViewType dialog_type =
       reset::DIALOG_VIEW_TYPE_SIZE;  // used by UMA metrics.
 
@@ -264,6 +273,8 @@
 void ResetScreen::Hide() {
   if (view_)
     view_->Hide();
+
+  scoped_guest_button_blocker_.reset();
 }
 
 void ResetScreen::OnViewDestroyed(ResetView* view) {
diff --git a/chrome/browser/chromeos/login/screens/reset_screen.h b/chrome/browser/chromeos/login/screens/reset_screen.h
index 77595c6..e298556 100644
--- a/chrome/browser/chromeos/login/screens/reset_screen.h
+++ b/chrome/browser/chromeos/login/screens/reset_screen.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_RESET_SCREEN_H_
 #define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_RESET_SCREEN_H_
 
+#include <memory>
 #include <set>
 #include <string>
 
@@ -21,10 +22,15 @@
 
 class PrefRegistrySimple;
 
+namespace ash {
+class ScopedGuestButtonBlocker;
+}
+
 namespace chromeos {
 
 class ErrorScreen;
 class ResetView;
+class ScopedGuestButtonBlocker;
 
 // Representation independent class that controls screen showing reset to users.
 // It run exit callback only if the user cancels the reset. Other user actions
@@ -92,6 +98,8 @@
   // Callback used to check whether a TPM firnware update is available.
   TpmFirmwareUpdateAvailabilityChecker tpm_firmware_update_checker_;
 
+  std::unique_ptr<ash::ScopedGuestButtonBlocker> scoped_guest_button_blocker_;
+
   base::WeakPtrFactory<ResetScreen> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ResetScreen);
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index 024214dc..68df516 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -1131,6 +1131,9 @@
   if (previous_screen_) {
     SetCurrentScreen(previous_screen_);
   } else {
+    if (current_screen_)
+      current_screen_->Hide();
+
     ShowLoginScreen(LoginScreenContext());
   }
 }
diff --git a/chrome/browser/ui/ash/test_login_screen.cc b/chrome/browser/ui/ash/test_login_screen.cc
index 72977e9..f366a81 100644
--- a/chrome/browser/ui/ash/test_login_screen.cc
+++ b/chrome/browser/ui/ash/test_login_screen.cc
@@ -4,6 +4,18 @@
 
 #include "chrome/browser/ui/ash/test_login_screen.h"
 
+#include <memory>
+
+#include "ash/public/cpp/scoped_guest_button_blocker.h"
+
+namespace {
+class ScopedGuestButtonBlockerTestImpl : public ash::ScopedGuestButtonBlocker {
+ public:
+  ScopedGuestButtonBlockerTestImpl() = default;
+  ~ScopedGuestButtonBlockerTestImpl() override = default;
+};
+}  // namespace
+
 TestLoginScreen::TestLoginScreen() = default;
 
 TestLoginScreen::~TestLoginScreen() = default;
@@ -41,3 +53,8 @@
     bool extra_dimmer) {}
 
 void TestLoginScreen::SetAllowLoginAsGuest(bool allow_guest) {}
+
+std::unique_ptr<ash::ScopedGuestButtonBlocker>
+TestLoginScreen::GetScopedGuestButtonBlocker() {
+  return std::make_unique<ScopedGuestButtonBlockerTestImpl>();
+}
diff --git a/chrome/browser/ui/ash/test_login_screen.h b/chrome/browser/ui/ash/test_login_screen.h
index cf55c56..e5fcc1a 100644
--- a/chrome/browser/ui/ash/test_login_screen.h
+++ b/chrome/browser/ui/ash/test_login_screen.h
@@ -13,6 +13,10 @@
 #include "chrome/browser/ui/ash/test_login_screen_model.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
+namespace ash {
+class ScopedGuestButtonBlocker;
+}
+
 // Test implementation of ash's mojo LoginScreen interface.
 //
 // Registers itself to ServiceManager on construction and deregisters
@@ -43,6 +47,8 @@
       ash::ParentAccessRequestReason reason,
       bool extra_dimmer) override;
   void SetAllowLoginAsGuest(bool allow_guest) override;
+  std::unique_ptr<ash::ScopedGuestButtonBlocker> GetScopedGuestButtonBlocker()
+      override;
 
  private:
   TestLoginScreenModel test_screen_model_;