cros: Add a debug button for cycling through the different types of auth error bubbles.

Bug: 863620
Change-Id: I2d9cef017c3c8c4c2feee99bc4f6913baf11c320
Reviewed-on: https://chromium-review.googlesource.com/1145686
Commit-Queue: Quan Nguyen <qnnguyen@chromium.org>
Reviewed-by: Jacob Dufault <jdufault@chromium.org>
Cr-Commit-Position: refs/heads/master@{#577675}
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc
index e46bfb73..dcfd984 100644
--- a/ash/login/ui/lock_contents_view.cc
+++ b/ash/login/ui/lock_contents_view.cc
@@ -868,6 +868,11 @@
     auth_user->password_view()->Clear();
 }
 
+void LockContentsView::ShowAuthErrorMessageForDebug(int unlock_attempt) {
+  unlock_attempt_ = unlock_attempt;
+  ShowAuthErrorMessage();
+}
+
 void LockContentsView::FocusNextWidget(bool reverse) {
   Shelf* shelf = Shelf::ForWindow(GetWidget()->GetNativeWindow());
   // Tell the focus direction to the status area or the shelf so they can focus
diff --git a/ash/login/ui/lock_contents_view.h b/ash/login/ui/lock_contents_view.h
index 7c9c3cc..d702dcd 100644
--- a/ash/login/ui/lock_contents_view.h
+++ b/ash/login/ui/lock_contents_view.h
@@ -192,6 +192,8 @@
   // chromeos::PowerManagerClient::Observer:
   void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
 
+  void ShowAuthErrorMessageForDebug(int unlock_attempt);
+
  private:
   class UserState {
    public:
diff --git a/ash/login/ui/lock_debug_view.cc b/ash/login/ui/lock_debug_view.cc
index 392ef42..44d363e 100644
--- a/ash/login/ui/lock_debug_view.cc
+++ b/ash/login/ui/lock_debug_view.cc
@@ -49,6 +49,7 @@
   kGlobalToggleDebugDetachableBase,
   kGlobalCycleDetachableBaseStatus,
   kGlobalCycleDetachableBaseId,
+  kGlobalCycleAuthErrorMessage,
 
   kPerUserTogglePin,
   kPerUserCycleEasyUnlockState,
@@ -630,6 +631,8 @@
             toggle_container);
   global_action_toggle_auth_ = AddButton(
       "Auth (allowed)", ButtonId::kGlobalToggleAuth, toggle_container);
+  AddButton("Cycle auth error", ButtonId::kGlobalCycleAuthErrorMessage,
+            toggle_container);
 
   auto* kiosk_container = add_horizontal_container();
   AddButton("Add kiosk app", ButtonId::kGlobalAddKioskApp, kiosk_container);
@@ -676,6 +679,46 @@
   container_->SizeToPreferredSize();
 }
 
+void LockDebugView::CycleAuthErrorMessage() {
+  switch (next_auth_error_type_) {
+    case AuthErrorType::kFirstUnlockFailed:
+      next_auth_error_type_ = AuthErrorType::kFirstUnlockFailedCapsLockOn;
+      Shell::Get()->ime_controller()->UpdateCapsLockState(
+          false /*caps_enabled*/);
+      debug_detachable_base_model_->SetPairingState(
+          DetachableBasePairingStatus::kNone,
+          DebugLoginDetachableBaseModel::kNullBaseId);
+      lock_->ShowAuthErrorMessageForDebug(1 /*unlock_attempt*/);
+      return;
+    case AuthErrorType::kFirstUnlockFailedCapsLockOn:
+      next_auth_error_type_ = AuthErrorType::kSecondUnlockFailed;
+      Shell::Get()->ime_controller()->UpdateCapsLockState(
+          true /*caps_enabled*/);
+      lock_->ShowAuthErrorMessageForDebug(1 /*unlock_attempt*/);
+      return;
+    case AuthErrorType::kSecondUnlockFailed:
+      next_auth_error_type_ = AuthErrorType::kSecondUnlockFailedCapsLockOn;
+      Shell::Get()->ime_controller()->UpdateCapsLockState(
+          false /*caps_enabled*/);
+      lock_->ShowAuthErrorMessageForDebug(2 /*unlock_attempt*/);
+      return;
+    case AuthErrorType::kSecondUnlockFailedCapsLockOn:
+      next_auth_error_type_ = AuthErrorType::kDetachableBaseFailed;
+      Shell::Get()->ime_controller()->UpdateCapsLockState(
+          true /*caps_enabled*/);
+      lock_->ShowAuthErrorMessageForDebug(2 /*unlock_attempt*/);
+      return;
+    case AuthErrorType::kDetachableBaseFailed:
+      next_auth_error_type_ = AuthErrorType::kFirstUnlockFailed;
+      debug_detachable_base_model_->SetPairingState(
+          DetachableBasePairingStatus::kNotAuthenticated,
+          DebugLoginDetachableBaseModel::kNullBaseId);
+      return;
+    default:
+      NOTREACHED();
+  }
+}
+
 void LockDebugView::ButtonPressed(views::Button* sender,
                                   const ui::Event& event) {
   // Add or remove a user.
@@ -817,6 +860,11 @@
     return;
   }
 
+  if (sender->id() == ButtonId::kGlobalCycleAuthErrorMessage) {
+    CycleAuthErrorMessage();
+    return;
+  }
+
   // Enable or disable PIN.
   if (sender->id() == ButtonId::kPerUserTogglePin)
     debug_data_dispatcher_->TogglePinStateForUserIndex(sender->tag());
diff --git a/ash/login/ui/lock_debug_view.h b/ash/login/ui/lock_debug_view.h
index 3f88106..5ac5200 100644
--- a/ash/login/ui/lock_debug_view.h
+++ b/ash/login/ui/lock_debug_view.h
@@ -47,6 +47,17 @@
  private:
   class DebugDataDispatcherTransformer;
   class DebugLoginDetachableBaseModel;
+  enum class AuthErrorType {
+    kFirstUnlockFailed,
+    kFirstUnlockFailedCapsLockOn,
+    kSecondUnlockFailed,
+    kSecondUnlockFailedCapsLockOn,
+    kDetachableBaseFailed,
+  };
+
+  // Cycle through the various types of auth error bubbles that can be shown on
+  // the login screen.
+  void CycleAuthErrorMessage();
 
   // Rebuilds the debug user column which contains per-user actions.
   void UpdatePerUserActionContainer();
@@ -89,6 +100,10 @@
   LoginScreenController::ForceFailAuth force_fail_auth_ =
       LoginScreenController::ForceFailAuth::kOff;
 
+  // The next type of authentication error bubble to show when the "Cycle auth
+  // error" button is clicked.
+  AuthErrorType next_auth_error_type_ = AuthErrorType::kFirstUnlockFailed;
+
   DISALLOW_COPY_AND_ASSIGN(LockDebugView);
 };