blob: ac7a5911099d3292fcef48ca5240ae0c84eb3163 [file] [log] [blame]
// Copyright 2019 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/views/autofill/autofill_bubble_handler_impl.h"
#include <concepts>
#include <memory>
#include "base/functional/callback_forward.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/actions/chrome_action_id.h"
#include "chrome/browser/ui/autofill/autofill_ai/autofill_ai_import_data_controller.h"
#include "chrome/browser/ui/autofill/autofill_bubble_base.h"
#include "chrome/browser/ui/autofill/payments/save_card_ui.h"
#include "chrome/browser/ui/autofill/payments/save_iban_ui.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/page_action/page_action_icon_type.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/views/autofill/address_sign_in_promo_view.h"
#include "chrome/browser/ui/views/autofill/autofill_ai/autofill_ai_import_data_bubble_view.h"
#include "chrome/browser/ui/views/autofill/payments/filled_card_information_bubble_views.h"
#include "chrome/browser/ui/views/autofill/payments/filled_card_information_icon_view.h"
#include "chrome/browser/ui/views/autofill/payments/manage_saved_iban_bubble_view.h"
#include "chrome/browser/ui/views/autofill/payments/mandatory_reauth_confirmation_bubble_view.h"
#include "chrome/browser/ui/views/autofill/payments/mandatory_reauth_opt_in_bubble_view.h"
#include "chrome/browser/ui/views/autofill/payments/offer_notification_bubble_views.h"
#include "chrome/browser/ui/views/autofill/payments/offer_notification_icon_view.h"
#include "chrome/browser/ui/views/autofill/payments/save_card_bubble_views.h"
#include "chrome/browser/ui/views/autofill/payments/save_card_manage_cards_bubble_views.h"
#include "chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.h"
#include "chrome/browser/ui/views/autofill/payments/save_iban_bubble_view.h"
#include "chrome/browser/ui/views/autofill/payments/save_payment_method_and_virtual_card_enroll_confirmation_bubble_views.h"
#include "chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.h"
#include "chrome/browser/ui/views/autofill/payments/virtual_card_enroll_icon_view.h"
#include "chrome/browser/ui/views/autofill/save_address_profile_view.h"
#include "chrome/browser/ui/views/autofill/update_address_profile_view.h"
#include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
#include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
#include "chrome/browser/ui/views/page_action/page_action_view.h"
#include "chrome/browser/ui/views/profiles/avatar_toolbar_button.h"
#include "components/autofill/content/browser/content_autofill_driver.h"
#include "components/autofill/content/browser/content_autofill_driver_factory.h"
#include "components/autofill/core/browser/foundations/autofill_client.h"
#include "components/autofill/core/browser/payments/virtual_card_enrollment_manager.h"
#include "components/autofill/core/browser/ui/payments/virtual_card_enroll_bubble_controller.h"
#include "components/autofill/core/common/autofill_payments_features.h"
#include "components/constrained_window/constrained_window_views.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
namespace autofill {
namespace {
template <typename View, typename... Args>
requires(std::derived_from<View, AutofillLocationBarBubble>)
View* ShowBubble(ToolbarButtonProvider* toolbar_button_provider,
std::optional<actions::ActionId> action_id,
PageActionIconType page_action_icon_type,
bool is_user_gesture,
Args&&... args) {
views::View* const anchor_view =
toolbar_button_provider->GetAnchorView(action_id);
auto bubble =
std::make_unique<View>(anchor_view, std::forward<Args>(args)...);
if (!views::Button::AsButton(anchor_view)) {
views::Button* icon_view;
if (IsPageActionMigrated(page_action_icon_type)) {
CHECK(action_id.has_value());
icon_view = toolbar_button_provider->GetPageActionView(action_id.value());
} else {
icon_view =
toolbar_button_provider->GetPageActionIconView(page_action_icon_type);
}
CHECK(icon_view);
bubble->SetHighlightedButton(icon_view);
}
View* const bubble_ptr = bubble.get();
views::BubbleDialogDelegateView::CreateBubble(std::move(bubble));
const LocationBarBubbleDelegateView::DisplayReason display_reason =
is_user_gesture ? LocationBarBubbleDelegateView::USER_GESTURE
: LocationBarBubbleDelegateView::AUTOMATIC;
// TODO(crbug.com/40679714): Check whether the Show methods can be eliminated
// in favor of just using ShowForReason.
if constexpr (requires { bubble_ptr->Show(display_reason); }) {
bubble_ptr->Show(display_reason);
} else {
bubble_ptr->ShowForReason(display_reason);
}
return bubble_ptr;
}
template <typename View, typename... Args>
requires std::derived_from<View, AutofillLocationBarBubble>
View* ShowAddressProfileBubble(ToolbarButtonProvider* toolbar_button_provider,
bool is_user_gesture,
Args&&... args) {
return ShowBubble<View>(toolbar_button_provider,
kActionShowAddressesBubbleOrPage,
PageActionIconType::kAutofillAddress, is_user_gesture,
std::forward<Args>(args)...);
}
} // namespace
AutofillBubbleHandlerImpl::AutofillBubbleHandlerImpl(
ToolbarButtonProvider* toolbar_button_provider)
: toolbar_button_provider_(toolbar_button_provider) {}
AutofillBubbleHandlerImpl::~AutofillBubbleHandlerImpl() = default;
AutofillBubbleBase* AutofillBubbleHandlerImpl::ShowSaveCreditCardBubble(
content::WebContents* web_contents,
SaveCardBubbleController* controller,
bool is_user_gesture) {
switch (controller->GetPaymentsBubbleType()) {
case PaymentsBubbleType::kLocalSave:
case PaymentsBubbleType::kLocalCvcSave:
case PaymentsBubbleType::kUploadSave:
case PaymentsBubbleType::kUploadCvcSave:
case PaymentsBubbleType::kUploadInProgress:
return ShowBubble<SaveCardOfferBubbleViews>(
toolbar_button_provider_, kActionShowPaymentsBubbleOrPage,
PageActionIconType::kSaveCard, is_user_gesture, web_contents,
controller);
case PaymentsBubbleType::kManageCards:
return ShowBubble<SaveCardManageCardsBubbleViews>(
toolbar_button_provider_, kActionShowPaymentsBubbleOrPage,
PageActionIconType::kSaveCard, is_user_gesture, web_contents,
controller);
case PaymentsBubbleType::kUploadComplete:
case PaymentsBubbleType::kInactive:
break;
}
NOTREACHED();
}
AutofillBubbleBase* AutofillBubbleHandlerImpl::ShowIbanBubble(
content::WebContents* web_contents,
IbanBubbleController* controller,
bool is_user_gesture,
IbanBubbleType bubble_type) {
switch (bubble_type) {
case IbanBubbleType::kLocalSave:
case IbanBubbleType::kUploadSave:
case IbanBubbleType::kUploadInProgress:
return ShowBubble<SaveIbanBubbleView>(
toolbar_button_provider_, kActionShowPaymentsBubbleOrPage,
PageActionIconType::kSaveIban, is_user_gesture, web_contents,
controller);
case IbanBubbleType::kManageSavedIban:
return ShowBubble<ManageSavedIbanBubbleView>(
toolbar_button_provider_, kActionShowPaymentsBubbleOrPage,
PageActionIconType::kSaveIban, is_user_gesture, web_contents,
controller);
case IbanBubbleType::kUploadCompleted:
case IbanBubbleType::kInactive:
break;
}
NOTREACHED();
}
AutofillBubbleBase* AutofillBubbleHandlerImpl::ShowOfferNotificationBubble(
content::WebContents* web_contents,
OfferNotificationBubbleController* controller,
bool is_user_gesture) {
return ShowBubble<OfferNotificationBubbleViews>(
toolbar_button_provider_, kActionOffersAndRewardsForPage,
PageActionIconType::kPaymentsOfferNotification, is_user_gesture,
web_contents, controller);
}
AutofillBubbleBase* AutofillBubbleHandlerImpl::ShowSaveAddressProfileBubble(
content::WebContents* web_contents,
std::unique_ptr<SaveAddressBubbleController> controller,
bool is_user_gesture) {
return ShowAddressProfileBubble<SaveAddressProfileView>(
toolbar_button_provider_, is_user_gesture, std::move(controller),
web_contents);
}
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
AutofillBubbleBase* AutofillBubbleHandlerImpl::ShowAddressSignInPromo(
content::WebContents* web_contents,
const AutofillProfile& autofill_profile) {
views::View* anchor_view =
toolbar_button_provider_->GetAnchorView(kActionShowAddressesBubbleOrPage);
AddressSignInPromoView* bubble =
new AddressSignInPromoView(anchor_view, web_contents, autofill_profile);
if (!views::Button::AsButton(anchor_view)) {
IconLabelBubbleView* icon_view =
toolbar_button_provider_->GetPageActionView(
kActionShowAddressesBubbleOrPage);
CHECK(icon_view);
bubble->SetHighlightedButton(icon_view);
}
views::BubbleDialogDelegateView::CreateBubble(bubble);
bubble->ShowForReason(LocationBarBubbleDelegateView::AUTOMATIC);
return bubble;
}
#endif // BUILDFLAG(ENABLE_DICE_SUPPORT)
AutofillBubbleBase* AutofillBubbleHandlerImpl::ShowSaveAutofillAiDataBubble(
content::WebContents* web_contents,
AutofillAiImportDataController* controller) {
return ShowBubble<AutofillAiImportDataBubbleView>(
toolbar_button_provider_, kActionShowAddressesBubbleOrPage,
PageActionIconType::kAutofillAddress, /*is_user_gesture=*/false,
web_contents, controller);
}
AutofillBubbleBase* AutofillBubbleHandlerImpl::ShowUpdateAddressProfileBubble(
content::WebContents* web_contents,
std::unique_ptr<UpdateAddressBubbleController> controller,
bool is_user_gesture) {
return ShowAddressProfileBubble<UpdateAddressProfileView>(
toolbar_button_provider_, is_user_gesture, std::move(controller),
web_contents);
}
AutofillBubbleBase* AutofillBubbleHandlerImpl::ShowFilledCardInformationBubble(
content::WebContents* web_contents,
FilledCardInformationBubbleController* controller,
bool is_user_gesture) {
return ShowBubble<FilledCardInformationBubbleViews>(
toolbar_button_provider_, kActionFilledCardInformation,
PageActionIconType::kFilledCardInformation, is_user_gesture, web_contents,
controller);
}
AutofillBubbleBase* AutofillBubbleHandlerImpl::ShowVirtualCardEnrollBubble(
content::WebContents* web_contents,
VirtualCardEnrollBubbleController* controller,
bool is_user_gesture) {
views::View* anchor_view =
toolbar_button_provider_->GetAnchorView(kActionVirtualCardEnroll);
VirtualCardEnrollBubbleViews* bubble =
new VirtualCardEnrollBubbleViews(anchor_view, web_contents, controller);
views::BubbleDialogDelegateView::CreateBubble(bubble);
// VirtualCardEnrollBubbleController::IsEnrollmentInProgress() == true when
// the bubble has been accepted and the enrollment is still in progress. In
// this case we do not want to offer enrollment again on reshow.
if (controller->IsEnrollmentInProgress()) {
bubble->SwitchToLoadingState();
}
bubble->ShowForReason(is_user_gesture
? VirtualCardEnrollBubbleViews::USER_GESTURE
: VirtualCardEnrollBubbleViews::AUTOMATIC);
if (!views::Button::AsButton(anchor_view)) {
IconLabelBubbleView* icon_view =
toolbar_button_provider_->GetPageActionView(kActionVirtualCardEnroll);
if (icon_view) {
bubble->SetHighlightedButton(icon_view);
}
}
return bubble;
}
AutofillBubbleBase*
AutofillBubbleHandlerImpl::ShowVirtualCardEnrollConfirmationBubble(
content::WebContents* web_contents,
VirtualCardEnrollBubbleController* controller) {
views::View* anchor_view =
toolbar_button_provider_->GetAnchorView(kActionVirtualCardEnroll);
base::OnceCallback<void(PaymentsUiClosedReason)> callback =
controller->GetOnBubbleClosedCallback();
IconLabelBubbleView* icon_view =
toolbar_button_provider_->GetPageActionView(kActionVirtualCardEnroll);
const SavePaymentMethodAndVirtualCardEnrollConfirmationUiParams& ui_params =
controller->GetConfirmationUiParams();
return ShowSaveCardAndVirtualCardEnrollConfirmationBubble(
anchor_view, web_contents, std::move(callback), icon_view, ui_params);
}
AutofillBubbleBase* AutofillBubbleHandlerImpl::ShowMandatoryReauthBubble(
content::WebContents* web_contents,
MandatoryReauthBubbleController* controller,
bool is_user_gesture,
MandatoryReauthBubbleType bubble_type) {
IconLabelBubbleView* icon_view = toolbar_button_provider_->GetPageActionView(
kActionAutofillMandatoryReauth);
views::View* anchor_view =
toolbar_button_provider_->GetAnchorView(kActionAutofillMandatoryReauth);
switch (bubble_type) {
case MandatoryReauthBubbleType::kOptIn: {
MandatoryReauthOptInBubbleView* bubble =
new MandatoryReauthOptInBubbleView(anchor_view, web_contents,
controller);
bubble->SetHighlightedButton(icon_view);
views::BubbleDialogDelegateView::CreateBubble(bubble);
bubble->Show(is_user_gesture ? LocationBarBubbleDelegateView::USER_GESTURE
: LocationBarBubbleDelegateView::AUTOMATIC);
return bubble;
}
case MandatoryReauthBubbleType::kConfirmation: {
MandatoryReauthConfirmationBubbleView* bubble =
new MandatoryReauthConfirmationBubbleView(anchor_view, web_contents,
controller);
bubble->SetHighlightedButton(icon_view);
views::BubbleDialogDelegateView::CreateBubble(bubble);
bubble->Show(is_user_gesture ? LocationBarBubbleDelegateView::USER_GESTURE
: LocationBarBubbleDelegateView::AUTOMATIC);
return bubble;
}
case MandatoryReauthBubbleType::kInactive:
NOTREACHED();
}
}
AutofillBubbleBase* AutofillBubbleHandlerImpl::ShowSaveCardConfirmationBubble(
content::WebContents* web_contents,
SaveCardBubbleController* controller) {
views::View* anchor_view =
toolbar_button_provider_->GetAnchorView(kActionShowPaymentsBubbleOrPage);
base::OnceCallback<void(PaymentsUiClosedReason)> callback =
controller->GetOnBubbleClosedCallback();
IconLabelBubbleView* icon_view;
if (IsPageActionMigrated(PageActionIconType::kSaveCard)) {
icon_view = toolbar_button_provider_->GetPageActionView(
kActionShowPaymentsBubbleOrPage);
} else {
icon_view = toolbar_button_provider_->GetPageActionIconView(
PageActionIconType::kSaveCard);
}
const SavePaymentMethodAndVirtualCardEnrollConfirmationUiParams& ui_params =
controller->GetConfirmationUiParams();
return ShowSaveCardAndVirtualCardEnrollConfirmationBubble(
anchor_view, web_contents, std::move(callback), icon_view, ui_params);
}
AutofillBubbleBase* AutofillBubbleHandlerImpl::ShowSaveIbanConfirmationBubble(
content::WebContents* web_contents,
IbanBubbleController* controller) {
views::View* anchor_view =
toolbar_button_provider_->GetAnchorView(kActionShowPaymentsBubbleOrPage);
base::OnceCallback<void(PaymentsUiClosedReason)> callback =
controller->GetOnBubbleClosedCallback();
IconLabelBubbleView* icon_view;
if (IsPageActionMigrated(PageActionIconType::kSaveIban)) {
icon_view = toolbar_button_provider_->GetPageActionView(
kActionShowPaymentsBubbleOrPage);
} else {
icon_view = toolbar_button_provider_->GetPageActionIconView(
PageActionIconType::kSaveIban);
}
return ShowSaveCardAndVirtualCardEnrollConfirmationBubble(
anchor_view, web_contents, std::move(callback), icon_view,
controller->GetConfirmationUiParams());
}
AutofillBubbleBase*
AutofillBubbleHandlerImpl::ShowSaveCardAndVirtualCardEnrollConfirmationBubble(
views::View* anchor_view,
content::WebContents* web_contents,
base::OnceCallback<void(PaymentsUiClosedReason)> controller_hide_callback,
views::Button* icon_view,
SavePaymentMethodAndVirtualCardEnrollConfirmationUiParams ui_params) {
SavePaymentMethodAndVirtualCardEnrollConfirmationBubbleViews* bubble =
new SavePaymentMethodAndVirtualCardEnrollConfirmationBubbleViews(
anchor_view, web_contents, std::move(controller_hide_callback),
std::move(ui_params));
if (!views::Button::AsButton(anchor_view)) {
bubble->SetHighlightedButton(icon_view);
}
views::BubbleDialogDelegateView::CreateBubble(bubble);
bubble->ShowForReason(LocationBarBubbleDelegateView::AUTOMATIC);
return bubble;
}
} // namespace autofill