[Autofill Auth UI] Merge MVCs of VerifyPendingDialog and WebauthnOfferDialog

The verify pending dialog will need to (UX decision) reuse the current
webauthn dialog UX format. Since they are both using this format, and
are for the same flow. It makes sense to merge the two sets of MVCs and
show different content based on different dialog state

This is a follow up of CL crrev.com/c/1925761

Bug: 991037
Change-Id: I4837e02adeef471d6a775587af0ab921646cdaf5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1931857
Commit-Queue: Siyu An <siyua@chromium.org>
Reviewed-by: Vasilii Sukhanov <vasilii@chromium.org>
Reviewed-by: Jared Saul <jsaul@google.com>
Reviewed-by: Fabio Tirelo <ftirelo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#720817}
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index a49b90b..e197446 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2043,16 +2043,13 @@
 
   if (is_win || is_mac || is_desktop_linux || is_chromeos) {
     sources += [
-      "autofill/payments/verify_pending_dialog_controller.h",
-      "autofill/payments/verify_pending_dialog_controller_impl.cc",
-      "autofill/payments/verify_pending_dialog_controller_impl.h",
-      "autofill/payments/verify_pending_dialog_view.h",
       "autofill/payments/webauthn_dialog_controller.h",
       "autofill/payments/webauthn_dialog_controller_impl.cc",
       "autofill/payments/webauthn_dialog_controller_impl.h",
       "autofill/payments/webauthn_dialog_model.cc",
       "autofill/payments/webauthn_dialog_model.h",
       "autofill/payments/webauthn_dialog_model_observer.h",
+      "autofill/payments/webauthn_dialog_state.h",
       "autofill/payments/webauthn_dialog_view.h",
       "frame/window_frame_util.cc",
       "frame/window_frame_util.h",
@@ -2061,8 +2058,6 @@
       "signin_view_controller_delegate.h",
       "tab_contents/chrome_web_contents_view_handle_drop.cc",
       "tab_contents/chrome_web_contents_view_handle_drop.h",
-      "views/autofill/payments/verify_pending_dialog_view_impl.cc",
-      "views/autofill/payments/verify_pending_dialog_view_impl.h",
       "views/autofill/payments/webauthn_dialog_view_impl.cc",
       "views/autofill/payments/webauthn_dialog_view_impl.h",
       "views/close_bubble_on_tab_activation_helper.cc",
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc
index a0504ed..2e10004 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client.cc
+++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -82,9 +82,8 @@
 #include "ui/android/window_android.h"
 #else  // !OS_ANDROID
 #include "chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h"
-#include "chrome/browser/ui/autofill/payments/verify_pending_dialog_controller_impl.h"
-#include "chrome/browser/ui/autofill/payments/verify_pending_dialog_view.h"
 #include "chrome/browser/ui/autofill/payments/webauthn_dialog_controller_impl.h"
+#include "chrome/browser/ui/autofill/payments/webauthn_dialog_state.h"
 #include "chrome/browser/ui/autofill/payments/webauthn_dialog_view.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
@@ -274,20 +273,27 @@
 
 #if !defined(OS_ANDROID)
 void ChromeAutofillClient::ShowWebauthnOfferDialog(
-    WebauthnOfferDialogCallback offer_dialog_callback) {
+    WebauthnDialogCallback offer_dialog_callback) {
   autofill::WebauthnDialogControllerImpl::CreateForWebContents(web_contents());
   autofill::WebauthnDialogControllerImpl::FromWebContents(web_contents())
       ->ShowOfferDialog(std::move(offer_dialog_callback));
 }
 
+void ChromeAutofillClient::ShowWebauthnVerifyPendingDialog(
+    WebauthnDialogCallback verify_pending_dialog_callback) {
+  autofill::WebauthnDialogControllerImpl::CreateForWebContents(web_contents());
+  autofill::WebauthnDialogControllerImpl::FromWebContents(web_contents())
+      ->ShowVerifyPendingDialog(std::move(verify_pending_dialog_callback));
+}
+
 void ChromeAutofillClient::UpdateWebauthnOfferDialogWithError() {
   WebauthnDialogControllerImpl* controller =
       autofill::WebauthnDialogControllerImpl::FromWebContents(web_contents());
   if (controller)
-    controller->UpdateDialogWithError();
+    controller->UpdateDialog(WebauthnDialogState::kOfferError);
 }
 
-bool ChromeAutofillClient::CloseWebauthnOfferDialog() {
+bool ChromeAutofillClient::CloseWebauthnDialog() {
   WebauthnDialogControllerImpl* controller =
       autofill::WebauthnDialogControllerImpl::FromWebContents(web_contents());
   if (controller)
@@ -295,24 +301,6 @@
 
   return false;
 }
-
-void ChromeAutofillClient::ShowWebauthnVerifyPendingDialog(
-    base::OnceClosure cancel_card_verification_callback) {
-  autofill::VerifyPendingDialogControllerImpl::CreateForWebContents(
-      web_contents());
-  autofill::VerifyPendingDialogControllerImpl::FromWebContents(web_contents())
-      ->ShowDialog(std::move(cancel_card_verification_callback));
-}
-
-void ChromeAutofillClient::CloseWebauthnVerifyPendingDialog() {
-  VerifyPendingDialogControllerImpl* controller =
-      autofill::VerifyPendingDialogControllerImpl::FromWebContents(
-          web_contents());
-  if (!controller)
-    return;
-
-  controller->OnCardVerificationCompleted();
-}
 #endif
 
 void ChromeAutofillClient::ConfirmSaveAutofillProfile(
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.h b/chrome/browser/ui/autofill/chrome_autofill_client.h
index 26389ce..c3c5ca9 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client.h
+++ b/chrome/browser/ui/autofill/chrome_autofill_client.h
@@ -88,12 +88,11 @@
       MigrationDeleteCardCallback delete_local_card_callback) override;
 #if !defined(OS_ANDROID)
   void ShowWebauthnOfferDialog(
-      WebauthnOfferDialogCallback offer_dialog_callback) override;
-  void UpdateWebauthnOfferDialogWithError() override;
-  bool CloseWebauthnOfferDialog() override;
+      WebauthnDialogCallback offer_dialog_callback) override;
   void ShowWebauthnVerifyPendingDialog(
-      base::OnceClosure cancel_card_verification_callback) override;
-  void CloseWebauthnVerifyPendingDialog() override;
+      WebauthnDialogCallback verify_pending_dialog_callback) override;
+  void UpdateWebauthnOfferDialogWithError() override;
+  bool CloseWebauthnDialog() override;
 #endif  // !defined(OS_ANDROID)
   void ConfirmSaveAutofillProfile(const AutofillProfile& profile,
                                   base::OnceClosure callback) override;
diff --git a/chrome/browser/ui/autofill/payments/verify_pending_dialog_controller.h b/chrome/browser/ui/autofill/payments/verify_pending_dialog_controller.h
deleted file mode 100644
index 580856f..0000000
--- a/chrome/browser/ui/autofill/payments/verify_pending_dialog_controller.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// 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 CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_VERIFY_PENDING_DIALOG_CONTROLLER_H_
-#define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_VERIFY_PENDING_DIALOG_CONTROLLER_H_
-
-#include "base/macros.h"
-#include "base/strings/string16.h"
-
-namespace autofill {
-
-// An interface that exposes necessary controller functionality to
-// VerifyPendingDialogView.
-class VerifyPendingDialogController {
- public:
-  VerifyPendingDialogController() = default;
-  virtual ~VerifyPendingDialogController() = default;
-
-  virtual base::string16 GetDialogTitle() const = 0;
-
-  virtual void OnCancel() = 0;
-  virtual void OnDialogClosed() = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(VerifyPendingDialogController);
-};
-
-}  // namespace autofill
-
-#endif  // CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_VERIFY_PENDING_DIALOG_CONTROLLER_H_
diff --git a/chrome/browser/ui/autofill/payments/verify_pending_dialog_controller_impl.cc b/chrome/browser/ui/autofill/payments/verify_pending_dialog_controller_impl.cc
deleted file mode 100644
index 26e707d..0000000
--- a/chrome/browser/ui/autofill/payments/verify_pending_dialog_controller_impl.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-// 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.
-
-#include "chrome/browser/ui/autofill/payments/verify_pending_dialog_controller_impl.h"
-
-#include "chrome/browser/ui/autofill/payments/verify_pending_dialog_view.h"
-#include "components/strings/grit/components_strings.h"
-#include "ui/base/l10n/l10n_util.h"
-
-namespace autofill {
-
-VerifyPendingDialogControllerImpl::VerifyPendingDialogControllerImpl(
-    content::WebContents* web_contents)
-    : content::WebContentsObserver(web_contents) {}
-
-VerifyPendingDialogControllerImpl::~VerifyPendingDialogControllerImpl() {
-  // If browser tab is closed when dialog is visible, the controller is
-  // destroyed before the view is, so need to reset view's reference to
-  // controller.
-  if (dialog_view_)
-    dialog_view_->Hide();
-}
-
-void VerifyPendingDialogControllerImpl::ShowDialog(
-    base::OnceClosure cancel_card_verification_callback) {
-  DCHECK(!dialog_view_);
-
-  cancel_card_verification_callback_ =
-      std::move(cancel_card_verification_callback);
-  dialog_view_ =
-      VerifyPendingDialogView::CreateDialogAndShow(this, web_contents());
-}
-
-void VerifyPendingDialogControllerImpl::OnCardVerificationCompleted() {
-  if (!dialog_view_)
-    return;
-
-  cancel_card_verification_callback_.Reset();
-  dialog_view_->Hide();
-}
-
-base::string16 VerifyPendingDialogControllerImpl::GetDialogTitle() const {
-  return l10n_util::GetStringUTF16(IDS_AUTOFILL_VERIFY_PENDING_DIALOG_TITLE);
-}
-
-void VerifyPendingDialogControllerImpl::OnCancel() {
-  if (cancel_card_verification_callback_)
-    std::move(cancel_card_verification_callback_).Run();
-}
-
-void VerifyPendingDialogControllerImpl::OnDialogClosed() {
-  dialog_view_ = nullptr;
-  cancel_card_verification_callback_.Reset();
-}
-
-WEB_CONTENTS_USER_DATA_KEY_IMPL(VerifyPendingDialogControllerImpl)
-
-}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/payments/verify_pending_dialog_controller_impl.h b/chrome/browser/ui/autofill/payments/verify_pending_dialog_controller_impl.h
deleted file mode 100644
index 2b652b3..0000000
--- a/chrome/browser/ui/autofill/payments/verify_pending_dialog_controller_impl.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// 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 CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_VERIFY_PENDING_DIALOG_CONTROLLER_IMPL_H_
-#define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_VERIFY_PENDING_DIALOG_CONTROLLER_IMPL_H_
-
-#include "base/macros.h"
-#include "chrome/browser/ui/autofill/payments/verify_pending_dialog_controller.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "content/public/browser/web_contents_user_data.h"
-
-namespace autofill {
-
-class VerifyPendingDialogView;
-
-// Implementation of the per-tab controller to control the
-// VerifyPendingDialogView. Lazily initialized when used.
-class VerifyPendingDialogControllerImpl
-    : public VerifyPendingDialogController,
-      public content::WebContentsObserver,
-      public content::WebContentsUserData<VerifyPendingDialogControllerImpl> {
- public:
-  ~VerifyPendingDialogControllerImpl() override;
-
-  void ShowDialog(base::OnceClosure cancel_card_verification_callback);
-
-  // Close the dialog when card verification is completed.
-  void OnCardVerificationCompleted();
-
-  // VerifyPendingDialogController:
-  base::string16 GetDialogTitle() const override;
-  void OnCancel() override;
-  void OnDialogClosed() override;
-
-  VerifyPendingDialogView* dialog_view() { return dialog_view_; }
-
- protected:
-  explicit VerifyPendingDialogControllerImpl(
-      content::WebContents* web_contents);
-
- private:
-  friend class content::WebContentsUserData<VerifyPendingDialogControllerImpl>;
-
-  // Callback invoked when the cancel button in the dialog is clicked. Will
-  // cancel the card verification in progress.
-  base::OnceClosure cancel_card_verification_callback_;
-
-  VerifyPendingDialogView* dialog_view_ = nullptr;
-
-  WEB_CONTENTS_USER_DATA_KEY_DECL();
-
-  DISALLOW_COPY_AND_ASSIGN(VerifyPendingDialogControllerImpl);
-};
-
-}  // namespace autofill
-
-#endif  // CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_VERIFY_PENDING_DIALOG_CONTROLLER_IMPL_H_
diff --git a/chrome/browser/ui/autofill/payments/verify_pending_dialog_view.h b/chrome/browser/ui/autofill/payments/verify_pending_dialog_view.h
deleted file mode 100644
index 77df5de..0000000
--- a/chrome/browser/ui/autofill/payments/verify_pending_dialog_view.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// 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 CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_VERIFY_PENDING_DIALOG_VIEW_H_
-#define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_VERIFY_PENDING_DIALOG_VIEW_H_
-
-namespace content {
-class WebContents;
-}
-
-namespace autofill {
-
-class VerifyPendingDialogController;
-
-// The dialog to show card verification is in progress.
-class VerifyPendingDialogView {
- public:
-  // Factory function implemented by dialog's view implementation.
-  static VerifyPendingDialogView* CreateDialogAndShow(
-      VerifyPendingDialogController* controller,
-      content::WebContents* web_contents);
-
-  // Close the dialog and prevent callbacks being invoked.
-  virtual void Hide() = 0;
-};
-
-}  // namespace autofill
-
-#endif  // CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_VERIFY_PENDING_DIALOG_VIEW_H_
diff --git a/chrome/browser/ui/autofill/payments/webauthn_dialog_controller_impl.cc b/chrome/browser/ui/autofill/payments/webauthn_dialog_controller_impl.cc
index 15f0e1a..1c54362 100644
--- a/chrome/browser/ui/autofill/payments/webauthn_dialog_controller_impl.cc
+++ b/chrome/browser/ui/autofill/payments/webauthn_dialog_controller_impl.cc
@@ -5,7 +5,9 @@
 #include "chrome/browser/ui/autofill/payments/webauthn_dialog_controller_impl.h"
 
 #include "chrome/browser/ui/autofill/payments/webauthn_dialog_model.h"
+#include "chrome/browser/ui/autofill/payments/webauthn_dialog_state.h"
 #include "chrome/browser/ui/autofill/payments/webauthn_dialog_view.h"
+#include "components/autofill/core/browser/payments/webauthn_callback_types.h"
 
 namespace autofill {
 
@@ -20,15 +22,26 @@
   // controller is not reset. Need to reset via WebauthnDialogViewImpl::Hide()
   // to avoid crash.
   if (dialog_model_)
-    dialog_model_->SetDialogState(WebauthnDialogModel::DialogState::kInactive);
+    dialog_model_->SetDialogState(WebauthnDialogState::kInactive);
 }
 
 void WebauthnDialogControllerImpl::ShowOfferDialog(
-    AutofillClient::WebauthnOfferDialogCallback offer_dialog_callback) {
+    AutofillClient::WebauthnDialogCallback offer_dialog_callback) {
   DCHECK(!dialog_model_);
 
-  offer_dialog_callback_ = std::move(offer_dialog_callback);
-  dialog_view_ = WebauthnDialogView::CreateAndShow(this);
+  callback_ = std::move(offer_dialog_callback);
+  dialog_view_ =
+      WebauthnDialogView::CreateAndShow(this, WebauthnDialogState::kOffer);
+  dialog_model_ = dialog_view_->GetDialogModel();
+}
+
+void WebauthnDialogControllerImpl::ShowVerifyPendingDialog(
+    AutofillClient::WebauthnDialogCallback verify_pending_dialog_callback) {
+  DCHECK(!dialog_model_);
+
+  callback_ = std::move(verify_pending_dialog_callback);
+  dialog_view_ = WebauthnDialogView::CreateAndShow(
+      this, WebauthnDialogState::kVerifyPending);
   dialog_model_ = dialog_view_->GetDialogModel();
 }
 
@@ -36,19 +49,24 @@
   if (!dialog_model_)
     return false;
 
-  dialog_model_->SetDialogState(WebauthnDialogModel::DialogState::kInactive);
+  dialog_model_->SetDialogState(WebauthnDialogState::kInactive);
   return true;
 }
 
