chromium/ios/chrome/browser/autofill/ui_bundled/card_unmask_prompt_view_bridge.mm

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

#import "ios/chrome/browser/autofill/ui_bundled/card_unmask_prompt_view_bridge.h"

#import "base/apple/foundation_util.h"
#import "base/notreached.h"
#import "base/strings/sys_string_conversions.h"
#import "components/autofill/core/browser/data_model/credit_card.h"
#import "components/autofill/core/browser/payments_data_manager.h"
#import "components/autofill/core/browser/personal_data_manager.h"
#import "components/autofill/core/browser/ui/payments/card_unmask_prompt_controller.h"
#import "ios/chrome/browser/autofill/model/credit_card/credit_card_data.h"
#import "ios/chrome/browser/shared/public/commands/browser_coordinator_commands.h"
#import "ios/chrome/browser/shared/public/commands/command_dispatcher.h"
#import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
#import "ios/chrome/browser/autofill/ui_bundled/card_unmask_prompt_view_controller.h"

namespace autofill {

#pragma mark CardUnmaskPromptViewBridge

CardUnmaskPromptViewBridge::CardUnmaskPromptViewBridge(
    CardUnmaskPromptController* controller,
    UINavigationController* navigation_controller,
    PersonalDataManager* personal_data_manager,
    id<BrowserCoordinatorCommands> browser_coordinator_commands_handler)
    : controller_(controller),
      navigation_controller_(navigation_controller),
      personal_data_manager_(personal_data_manager),
      browser_coordinator_commands_handler_(
          browser_coordinator_commands_handler),
      weak_ptr_factory_(this) {
  CHECK(controller_);
  CHECK(personal_data_manager_);
  credit_card_data_ =
      [[CreditCardData alloc] initWithCreditCard:controller_->GetCreditCard()
                                            icon:GetCardIcon()];
}

CardUnmaskPromptViewBridge::~CardUnmaskPromptViewBridge() {
  [prompt_view_controller_ disconnectFromBridge];
  if (controller_) {
    controller_->OnUnmaskDialogClosed();
  }
}

void CardUnmaskPromptViewBridge::Show() {
  prompt_view_controller_ =
      [[CardUnmaskPromptViewController alloc] initWithBridge:this];

  navigation_controller_.presentationController.delegate =
      prompt_view_controller_;

  [navigation_controller_ pushViewController:prompt_view_controller_
                                    animated:YES];
}

void CardUnmaskPromptViewBridge::Dismiss() {
  PerformClose();
}

void CardUnmaskPromptViewBridge::ControllerGone() {
  controller_ = nullptr;
  PerformClose();
}

void CardUnmaskPromptViewBridge::DisableAndWaitForVerification() {
  [prompt_view_controller_ showLoadingState];
}

void CardUnmaskPromptViewBridge::GotVerificationResult(
    const std::u16string& error_message,
    bool allow_retry) {
  // No error. Dismiss the prompt.
  if (error_message.empty()) {
    PerformClose();
  } else {
    [prompt_view_controller_
        showErrorAlertWithMessage:base::SysUTF16ToNSString(error_message)
                   closeOnDismiss:!allow_retry];
  }
}

CardUnmaskPromptController* CardUnmaskPromptViewBridge::GetController() {
  // This public accessor is used by the view controller, which shouldn't access
  // the controller after it was released. Adding a CHECK to explicitly catch
  // any UAF errors.
  CHECK(controller_);
  return controller_;
}

void CardUnmaskPromptViewBridge::PerformClose() {
  // Disconnect the vc from the bridge, and dismiss it.
  [prompt_view_controller_ disconnectFromBridge];

  [browser_coordinator_commands_handler_ dismissCardUnmaskAuthentication];
}

UIImage* CardUnmaskPromptViewBridge::GetCardIcon() {
  // Firstly check if card art image is available.
  const CreditCard& credit_card = GetController()->GetCreditCard();
  gfx::Image* image =
      personal_data_manager_->payments_data_manager()
          .GetCreditCardArtImageForUrl(credit_card.card_art_url());
  if (image) {
    return image->ToUIImage();
  }

  // Use card network icon.
  Suggestion::Icon icon = credit_card.CardIconForAutofillSuggestion();
  return icon == Suggestion::Icon::kNoIcon
             ? nil
             : NativeImage(CreditCard::IconResourceId(
                   credit_card.CardIconForAutofillSuggestion()));
}

}  // namespace autofill