Reapply "Reapply "[FedCM] Protect from `this` getting deleted""

This reverts commit 1cd94ca747514b2cd3a73956dd591f6d8d576318.

Relanding without the test so that this can be merged to the branch.

Bug: 325936438, 40279117
Change-Id: I54415209c403119e6be0d200b18cd8bf2b8f159f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5324640
Reviewed-by: Nicolás Peña <npm@chromium.org>
Commit-Queue: Christian Biesinger <cbiesinger@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1265348}
diff --git a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc
index b6d61d6..7186d0c1 100644
--- a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc
+++ b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc
@@ -152,8 +152,12 @@
     // account and its IDP.
     DCHECK_EQ(idp_display_data_list_.size(), 1u);
     DCHECK_EQ(idp_display_data_list_[0].accounts.size(), 1u);
-    ShowVerifyingSheet(idp_display_data_list_[0].accounts[0],
-                       idp_display_data_list_[0]);
+    // If ShowVerifyingSheet returns false, `this` got deleted, so just
+    // return.
+    if (!ShowVerifyingSheet(idp_display_data_list_[0].accounts[0],
+                            idp_display_data_list_[0])) {
+      return;
+    }
   } else if (new_account_idp) {
     // When we just logged in to an account, show that account right away.
     // TODO(crbug.com/41490360): verify this works on modal dialog.
@@ -196,7 +200,14 @@
     input_protector_ = std::make_unique<views::InputEventActivationProtector>();
   }
 
-  if (create_view || is_modal_closed_but_accounts_fetch_pending_) {
+  // The popup_window_state_ check is for the case when we received new accounts
+  // while the modal dialog is visible and we are called from CloseModalDialog.
+  // Because the modal dialog is now closed, we should show the account chooser
+  // now.
+  if (create_view || is_modal_closed_but_accounts_fetch_pending_ ||
+      (popup_window_state_ &&
+       *popup_window_state_ ==
+           PopupWindowResult::kAccountsReceivedAndPopupNotClosedByIdp)) {
     is_modal_closed_but_accounts_fetch_pending_ = false;
     if (is_web_contents_visible_) {
       input_protector_->VisibilityChanged(true);
@@ -639,10 +650,8 @@
 
   if (show_accounts_dialog_callback_) {
     std::move(show_accounts_dialog_callback_).Run();
-    if (is_web_contents_visible_) {
-      input_protector_->VisibilityChanged(true);
-      GetDialogWidget()->Show();
-    }
+    // `this` might be deleted now, do not access member variables
+    // after this point.
   }
 }
 
@@ -655,7 +664,7 @@
   Close();
 }
 
-void FedCmAccountSelectionView::ShowVerifyingSheet(
+bool FedCmAccountSelectionView::ShowVerifyingSheet(
     const Account& account,
     const IdentityProviderDisplayData& idp_display_data) {
   DCHECK(state_ == State::VERIFYING || state_ == State::AUTO_REAUTHN);
@@ -668,7 +677,7 @@
   // AccountSelectionView::Delegate::OnAccountSelected() might delete this.
   // See https://crbug.com/1393650 for details.
   if (!weak_ptr) {
-    return;
+    return false;
   }
 
   const std::u16string title =
@@ -676,6 +685,7 @@
           ? l10n_util::GetStringUTF16(IDS_VERIFY_SHEET_TITLE_AUTO_REAUTHN)
           : l10n_util::GetStringUTF16(IDS_VERIFY_SHEET_TITLE);
   account_selection_view_->ShowVerifyingSheet(account, idp_display_data, title);
+  return true;
 }
 
 FedCmAccountSelectionView::SheetType FedCmAccountSelectionView::GetSheetType() {
@@ -733,9 +743,9 @@
   // Pop-up window can only be opened through clicking the "Continue" button on
   // the mismatch dialog. Hence, we record the outcome only after the dialog is
   // closed.
-  if (is_mismatch_continue_clicked_) {
+  if (is_mismatch_continue_clicked_ && popup_window_state_) {
     UMA_HISTOGRAM_ENUMERATION("Blink.FedCm.IdpSigninStatus.PopupWindowResult",
-                              popup_window_state_);
+                              *popup_window_state_);
   }
 
   ResetAccountSelectionView();
diff --git a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h
index 1093ba89..51477c5f 100644
--- a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h
+++ b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h
@@ -202,7 +202,8 @@
   // This enum describes the outcome of the pop-up window and is used for
   // histograms. Do not remove or modify existing values, but you may add new
   // values at the end. This enum should be kept in sync with
-  // FedCmPopupWindowResult in tools/metrics/histograms/enums.xml.
+  // FedCmPopupWindowResult in
+  // tools/metrics/histograms/metadata/blink/enums.xml.
   enum class PopupWindowResult {
     kAccountsReceivedAndPopupClosedByIdp,
     kAccountsReceivedAndPopupNotClosedByIdp,
@@ -230,7 +231,9 @@
   void OnGotIt(const ui::Event& event) override;
   void OnMoreDetails(const ui::Event& event) override;
 
-  void ShowVerifyingSheet(const Account& account,
+  // Returns false if `this` got deleted. In that case, the caller should not
+  // access any further member variables.
+  bool ShowVerifyingSheet(const Account& account,
                           const IdentityProviderDisplayData& idp_display_data);
 
   // Returns the SheetType to be used for metrics reporting.
@@ -313,7 +316,8 @@
   base::TimeTicks idp_close_popup_time_;
 
   // The current state of the IDP sign-in pop-up window, if initiated by user.
-  PopupWindowResult popup_window_state_;
+  // This is nullopt when no popup window has been opened.
+  std::optional<PopupWindowResult> popup_window_state_;
 
   // An AccountSelectionViewBase to render bubble dialogs for widget flows,
   // otherwise returns an AccountSelectionViewBase to render modal dialogs