-void WebauthnDialogControllerImpl::UpdateDialogWithError() {
-  dialog_model_->SetDialogState(WebauthnDialogModel::DialogState::kError);
-  offer_dialog_callback_.Reset();
+void WebauthnDialogControllerImpl::UpdateDialog(
+    WebauthnDialogState dialog_state) {
+  dialog_model_->SetDialogState(dialog_state);
+  // TODO(crbug.com/991037): Handle callback resetting for verify pending
+  // dialog. Right now this function should only be passed in
+  // WebauthnDialogState::kOfferError.
+  DCHECK_EQ(dialog_state, WebauthnDialogState::kOfferError);
+  callback_.Reset();
 }
 
 void WebauthnDialogControllerImpl::OnDialogClosed() {
   dialog_model_ = nullptr;
   dialog_view_ = nullptr;
-  offer_dialog_callback_.Reset();
+  callback_.Reset();
 }
 
 content::WebContents* WebauthnDialogControllerImpl::GetWebContents() {
@@ -56,14 +74,30 @@
 }
 
 void WebauthnDialogControllerImpl::OnOkButtonClicked() {
-  DCHECK(offer_dialog_callback_);
-  offer_dialog_callback_.Run(/*did_accept=*/true);
-  dialog_model_->SetDialogState(WebauthnDialogModel::DialogState::kPending);
+  // The OK button is available only when the dialog is in
+  // WebauthnDialogState::kOffer state.
+  DCHECK(callback_);
+  callback_.Run(WebauthnDialogCallbackType::kOfferAccepted);
+  dialog_model_->SetDialogState(WebauthnDialogState::kOfferPending);
 }
 
 void WebauthnDialogControllerImpl::OnCancelButtonClicked() {
-  DCHECK(offer_dialog_callback_);
-  offer_dialog_callback_.Run(/*did_accept=*/false);
+  switch (dialog_model_->dialog_state()) {
+    case WebauthnDialogState::kOffer:
+    case WebauthnDialogState::kOfferPending:
+      DCHECK(callback_);
+      callback_.Run(WebauthnDialogCallbackType::kOfferCancelled);
+      return;
+    case WebauthnDialogState::kVerifyPending:
+      DCHECK(callback_);
+      callback_.Run(WebauthnDialogCallbackType::kVerificationCancelled);
+      return;
+    case WebauthnDialogState::kUnknown:
+    case WebauthnDialogState::kInactive:
+    case WebauthnDialogState::kOfferError:
+      NOTREACHED();
+      return;
+  }
 }
 
 WEB_CONTENTS_USER_DATA_KEY_IMPL(WebauthnDialogControllerImpl)
diff --git a/chrome/browser/ui/autofill/payments/webauthn_dialog_controller_impl.h b/chrome/browser/ui/autofill/payments/webauthn_dialog_controller_impl.h
index 871386f..ecd6979 100644
--- a/chrome/browser/ui/autofill/payments/webauthn_dialog_controller_impl.h
+++ b/chrome/browser/ui/autofill/payments/webauthn_dialog_controller_impl.h
@@ -15,6 +15,7 @@
 
 class WebauthnDialogModel;
 class WebauthnDialogView;
+enum class WebauthnDialogState;
 
 // Implementation of the per-tab controller to control the
 // WebauthnDialogView. Lazily initialized when used.
@@ -26,9 +27,11 @@
   ~WebauthnDialogControllerImpl() override;
 
   void ShowOfferDialog(
-      AutofillClient::WebauthnOfferDialogCallback offer_dialog_callback);
+      AutofillClient::WebauthnDialogCallback offer_dialog_callback);
+  void ShowVerifyPendingDialog(
+      AutofillClient::WebauthnDialogCallback verify_pending_dialog_callback);
   bool CloseDialog();
