File: iban_access_manager.cc

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (201 lines) | stat: -rw-r--r-- 9,109 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
// 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 "components/autofill/core/browser/payments/iban_access_manager.h"

#include <variant>

#include "components/autofill/core/browser/data_manager/personal_data_manager.h"
#include "components/autofill/core/browser/foundations/autofill_client.h"
#include "components/autofill/core/browser/metrics/payments/iban_metrics.h"
#include "components/autofill/core/browser/payments/autofill_error_dialog_context.h"
#include "components/autofill/core/browser/payments/payments_autofill_client.h"
#include "components/autofill/core/browser/payments/payments_network_interface.h"
#include "components/autofill/core/browser/payments/payments_requests/payments_request.h"
#include "components/autofill/core/browser/payments/payments_util.h"
#include "components/autofill/core/browser/suggestions/suggestion.h"
#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"

namespace autofill {

IbanAccessManager::IbanAccessManager(AutofillClient* client)
    : client_(client) {}

IbanAccessManager::~IbanAccessManager() = default;

void IbanAccessManager::FetchValue(const Suggestion::Payload& payload,
                                   OnIbanFetchedCallback on_iban_fetched) {
  if (auto* form_data_importer = client_->GetFormDataImporter()) {
    // Reset the variable in FormDataImporter that denotes if non-interactive
    // authentication happened. This variable will be set to a value if a
    // payments autofill non-interactive flow successfully completes.
    form_data_importer
        ->SetPaymentMethodTypeIfNonInteractiveAuthenticationFlowCompleted(
            std::nullopt);
  }

  // If `Guid` has a value then that means that it's a local IBAN suggestion.
  // In this case, retrieving the complete IBAN value requires accessing the
  // saved IBAN from the PersonalDataManager.
  if (const Suggestion::Guid* guid = std::get_if<Suggestion::Guid>(&payload)) {
    const Iban* iban = GetPaymentsDataManager().GetIbanByGUID(guid->value());
    if (iban) {
      Iban iban_copy = *iban;
      GetPaymentsDataManager().RecordUseOfIban(iban_copy);
      if (GetPaymentsDataManager().IsPaymentMethodsMandatoryReauthEnabled()) {
        StartDeviceAuthenticationForFilling(
            std::move(on_iban_fetched), iban_copy.value(),
            NonInteractivePaymentMethodType::kLocalIban);
      } else {
        std::move(on_iban_fetched).Run(iban_copy.value());
        if (auto* form_data_importer = client_->GetFormDataImporter()) {
          form_data_importer
              ->SetPaymentMethodTypeIfNonInteractiveAuthenticationFlowCompleted(
                  payments::MandatoryReauthManager::
                      GetNonInteractivePaymentMethodType(
                          Iban::RecordType::kLocalIban));
        }
      }
    }
    return;
  }

  int64_t instrument_id = std::get<Suggestion::InstrumentId>(payload).value();

  // The suggestion is now presumed to be a masked server IBAN.
  // If there are no server IBANs in the PersonalDataManager that have the same
  // instrument ID as the provided `instrument_id`, then abort the operation.
  if (!GetPaymentsDataManager().GetIbanByInstrumentId(instrument_id)) {
    return;
  }

  GetPaymentsAutofillClient().ShowAutofillProgressDialog(
      AutofillProgressDialogType::kServerIbanUnmaskProgressDialog,
      base::BindOnce(&IbanAccessManager::OnServerIbanUnmaskCancelled,
                     weak_ptr_factory_.GetWeakPtr()));

  // Construct `UnmaskIbanRequestDetails` and send `UnmaskIban` to fetch the
  // full value of the server IBAN.
  const Iban* iban =
      GetPaymentsDataManager().GetIbanByInstrumentId(instrument_id);
  if (!iban) {
    return;
  }
  Iban iban_copy = *iban;
  GetPaymentsDataManager().RecordUseOfIban(iban_copy);
  payments::UnmaskIbanRequestDetails request_details;
  request_details.billing_customer_number =
      payments::GetBillingCustomerId(GetPaymentsDataManager());
  request_details.instrument_id = instrument_id;
  base::TimeTicks unmask_request_timestamp = base::TimeTicks::Now();
  GetPaymentsAutofillClient().GetPaymentsNetworkInterface()->UnmaskIban(
      request_details,
      base::BindOnce(&IbanAccessManager::OnUnmaskResponseReceived,
                     weak_ptr_factory_.GetWeakPtr(), std::move(on_iban_fetched),
                     unmask_request_timestamp));
}

void IbanAccessManager::OnUnmaskResponseReceived(
    OnIbanFetchedCallback on_iban_fetched,
    base::TimeTicks unmask_request_timestamp,
    payments::PaymentsAutofillClient::PaymentsRpcResult result,
    const std::u16string& value) {
  bool is_successful =
      result == payments::PaymentsAutofillClient::PaymentsRpcResult::kSuccess;
  autofill_metrics::LogServerIbanUnmaskLatency(
      base::TimeTicks::Now() - unmask_request_timestamp, is_successful);
  autofill_metrics::LogServerIbanUnmaskStatus(is_successful);
  if (is_successful) {
    if (GetPaymentsDataManager().IsPaymentMethodsMandatoryReauthEnabled()) {
      // On some operating systems (for example, macOS and Windows), the
      // device authentication prompt freezes Chrome. Thus we can only trigger
      // the prompt after the progress dialog has been closed, which we can do
      // by using the `no_interactive_authentication_callback` parameter in
      // `PaymentsAutofillClient::CloseAutofillProgressDialog()`.
      GetPaymentsAutofillClient().CloseAutofillProgressDialog(
          /*show_confirmation_before_closing=*/false,
          /*no_interactive_authentication_callback=*/base::BindOnce(
              // `StartDeviceAuthenticationForFilling()` will asynchronously
              // trigger the re-authentication flow, so we should avoid
              // calling `Reset()` until the re-authentication flow is
              // complete.
              &IbanAccessManager::StartDeviceAuthenticationForFilling,
              weak_ptr_factory_.GetWeakPtr(), std::move(on_iban_fetched), value,
              NonInteractivePaymentMethodType::kServerIban));
    } else {
      GetPaymentsAutofillClient().CloseAutofillProgressDialog(
          /*show_confirmation_before_closing=*/false,
          /*no_interactive_authentication_callback=*/base::OnceClosure());
      std::move(on_iban_fetched).Run(value);
      if (auto* form_data_importer = client_->GetFormDataImporter()) {
        form_data_importer
            ->SetPaymentMethodTypeIfNonInteractiveAuthenticationFlowCompleted(
                payments::MandatoryReauthManager::
                    GetNonInteractivePaymentMethodType(
                        Iban::RecordType::kServerIban));
      }
    }
    return;
  }

  // Immediately close the progress dialog before showing the error dialog.
  GetPaymentsAutofillClient().CloseAutofillProgressDialog(
      /*show_confirmation_before_closing=*/false,
      /*no_interactive_authentication_callback=*/base::OnceClosure());
  AutofillErrorDialogContext error_context;
  error_context.type =
      AutofillErrorDialogType::kMaskedServerIbanUnmaskingTemporaryError;
  GetPaymentsAutofillClient().ShowAutofillErrorDialog(error_context);
}

void IbanAccessManager::OnServerIbanUnmaskCancelled() {
  // TODO(crbug.com/296651899): Log the cancel metrics.
}

void IbanAccessManager::StartDeviceAuthenticationForFilling(
    OnIbanFetchedCallback on_iban_fetched,
    const std::u16string& value,
    NonInteractivePaymentMethodType non_interactive_payment_method_type) {
  GetPaymentsAutofillClient()
      .GetOrCreatePaymentsMandatoryReauthManager()
      ->StartDeviceAuthentication(
          non_interactive_payment_method_type,
          base::BindOnce(
              &IbanAccessManager::OnDeviceAuthenticationResponseForFilling,
              weak_ptr_factory_.GetWeakPtr(), std::move(on_iban_fetched), value,
              non_interactive_payment_method_type,
              GetPaymentsAutofillClient()
                  .GetOrCreatePaymentsMandatoryReauthManager()
                  ->GetAuthenticationMethod()));
}

void IbanAccessManager::OnDeviceAuthenticationResponseForFilling(
    OnIbanFetchedCallback on_iban_fetched,
    const std::u16string& value,
    NonInteractivePaymentMethodType non_interactive_payment_method_type,
    payments::MandatoryReauthAuthenticationMethod authentication_method,
    bool successful_auth) {
  LogMandatoryReauthCheckoutFlowUsageEvent(
      non_interactive_payment_method_type, authentication_method,
      successful_auth
          ? autofill_metrics::MandatoryReauthAuthenticationFlowEvent::
                kFlowSucceeded
          : autofill_metrics::MandatoryReauthAuthenticationFlowEvent::
                kFlowFailed);
  if (successful_auth) {
    std::move(on_iban_fetched).Run(value);
  }
}

payments::PaymentsAutofillClient&
IbanAccessManager::GetPaymentsAutofillClient() {
  return *client_->GetPaymentsAutofillClient();
}

PaymentsDataManager& IbanAccessManager::GetPaymentsDataManager() {
  return client_->GetPersonalDataManager().payments_data_manager();
}

}  // namespace autofill