#include "components/autofill/core/browser/payments/iban_access_manager.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
#include "base/test/task_environment.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/form_data_importer_test_api.h"
#include "components/autofill/core/browser/payments/mock_test_payments_network_interface.h"
#include "components/autofill/core/browser/payments/payments_autofill_client.h"
#include "components/autofill/core/browser/payments_data_manager.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
#include "components/autofill/core/browser/ui/suggestion.h"
#include "components/autofill/core/browser/ui/suggestion_type.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/sync/test/test_sync_service.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(IS_ANDROID)
#include "base/android/build_info.h"
#endif
namespace autofill {
namespace {
constexpr char16_t kFullIbanValue[] = …;
constexpr int64_t kInstrumentId = …;
constexpr int kDaysSinceLastUsed = …;
constexpr int kDefaultUnmaskIbanLatencyMs = …;
constexpr size_t kDefaultUseCount = …;
}
class IbanAccessManagerTest : public testing::Test { … };
TEST_F(IbanAccessManagerTest, FetchValue_ExistingLocalIban) { … }
TEST_F(IbanAccessManagerTest, FetchValue_NonExistingLocalIban) { … }
TEST_F(IbanAccessManagerTest, NoServerIbanWithBackendId_DoesNotUnmask) { … }
TEST_F(IbanAccessManagerTest, ServerIban_BackendId_Success) { … }
TEST_F(IbanAccessManagerTest, ServerIban_BackendId_Failure) { … }
TEST_F(IbanAccessManagerTest, FetchValue_LocalIbanNoProgressDialog) { … }
TEST_F(IbanAccessManagerTest, FetchValue_ServerIban_ProgressDialog_Success) { … }
TEST_F(IbanAccessManagerTest, FetchValue_ServerIban_ProgressDialog_Failure) { … }
TEST_F(IbanAccessManagerTest, LocalIban_LogUsageMetric) { … }
TEST_F(IbanAccessManagerTest, ServerIban_LogUsageMetric) { … }
TEST_F(IbanAccessManagerTest, UnmaskServerIban_Success_Metric) { … }
TEST_F(IbanAccessManagerTest, UnmaskServerIban_Failure_Metric) { … }
TEST_F(IbanAccessManagerTest, UnmaskIbanResult_Metric_Success) { … }
TEST_F(IbanAccessManagerTest, UnmaskIbanResult_Metric_Failure) { … }
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
class IbanAccessManagerMandatoryReauthTest : public IbanAccessManagerTest {
public:
IbanAccessManagerMandatoryReauthTest() = default;
~IbanAccessManagerMandatoryReauthTest() override = default;
protected:
void SetUp() override {
IbanAccessManagerTest::SetUp();
autofill_client_.GetPrefs()->SetBoolean(
prefs::kAutofillPaymentMethodsMandatoryReauth, true);
}
void SetUpDeviceAuthenticatorResponseMock(bool success) {
ON_CALL(mandatory_reauth_manager(), StartDeviceAuthentication)
.WillByDefault(testing::WithArg<1>(
testing::Invoke([success](base::OnceCallback<void(bool)> callback) {
std::move(callback).Run(success);
})));
}
payments::MockMandatoryReauthManager& mandatory_reauth_manager() {
return *static_cast<payments::MockMandatoryReauthManager*>(
autofill_client_.GetPaymentsAutofillClient()
->GetOrCreatePaymentsMandatoryReauthManager());
}
};
TEST_F(IbanAccessManagerMandatoryReauthTest, FetchValue_Local_Reauth_Success) {
base::HistogramTester histogram_tester;
SetUpDeviceAuthenticatorResponseMock(true);
Suggestion suggestion(SuggestionType::kIbanEntry);
Iban local_iban = test::GetLocalIban();
local_iban.set_value(kFullIbanValue);
personal_data().test_payments_data_manager().AddIbanForTest(
std::make_unique<Iban>(local_iban));
suggestion.payload =
Suggestion::BackendId(Suggestion::Guid(local_iban.guid()));
base::MockCallback<IbanAccessManager::OnIbanFetchedCallback> callback;
EXPECT_CALL(callback, Run(std::u16string(kFullIbanValue)));
iban_access_manager_->FetchValue(
suggestion.GetPayload<Suggestion::BackendId>(), callback.Get());
}
TEST_F(IbanAccessManagerMandatoryReauthTest, FetchValue_Local_Reauth_Fail) {
SetUpDeviceAuthenticatorResponseMock(false);
Suggestion suggestion(SuggestionType::kIbanEntry);
Iban local_iban = test::GetLocalIban();
local_iban.set_value(kFullIbanValue);
personal_data().test_payments_data_manager().AddIbanForTest(
std::make_unique<Iban>(local_iban));
suggestion.payload =
Suggestion::BackendId(Suggestion::Guid(local_iban.guid()));
base::MockCallback<IbanAccessManager::OnIbanFetchedCallback> callback;
EXPECT_CALL(callback, Run(std::u16string(kFullIbanValue))).Times(0);
iban_access_manager_->FetchValue(
suggestion.GetPayload<Suggestion::BackendId>(), callback.Get());
}
TEST_F(IbanAccessManagerMandatoryReauthTest, FetchValue_Server_Reauth_Success) {
SetUpDeviceAuthenticatorResponseMock(true);
SetUpUnmaskIbanCall(true, kFullIbanValue);
Iban server_iban = test::GetServerIban();
server_iban.set_identifier(Iban::InstrumentId(kInstrumentId));
personal_data().test_payments_data_manager().AddServerIban(server_iban);
Suggestion suggestion(SuggestionType::kIbanEntry);
suggestion.payload = Suggestion::InstrumentId(kInstrumentId);
base::MockCallback<IbanAccessManager::OnIbanFetchedCallback> callback;
EXPECT_CALL(callback, Run(std::u16string(kFullIbanValue)));
iban_access_manager_->FetchValue(
suggestion.GetPayload<Suggestion::BackendId>(), callback.Get());
}
TEST_F(IbanAccessManagerMandatoryReauthTest, FetchValue_Server_Reauth_Fail) {
SetUpDeviceAuthenticatorResponseMock(false);
SetUpUnmaskIbanCall(true, kFullIbanValue);
Iban server_iban = test::GetServerIban();
server_iban.set_identifier(Iban::InstrumentId(kInstrumentId));
personal_data().test_payments_data_manager().AddServerIban(server_iban);
Suggestion suggestion(SuggestionType::kIbanEntry);
suggestion.payload = Suggestion::InstrumentId(kInstrumentId);
base::MockCallback<IbanAccessManager::OnIbanFetchedCallback> callback;
EXPECT_CALL(callback, Run(std::u16string(kFullIbanValue))).Times(0);
iban_access_manager_->FetchValue(
suggestion.GetPayload<Suggestion::BackendId>(), callback.Get());
}
TEST_F(IbanAccessManagerMandatoryReauthTest,
NonInteractivePaymentMethodType_Local) {
autofill_client_.GetPrefs()->SetBoolean(
prefs::kAutofillPaymentMethodsMandatoryReauth, false);
SetUpDeviceAuthenticatorResponseMock(true);
Iban local_iban = test::GetLocalIban();
personal_data().test_payments_data_manager().AddIbanForTest(
std::make_unique<Iban>(local_iban));
Suggestion suggestion(SuggestionType::kIbanEntry);
suggestion.payload =
Suggestion::BackendId(Suggestion::Guid(local_iban.guid()));
iban_access_manager_->FetchValue(
suggestion.GetPayload<Suggestion::BackendId>(), base::DoNothing());
EXPECT_EQ(
test_api(*autofill_client_.GetFormDataImporter())
.payment_method_type_if_non_interactive_authentication_flow_completed(),
NonInteractivePaymentMethodType::kLocalIban);
}
TEST_F(IbanAccessManagerMandatoryReauthTest,
NonInteractivePaymentMethodType_Server) {
autofill_client_.GetPrefs()->SetBoolean(
prefs::kAutofillPaymentMethodsMandatoryReauth, false);
SetUpDeviceAuthenticatorResponseMock(true);
SetUpUnmaskIbanCall(true, kFullIbanValue);
Iban server_iban = test::GetServerIban();
personal_data().test_payments_data_manager().AddServerIban(server_iban);
Suggestion suggestion(SuggestionType::kIbanEntry);
suggestion.payload = Suggestion::InstrumentId(server_iban.instrument_id());
iban_access_manager_->FetchValue(
suggestion.GetPayload<Suggestion::BackendId>(), base::DoNothing());
EXPECT_EQ(
test_api(*autofill_client_.GetFormDataImporter())
.payment_method_type_if_non_interactive_authentication_flow_completed(),
NonInteractivePaymentMethodType::kServerIban);
}
TEST_F(IbanAccessManagerMandatoryReauthTest, ReauthUsage_LocalIban_Succcess) {
base::HistogramTester histogram_tester;
SetUpDeviceAuthenticatorResponseMock(
true);
Suggestion suggestion(SuggestionType::kIbanEntry);
Iban local_iban = test::GetLocalIban();
local_iban.set_value(kFullIbanValue);
personal_data().test_payments_data_manager().AddIbanForTest(
std::make_unique<Iban>(local_iban));
suggestion.payload =
Suggestion::BackendId(Suggestion::Guid(local_iban.guid()));
ON_CALL(mandatory_reauth_manager(), StartDeviceAuthentication)
.WillByDefault([this](NonInteractivePaymentMethodType
non_interactive_payment_method_type,
base::OnceCallback<void(bool)> callback) {
base::MockCallback<IbanAccessManager::OnIbanFetchedCallback>
on_iban_fetched_callback;
iban_access_manager_
->OnDeviceAuthenticationResponseForFillingForTesting(
on_iban_fetched_callback.Get(), std::u16string(kFullIbanValue),
NonInteractivePaymentMethodType::kLocalIban, true);
});
iban_access_manager_->FetchValue(
suggestion.GetPayload<Suggestion::BackendId>(), base::DoNothing());
histogram_tester.ExpectBucketCount(
"Autofill.PaymentMethods.CheckoutFlow.ReauthUsage.LocalIban.Biometric",
autofill_metrics::MandatoryReauthAuthenticationFlowEvent::kFlowSucceeded,
1);
}
TEST_F(IbanAccessManagerMandatoryReauthTest, ReauthUsage_LocalIban_Fail) {
base::HistogramTester histogram_tester;
SetUpDeviceAuthenticatorResponseMock(false);
Suggestion suggestion(SuggestionType::kIbanEntry);
Iban local_iban = test::GetLocalIban();
local_iban.set_value(kFullIbanValue);
personal_data().test_payments_data_manager().AddIbanForTest(
std::make_unique<Iban>(local_iban));
suggestion.payload =
Suggestion::BackendId(Suggestion::Guid(local_iban.guid()));
ON_CALL(mandatory_reauth_manager(), StartDeviceAuthentication)
.WillByDefault([this](NonInteractivePaymentMethodType
non_interactive_payment_method_type,
base::OnceCallback<void(bool)> callback) {
base::MockCallback<IbanAccessManager::OnIbanFetchedCallback>
on_iban_fetched_callback;
iban_access_manager_
->OnDeviceAuthenticationResponseForFillingForTesting(
on_iban_fetched_callback.Get(), std::u16string(kFullIbanValue),
NonInteractivePaymentMethodType::kLocalIban, false);
});
iban_access_manager_->FetchValue(
suggestion.GetPayload<Suggestion::BackendId>(), base::DoNothing());
histogram_tester.ExpectBucketCount(
"Autofill.PaymentMethods.CheckoutFlow.ReauthUsage.LocalIban.Biometric",
autofill_metrics::MandatoryReauthAuthenticationFlowEvent::kFlowFailed, 1);
}
TEST_F(IbanAccessManagerMandatoryReauthTest, ReauthUsage_ServerIban_Succcess) {
base::HistogramTester histogram_tester;
SetUpDeviceAuthenticatorResponseMock(true);
SetUpUnmaskIbanCall(true, kFullIbanValue);
Iban server_iban = test::GetServerIban();
server_iban.set_identifier(Iban::InstrumentId(kInstrumentId));
personal_data().test_payments_data_manager().AddServerIban(server_iban);
Suggestion suggestion(SuggestionType::kIbanEntry);
suggestion.payload = Suggestion::InstrumentId(kInstrumentId);
ON_CALL(mandatory_reauth_manager(), StartDeviceAuthentication)
.WillByDefault([this](NonInteractivePaymentMethodType
non_interactive_payment_method_type,
base::OnceCallback<void(bool)> callback) {
base::MockCallback<IbanAccessManager::OnIbanFetchedCallback>
on_iban_fetched_callback;
iban_access_manager_
->OnDeviceAuthenticationResponseForFillingForTesting(
on_iban_fetched_callback.Get(), std::u16string(kFullIbanValue),
NonInteractivePaymentMethodType::kServerIban, true);
});
iban_access_manager_->FetchValue(
suggestion.GetPayload<Suggestion::BackendId>(), base::DoNothing());
histogram_tester.ExpectBucketCount(
"Autofill.PaymentMethods.CheckoutFlow.ReauthUsage.ServerIban.Biometric",
autofill_metrics::MandatoryReauthAuthenticationFlowEvent::kFlowSucceeded,
1);
}
TEST_F(IbanAccessManagerMandatoryReauthTest, ReauthUsage_ServerIban_Fail) {
base::HistogramTester histogram_tester;
SetUpDeviceAuthenticatorResponseMock(false);
SetUpUnmaskIbanCall(true, kFullIbanValue);
Iban server_iban = test::GetServerIban();
server_iban.set_identifier(Iban::InstrumentId(kInstrumentId));
personal_data().test_payments_data_manager().AddServerIban(server_iban);
Suggestion suggestion(SuggestionType::kIbanEntry);
suggestion.payload = Suggestion::InstrumentId(kInstrumentId);
ON_CALL(mandatory_reauth_manager(), StartDeviceAuthentication)
.WillByDefault([this](NonInteractivePaymentMethodType
non_interactive_payment_method_type,
base::OnceCallback<void(bool)> callback) {
base::MockCallback<IbanAccessManager::OnIbanFetchedCallback>
on_iban_fetched_callback;
iban_access_manager_
->OnDeviceAuthenticationResponseForFillingForTesting(
on_iban_fetched_callback.Get(), std::u16string(kFullIbanValue),
NonInteractivePaymentMethodType::kServerIban,
false);
});
iban_access_manager_->FetchValue(
suggestion.GetPayload<Suggestion::BackendId>(), base::DoNothing());
histogram_tester.ExpectBucketCount(
"Autofill.PaymentMethods.CheckoutFlow.ReauthUsage.ServerIban.Biometric",
autofill_metrics::MandatoryReauthAuthenticationFlowEvent::kFlowFailed, 1);
}
#endif
}