-  void UpdateDialogWithError();
+  void UpdateDialog(WebauthnDialogState dialog_state);
 
   // WebauthnDialogController:
   void OnOkButtonClicked() override;
@@ -44,10 +47,11 @@
  private:
   friend class content::WebContentsUserData<WebauthnDialogControllerImpl>;
 
-  // Callback invoked when any button in the offer dialog is clicked. Note this
-  // repeating callback can be run twice, since after the accept button is
-  // clicked, the offer dialog stays and the cancel button is still clickable.
-  AutofillClient::WebauthnOfferDialogCallback offer_dialog_callback_;
+  // Clicking either the OK button or the cancel button in the dialog
+  // will invoke this repeating callback. Note this repeating callback can
+  // be run twice, since after the accept button in the offer dialog is
+  // clicked, the dialog stays and the cancel button is still clickable.
+  AutofillClient::WebauthnDialogCallback callback_;
 
   WebauthnDialogModel* dialog_model_ = nullptr;
   WebauthnDialogView* dialog_view_ = nullptr;
diff --git a/chrome/browser/ui/autofill/payments/webauthn_dialog_model.cc b/chrome/browser/ui/autofill/payments/webauthn_dialog_model.cc
index 646b3dc..b53327c 100644
--- a/chrome/browser/ui/autofill/payments/webauthn_dialog_model.cc
+++ b/chrome/browser/ui/autofill/payments/webauthn_dialog_model.cc
@@ -6,19 +6,19 @@
 
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/ui/autofill/payments/webauthn_dialog_model_observer.h"
+#include "chrome/browser/ui/autofill/payments/webauthn_dialog_state.h"
 #include "components/strings/grit/components_strings.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/paint_vector_icon.h"
 
 namespace autofill {
 
-WebauthnDialogModel::WebauthnDialogModel() {
-  state_ = kOffer;
-}
+WebauthnDialogModel::WebauthnDialogModel(WebauthnDialogState dialog_state)
+    : state_(dialog_state) {}
 
 WebauthnDialogModel::~WebauthnDialogModel() = default;
 
-void WebauthnDialogModel::SetDialogState(DialogState state) {
+void WebauthnDialogModel::SetDialogState(WebauthnDialogState state) {
   state_ = state;
   for (WebauthnDialogModelObserver& observer : observers_)
     observer.OnDialogStateChanged();
@@ -34,7 +34,8 @@
 }
 
 bool WebauthnDialogModel::IsActivityIndicatorVisible() const {
-  return state_ == DialogState::kPending;
+  return state_ == WebauthnDialogState::kOfferPending ||
+         state_ == WebauthnDialogState::kVerifyPending;
 }
 
 bool WebauthnDialogModel::IsBackButtonVisible() const {
@@ -47,26 +48,30 @@
 
 base::string16 WebauthnDialogModel::GetCancelButtonLabel() const {
   switch (state_) {
-    case DialogState::kOffer:
-    case DialogState::kPending:
+    case WebauthnDialogState::kOffer:
+    case WebauthnDialogState::kOfferPending:
       return l10n_util::GetStringUTF16(
           IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_CANCEL_BUTTON_LABEL);
-    case DialogState::kError:
+    case WebauthnDialogState::kOfferError:
       return l10n_util::GetStringUTF16(
           IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_CANCEL_BUTTON_LABEL_ERROR);
-    case DialogState::kInactive:
-    case DialogState::kUnknown:
+    case WebauthnDialogState::kVerifyPending:
+      return l10n_util::GetStringUTF16(
+          IDS_AUTOFILL_WEBAUTHN_VERIFY_PENDING_DIALOG_CANCEL_BUTTON_LABEL);
+    case WebauthnDialogState::kInactive:
+    case WebauthnDialogState::kUnknown:
       break;
   }
   return base::string16();
 }
 
 bool WebauthnDialogModel::IsAcceptButtonVisible() const {
-  return state_ == DialogState::kOffer || state_ == DialogState::kPending;
+  return state_ == WebauthnDialogState::kOffer ||
+         state_ == WebauthnDialogState::kOfferPending;
 }
 
 bool WebauthnDialogModel::IsAcceptButtonEnabled() const {
-  return state_ != DialogState::kPending;
+  return state_ != WebauthnDialogState::kOfferPending;
 }
 
 base::string16 WebauthnDialogModel::GetAcceptButtonLabel() const {
@@ -77,16 +82,17 @@
 const gfx::VectorIcon& WebauthnDialogModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
   switch (state_) {
-    case DialogState::kOffer:
-    case DialogState::kPending:
+    case WebauthnDialogState::kOffer:
+    case WebauthnDialogState::kOfferPending:
+    case WebauthnDialogState::kVerifyPending:
       return color_scheme == ImageColorScheme::kDark
                  ? kWebauthnDialogHeaderDarkIcon
                  : kWebauthnDialogHeaderIcon;
-    case DialogState::kError:
+    case WebauthnDialogState::kOfferError:
       return color_scheme == ImageColorScheme::kDark ? kWebauthnErrorDarkIcon
                                                      : kWebauthnErrorIcon;
-    case DialogState::kInactive:
-    case DialogState::kUnknown:
+    case WebauthnDialogState::kInactive:
+    case WebauthnDialogState::kUnknown:
       break;
   }
   NOTREACHED();
@@ -95,15 +101,18 @@
 
 base::string16 WebauthnDialogModel::GetStepTitle() const {
   switch (state_) {
-    case DialogState::kOffer:
-    case DialogState::kPending:
+    case WebauthnDialogState::kOffer:
+    case WebauthnDialogState::kOfferPending:
       return l10n_util::GetStringUTF16(
           IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_TITLE);
-    case DialogState::kError:
+    case WebauthnDialogState::kOfferError:
       return l10n_util::GetStringUTF16(
           IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_TITLE_ERROR);
-    case DialogState::kInactive:
-    case DialogState::kUnknown:
+    case WebauthnDialogState::kVerifyPending:
+      return l10n_util::GetStringUTF16(
+          IDS_AUTOFILL_WEBAUTHN_VERIFY_PENDING_DIALOG_TITLE);
+    case WebauthnDialogState::kInactive:
+    case WebauthnDialogState::kUnknown:
       break;
   }
   NOTREACHED();
@@ -112,15 +121,17 @@
 
 base::string16 WebauthnDialogModel::GetStepDescription() const {
   switch (state_) {
-    case DialogState::kOffer:
-    case DialogState::kPending:
+    case WebauthnDialogState::kOffer:
+    case WebauthnDialogState::kOfferPending:
       return l10n_util::GetStringUTF16(
           IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_INSTRUCTION);
-    case DialogState::kError:
+    case WebauthnDialogState::kOfferError:
       return l10n_util::GetStringUTF16(
           IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_INSTRUCTION_ERROR);
-    case DialogState::kInactive:
-    case DialogState::kUnknown:
+    case WebauthnDialogState::kVerifyPending:
+      return base::string16();
+    case WebauthnDialogState::kInactive:
+    case WebauthnDialogState::kUnknown:
       break;
   }
   NOTREACHED();
diff --git a/chrome/browser/ui/autofill/payments/webauthn_dialog_model.h b/chrome/browser/ui/autofill/payments/webauthn_dialog_model.h
index 3cc8ac0..1c3d22a8 100644
--- a/chrome/browser/ui/autofill/payments/webauthn_dialog_model.h
+++ b/chrome/browser/ui/autofill/payments/webauthn_dialog_model.h
@@ -13,29 +13,20 @@
 namespace autofill {
 
 class WebauthnDialogModelObserver;
+enum class WebauthnDialogState;
 
 // The model for WebauthnDialogView determining what content is shown.
 // Owned by the AuthenticatorRequestSheetView.
 class WebauthnDialogModel : public AuthenticatorRequestSheetModel {
  public:
-  enum DialogState {
-    kUnknown,
-    // The dialog is about to be closed automatically. This happens only after
-    // authentication challenge is successfully fetched.
-    kInactive,
-    // The option of using platform authenticator is being offered.
-    kOffer,
-    // Offer was accepted, fetching authentication challenge.
-    kPending,
-    // Fetching authentication challenge failed.
-    kError,
-  };
-
-  WebauthnDialogModel();
+  explicit WebauthnDialogModel(WebauthnDialogState dialog_state);
   ~WebauthnDialogModel() override;
 
-  void SetDialogState(DialogState state);
-  DialogState dialog_state() { return state_; }
+  // Update the current state the dialog should be. When the state is changed,
+  // the view's contents should be re-initialized. This should not be used
+  // before the view is created.
+  void SetDialogState(WebauthnDialogState state);
+  WebauthnDialogState dialog_state() { return state_; }
 
   void AddObserver(WebauthnDialogModelObserver* observer);
   void RemoveObserver(WebauthnDialogModelObserver* observer);
@@ -60,7 +51,7 @@
   void OnCancel() override {}
 
  private:
-  DialogState state_ = DialogState::kUnknown;
+  WebauthnDialogState state_;
 
   base::ObserverList<WebauthnDialogModelObserver> observers_;
 
diff --git a/chrome/browser/ui/autofill/payments/webauthn_dialog_state.h b/chrome/browser/ui/autofill/payments/webauthn_dialog_state.h
new file mode 100644
index 0000000..35123de
--- /dev/null
+++ b/chrome/browser/ui/autofill/payments/webauthn_dialog_state.h
@@ -0,0 +1,31 @@
+// 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 CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_WEBAUTHN_DIALOG_STATE_H_
+#define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_WEBAUTHN_DIALOG_STATE_H_
+
+namespace autofill {
+
+// The type of save card bubble to show.
+enum class WebauthnDialogState {
+  kUnknown,
+  // The dialog is about to be closed automatically. This happens only after
+  // authentication challenge is successfully fetched.
+  kInactive,
+  // The option of using platform authenticator is being offered.
+  kOffer,
+  // Offer was accepted, fetching authentication challenge.
+  kOfferPending,
+  // Fetching authentication challenge failed.
+  kOfferError,
+  // Indicating the card verification is in progress. Shown only for opted-in
+  // users.
+  kVerifyPending,
+  // TODO(crbug.com/991037): Add an extra state for case when the cancel button
+  // in the verify pending dialog should be disabled.
+};
+
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_WEBAUTHN_DIALOG_STATE_H_
diff --git a/chrome/browser/ui/autofill/payments/webauthn_dialog_view.h b/chrome/browser/ui/autofill/payments/webauthn_dialog_view.h
index 450fdab..dd5a397 100644
--- a/chrome/browser/ui/autofill/payments/webauthn_dialog_view.h
+++ b/chrome/browser/ui/autofill/payments/webauthn_dialog_view.h
@@ -9,14 +9,15 @@
 
 class WebauthnDialogController;
 class WebauthnDialogModel;
+enum class WebauthnDialogState;
 
 // The view of the dialog that offers the option to use device's platform
 // authenticator. It is shown automatically after card unmasked details are
 // obtained and filled into the form.
 class WebauthnDialogView {
  public:
-  static WebauthnDialogView* CreateAndShow(
-      WebauthnDialogController* controller);
+  static WebauthnDialogView* CreateAndShow(WebauthnDialogController* controller,
+                                           WebauthnDialogState dialog_state);
 
   virtual WebauthnDialogModel* GetDialogModel() const = 0;
 };
diff --git a/chrome/browser/ui/views/autofill/payments/verify_pending_dialog_view_browsertest.cc b/chrome/browser/ui/views/autofill/payments/verify_pending_dialog_view_browsertest.cc
deleted file mode 100644
index c413b91..0000000
--- a/chrome/browser/ui/views/autofill/payments/verify_pending_dialog_view_browsertest.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-// 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.
-
-#include "chrome/browser/ui/autofill/payments/verify_pending_dialog_controller_impl.h"
-#include "chrome/browser/ui/autofill/payments/verify_pending_dialog_view.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/test/test_browser_dialog.h"
-#include "chrome/browser/ui/views/autofill/payments/verify_pending_dialog_view_impl.h"
-
-namespace autofill {
-
-class VerifyPendingDialogViewBrowserTest : public DialogBrowserTest {
- public:
-  VerifyPendingDialogViewBrowserTest() = default;
-  // DialogBrowserTest:
-  void ShowUi(const std::string& name) override {
-    content::WebContents* web_contents =
-        browser()->tab_strip_model()->GetActiveWebContents();
-    // Do lazy initialization of VerifyPendingDialogControllerImpl.
-    VerifyPendingDialogControllerImpl::CreateForWebContents(web_contents);
-    controller_ =
-        VerifyPendingDialogControllerImpl::FromWebContents(web_contents);
-    DCHECK(controller_);
-    controller_->ShowDialog(base::DoNothing());
-  }
-
-  VerifyPendingDialogViewImpl* GetVerifyPendingDialog() {
-    if (!controller_)
-      return nullptr;
-    VerifyPendingDialogView* verify_pending_dialog_view =
-        controller_->dialog_view();
-    if (!verify_pending_dialog_view)
-      return nullptr;
-    return static_cast<VerifyPendingDialogViewImpl*>(
-        verify_pending_dialog_view);
-  }
-
-  VerifyPendingDialogControllerImpl* controller() { return controller_; }
-
- private:
-  VerifyPendingDialogControllerImpl* controller_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(VerifyPendingDialogViewBrowserTest);
-};
-
-IN_PROC_BROWSER_TEST_F(VerifyPendingDialogViewBrowserTest, InvokeUi_default) {
-  ShowAndVerifyUi();
-}
-
-// This test ensures an edge case (closing tab while dialog being visible) is
-// correctly handled, otherwise this test will crash during web contents being
-// closed.
-IN_PROC_BROWSER_TEST_F(VerifyPendingDialogViewBrowserTest,
-                       CanCloseTabWhileDialogShowing) {
-  ShowUi(std::string());
-  VerifyUi();
-  browser()->tab_strip_model()->GetActiveWebContents()->Close();
-  base::RunLoop().RunUntilIdle();
-}
-
-// Ensures closing browser while dialog being visible is correctly handled.
-IN_PROC_BROWSER_TEST_F(VerifyPendingDialogViewBrowserTest,
-                       CanCloseBrowserWhileDialogShowing) {
-  ShowUi(std::string());
-  VerifyUi();
-  browser()->window()->Close();
-  base::RunLoop().RunUntilIdle();
-}
-
-// Ensures dialog can be closed when verification finishes.
-IN_PROC_BROWSER_TEST_F(VerifyPendingDialogViewBrowserTest,
-                       VerificationFinishes) {
-  ShowUi(std::string());
-  VerifyUi();
-  GetVerifyPendingDialog()->Hide();
-  base::RunLoop().RunUntilIdle();
-}
-
-// Ensures dialog is closed when cancel button is clicked.
-IN_PROC_BROWSER_TEST_F(VerifyPendingDialogViewBrowserTest, ClickCancelButton) {
-  ShowUi(std::string());
-  VerifyUi();
-  GetVerifyPendingDialog()->CancelDialog();
-  base::RunLoop().RunUntilIdle();
-}
-
-// TODO(crbug.com/991037): Add more browser tests:
-// 1. Make sure callback runs if cancel button clicked.
-
-}  // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/payments/verify_pending_dialog_view_impl.cc b/chrome/browser/ui/views/autofill/payments/verify_pending_dialog_view_impl.cc
deleted file mode 100644
index e827cb1..0000000
--- a/chrome/browser/ui/views/autofill/payments/verify_pending_dialog_view_impl.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-// 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.
-
-#include "chrome/browser/ui/views/autofill/payments/verify_pending_dialog_view_impl.h"
-
-#include "chrome/browser/ui/autofill/payments/verify_pending_dialog_controller.h"
-#include "chrome/browser/ui/views/chrome_layout_provider.h"
-#include "components/constrained_window/constrained_window_views.h"
-#include "components/strings/grit/components_strings.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/views/bubble/bubble_frame_view.h"
-
-namespace autofill {
-
-VerifyPendingDialogViewImpl::VerifyPendingDialogViewImpl(
-    VerifyPendingDialogController* controller)
-    : controller_(controller) {
-  DialogDelegate::set_buttons(ui::DIALOG_BUTTON_CANCEL);
-  DialogDelegate::set_button_label(
-      ui::DIALOG_BUTTON_CANCEL,
-      l10n_util::GetStringUTF16(
-          IDS_AUTOFILL_VERIFY_PENDING_DIALOG_CANCEL_BUTTON_LABEL));
-  // TODO(crbug.com/1014278): Should get correct width automatically when
-  // snapping.
-  const int width = ChromeLayoutProvider::Get()->GetDistanceMetric(
-      DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH);
-  // TODO(crbug.com/1014334): Investigate why CalculatePreferredSize can not be
-  // overridden when there is no layout manager.
-  SetPreferredSize(gfx::Size(width, GetHeightForWidth(width)));
-}
-
-VerifyPendingDialogViewImpl::~VerifyPendingDialogViewImpl() {
-  if (controller_) {
-    controller_->OnDialogClosed();
-    controller_ = nullptr;
-  }
-}
-
-// static
-VerifyPendingDialogView* VerifyPendingDialogView::CreateDialogAndShow(
-    VerifyPendingDialogController* controller,
-    content::WebContents* web_contents) {
-  VerifyPendingDialogViewImpl* dialog =
-      new VerifyPendingDialogViewImpl(controller);
-  constrained_window::ShowWebModalDialogViews(dialog, web_contents);
-  return dialog;
-}
-
-void VerifyPendingDialogViewImpl::Hide() {
-  if (controller_) {
-    controller_->OnDialogClosed();
-    controller_ = nullptr;
-  }
-  GetWidget()->Close();
-}
-
-void VerifyPendingDialogViewImpl::AddedToWidget() {
-  GetBubbleFrameView()->SetProgress(/*Infinite animation*/ -1);
-}
-
-bool VerifyPendingDialogViewImpl::Cancel() {
-  if (controller_)
-    controller_->OnCancel();
-
-  return true;
-}
-
-ui::ModalType VerifyPendingDialogViewImpl::GetModalType() const {
-  return ui::MODAL_TYPE_CHILD;
-}
-
-base::string16 VerifyPendingDialogViewImpl::GetWindowTitle() const {
-  return controller_->GetDialogTitle();
-}
-
-bool VerifyPendingDialogViewImpl::ShouldShowCloseButton() const {
-  return false;
-}
-
-}  // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/payments/verify_pending_dialog_view_impl.h b/chrome/browser/ui/views/autofill/payments/verify_pending_dialog_view_impl.h
deleted file mode 100644
index ec1c05e..0000000
--- a/chrome/browser/ui/views/autofill/payments/verify_pending_dialog_view_impl.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// 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 CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_VERIFY_PENDING_DIALOG_VIEW_IMPL_H_
-#define CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_VERIFY_PENDING_DIALOG_VIEW_IMPL_H_
-
-#include "base/macros.h"
-#include "chrome/browser/ui/autofill/payments/verify_pending_dialog_view.h"
-#include "ui/views/window/dialog_delegate.h"
-
-namespace autofill {
-
-class VerifyPendingDialogController;
-
-// The Views implementation of the dialog that shows the card verification is in
-// progress. It is shown when card verification process starts only if WebAuthn
-// has been enabled and opted in.
-class VerifyPendingDialogViewImpl : public VerifyPendingDialogView,
-                                    public views::DialogDelegateView {
- public:
-  explicit VerifyPendingDialogViewImpl(
-      VerifyPendingDialogController* controller);
-  ~VerifyPendingDialogViewImpl() override;
-
-  // VerifyPendingDialogView:
-  void Hide() override;
-
-  // views::DialogDelegateView:
-  void AddedToWidget() override;
-  bool Cancel() override;
-  ui::ModalType GetModalType() const override;
-  base::string16 GetWindowTitle() const override;
-  bool ShouldShowCloseButton() const override;
-
- private:
-  VerifyPendingDialogController* controller_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(VerifyPendingDialogViewImpl);
-};
-
-}  // namespace autofill
-
-#endif  // CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_VERIFY_PENDING_DIALOG_VIEW_IMPL_H_
diff --git a/chrome/browser/ui/views/autofill/payments/webauthn_dialog_browsertest.cc b/chrome/browser/ui/views/autofill/payments/webauthn_dialog_browsertest.cc
index ff7626b..41de9cc 100644
--- a/chrome/browser/ui/views/autofill/payments/webauthn_dialog_browsertest.cc
+++ b/chrome/browser/ui/views/autofill/payments/webauthn_dialog_browsertest.cc
@@ -12,6 +12,13 @@
 
 namespace autofill {
 
+namespace {
+// If ShowAndVerifyUi() is used, the tests must be named as "InvokeUi_"
+// appending these names.
+constexpr char kOfferDialogName[] = "Offer";
+constexpr char kVerifyDialogName[] = "Verify";
+}  // namespace
+
 class WebauthnDialogBrowserTest : public DialogBrowserTest {
  public:
   WebauthnDialogBrowserTest() = default;
@@ -23,8 +30,12 @@
 
     // Do lazy initialization of WebauthnDialogControllerImpl.
     WebauthnDialogControllerImpl::CreateForWebContents(web_contents);
-    DCHECK(controller());
-    controller()->ShowOfferDialog(base::DoNothing());
+
+    if (name == kOfferDialogName) {
+      controller()->ShowOfferDialog(base::DoNothing());
+    } else if (name == kVerifyDialogName) {
+      controller()->ShowVerifyPendingDialog(base::DoNothing());
+    }
   }
 
   WebauthnDialogViewImpl* GetWebauthnDialog() {
@@ -51,15 +62,15 @@
   DISALLOW_COPY_AND_ASSIGN(WebauthnDialogBrowserTest);
 };
 
-IN_PROC_BROWSER_TEST_F(WebauthnDialogBrowserTest, InvokeUi_default) {
+IN_PROC_BROWSER_TEST_F(WebauthnDialogBrowserTest, InvokeUi_Offer) {
   ShowAndVerifyUi();
 }
 
 // Ensures closing tab while dialog being visible is correctly handled.
 // RunUntilIdle() makes sure that nothing crashes after browser tab is closed.
 IN_PROC_BROWSER_TEST_F(WebauthnDialogBrowserTest,
-                       CanCloseTabWhileDialogShowing) {
-  ShowUi(std::string());
+                       OfferDialog_CanCloseTabWhileDialogShowing) {
+  ShowUi(kOfferDialogName);
   VerifyUi();
   browser()->tab_strip_model()->GetActiveWebContents()->Close();
   base::RunLoop().RunUntilIdle();
@@ -67,16 +78,56 @@
 
 // Ensures closing browser while dialog being visible is correctly handled.
 IN_PROC_BROWSER_TEST_F(WebauthnDialogBrowserTest,
-                       CanCloseBrowserWhileDialogShowing) {
-  ShowUi(std::string());
+                       OfferDialog_CanCloseBrowserWhileDialogShowing) {
+  ShowUi(kOfferDialogName);
   VerifyUi();
   browser()->window()->Close();
   base::RunLoop().RunUntilIdle();
 }
 
 // Ensures dialog is closed when cancel button is clicked.
-IN_PROC_BROWSER_TEST_F(WebauthnDialogBrowserTest, ClickCancelButton) {
-  ShowUi(std::string());
+IN_PROC_BROWSER_TEST_F(WebauthnDialogBrowserTest,
+                       OfferDialog_ClickCancelButton) {
+  ShowUi(kOfferDialogName);
+  VerifyUi();
+  GetWebauthnDialog()->CancelDialog();
+  base::RunLoop().RunUntilIdle();
+}
+
+IN_PROC_BROWSER_TEST_F(WebauthnDialogBrowserTest, InvokeUi_Verify) {
+  ShowAndVerifyUi();
+}
+
+IN_PROC_BROWSER_TEST_F(WebauthnDialogBrowserTest,
+                       VerifyPendingDialog_CanCloseTabWhileDialogShowing) {
+  ShowUi(kVerifyDialogName);
+  VerifyUi();
+  browser()->tab_strip_model()->GetActiveWebContents()->Close();
+  base::RunLoop().RunUntilIdle();
+}
+
+// Ensures closing browser while dialog being visible is correctly handled.
+IN_PROC_BROWSER_TEST_F(WebauthnDialogBrowserTest,
+                       VerifyPendingDialog_CanCloseBrowserWhileDialogShowing) {
+  ShowUi(kVerifyDialogName);
+  VerifyUi();
+  browser()->window()->Close();
+  base::RunLoop().RunUntilIdle();
+}
+
+// Ensures dialog can be closed when verification finishes.
+IN_PROC_BROWSER_TEST_F(WebauthnDialogBrowserTest,
+                       VerifyPendingDialog_VerificationFinishes) {
+  ShowUi(kVerifyDialogName);
+  VerifyUi();
+  controller()->CloseDialog();
+  base::RunLoop().RunUntilIdle();
+}
+
+// Ensures dialog is closed when cancel button is clicked.
+IN_PROC_BROWSER_TEST_F(WebauthnDialogBrowserTest,
+                       VerifyPendingDialog_ClickCancelButton) {
+  ShowUi(kVerifyDialogName);
   VerifyUi();
   GetWebauthnDialog()->CancelDialog();
   base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/ui/views/autofill/payments/webauthn_dialog_view_impl.cc b/chrome/browser/ui/views/autofill/payments/webauthn_dialog_view_impl.cc
index dcd333d..c1ca9c2 100644
--- a/chrome/browser/ui/views/autofill/payments/webauthn_dialog_view_impl.cc
+++ b/chrome/browser/ui/views/autofill/payments/webauthn_dialog_view_impl.cc
@@ -6,6 +6,7 @@
 
 #include "chrome/browser/ui/autofill/payments/webauthn_dialog_controller.h"
 #include "chrome/browser/ui/autofill/payments/webauthn_dialog_model.h"
+#include "chrome/browser/ui/autofill/payments/webauthn_dialog_state.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.h"
 #include "chrome/browser/ui/views/webauthn/sheet_view_factory.h"
@@ -19,11 +20,12 @@
 namespace autofill {
 
 WebauthnDialogViewImpl::WebauthnDialogViewImpl(
-    WebauthnDialogController* controller)
+    WebauthnDialogController* controller,
+    WebauthnDialogState dialog_state)
     : controller_(controller) {
   SetLayoutManager(std::make_unique<views::FillLayout>());
   std::unique_ptr<WebauthnDialogModel> model =
-      std::make_unique<WebauthnDialogModel>();
+      std::make_unique<WebauthnDialogModel>(dialog_state);
   model_ = model.get();
   model_->AddObserver(this);
   sheet_view_ =
@@ -46,8 +48,10 @@
 
 // static
 WebauthnDialogView* WebauthnDialogView::CreateAndShow(
-    WebauthnDialogController* controller) {
-  WebauthnDialogViewImpl* dialog = new WebauthnDialogViewImpl(controller);
+    WebauthnDialogController* controller,
+    WebauthnDialogState dialog_state) {
+  WebauthnDialogViewImpl* dialog =
+      new WebauthnDialogViewImpl(controller, dialog_state);
   constrained_window::ShowWebModalDialogViews(dialog,
                                               controller->GetWebContents());
   return dialog;
@@ -59,15 +63,16 @@
 
 void WebauthnDialogViewImpl::OnDialogStateChanged() {
   switch (model_->dialog_state()) {
-    case WebauthnDialogModel::DialogState::kInactive:
+    case WebauthnDialogState::kInactive:
       Hide();
       break;
-    case WebauthnDialogModel::DialogState::kPending:
-    case WebauthnDialogModel::DialogState::kError:
+    case WebauthnDialogState::kOfferPending:
+    case WebauthnDialogState::kOfferError:
+    case WebauthnDialogState::kVerifyPending:
       RefreshContent();
       break;
-    case WebauthnDialogModel::DialogState::kUnknown:
-    case WebauthnDialogModel::DialogState::kOffer:
+    case WebauthnDialogState::kUnknown:
+    case WebauthnDialogState::kOffer:
       NOTREACHED();
   }
 }
@@ -79,24 +84,21 @@
 }
 
 bool WebauthnDialogViewImpl::Accept() {
-  DCHECK_EQ(model_->dialog_state(), WebauthnDialogModel::DialogState::kOffer);
+  DCHECK_EQ(model_->dialog_state(), WebauthnDialogState::kOffer);
   controller_->OnOkButtonClicked();
   return false;
 }
 
 bool WebauthnDialogViewImpl::Cancel() {
-  if (model_->dialog_state() == WebauthnDialogModel::DialogState::kOffer ||
-      model_->dialog_state() == WebauthnDialogModel::DialogState::kPending) {
+  if (model_->dialog_state() == WebauthnDialogState::kOffer ||
+      model_->dialog_state() == WebauthnDialogState::kOfferPending ||
+      model_->dialog_state() == WebauthnDialogState::kVerifyPending) {
     controller_->OnCancelButtonClicked();
   }
 
   return true;
 }
 
-bool WebauthnDialogViewImpl::Close() {
-  return true;
-}
-
 int WebauthnDialogViewImpl::GetDialogButtons() const {
   // Cancel button is always visible but OK button depends on dialog state.
   DCHECK(model_->IsCancelButtonVisible());
diff --git a/chrome/browser/ui/views/autofill/payments/webauthn_dialog_view_impl.h b/chrome/browser/ui/views/autofill/payments/webauthn_dialog_view_impl.h
index 48ba4dc..e3ff491 100644
--- a/chrome/browser/ui/views/autofill/payments/webauthn_dialog_view_impl.h
+++ b/chrome/browser/ui/views/autofill/payments/webauthn_dialog_view_impl.h
@@ -21,7 +21,8 @@
                                public WebauthnDialogModelObserver,
                                public views::DialogDelegateView {
  public:
-  explicit WebauthnDialogViewImpl(WebauthnDialogController* controller);
+  WebauthnDialogViewImpl(WebauthnDialogController* controller,
+                         WebauthnDialogState dialog_state);
   ~WebauthnDialogViewImpl() override;
 
   // WebauthnDialogView:
@@ -34,7 +35,6 @@
   gfx::Size CalculatePreferredSize() const override;
   bool Accept() override;
   bool Cancel() override;
-  bool Close() override;
   int GetDialogButtons() const override;
   bool IsDialogButtonEnabled(ui::DialogButton button) const override;
   ui::ModalType GetModalType() const override;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 298440b..b94cb27 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1299,7 +1299,6 @@
       "../browser/ui/toolbar/browser_actions_bar_browsertest.h",
       "../browser/ui/update_chrome_dialog_browsertest.cc",
       "../browser/ui/views/apps/app_info_dialog/app_info_dialog_views_browsertest.cc",
-      "../browser/ui/views/autofill/payments/verify_pending_dialog_view_browsertest.cc",
       "../browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc",
       "../browser/ui/views/chrome_cleaner_dialog_browsertest_win.cc",
       "../browser/ui/views/chrome_cleaner_reboot_dialog_browsertest_win.cc",
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn
index 150dff2..d37fe3ed 100644
--- a/components/autofill/core/browser/BUILD.gn
+++ b/components/autofill/core/browser/BUILD.gn
@@ -197,6 +197,7 @@
     "payments/strike_database_integrator_test_strike_database.h",
     "payments/upi_vpa_save_manager.cc",
     "payments/upi_vpa_save_manager.h",
+    "payments/webauthn_callback_types.h",
     "personal_data_manager.cc",
     "personal_data_manager.h",
     "personal_data_manager_observer.h",
diff --git a/components/autofill/core/browser/autofill_client.h b/components/autofill/core/browser/autofill_client.h
index 3e136eb..c6d4043 100644
--- a/components/autofill/core/browser/autofill_client.h
+++ b/components/autofill/core/browser/autofill_client.h
@@ -64,6 +64,8 @@
 class MigratableCreditCard;
 class PersonalDataManager;
 class StrikeDatabase;
+enum class WebauthnDialogCallbackType;
+enum class WebauthnDialogState;
 struct Suggestion;
 
 namespace payments {
@@ -215,10 +217,10 @@
   typedef base::RepeatingCallback<void(const std::string&)>
       MigrationDeleteCardCallback;
 
-  // Callback to run if the OK button or the cancel button in the
-  // WebauthnOfferDialog is clicked. Will pass to CreditCardFIDOAuthenticator a
-  // bool indicating if offer was accepted or declined.
-  typedef base::RepeatingCallback<void(bool)> WebauthnOfferDialogCallback;
+  // Callback to run if the OK button or the cancel button in a
+  // Webauthn dialog is clicked.
+  typedef base::RepeatingCallback<void(WebauthnDialogCallbackType)>
+      WebauthnDialogCallback;
 
   ~AutofillClient() override {}
 
@@ -307,32 +309,30 @@
       MigrationDeleteCardCallback delete_local_card_callback) = 0;
 
 #if !defined(OS_ANDROID) && !defined(OS_IOS)
+  // TODO(crbug.com/991037): Find a way to merge these two functions. Shouldn't
+  // use WebauthnDialogState as that state is a purely UI state (should not be
+  // accessible for managers?), and some of the states |KInactive| may be
+  // confusing here. Do we want to add another Enum?
+
   // Will show a dialog offering the option to use device's platform
   // authenticator in the future instead of CVC to verify the card being
   // unmasked. Runs |offer_dialog_callback| if the OK button or the cancel
-  // button in the dialog is clicked. This is only implemented on desktop.
+  // button in the dialog is clicked.
   virtual void ShowWebauthnOfferDialog(
-      WebauthnOfferDialogCallback offer_dialog_callback) = 0;
-
-  // Will update the WebAuthn offer dialog content to the error state.
-  // Implemented only on desktop.
-  virtual void UpdateWebauthnOfferDialogWithError() = 0;
-
-  // TODO(crbug.com/949269): Merge CloseWebauthnOfferDialog() and
-  // CloseWebauthnVerifyPendingDialog() into one function.
-  // Will close the WebAuthn offer dialog. Returns true if dialog was visible
-  // and has been closed. Implemented only on desktop.
-  virtual bool CloseWebauthnOfferDialog() = 0;
+      WebauthnDialogCallback offer_dialog_callback) = 0;
 
   // Will show a dialog indicating the card verification is in progress. It is
   // shown after verification starts only if the WebAuthn is enabled.
-  // Implemented only on desktop.
   virtual void ShowWebauthnVerifyPendingDialog(
-      base::OnceClosure cancel_card_verification_callback) = 0;
+      WebauthnDialogCallback verify_pending_dialog_callback) = 0;
 
-  // Close the verify pending dialog once the card verificiation is completed or
-  // verification falls back to CVC.
-  virtual void CloseWebauthnVerifyPendingDialog() = 0;
+  // Will update the WebAuthn dialog content when there is an error fetching the
+  // challenge.
+  virtual void UpdateWebauthnOfferDialogWithError() = 0;
+
+  // Will close the current visible WebAuthn dialog. Returns true if dialog was
+  // visible and has been closed.
+  virtual bool CloseWebauthnDialog() = 0;
 #endif
 
   // Runs |callback| if the |profile| should be imported as personal data.
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager.cc b/components/autofill/core/browser/payments/credit_card_access_manager.cc
index 4b2eb9d..a43e7e1 100644
--- a/components/autofill/core/browser/payments/credit_card_access_manager.cc
+++ b/components/autofill/core/browser/payments/credit_card_access_manager.cc
@@ -25,6 +25,7 @@
 #include "components/autofill/core/browser/data_model/credit_card.h"
 #include "components/autofill/core/browser/metrics/credit_card_form_event_logger.h"
 #include "components/autofill/core/browser/payments/payments_client.h"
+#include "components/autofill/core/browser/payments/webauthn_callback_types.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_tick_clock.h"
@@ -336,8 +337,7 @@
   return;
 #else
   if (opt_in) {
-    GetOrCreateFIDOAuthenticator()->ShowWebauthnOfferDialog(
-        /*card_authorization_token=*/std::string());
+    ShowWebauthnOfferDialog(/*card_authorization_token=*/std::string());
   } else {
     GetOrCreateFIDOAuthenticator()->OptOut();
     GetOrCreateFIDOAuthenticator()
@@ -408,9 +408,9 @@
 #endif
   } else {
 #if !defined(OS_ANDROID) && !defined(OS_IOS)
-    // Close the verify pending dialog if it enters CVC authentication flow
-    // since the card unmask prompt will pop up.
-    client_->CloseWebauthnVerifyPendingDialog();
+    // Close the Webauthn verify pending dialog if it enters CVC authentication
+    // flow since the card unmask prompt will pop up.
+    client_->CloseWebauthnDialog();
 #endif
     GetOrCreateCVCAuthenticator()->Authenticate(
         card_, weak_ptr_factory_.GetWeakPtr(), personal_data_manager_,
@@ -476,8 +476,7 @@
     GetOrCreateFIDOAuthenticator()->Authorize(
         response.card_authorization_token, response.request_options->Clone());
   } else if (should_offer_fido_auth) {
-    GetOrCreateFIDOAuthenticator()->ShowWebauthnOfferDialog(
-        response.card_authorization_token);
+    ShowWebauthnOfferDialog(response.card_authorization_token);
   } else if (should_follow_up_cvc_with_fido_auth_) {
     DCHECK(unmask_details_.fido_request_options.is_dict());
     GetOrCreateFIDOAuthenticator()->Authorize(
@@ -492,10 +491,10 @@
     bool did_succeed,
     const CreditCard* card) {
 #if !defined(OS_ANDROID)
-  // Close the verify pending dialog. If FIDO authentication succeeded, card is
-  // filled to the form, otherwise fall back to CVC authentication which does
-  // not need the verify pending dialog either.
-  client_->CloseWebauthnVerifyPendingDialog();
+  // Close the Webauthn verify pending dialog. If FIDO authentication succeeded,
+  // card is filled to the form, otherwise fall back to CVC authentication which
+  // does not need the verify pending dialog either.
+  client_->CloseWebauthnDialog();
 #endif
 
   if (did_succeed) {
@@ -525,20 +524,44 @@
 #endif
 }
 
+void CreditCardAccessManager::ShowWebauthnOfferDialog(
+    std::string card_authorization_token) {
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+  GetOrCreateFIDOAuthenticator()->OnWebauthnOfferDialogRequested(
+      card_authorization_token);
+  client_->ShowWebauthnOfferDialog(
+      base::BindRepeating(&CreditCardAccessManager::HandleDialogUserResponse,
+                          weak_ptr_factory_.GetWeakPtr()));
+#endif
+}
+
 #if !defined(OS_ANDROID) && !defined(OS_IOS)
 void CreditCardAccessManager::ShowVerifyPendingDialog() {
   client_->ShowWebauthnVerifyPendingDialog(
-      base::BindOnce(&CreditCardAccessManager::OnDidCancelCardVerification,
-                     weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&CreditCardAccessManager::HandleDialogUserResponse,
+                          weak_ptr_factory_.GetWeakPtr()));
 }
 
-void CreditCardAccessManager::OnDidCancelCardVerification() {
-  // TODO(crbug.com/949269): Add tests and logging for canceling verify pending
-  // dialog.
-  GetOrCreateFIDOAuthenticator()->CancelVerification();
-  unmask_details_request_in_progress_ = false;
-  is_authentication_in_progress_ = false;
-  SignalCanFetchUnmaskDetails();
+void CreditCardAccessManager::HandleDialogUserResponse(
+    WebauthnDialogCallbackType type) {
+  switch (type) {
+    case WebauthnDialogCallbackType::kOfferAccepted:
+      GetOrCreateFIDOAuthenticator()->OnWebauthnOfferDialogUserResponse(
+          /*did_accept=*/true);
+      break;
+    case WebauthnDialogCallbackType::kOfferCancelled:
+      GetOrCreateFIDOAuthenticator()->OnWebauthnOfferDialogUserResponse(
+          /*did_accept=*/false);
+      break;
+    case WebauthnDialogCallbackType::kVerificationCancelled:
+      // TODO(crbug.com/949269): Add tests and logging for canceling verify
+      // pending dialog.
+      GetOrCreateFIDOAuthenticator()->CancelVerification();
+      unmask_details_request_in_progress_ = false;
+      is_authentication_in_progress_ = false;
+      SignalCanFetchUnmaskDetails();
+      break;
+  }
 }
 #endif
 
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager.h b/components/autofill/core/browser/payments/credit_card_access_manager.h
index 55e8ee55..fdcdd19 100644
--- a/components/autofill/core/browser/payments/credit_card_access_manager.h
+++ b/components/autofill/core/browser/payments/credit_card_access_manager.h
@@ -29,6 +29,7 @@
 namespace autofill {
 
 class AutofillManager;
+enum class WebauthnDialogCallbackType;
 
 // Manages logic for accessing credit cards either stored locally or stored
 // with Google Payments. Owned by AutofillManager.
@@ -161,14 +162,19 @@
   // immediately.
   bool AuthenticationRequiresUnmaskDetails();
 
+  // TODO(crbug.com/991037): Move this function under the build flags after the
+  // refactoring is done.
+  // Offer the option to use WebAuthn for authenticating future card unmasking.
+  void ShowWebauthnOfferDialog(std::string card_authorization_token);
+
 #if !defined(OS_ANDROID) && !defined(OS_IOS)
   // After card verification starts, shows the verify pending dialog if WebAuthn
   // is enabled, indicating some verification steps are in progress.
   void ShowVerifyPendingDialog();
 
-  // The callback function invoked when the cancel button in the verify pending
-  // dialog is clicked. Will cancel the attempt to fetch unmask details.
-  void OnDidCancelCardVerification();
+  // Invokes the corresponding callback on different user's responses on either
+  // the Webauthn offer dialog or verify pending dialog.
+  void HandleDialogUserResponse(WebauthnDialogCallbackType type);
 #endif
 
   // Used with PostTaskWithDelay() to signal |can_fetch_unmask_details_| event
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc b/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
index e72d79d..4d25df8 100644
--- a/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
+++ b/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
@@ -330,17 +330,19 @@
     GetFIDOAuthenticator()->OnDidGetOptChangeResult(result, response);
   }
 
-  // Mocks user response for the offer dialog.
-  void AcceptWebauthnOfferDialog(bool did_accept) {
-    GetFIDOAuthenticator()->OnWebauthnOfferDialogUserResponse(did_accept);
-  }
-
   TestCreditCardFIDOAuthenticator* GetFIDOAuthenticator() {
     return static_cast<TestCreditCardFIDOAuthenticator*>(
         credit_card_access_manager_->GetOrCreateFIDOAuthenticator());
   }
 #endif
 
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+  // Mocks user response for the offer dialog.
+  void AcceptWebauthnOfferDialog(bool did_accept) {
+    GetFIDOAuthenticator()->OnWebauthnOfferDialogUserResponse(did_accept);
+  }
+#endif
+
   void InvokeUnmaskDetailsTimeout() {
     credit_card_access_manager_->ready_to_start_authentication_.Signal();
     credit_card_access_manager_->can_fetch_unmask_details_.Signal();
diff --git a/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc b/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc
index e175ba6..7b60ac0 100644
--- a/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc
+++ b/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc
@@ -61,18 +61,6 @@
 
 CreditCardFIDOAuthenticator::~CreditCardFIDOAuthenticator() {}
 
-void CreditCardFIDOAuthenticator::ShowWebauthnOfferDialog(
-    std::string card_authorization_token) {
-#if !defined(OS_ANDROID)
-  card_authorization_token_ = card_authorization_token;
-  autofill_client_->ShowWebauthnOfferDialog(base::BindRepeating(
-      &CreditCardFIDOAuthenticator::OnWebauthnOfferDialogUserResponse,
-      weak_ptr_factory_.GetWeakPtr()));
-  AutofillMetrics::LogWebauthnOptInPromoShown(
-      /*is_checkout_flow=*/!card_authorization_token_.empty());
-#endif
-}
-
 void CreditCardFIDOAuthenticator::Authenticate(
     const CreditCard* card,
     base::WeakPtr<Requester> requester,
@@ -177,6 +165,42 @@
     full_card_request_->OnFIDOVerificationCancelled();
 }
 
+#if !defined(OS_ANDROID)
+void CreditCardFIDOAuthenticator::OnWebauthnOfferDialogRequested(
+    std::string card_authorization_token) {
+  card_authorization_token_ = card_authorization_token;
+  AutofillMetrics::LogWebauthnOptInPromoShown(
+      /*is_checkout_flow=*/!card_authorization_token_.empty());
+}
+
+void CreditCardFIDOAuthenticator::OnWebauthnOfferDialogUserResponse(
+    bool did_accept) {
+  if (did_accept) {
+    // Wait until GetAssertion()/MakeCredential() to log user acceptance, since
+    // user still has the option to cancel the dialog while the challenge is
+    // being fetched.
+    Register(card_authorization_token_);
+  } else {
+    // If user declined, log user decision. User may have initially accepted the
+    // dialog, but then chose to cancel while the challenge was being fetched.
+    AutofillMetrics::LogWebauthnOptInPromoUserDecision(
+        /*is_checkout_flow=*/!card_authorization_token_.empty(),
+        current_flow_ == OPT_IN_FETCH_CHALLENGE_FLOW
+            ? AutofillMetrics::WebauthnOptInPromoUserDecisionMetric::
+                  kDeclinedAfterAccepting
+            : AutofillMetrics::WebauthnOptInPromoUserDecisionMetric::
+                  kDeclinedImmediately);
+    payments_client_->CancelRequest();
+    card_authorization_token_ = std::string();
+    current_flow_ = NONE_FLOW;
+    GetOrCreateFidoAuthenticationStrikeDatabase()->AddStrikes(
+        FidoAuthenticationStrikeDatabase::kStrikesToAddWhenOptInOfferDeclined);
+    ::autofill::prefs::SetCreditCardFIDOAuthEnabled(
+        autofill_client_->GetPrefs(), false);
+  }
+}
+#endif
+
 FidoAuthenticationStrikeDatabase*
 CreditCardFIDOAuthenticator::GetOrCreateFidoAuthenticationStrikeDatabase() {
   if (!fido_authentication_strike_database_) {
@@ -200,7 +224,7 @@
   // closed, then the offer was declined during the fetching challenge process,
   // and thus returned early.
   if (current_flow_ == OPT_IN_WITH_CHALLENGE_FLOW) {
-    if (autofill_client_->CloseWebauthnOfferDialog()) {
+    if (autofill_client_->CloseWebauthnDialog()) {
       // Now that the dialog has closed and will proceed to a WebAuthn prompt,
       // the user must have accepted the dialog without cancelling.
       AutofillMetrics::LogWebauthnOptInPromoUserDecision(
@@ -229,7 +253,7 @@
   // level authentication dialog. If dialog is already closed, then the offer
   // was declined during the fetching challenge process, and thus returned
   // early.
-  if (autofill_client_->CloseWebauthnOfferDialog()) {
+  if (autofill_client_->CloseWebauthnDialog()) {
     // Now that the dialog has closed and will proceed to a WebAuthn prompt,
     // the user must have accepted the dialog without cancelling.
     AutofillMetrics::LogWebauthnOptInPromoUserDecision(
@@ -413,33 +437,6 @@
   }
 }
 
-void CreditCardFIDOAuthenticator::OnWebauthnOfferDialogUserResponse(
-    bool did_accept) {
-  if (did_accept) {
-    // Wait until GetAssertion()/MakeCredential() to log user acceptance, since
-    // user still has the option to cancel the dialog while the challenge is
-    // being fetched.
-    Register(card_authorization_token_);
-  } else {
-    // If user declined, log user decision. User may have initially accepted the
-    // dialog, but then chose to cancel while the challenge was being fetched.
-    AutofillMetrics::LogWebauthnOptInPromoUserDecision(
-        /*is_checkout_flow=*/!card_authorization_token_.empty(),
-        current_flow_ == OPT_IN_FETCH_CHALLENGE_FLOW
-            ? AutofillMetrics::WebauthnOptInPromoUserDecisionMetric::
-                  kDeclinedAfterAccepting
-            : AutofillMetrics::WebauthnOptInPromoUserDecisionMetric::
-                  kDeclinedImmediately);
-    payments_client_->CancelRequest();
-    card_authorization_token_ = std::string();
-    current_flow_ = NONE_FLOW;
-    GetOrCreateFidoAuthenticationStrikeDatabase()->AddStrikes(
-        FidoAuthenticationStrikeDatabase::kStrikesToAddWhenOptInOfferDeclined);
-    ::autofill::prefs::SetCreditCardFIDOAuthEnabled(
-        autofill_client_->GetPrefs(), false);
-  }
-}
-
 void CreditCardFIDOAuthenticator::OnFullCardRequestSucceeded(
     const payments::FullCardRequest& full_card_request,
     const CreditCard& card,
diff --git a/components/autofill/core/browser/payments/credit_card_fido_authenticator.h b/components/autofill/core/browser/payments/credit_card_fido_authenticator.h
index a35fe0e..ccba3ad 100644
--- a/components/autofill/core/browser/payments/credit_card_fido_authenticator.h
+++ b/components/autofill/core/browser/payments/credit_card_fido_authenticator.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "base/strings/string16.h"
+#include "build/build_config.h"
 #include "components/autofill/core/browser/autofill_client.h"
 #include "components/autofill/core/browser/autofill_driver.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
@@ -73,9 +74,6 @@
   CreditCardFIDOAuthenticator(AutofillDriver* driver, AutofillClient* client);
   ~CreditCardFIDOAuthenticator() override;
 
-  // Offer the option to use WebAuthn for authenticating future card unmasking.
-  void ShowWebauthnOfferDialog(std::string card_authorization_token);
-
   // Invokes Authentication flow. Responds to |accessor_| with full pan.
   void Authenticate(const CreditCard* card,
                     base::WeakPtr<Requester> requester,
@@ -112,6 +110,14 @@
   // and in the FullCardRequest if any.
   void CancelVerification();
 
+#if !defined(OS_ANDROID)
+  // Invoked when a Webauthn offer dialog is about to be shown.
+  void OnWebauthnOfferDialogRequested(std::string card_authorization_token);
+
+  // Invoked when the WebAuthn offer dialog is accepted or declined/cancelled.
+  void OnWebauthnOfferDialogUserResponse(bool did_accept);
+#endif
+
   // Retrieves the strike database for offering FIDO authentication.
   FidoAuthenticationStrikeDatabase*
   GetOrCreateFidoAuthenticationStrikeDatabase();
@@ -165,10 +171,6 @@
       AutofillClient::PaymentsRpcResult result,
       payments::PaymentsClient::OptChangeResponseDetails& response);
 
-  // The callback invoked from the WebAuthn offer dialog when it is accepted or
-  // declined/cancelled.
-  void OnWebauthnOfferDialogUserResponse(bool did_accept);
-
   // payments::FullCardRequest::ResultDelegate:
   void OnFullCardRequestSucceeded(
       const payments::FullCardRequest& full_card_request,
diff --git a/components/autofill/core/browser/payments/webauthn_callback_types.h b/components/autofill/core/browser/payments/webauthn_callback_types.h
new file mode 100644
index 0000000..24a15ff
--- /dev/null
+++ b/components/autofill/core/browser/payments/webauthn_callback_types.h
@@ -0,0 +1,24 @@
+// 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 COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_WEBAUTHN_CALLBACK_TYPES_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_WEBAUTHN_CALLBACK_TYPES_H_
+
+namespace autofill {
+
+// The callback that should be invoked on user decision.
+enum class WebauthnDialogCallbackType {
+  // Invoked when the OK button in the Webauthn offer dialog is clicked.
+  kOfferAccepted = 0,
+  // Invoked when the cancel button in the Webauthn offer dialog is clicked.
+  kOfferCancelled = 1,
+  // Invoked when the cancel button in the Webauthn verify pending dialog
+  // is clicked.
+  kVerificationCancelled = 2,
+  kMaxValue = kVerificationCancelled,
+};
+
+}  // namespace autofill
+
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_WEBAUTHN_CALLBACK_TYPES_H_
diff --git a/components/autofill/core/browser/test_autofill_client.cc b/components/autofill/core/browser/test_autofill_client.cc
index e7e668a..630df03 100644
--- a/components/autofill/core/browser/test_autofill_client.cc
+++ b/components/autofill/core/browser/test_autofill_client.cc
@@ -109,18 +109,16 @@
 
 #if !defined(OS_ANDROID) && !defined(OS_IOS)
 void TestAutofillClient::ShowWebauthnOfferDialog(
-    WebauthnOfferDialogCallback offer_dialog_callback) {}
+    WebauthnDialogCallback offer_dialog_callback) {}
+
+void TestAutofillClient::ShowWebauthnVerifyPendingDialog(
+    WebauthnDialogCallback verify_pending_dialog_callback) {}
 
 void TestAutofillClient::UpdateWebauthnOfferDialogWithError() {}
 
-bool TestAutofillClient::CloseWebauthnOfferDialog() {
+bool TestAutofillClient::CloseWebauthnDialog() {
   return true;
 }
-
-void TestAutofillClient::ShowWebauthnVerifyPendingDialog(
-    base::OnceClosure cancel_card_verification_callback) {}
-
-void TestAutofillClient::CloseWebauthnVerifyPendingDialog() {}
 #endif
 
 void TestAutofillClient::ConfirmSaveAutofillProfile(
diff --git a/components/autofill/core/browser/test_autofill_client.h b/components/autofill/core/browser/test_autofill_client.h
index 95d86f3..8253d7b 100644
--- a/components/autofill/core/browser/test_autofill_client.h
+++ b/components/autofill/core/browser/test_autofill_client.h
@@ -67,12 +67,11 @@
       MigrationDeleteCardCallback delete_local_card_callback) override;
 #if !defined(OS_ANDROID) && !defined(OS_IOS)
   void ShowWebauthnOfferDialog(
-      WebauthnOfferDialogCallback offer_dialog_callback) override;
-  void UpdateWebauthnOfferDialogWithError() override;
-  bool CloseWebauthnOfferDialog() override;
+      WebauthnDialogCallback offer_dialog_callback) override;
   void ShowWebauthnVerifyPendingDialog(
-      base::OnceClosure cancel_card_verification_callback) override;
-  void CloseWebauthnVerifyPendingDialog() override;
+      WebauthnDialogCallback verify_pending_dialog_callback) override;
+  void UpdateWebauthnOfferDialogWithError() override;
+  bool CloseWebauthnDialog() override;
 #endif
   void ConfirmSaveAutofillProfile(const AutofillProfile& profile,
                                   base::OnceClosure callback) override;
diff --git a/components/autofill_payments_strings.grdp b/components/autofill_payments_strings.grdp
index 3b93b6a..7814b6cd 100644
--- a/components/autofill_payments_strings.grdp
+++ b/components/autofill_payments_strings.grdp
@@ -454,13 +454,12 @@
     </message>
   </if>
 
-
-  <!-- Verify pending dialog (Desktop only) -->
+  <!-- Webauthn verify pending dialog (Desktop only) -->
   <if expr="not is_ios and not is_android">
-    <message name="IDS_AUTOFILL_VERIFY_PENDING_DIALOG_TITLE" desc="Headline showing the card verification is in progress.">
+    <message name="IDS_AUTOFILL_WEBAUTHN_VERIFY_PENDING_DIALOG_TITLE" desc="Headline of the dialog shown when user has opted in to use platform biometric authenticator and has selected one card to fill the form. This shows the verification of the selected card is in progress.">
         Verifying your identity...
     </message>
-    <message name="IDS_AUTOFILL_VERIFY_PENDING_DIALOG_CANCEL_BUTTON_LABEL" desc="Button that allows the user to cancel the card verification.">
+    <message name="IDS_AUTOFILL_WEBAUTHN_VERIFY_PENDING_DIALOG_CANCEL_BUTTON_LABEL" desc="Label of the cancel button in the dialog shown when user has opted in to use platform biometric authenticator and has selected one card to fill the form. This cancel button allows the user to cancel the entire the verification process.">
         Cancel
     </message>
   </if>