chromium/chrome/browser/ui/autofill/payments/autofill_snackbar_controller_impl.cc

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/autofill/payments/autofill_snackbar_controller_impl.h"

#include <optional>
#include <string>

#include "base/metrics/histogram_functions.h"
#include "base/strings/strcat.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "chrome/browser/android/preferences/autofill/settings_launcher_helper.h"
#include "chrome/browser/keyboard_accessory/android/manual_filling_controller.h"
#include "chrome/browser/keyboard_accessory/android/manual_filling_controller_impl.h"
#include "chrome/browser/ui/android/autofill/snackbar/autofill_snackbar_view_android.h"
#include "chrome/browser/ui/autofill/payments/autofill_snackbar_type.h"
#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"

namespace autofill {

AutofillSnackbarControllerImpl::AutofillSnackbarControllerImpl(
    content::WebContents* web_contents)
    : web_contents_(web_contents) {}

AutofillSnackbarControllerImpl::~AutofillSnackbarControllerImpl() {
  // If the tab is killed then dismiss the snackbar if it's showing.
  Dismiss();
}

void AutofillSnackbarControllerImpl::Show(
    AutofillSnackbarType autofill_snackbar_type) {
  ShowWithDurationAndCallback(autofill_snackbar_type, kDefaultSnackbarDuration,
                              std::nullopt);
}

void AutofillSnackbarControllerImpl::ShowWithDurationAndCallback(
    AutofillSnackbarType autofill_snackbar_type,
    base::TimeDelta snackbar_duration,
    std::optional<base::OnceClosure> on_dismiss_callback) {
  CHECK_NE(autofill_snackbar_type, AutofillSnackbarType::kUnspecified);
  if (autofill_snackbar_view_) {
    // A snackbar is already showing. Ignore the new request.
    return;
  }

  on_dismiss_callback_ = std::move(on_dismiss_callback);

  autofill_snackbar_type_ = autofill_snackbar_type;
  autofill_snackbar_view_ = AutofillSnackbarView::Create(this);
  autofill_snackbar_duration_ = snackbar_duration;
  autofill_snackbar_view_->Show();
  base::UmaHistogramBoolean(
      base::StrCat(
          {"Autofill.Snackbar.", GetSnackbarTypeForLogging(), ".Shown"}),
      true);
}

void AutofillSnackbarControllerImpl::OnActionClicked() {
  base::UmaHistogramBoolean(
      base::StrCat({"Autofill.Snackbar.", GetSnackbarTypeForLogging(),
                    ".ActionClicked"}),
      true);

  switch (autofill_snackbar_type_) {
    case AutofillSnackbarType::kVirtualCard:
      ManualFillingControllerImpl::GetOrCreate(GetWebContents())
          ->ShowAccessorySheetTab(autofill::AccessoryTabType::CREDIT_CARDS);
      break;
    case AutofillSnackbarType::kMandatoryReauth:
      // For mandatory reauth snackbar, we will show Android credit card
      // settings page.
      ShowAutofillCreditCardSettings(GetWebContents());
      break;
    case AutofillSnackbarType::kSaveCardSuccess:
    case AutofillSnackbarType::kVirtualCardEnrollSuccess:
    case AutofillSnackbarType::kSaveServerIbanSuccess:
      // SnackbarManager.java will dismiss the snackbar after the click.
      break;
    case AutofillSnackbarType::kUnspecified:
      NOTREACHED();
  }
}

void AutofillSnackbarControllerImpl::OnDismissed() {
  autofill_snackbar_view_ = nullptr;
  autofill_snackbar_type_ = AutofillSnackbarType::kUnspecified;
  autofill_snackbar_duration_ = kDefaultSnackbarDuration;

  if (on_dismiss_callback_) {
    std::move(*on_dismiss_callback_).Run();
    on_dismiss_callback_.reset();
  }
}

std::u16string AutofillSnackbarControllerImpl::GetMessageText() const {
  switch (autofill_snackbar_type_) {
    case AutofillSnackbarType::kVirtualCard:
      return l10n_util::GetStringUTF16(
          IDS_AUTOFILL_VIRTUAL_CARD_NUMBER_SNACKBAR_MESSAGE_TEXT);
    case AutofillSnackbarType::kMandatoryReauth:
      return l10n_util::GetStringUTF16(
          IDS_AUTOFILL_MANDATORY_REAUTH_SNACKBAR_MESSAGE_TEXT);
    case AutofillSnackbarType::kSaveCardSuccess:
      return l10n_util::GetStringUTF16(
          IDS_AUTOFILL_SAVE_CARD_CONFIRMATION_SUCCESS_DESCRIPTION_TEXT);
    case AutofillSnackbarType::kVirtualCardEnrollSuccess:
      return l10n_util::GetStringUTF16(
          IDS_AUTOFILL_VIRTUAL_CARD_ENROLL_CONFIRMATION_SUCCESS_DESCRIPTION_TEXT);
    case AutofillSnackbarType::kSaveServerIbanSuccess:
      return l10n_util::GetStringUTF16(
          IDS_AUTOFILL_SAVE_SERVER_IBAN_SUCCESS_SNACKBAR_MESSAGE_TEXT);
    case AutofillSnackbarType::kUnspecified:
      NOTREACHED();
  }
}

std::u16string AutofillSnackbarControllerImpl::GetActionButtonText() const {
  switch (autofill_snackbar_type_) {
    case AutofillSnackbarType::kVirtualCard:
      return l10n_util::GetStringUTF16(
          IDS_AUTOFILL_VIRTUAL_CARD_NUMBER_SNACKBAR_ACTION_TEXT);
    case AutofillSnackbarType::kMandatoryReauth:
      return l10n_util::GetStringUTF16(
          IDS_AUTOFILL_MANDATORY_REAUTH_SNACKBAR_ACTION_TEXT);
    case AutofillSnackbarType::kSaveCardSuccess:
    case AutofillSnackbarType::kVirtualCardEnrollSuccess:
      return l10n_util::GetStringUTF16(
          IDS_AUTOFILL_SAVE_CARD_AND_VIRTUAL_CARD_ENROLL_CONFIRMATION_BUTTON_TEXT);
    case AutofillSnackbarType::kSaveServerIbanSuccess:
      return l10n_util::GetStringUTF16(
          IDS_AUTOFILL_SAVE_SERVER_IBAN_SUCCESS_SNACKBAR_BUTTON_TEXT);
    case AutofillSnackbarType::kUnspecified:
      NOTREACHED();
  }
}

base::TimeDelta AutofillSnackbarControllerImpl::GetDuration() const {
  return autofill_snackbar_duration_;
}

content::WebContents* AutofillSnackbarControllerImpl::GetWebContents() const {
  return web_contents_;
}

void AutofillSnackbarControllerImpl::Dismiss() {
  if (!autofill_snackbar_view_) {
    return;
  }

  autofill_snackbar_view_->Dismiss();
}

std::string AutofillSnackbarControllerImpl::GetSnackbarTypeForLogging() {
  switch (autofill_snackbar_type_) {
    case AutofillSnackbarType::kVirtualCard:
      return "VirtualCard";
    case AutofillSnackbarType::kMandatoryReauth:
      return "MandatoryReauth";
    case AutofillSnackbarType::kSaveCardSuccess:
      return "SaveCardSuccess";
    case AutofillSnackbarType::kVirtualCardEnrollSuccess:
      return "VirtualCardEnrollSuccess";
    case AutofillSnackbarType::kSaveServerIbanSuccess:
      return "SaveServerIbanSuccess";
    case AutofillSnackbarType::kUnspecified:
      return "Unspecified";
  }
}

}  // namespace autofill