blob: 6139b6701e6ba2de7f3319fe31d9448a802cdb0e [file] [log] [blame]
// Copyright 2023 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/chrome_payments_autofill_client.h"
#include "base/check_deref.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/autofill/payments/create_card_unmask_prompt_view.h"
#include "chrome/browser/ui/autofill/payments/view_factory.h"
#include "chrome/browser/ui/autofill/risk_util.h"
#include "components/autofill/content/browser/content_autofill_client.h"
#include "components/autofill/core/browser/metrics/payments/risk_data_metrics.h"
#include "components/autofill/core/browser/payments/autofill_error_dialog_context.h"
#include "components/autofill/core/browser/payments/card_unmask_challenge_option.h"
#include "components/autofill/core/browser/payments/otp_unmask_delegate.h"
#include "components/autofill/core/browser/payments/otp_unmask_result.h"
#include "components/autofill/core/browser/payments/payments_network_interface.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/ui/payments/autofill_error_dialog_controller_impl.h"
#include "components/autofill/core/browser/ui/payments/autofill_progress_dialog_controller_impl.h"
#include "components/autofill/core/browser/ui/payments/card_unmask_otp_input_dialog_controller_impl.h"
#include "components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.h"
#include "components/autofill/core/browser/ui/payments/card_unmask_prompt_view.h"
#include "components/autofill/core/common/autofill_payments_features.h"
#include "components/user_prefs/user_prefs.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#if !BUILDFLAG(IS_ANDROID)
#include "chrome/browser/ui/autofill/payments/desktop_payments_window_manager.h"
#include "chrome/browser/ui/autofill/payments/manage_migration_ui_controller.h"
#include "chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h"
#include "chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h"
#include "components/autofill/core/browser/payments/local_card_migration_manager.h"
#include "components/autofill/core/common/autofill_payments_features.h"
#endif // !BUILDFLAG(IS_ANDROID)
namespace autofill::payments {
ChromePaymentsAutofillClient::ChromePaymentsAutofillClient(
ContentAutofillClient* client)
: content::WebContentsObserver(&client->GetWebContents()),
client_(CHECK_DEREF(client)),
unmask_controller_(std::make_unique<CardUnmaskPromptControllerImpl>(
user_prefs::UserPrefs::Get(
client->GetWebContents().GetBrowserContext()))) {}
ChromePaymentsAutofillClient::~ChromePaymentsAutofillClient() = default;
void ChromePaymentsAutofillClient::LoadRiskData(
base::OnceCallback<void(const std::string&)> callback) {
risk_util::LoadRiskData(
0, web_contents(),
base::BindOnce(
[](base::OnceCallback<void(const std::string&)> callback,
base::TimeTicks start_time, const std::string& risk_data) {
autofill::autofill_metrics::LogRiskDataLoadingLatency(
base::TimeTicks::Now() - start_time);
std::move(callback).Run(risk_data);
},
std::move(callback), base::TimeTicks::Now()));
}
#if !BUILDFLAG(IS_ANDROID)
void ChromePaymentsAutofillClient::ShowLocalCardMigrationDialog(
base::OnceClosure show_migration_dialog_closure) {
ManageMigrationUiController::CreateForWebContents(web_contents());
ManageMigrationUiController* controller =
ManageMigrationUiController::FromWebContents(web_contents());
controller->ShowBubble(std::move(show_migration_dialog_closure));
}
void ChromePaymentsAutofillClient::ConfirmMigrateLocalCardToCloud(
const LegalMessageLines& legal_message_lines,
const std::string& user_email,
const std::vector<MigratableCreditCard>& migratable_credit_cards,
LocalCardMigrationCallback start_migrating_cards_callback) {
ManageMigrationUiController::CreateForWebContents(web_contents());
ManageMigrationUiController* controller =
ManageMigrationUiController::FromWebContents(web_contents());
controller->ShowOfferDialog(legal_message_lines, user_email,
migratable_credit_cards,
std::move(start_migrating_cards_callback));
}
void ChromePaymentsAutofillClient::ShowLocalCardMigrationResults(
bool has_server_error,
const std::u16string& tip_message,
const std::vector<MigratableCreditCard>& migratable_credit_cards,
MigrationDeleteCardCallback delete_local_card_callback) {
ManageMigrationUiController::CreateForWebContents(web_contents());
ManageMigrationUiController* controller =
ManageMigrationUiController::FromWebContents(web_contents());
controller->UpdateCreditCardIcon(has_server_error, tip_message,
migratable_credit_cards,
delete_local_card_callback);
}
void ChromePaymentsAutofillClient::VirtualCardEnrollCompleted(
bool is_vcn_enrolled) {
if (base::FeatureList::IsEnabled(
features::kAutofillEnableVcnEnrollLoadingAndConfirmation)) {
VirtualCardEnrollBubbleControllerImpl::CreateForWebContents(web_contents());
VirtualCardEnrollBubbleControllerImpl* controller =
VirtualCardEnrollBubbleControllerImpl::FromWebContents(web_contents());
if (controller && controller->IsIconVisible()) {
controller->ShowConfirmationBubbleView(is_vcn_enrolled);
}
}
}
#endif // BUILDFLAG(IS_ANDROID)
void ChromePaymentsAutofillClient::CreditCardUploadCompleted(bool card_saved) {
#if !BUILDFLAG(IS_ANDROID)
if (SaveCardBubbleControllerImpl* controller =
SaveCardBubbleControllerImpl::FromWebContents(web_contents())) {
controller->ShowConfirmationBubbleView(card_saved);
}
#endif
}
bool ChromePaymentsAutofillClient::IsSaveCardPromptVisible() const {
#if !BUILDFLAG(IS_ANDROID)
SaveCardBubbleControllerImpl* controller =
SaveCardBubbleControllerImpl::FromWebContents(web_contents());
return controller && controller->IsIconVisible();
#else
return false;
#endif
}
void ChromePaymentsAutofillClient::HideSaveCardPromptPrompt() {
#if !BUILDFLAG(IS_ANDROID)
SaveCardBubbleControllerImpl* controller =
SaveCardBubbleControllerImpl::FromWebContents(web_contents());
if (controller) {
controller->HideSaveCardBubble();
}
#endif
}
void ChromePaymentsAutofillClient::ShowAutofillProgressDialog(
AutofillProgressDialogType autofill_progress_dialog_type,
base::OnceClosure cancel_callback) {
autofill_progress_dialog_controller_ =
std::make_unique<AutofillProgressDialogControllerImpl>(
autofill_progress_dialog_type, std::move(cancel_callback));
autofill_progress_dialog_controller_->ShowDialog(
base::BindOnce(&CreateAndShowProgressDialog,
autofill_progress_dialog_controller_->GetWeakPtr(),
base::Unretained(web_contents())));
}
void ChromePaymentsAutofillClient::CloseAutofillProgressDialog(
bool show_confirmation_before_closing,
base::OnceClosure no_interactive_authentication_callback) {
DCHECK(autofill_progress_dialog_controller_);
autofill_progress_dialog_controller_->DismissDialog(
show_confirmation_before_closing,
std::move(no_interactive_authentication_callback));
}
void ChromePaymentsAutofillClient::ShowCardUnmaskOtpInputDialog(
const CardUnmaskChallengeOption& challenge_option,
base::WeakPtr<OtpUnmaskDelegate> delegate) {
card_unmask_otp_input_dialog_controller_ =
std::make_unique<CardUnmaskOtpInputDialogControllerImpl>(challenge_option,
delegate);
card_unmask_otp_input_dialog_controller_->ShowDialog(
base::BindOnce(&CreateAndShowOtpInputDialog,
card_unmask_otp_input_dialog_controller_->GetWeakPtr(),
base::Unretained(web_contents())));
}
void ChromePaymentsAutofillClient::OnUnmaskOtpVerificationResult(
OtpUnmaskResult unmask_result) {
CHECK(card_unmask_otp_input_dialog_controller_);
card_unmask_otp_input_dialog_controller_->OnOtpVerificationResult(
unmask_result);
}
PaymentsNetworkInterface*
ChromePaymentsAutofillClient::GetPaymentsNetworkInterface() {
if (!payments_network_interface_) {
payments_network_interface_ = std::make_unique<PaymentsNetworkInterface>(
Profile::FromBrowserContext(web_contents()->GetBrowserContext())
->GetURLLoaderFactory(),
client_->GetIdentityManager(), client_->GetPersonalDataManager(),
Profile::FromBrowserContext(web_contents()->GetBrowserContext())
->IsOffTheRecord());
}
return payments_network_interface_.get();
}
void ChromePaymentsAutofillClient::ShowAutofillErrorDialog(
AutofillErrorDialogContext context) {
autofill_error_dialog_controller_ =
std::make_unique<AutofillErrorDialogControllerImpl>(std::move(context));
autofill_error_dialog_controller_->Show(
base::BindOnce(&CreateAndShowAutofillErrorDialog,
base::Unretained(autofill_error_dialog_controller_.get()),
base::Unretained(web_contents())));
}
PaymentsWindowManager*
ChromePaymentsAutofillClient::GetPaymentsWindowManager() {
#if !BUILDFLAG(IS_ANDROID)
if (!payments_window_manager_) {
payments_window_manager_ =
std::make_unique<DesktopPaymentsWindowManager>(&*client_);
}
return payments_window_manager_.get();
#else
return nullptr;
#endif // !BUILDFLAG(IS_ANDROID)
}
void ChromePaymentsAutofillClient::ShowUnmaskPrompt(
const CreditCard& card,
const CardUnmaskPromptOptions& card_unmask_prompt_options,
base::WeakPtr<CardUnmaskDelegate> delegate) {
unmask_controller_->ShowPrompt(
base::BindOnce(&CreateCardUnmaskPromptView,
base::Unretained(unmask_controller_.get()),
base::Unretained(web_contents())),
card, card_unmask_prompt_options, delegate);
}
// TODO(crbug.com/1220990): Refactor this for both CVC and Biometrics flows.
void ChromePaymentsAutofillClient::OnUnmaskVerificationResult(
AutofillClient::PaymentsRpcResult result) {
unmask_controller_->OnVerificationResult(result);
#if BUILDFLAG(IS_ANDROID)
// For VCN-related errors, on Android we show a new error dialog instead of
// updating the CVC unmask prompt with the error message.
switch (result) {
case AutofillClient::PaymentsRpcResult::kVcnRetrievalPermanentFailure:
ShowAutofillErrorDialog(
AutofillErrorDialogContext::WithVirtualCardPermanentOrTemporaryError(
/*is_permanent_error=*/true));
break;
case AutofillClient::PaymentsRpcResult::kVcnRetrievalTryAgainFailure:
ShowAutofillErrorDialog(
AutofillErrorDialogContext::WithVirtualCardPermanentOrTemporaryError(
/*is_permanent_error=*/false));
break;
case AutofillClient::PaymentsRpcResult::kSuccess:
case AutofillClient::PaymentsRpcResult::kTryAgainFailure:
case AutofillClient::PaymentsRpcResult::kPermanentFailure:
case AutofillClient::PaymentsRpcResult::kNetworkError:
// Do nothing
break;
case AutofillClient::PaymentsRpcResult::kNone:
NOTREACHED();
return;
}
#endif // BUILDFLAG(IS_ANDROID)
}
} // namespace autofill::payments