#include "components/autofill/core/browser/payments/credit_card_access_manager.h"
#include <stddef.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/base64.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/browser/form_data_importer_test_api.h"
#include "components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.h"
#include "components/autofill/core/browser/metrics/payments/better_auth_metrics.h"
#include "components/autofill/core/browser/metrics/payments/card_unmask_authentication_metrics.h"
#include "components/autofill/core/browser/metrics/payments/card_unmask_flow_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/credit_card_access_manager_test_api.h"
#include "components/autofill/core/browser/payments/credit_card_cvc_authenticator.h"
#include "components/autofill/core/browser/payments/credit_card_risk_based_authenticator.h"
#include "components/autofill/core/browser/payments/mandatory_reauth_manager.h"
#include "components/autofill/core/browser/payments/payments_autofill_client.h"
#include "components/autofill/core/browser/payments/test/mock_payments_window_manager.h"
#include "components/autofill/core/browser/payments/test/test_credit_card_otp_authenticator.h"
#include "components/autofill/core/browser/payments/test_payments_autofill_client.h"
#include "components/autofill/core/browser/payments/test_payments_network_interface.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_autofill_driver.h"
#include "components/autofill/core/browser/test_browser_autofill_manager.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
#include "components/autofill/core/browser/validation.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_payments_features.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/strings/grit/components_strings.h"
#include "components/sync/test/test_sync_service.h"
#include "components/variations/scoped_variations_ids_provider.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID)
#include "components/autofill/core/browser/payments/test_credit_card_fido_authenticator.h"
#include "components/autofill/core/browser/payments/test_internal_authenticator.h"
#include "components/autofill/core/browser/strike_databases/payments/fido_authentication_strike_database.h"
#include "content/public/test/mock_navigation_handle.h"
#endif
#if BUILDFLAG(IS_ANDROID)
#include "base/android/build_info.h"
#endif
ASCIIToUTF16;
NiceMock;
namespace autofill {
namespace {
PaymentsRpcCardType;
PaymentsRpcResult;
constexpr char kTestGUID[] = …;
constexpr char kTestGUID2[] = …;
constexpr char kTestNumber[] = …;
constexpr char kTestNumber2[] = …;
constexpr char16_t kTestNumber16[] = …;
constexpr char16_t kTestCvc16[] = …;
constexpr char kTestServerId[] = …;
constexpr char kTestServerId2[] = …;
CreditCardFormEventLogger;
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID)
constexpr char kTestCvc[] = "123";
constexpr char kTestChallenge[] = "VGhpcyBpcyBhIHRlc3QgY2hhbGxlbmdl";
constexpr char kCredentialId[] = "VGhpcyBpcyBhIHRlc3QgQ3JlZGVudGlhbCBJRC4=";
constexpr char kGooglePaymentsRpid[] = "google.com";
std::string BytesToBase64(const std::vector<uint8_t>& bytes) {
return base::Base64Encode(bytes);
}
#endif
class TestAccessor { … };
}
class CreditCardAccessManagerTest : public testing::Test { … };
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID) || \
BUILDFLAG(IS_IOS)
class CreditCardAccessManagerMandatoryReauthTest
: public CreditCardAccessManagerTest {
public:
CreditCardAccessManagerMandatoryReauthTest() = default;
~CreditCardAccessManagerMandatoryReauthTest() override = default;
protected:
void SetUp() override {
CreditCardAccessManagerTest::SetUp();
feature_list_.InitAndEnableFeature(
features::kAutofillEnableFpanRiskBasedAuthentication);
#if BUILDFLAG(IS_ANDROID)
if (base::android::BuildInfo::GetInstance()->is_automotive()) {
autofill_client_.GetPrefs()->SetBoolean(
prefs::kAutofillPaymentMethodsMandatoryReauth,
true);
return;
}
#endif
autofill_client_.GetPrefs()->SetBoolean(
prefs::kAutofillPaymentMethodsMandatoryReauth,
PrefIsEnabled());
}
void SetUpDeviceAuthenticatorResponseMock() {
ON_CALL(mandatory_reauth_manager(), GetAuthenticationMethod)
.WillByDefault(testing::Return(GetAuthenticationMethod()));
if (IsMandatoryReauthEnabled()) {
ON_CALL(mandatory_reauth_manager(),
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS)
AuthenticateWithMessage)
.WillByDefault(testing::WithArg<1>(
#elif BUILDFLAG(IS_ANDROID)
Authenticate)
.WillByDefault(testing::WithArg<0>(
#endif
testing::Invoke([mandatory_reauth_response_is_success =
MandatoryReauthResponseIsSuccess()](
base::OnceCallback<void(bool)> callback) {
std::move(callback).Run(mandatory_reauth_response_is_success);
})));
} else {
EXPECT_CALL(mandatory_reauth_manager(),
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS)
AuthenticateWithMessage)
#elif BUILDFLAG(IS_ANDROID)
Authenticate)
#endif
.Times(0);
}
}
payments::MockMandatoryReauthManager& mandatory_reauth_manager() {
return *static_cast<payments::MockMandatoryReauthManager*>(
autofill_client_.GetPaymentsAutofillClient()
->GetOrCreatePaymentsMandatoryReauthManager());
}
virtual bool PrefIsEnabled() const = 0;
virtual bool MandatoryReauthResponseIsSuccess() const = 0;
virtual bool HasAuthenticator() const = 0;
virtual payments::MandatoryReauthAuthenticationMethod
GetAuthenticationMethod() const = 0;
bool IsMandatoryReauthEnabled() {
#if BUILDFLAG(IS_ANDROID)
if (base::android::BuildInfo::GetInstance()->is_automotive()) {
return true;
}
#endif
return PrefIsEnabled();
}
base::test::ScopedFeatureList feature_list_;
};
class CreditCardAccessManagerMandatoryReauthFunctionalTest
: public CreditCardAccessManagerMandatoryReauthTest,
public testing::WithParamInterface<
std::tuple<bool,
bool,
payments::MandatoryReauthAuthenticationMethod>> {
public:
CreditCardAccessManagerMandatoryReauthFunctionalTest() = default;
~CreditCardAccessManagerMandatoryReauthFunctionalTest() override = default;
bool PrefIsEnabled() const override { return std::get<0>(GetParam()); }
bool MandatoryReauthResponseIsSuccess() const override {
return std::get<1>(GetParam());
}
bool HasAuthenticator() const override {
return std::get<2>(GetParam()) !=
payments::MandatoryReauthAuthenticationMethod::kUnsupportedMethod;
}
payments::MandatoryReauthAuthenticationMethod GetAuthenticationMethod()
const override {
return std::get<2>(GetParam());
}
std::string GetStringForAuthenticationMethod() const {
switch (GetAuthenticationMethod()) {
case payments::MandatoryReauthAuthenticationMethod::kUnsupportedMethod:
return ".UnsupportedMethod";
case payments::MandatoryReauthAuthenticationMethod::kBiometric:
return ".Biometric";
case payments::MandatoryReauthAuthenticationMethod::kScreenLock:
return ".ScreenLock";
case payments::MandatoryReauthAuthenticationMethod::kUnknown:
NOTIMPLEMENTED();
return "";
}
}
};
TEST_P(CreditCardAccessManagerMandatoryReauthFunctionalTest,
MandatoryReauth_FetchLocalCard) {
base::HistogramTester histogram_tester;
CreateLocalCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
card->set_cvc(kTestCvc16);
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
SetUpDeviceAuthenticatorResponseMock();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
if (IsMandatoryReauthEnabled() && HasAuthenticator() &&
!MandatoryReauthResponseIsSuccess()) {
EXPECT_EQ(accessor_->result(), CreditCardFetchResult::kTransientError);
EXPECT_TRUE(accessor_->number().empty());
} else {
EXPECT_EQ(accessor_->result(), CreditCardFetchResult::kSuccess);
EXPECT_EQ(accessor_->number(), kTestNumber16);
EXPECT_EQ(accessor_->cvc(), kTestCvc16);
}
std::string reauth_usage_histogram_name =
"Autofill.PaymentMethods.CheckoutFlow.ReauthUsage.LocalCard";
reauth_usage_histogram_name += GetStringForAuthenticationMethod();
if (IsMandatoryReauthEnabled()) {
if (HasAuthenticator()) {
histogram_tester.ExpectBucketCount(
reauth_usage_histogram_name,
autofill_metrics::MandatoryReauthAuthenticationFlowEvent::
kFlowStarted,
1);
histogram_tester.ExpectBucketCount(
reauth_usage_histogram_name,
MandatoryReauthResponseIsSuccess()
? autofill_metrics::MandatoryReauthAuthenticationFlowEvent::
kFlowSucceeded
: autofill_metrics::MandatoryReauthAuthenticationFlowEvent::
kFlowFailed,
1);
histogram_tester.ExpectUniqueSample(
"Autofill.ServerCardUnmask.LocalCard.Result.DeviceUnlock",
MandatoryReauthResponseIsSuccess()
? autofill_metrics::ServerCardUnmaskResult::
kAuthenticationUnmasked
: autofill_metrics::ServerCardUnmaskResult::kAuthenticationError,
1);
} else {
histogram_tester.ExpectBucketCount(
reauth_usage_histogram_name,
autofill_metrics::MandatoryReauthAuthenticationFlowEvent::
kFlowSkipped,
1);
}
} else {
histogram_tester.ExpectBucketCount(
reauth_usage_histogram_name,
autofill_metrics::MandatoryReauthAuthenticationFlowEvent::kFlowStarted,
0);
}
}
TEST_P(CreditCardAccessManagerMandatoryReauthFunctionalTest,
MandatoryReauth_FetchVirtualCard) {
base::HistogramTester histogram_tester;
CreateServerCard(kTestGUID, kTestNumber, kTestServerId);
CreditCard* virtual_card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
virtual_card->set_record_type(CreditCard::RecordType::kVirtualCard);
credit_card_access_manager().FetchCreditCard(
virtual_card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
EXPECT_TRUE(autofill_client_.GetPaymentsAutofillClient()
->risk_based_authentication_invoked());
payments::PaymentsNetworkInterface::UnmaskResponseDetails response;
response.real_pan = "4111111111111111";
response.dcvv = "321";
response.expiration_month = test::NextMonth();
response.expiration_year = test::NextYear();
response.card_type = PaymentsRpcCardType::kVirtualCard;
SetUpDeviceAuthenticatorResponseMock();
credit_card_access_manager()
.OnVirtualCardRiskBasedAuthenticationResponseReceived(
PaymentsRpcResult::kSuccess, response);
if (IsMandatoryReauthEnabled() && HasAuthenticator() &&
!MandatoryReauthResponseIsSuccess()) {
EXPECT_EQ(accessor_->result(), CreditCardFetchResult::kTransientError);
} else {
EXPECT_EQ(accessor_->result(), CreditCardFetchResult::kSuccess);
EXPECT_EQ(accessor_->number(), u"4111111111111111");
EXPECT_EQ(accessor_->cvc(), u"321");
EXPECT_EQ(accessor_->expiry_month(), base::UTF8ToUTF16(test::NextMonth()));
EXPECT_EQ(accessor_->expiry_year(), base::UTF8ToUTF16(test::NextYear()));
}
std::string reauth_usage_histogram_name =
"Autofill.PaymentMethods.CheckoutFlow.ReauthUsage.VirtualCard";
reauth_usage_histogram_name += GetStringForAuthenticationMethod();
if (IsMandatoryReauthEnabled()) {
if (HasAuthenticator()) {
histogram_tester.ExpectBucketCount(
reauth_usage_histogram_name,
autofill_metrics::MandatoryReauthAuthenticationFlowEvent::
kFlowStarted,
1);
histogram_tester.ExpectBucketCount(
reauth_usage_histogram_name,
MandatoryReauthResponseIsSuccess()
? autofill_metrics::MandatoryReauthAuthenticationFlowEvent::
kFlowSucceeded
: autofill_metrics::MandatoryReauthAuthenticationFlowEvent::
kFlowFailed,
1);
histogram_tester.ExpectUniqueSample(
"Autofill.CvcStorage.CvcFilling.VirtualCard",
autofill_metrics::CvcFillingFlowType::kMandatoryReauth,
MandatoryReauthResponseIsSuccess() ? 1 : 0);
histogram_tester.ExpectUniqueSample(
"Autofill.ServerCardUnmask.VirtualCard.Result.DeviceUnlock",
MandatoryReauthResponseIsSuccess()
? autofill_metrics::ServerCardUnmaskResult::
kAuthenticationUnmasked
: autofill_metrics::ServerCardUnmaskResult::kAuthenticationError,
1);
} else {
histogram_tester.ExpectBucketCount(
reauth_usage_histogram_name,
autofill_metrics::MandatoryReauthAuthenticationFlowEvent::
kFlowSkipped,
1);
}
} else {
histogram_tester.ExpectBucketCount(
reauth_usage_histogram_name,
autofill_metrics::MandatoryReauthAuthenticationFlowEvent::kFlowStarted,
0);
}
}
TEST_P(CreditCardAccessManagerMandatoryReauthFunctionalTest,
MandatoryReauth_FetchMaskedServerCard) {
std::string test_number = "4444333322221111";
base::HistogramTester histogram_tester;
CreateServerCard(kTestGUID, test_number, kTestServerId);
CreditCard* masked_server_card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
credit_card_access_manager().FetchCreditCard(
masked_server_card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
EXPECT_TRUE(autofill_client_.GetPaymentsAutofillClient()
->risk_based_authentication_invoked());
CreditCard card = *masked_server_card;
card.set_record_type(CreditCard::RecordType::kFullServerCard);
SetUpDeviceAuthenticatorResponseMock();
credit_card_access_manager().OnRiskBasedAuthenticationResponseReceived(
CreditCardRiskBasedAuthenticator::RiskBasedAuthenticationResponse()
.with_result(CreditCardRiskBasedAuthenticator::
RiskBasedAuthenticationResponse::Result::
kNoAuthenticationRequired)
.with_card(card));
if (IsMandatoryReauthEnabled() && HasAuthenticator() &&
!MandatoryReauthResponseIsSuccess()) {
EXPECT_EQ(accessor_->result(), CreditCardFetchResult::kTransientError);
} else {
EXPECT_EQ(accessor_->result(), CreditCardFetchResult::kSuccess);
EXPECT_EQ(accessor_->number(), base::UTF8ToUTF16(test_number));
}
std::string reauth_usage_histogram_name =
"Autofill.PaymentMethods.CheckoutFlow.ReauthUsage.ServerCard";
reauth_usage_histogram_name += GetStringForAuthenticationMethod();
if (IsMandatoryReauthEnabled()) {
if (HasAuthenticator()) {
histogram_tester.ExpectBucketCount(
reauth_usage_histogram_name,
autofill_metrics::MandatoryReauthAuthenticationFlowEvent::
kFlowStarted,
1);
histogram_tester.ExpectBucketCount(
reauth_usage_histogram_name,
MandatoryReauthResponseIsSuccess()
? autofill_metrics::MandatoryReauthAuthenticationFlowEvent::
kFlowSucceeded
: autofill_metrics::MandatoryReauthAuthenticationFlowEvent::
kFlowFailed,
1);
histogram_tester.ExpectUniqueSample(
"Autofill.ServerCardUnmask.ServerCard.Result.DeviceUnlock",
MandatoryReauthResponseIsSuccess()
? autofill_metrics::ServerCardUnmaskResult::
kAuthenticationUnmasked
: autofill_metrics::ServerCardUnmaskResult::kAuthenticationError,
1);
} else {
histogram_tester.ExpectBucketCount(
reauth_usage_histogram_name,
autofill_metrics::MandatoryReauthAuthenticationFlowEvent::
kFlowSkipped,
1);
}
} else {
histogram_tester.ExpectBucketCount(
reauth_usage_histogram_name,
autofill_metrics::MandatoryReauthAuthenticationFlowEvent::kFlowStarted,
0);
}
}
INSTANTIATE_TEST_SUITE_P(
,
CreditCardAccessManagerMandatoryReauthFunctionalTest,
testing::Combine(
testing::Bool(),
testing::Bool(),
testing::Values(
payments::MandatoryReauthAuthenticationMethod::kUnsupportedMethod,
payments::MandatoryReauthAuthenticationMethod::kBiometric,
payments::MandatoryReauthAuthenticationMethod::kScreenLock)));
class CreditCardAccessManagerMandatoryReauthIntegrationTest
: public CreditCardAccessManagerMandatoryReauthTest,
public testing::WithParamInterface<bool> {
public:
CreditCardAccessManagerMandatoryReauthIntegrationTest() = default;
~CreditCardAccessManagerMandatoryReauthIntegrationTest() override = default;
protected:
bool PrefIsEnabled() const override { return true; }
bool MandatoryReauthResponseIsSuccess() const override { return GetParam(); }
bool HasAuthenticator() const override { return true; }
payments::MandatoryReauthAuthenticationMethod GetAuthenticationMethod()
const override {
return payments::MandatoryReauthAuthenticationMethod::kBiometric;
}
};
TEST_P(CreditCardAccessManagerMandatoryReauthIntegrationTest,
MandatoryReauth_FetchLocalCard_CvcFillWorksCorrectly) {
base::HistogramTester histogram_tester;
CreateLocalCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
SetUpDeviceAuthenticatorResponseMock();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
EXPECT_EQ(accessor_->cvc(),
MandatoryReauthResponseIsSuccess() ? kTestCvc16 : u"");
histogram_tester.ExpectBucketCount(
"Autofill.CvcStorage.CvcFilling.LocalCard",
autofill_metrics::CvcFillingFlowType::kMandatoryReauth,
MandatoryReauthResponseIsSuccess() ? 1 : 0);
}
TEST_P(CreditCardAccessManagerMandatoryReauthIntegrationTest,
MandatoryReauth_FetchLocalCard_NoCvcFillWorksCorrectly) {
base::HistogramTester histogram_tester;
CreateLocalCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
card->set_cvc(u"");
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
SetUpDeviceAuthenticatorResponseMock();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
EXPECT_EQ(accessor_->cvc(), u"");
histogram_tester.ExpectBucketCount(
"Autofill.CvcStorage.CvcFilling.LocalCard",
autofill_metrics::CvcFillingFlowType::kMandatoryReauth, 0);
}
TEST_P(CreditCardAccessManagerMandatoryReauthIntegrationTest,
MandatoryReauth_FetchMaskedServerCard_CvcFillWorksCorrectly) {
base::HistogramTester histogram_tester;
std::string test_number = "4444333322221111";
CreateServerCard(kTestGUID, test_number, kTestServerId);
CreditCard* masked_server_card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
credit_card_access_manager().FetchCreditCard(
masked_server_card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
SetUpDeviceAuthenticatorResponseMock();
credit_card_access_manager().OnRiskBasedAuthenticationResponseReceived(
CreditCardRiskBasedAuthenticator::RiskBasedAuthenticationResponse()
.with_result(CreditCardRiskBasedAuthenticator::
RiskBasedAuthenticationResponse::Result::
kNoAuthenticationRequired)
.with_card(*masked_server_card));
EXPECT_EQ(accessor_->cvc(),
MandatoryReauthResponseIsSuccess() ? kTestCvc16 : u"");
histogram_tester.ExpectBucketCount(
"Autofill.CvcStorage.CvcFilling.ServerCard",
autofill_metrics::CvcFillingFlowType::kMandatoryReauth,
MandatoryReauthResponseIsSuccess() ? 1 : 0);
}
TEST_P(CreditCardAccessManagerMandatoryReauthIntegrationTest,
MandatoryReauth_FetchMaskedServerCard_NoCvcFillWorksCorrectly) {
base::HistogramTester histogram_tester;
std::string test_number = "4444333322221111";
CreateServerCard(kTestGUID, test_number, kTestServerId);
CreditCard* masked_server_card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
masked_server_card->set_cvc(u"");
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
credit_card_access_manager().FetchCreditCard(
masked_server_card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
SetUpDeviceAuthenticatorResponseMock();
credit_card_access_manager().OnRiskBasedAuthenticationResponseReceived(
CreditCardRiskBasedAuthenticator::RiskBasedAuthenticationResponse()
.with_result(CreditCardRiskBasedAuthenticator::
RiskBasedAuthenticationResponse::Result::
kNoAuthenticationRequired)
.with_card(*masked_server_card));
EXPECT_EQ(accessor_->cvc(), u"");
histogram_tester.ExpectBucketCount(
"Autofill.CvcStorage.CvcFilling.ServerCard",
autofill_metrics::CvcFillingFlowType::kMandatoryReauth, 0);
}
INSTANTIATE_TEST_SUITE_P(,
CreditCardAccessManagerMandatoryReauthIntegrationTest,
testing::Bool());
#endif
TEST_F(CreditCardAccessManagerTest, FetchLocalCardSuccess) { … }
TEST_F(CreditCardAccessManagerTest, FetchNullptrFailure) { … }
TEST_F(CreditCardAccessManagerTest, FetchServerCardCVCSuccess) { … }
TEST_F(CreditCardAccessManagerTest, FetchServerCardCVCNetworkError) { … }
TEST_F(CreditCardAccessManagerTest, FetchServerCardCVCPermanentFailure) { … }
TEST_F(CreditCardAccessManagerTest, FetchServerCardCVCTryAgainFailure) { … }
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID)
class CreditCardAccessManagerBetterAuthLogTest
: public CreditCardAccessManagerTest,
public testing::WithParamInterface<std::tuple<bool, bool>> {
public:
CreditCardAccessManagerBetterAuthLogTest() = default;
~CreditCardAccessManagerBetterAuthLogTest() override = default;
bool HasServerCard() { return std::get<0>(GetParam()); }
bool IsUserOptedIn() { return std::get<1>(GetParam()); }
void SetUp() override {
ClearCards();
if (HasServerCard()) {
CreateServerCard(kTestGUID, kTestNumber);
} else {
CreateLocalCard(kTestGUID, kTestNumber);
}
CreditCardAccessManagerTest::SetUp();
}
const std::string kVerifiabilityCheckDurationMetrics =
"Autofill.BetterAuth.UserVerifiabilityCheckDuration";
const std::string kPreflightCallMetrics =
"Autofill.BetterAuth.CardUnmaskPreflightCalledWithFidoOptInStatus";
const std::string kPreflightLatencyMetrics =
"Autofill.BetterAuth.CardUnmaskPreflightDuration";
const std::string kPreflightFlowInitiatedMetrics =
"Autofill.BetterAuth.CardUnmaskPreflightInitiated";
};
TEST_P(CreditCardAccessManagerBetterAuthLogTest,
CardUnmaskPreflightCalledMetric_FidoEligible) {
base::HistogramTester histogram_tester;
auto* fido_authenticator = GetFIDOAuthenticator();
fido_authenticator->SetUserVerifiable(true);
fido_authenticator->set_is_user_opted_in(IsUserOptedIn());
ResetFetchCreditCard();
credit_card_access_manager().PrepareToFetchCreditCard();
InvokeUnmaskDetailsTimeout();
WaitForCallbacks();
histogram_tester.ExpectTotalCount(kVerifiabilityCheckDurationMetrics,
HasServerCard() ? 1 : 0);
if (HasServerCard()) {
histogram_tester.ExpectUniqueSample(kPreflightCallMetrics,
IsUserOptedIn(),
1);
} else {
histogram_tester.ExpectTotalCount(kPreflightCallMetrics,
0);
}
histogram_tester.ExpectTotalCount(kPreflightCallMetrics,
HasServerCard() ? 1 : 0);
histogram_tester.ExpectTotalCount(kPreflightLatencyMetrics,
HasServerCard() ? 1 : 0);
histogram_tester.ExpectTotalCount(kPreflightFlowInitiatedMetrics,
HasServerCard() ? 1 : 0);
}
TEST_P(CreditCardAccessManagerBetterAuthLogTest,
CardUnmaskPreflightCalledMetric_NotFidoEligible) {
base::HistogramTester histogram_tester;
GetFIDOAuthenticator()->SetUserVerifiable(false);
ResetFetchCreditCard();
credit_card_access_manager().PrepareToFetchCreditCard();
InvokeUnmaskDetailsTimeout();
WaitForCallbacks();
if (HasServerCard()) {
histogram_tester.ExpectUniqueSample(
kPreflightFlowInitiatedMetrics, true,
1);
histogram_tester.ExpectTotalCount(
kVerifiabilityCheckDurationMetrics,
1);
} else {
histogram_tester.ExpectTotalCount(kPreflightFlowInitiatedMetrics,
0);
histogram_tester.ExpectTotalCount(
kVerifiabilityCheckDurationMetrics,
0);
}
histogram_tester.ExpectTotalCount(
kPreflightCallMetrics,
0);
histogram_tester.ExpectTotalCount(kPreflightLatencyMetrics,
0);
}
INSTANTIATE_TEST_SUITE_P(,
CreditCardAccessManagerBetterAuthLogTest,
testing::Combine(testing::Bool(), testing::Bool()));
TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOSuccess) {
base::HistogramTester histogram_tester;
std::string unmask_decision_histogram_name =
"Autofill.BetterAuth.CardUnmaskTypeDecision";
std::string webauthn_result_histogram_name =
"Autofill.BetterAuth.WebauthnResult.ImmediateAuthentication";
std::string flow_events_histogram_name =
"Autofill.BetterAuth.FlowEvents.Fido";
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(true);
payments_network_interface().AddFidoEligibleCard(
card->server_id(), kCredentialId, kGooglePaymentsRpid);
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
WaitForCallbacks();
histogram_tester.ExpectUniqueSample(
flow_events_histogram_name,
CreditCardFormEventLogger::UnmaskAuthFlowEvent::kPromptShown, 1);
EXPECT_EQ(CreditCardFidoAuthenticator::Flow::AUTHENTICATION_FLOW,
GetFIDOAuthenticator()->current_flow());
TestCreditCardFidoAuthenticator::GetAssertion(GetFIDOAuthenticator(),
true);
EXPECT_TRUE(GetRealPanForFIDOAuth(PaymentsRpcResult::kSuccess, kTestNumber));
EXPECT_EQ(accessor_->result(), CreditCardFetchResult::kSuccess);
EXPECT_EQ(kCredentialId,
BytesToBase64(GetFIDOAuthenticator()->GetCredentialId()));
EXPECT_EQ(kTestNumber16, accessor_->number());
EXPECT_EQ(kTestCvc16, accessor_->cvc());
histogram_tester.ExpectUniqueSample(
unmask_decision_histogram_name,
autofill_metrics::CardUnmaskTypeDecisionMetric::kFidoOnly, 1);
histogram_tester.ExpectUniqueSample(
webauthn_result_histogram_name,
autofill_metrics::WebauthnResultMetric::kSuccess, 1);
histogram_tester.ExpectTotalCount(
"Autofill.BetterAuth.CardUnmaskDuration.Fido", 1);
histogram_tester.ExpectTotalCount(
"Autofill.BetterAuth.CardUnmaskDuration.Fido.ServerCard.Success", 1);
histogram_tester.ExpectBucketCount(
flow_events_histogram_name,
CreditCardFormEventLogger::UnmaskAuthFlowEvent::kPromptCompleted, 1);
}
TEST_F(CreditCardAccessManagerTest, LogCvcFillingFIDOSuccess) {
base::HistogramTester histogram_tester;
CreditCard server_card = test::WithCvc(test::GetMaskedServerCard());
personal_data().test_payments_data_manager().AddServerCreditCard(server_card);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByInstrumentId(
server_card.instrument_id());
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(true);
payments_network_interface().AddFidoEligibleCard(
card->server_id(), kCredentialId, kGooglePaymentsRpid);
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
WaitForCallbacks();
TestCreditCardFidoAuthenticator::GetAssertion(GetFIDOAuthenticator(),
true);
EXPECT_TRUE(GetRealPanForFIDOAuth(PaymentsRpcResult::kSuccess, kTestNumber));
histogram_tester.ExpectUniqueSample(
"Autofill.CvcStorage.CvcFilling.ServerCard",
autofill_metrics::CvcFillingFlowType::kFido, 1);
}
TEST_F(CreditCardAccessManagerTest, DoNotLogCvcFillingFIDOSuccess) {
base::HistogramTester histogram_tester;
CreditCard server_card = test::GetMaskedServerCard();
server_card.set_cvc(u"");
personal_data().test_payments_data_manager().AddServerCreditCard(server_card);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByInstrumentId(
server_card.instrument_id());
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(true);
payments_network_interface().AddFidoEligibleCard(
card->server_id(), kCredentialId, kGooglePaymentsRpid);
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
WaitForCallbacks();
TestCreditCardFidoAuthenticator::GetAssertion(GetFIDOAuthenticator(),
true);
EXPECT_TRUE(GetRealPanForFIDOAuth(PaymentsRpcResult::kSuccess, kTestNumber));
histogram_tester.ExpectUniqueSample(
"Autofill.CvcStorage.CvcFilling.ServerCard",
autofill_metrics::CvcFillingFlowType::kFido, 0);
}
TEST_F(CreditCardAccessManagerTest,
LogCvcFillingWithoutInteractiveAuthentication) {
base::HistogramTester histogram_tester;
CreditCard local_card = test::WithCvc(test::GetCreditCard());
personal_data().payments_data_manager().AddCreditCard(local_card);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(
local_card.guid());
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
histogram_tester.ExpectUniqueSample(
"Autofill.CvcStorage.CvcFilling.LocalCard",
autofill_metrics::CvcFillingFlowType::kNoInteractiveAuthentication, 1);
}
TEST_F(CreditCardAccessManagerTest,
DoNotLogCvcFillingWithoutInteractiveAuthentication) {
base::HistogramTester histogram_tester;
CreditCard local_card = test::GetCreditCard();
personal_data().payments_data_manager().AddCreditCard(local_card);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(
local_card.guid());
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
histogram_tester.ExpectUniqueSample(
"Autofill.CvcStorage.CvcFilling.LocalCard",
autofill_metrics::CvcFillingFlowType::kNoInteractiveAuthentication, 0);
}
TEST_F(CreditCardAccessManagerTest, FetchServerCardWithoutCvcFIDOSuccess) {
CreditCard server_card = CreditCard();
test::SetCreditCardInfo(&server_card, "Elvis Presley", kTestNumber,
test::NextMonth().c_str(), test::NextYear().c_str(),
"1", u"");
server_card.set_guid(kTestGUID);
server_card.set_record_type(CreditCard::RecordType::kMaskedServerCard);
personal_data().test_payments_data_manager().AddServerCreditCard(server_card);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(true);
payments_network_interface().AddFidoEligibleCard(
card->server_id(), kCredentialId, kGooglePaymentsRpid);
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
WaitForCallbacks();
EXPECT_EQ(CreditCardFidoAuthenticator::Flow::AUTHENTICATION_FLOW,
GetFIDOAuthenticator()->current_flow());
TestCreditCardFidoAuthenticator::GetAssertion(GetFIDOAuthenticator(),
true);
EXPECT_TRUE(GetRealPanForFIDOAuth(PaymentsRpcResult::kSuccess, kTestNumber));
EXPECT_EQ(u"", accessor_->cvc());
}
TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOSuccessWithDcvv) {
prefs::SetCreditCardFIDOAuthEnabled(autofill_client_.GetPrefs(), true);
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
payments_network_interface().AddFidoEligibleCard(
card->server_id(), kCredentialId, kGooglePaymentsRpid);
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
WaitForCallbacks();
TestCreditCardFidoAuthenticator::GetAssertion(GetFIDOAuthenticator(),
true);
EXPECT_TRUE(GetRealPanForFIDOAuth(PaymentsRpcResult::kSuccess, kTestNumber,
kTestCvc));
EXPECT_EQ(accessor_->result(), CreditCardFetchResult::kSuccess);
EXPECT_EQ(kTestNumber16, accessor_->number());
EXPECT_EQ(kTestCvc16, accessor_->cvc());
}
TEST_F(CreditCardAccessManagerTest,
FetchServerCardFIDOVerificationFailureCVCFallback) {
base::HistogramTester histogram_tester;
std::string webauthn_result_histogram_name =
"Autofill.BetterAuth.WebauthnResult.ImmediateAuthentication";
std::string flow_events_fido_histogram_name =
"Autofill.BetterAuth.FlowEvents.Fido";
std::string flow_events_cvc_fallback_histogram_name =
"Autofill.BetterAuth.FlowEvents.CvcFallbackFromFido";
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(true);
payments_network_interface().AddFidoEligibleCard(
card->server_id(), kCredentialId, kGooglePaymentsRpid);
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
WaitForCallbacks();
histogram_tester.ExpectUniqueSample(
flow_events_fido_histogram_name,
CreditCardFormEventLogger::UnmaskAuthFlowEvent::kPromptShown, 1);
EXPECT_EQ(CreditCardFidoAuthenticator::Flow::AUTHENTICATION_FLOW,
GetFIDOAuthenticator()->current_flow());
TestCreditCardFidoAuthenticator::GetAssertion(GetFIDOAuthenticator(),
false);
histogram_tester.ExpectBucketCount(
flow_events_cvc_fallback_histogram_name,
CreditCardFormEventLogger::UnmaskAuthFlowEvent::kPromptShown, 1);
EXPECT_FALSE(GetRealPanForFIDOAuth(PaymentsRpcResult::kSuccess, kTestNumber));
EXPECT_NE(accessor_->result(), CreditCardFetchResult::kSuccess);
EXPECT_EQ(CreditCardFidoAuthenticator::Flow::NONE_FLOW,
GetFIDOAuthenticator()->current_flow());
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber));
EXPECT_EQ(accessor_->result(), CreditCardFetchResult::kSuccess);
EXPECT_EQ(kTestNumber16, accessor_->number());
EXPECT_EQ(kTestCvc16, accessor_->cvc());
histogram_tester.ExpectUniqueSample(
webauthn_result_histogram_name,
autofill_metrics::WebauthnResultMetric::kNotAllowedError, 1);
histogram_tester.ExpectBucketCount(
flow_events_fido_histogram_name,
CreditCardFormEventLogger::UnmaskAuthFlowEvent::kPromptCompleted, 0);
histogram_tester.ExpectBucketCount(
flow_events_cvc_fallback_histogram_name,
CreditCardFormEventLogger::UnmaskAuthFlowEvent::kPromptCompleted, 1);
}
TEST_F(CreditCardAccessManagerTest,
FetchServerCardFIDOServerFailureCVCFallback) {
base::HistogramTester histogram_tester;
std::string histogram_name =
"Autofill.BetterAuth.WebauthnResult.ImmediateAuthentication";
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(true);
payments_network_interface().AddFidoEligibleCard(
card->server_id(), kCredentialId, kGooglePaymentsRpid);
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
WaitForCallbacks();
EXPECT_EQ(CreditCardFidoAuthenticator::Flow::AUTHENTICATION_FLOW,
GetFIDOAuthenticator()->current_flow());
TestCreditCardFidoAuthenticator::GetAssertion(GetFIDOAuthenticator(),
true);
EXPECT_TRUE(
GetRealPanForFIDOAuth(PaymentsRpcResult::kPermanentFailure, kTestNumber));
EXPECT_NE(accessor_->result(), CreditCardFetchResult::kSuccess);
EXPECT_EQ(CreditCardFidoAuthenticator::Flow::NONE_FLOW,
GetFIDOAuthenticator()->current_flow());
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber));
EXPECT_EQ(accessor_->result(), CreditCardFetchResult::kSuccess);
EXPECT_EQ(kTestNumber16, accessor_->number());
EXPECT_EQ(kTestCvc16, accessor_->cvc());
histogram_tester.ExpectUniqueSample(
histogram_name, autofill_metrics::WebauthnResultMetric::kSuccess, 1);
histogram_tester.ExpectTotalCount(
"Autofill.BetterAuth.CardUnmaskDuration.Fido", 1);
histogram_tester.ExpectTotalCount(
"Autofill.BetterAuth.CardUnmaskDuration.Fido.ServerCard.Failure", 1);
}
TEST_F(CreditCardAccessManagerTest,
FetchServerCardBadRequestOptionsCVCFallback) {
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(true);
payments_network_interface().AddFidoEligibleCard(
card->server_id(), "", kGooglePaymentsRpid);
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
WaitForCallbacks();
EXPECT_FALSE(GetRealPanForFIDOAuth(PaymentsRpcResult::kSuccess, kTestNumber));
EXPECT_NE(accessor_->result(), CreditCardFetchResult::kSuccess);
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber));
EXPECT_EQ(accessor_->result(), CreditCardFetchResult::kSuccess);
EXPECT_EQ(kTestNumber16, accessor_->number());
EXPECT_EQ(kTestCvc16, accessor_->cvc());
}
TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOTimeoutCVCFallback) {
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(true);
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
InvokeUnmaskDetailsTimeout();
WaitForCallbacks();
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber));
EXPECT_EQ(accessor_->result(), CreditCardFetchResult::kSuccess);
EXPECT_EQ(kTestNumber16, accessor_->number());
EXPECT_EQ(kTestCvc16, accessor_->cvc());
}
TEST_F(CreditCardAccessManagerTest,
Metrics_LoggingExistenceOfUserPerceivedLatency) {
std::string server_guid = "00000000-0000-0000-0000-000000000001";
std::string local_guid = "00000000-0000-0000-0000-000000000003";
CreateServerCard(server_guid, "4594299181086168");
CreateLocalCard(local_guid, "4409763681177079");
CreditCard* server_card =
personal_data().payments_data_manager().GetCreditCardByGUID(server_guid);
CreditCard* local_card =
personal_data().payments_data_manager().GetCreditCardByGUID(local_guid);
GetFIDOAuthenticator()->SetUserVerifiable(true);
for (bool user_is_opted_in : {true, false}) {
std::string histogram_name =
"Autofill.BetterAuth.UserPerceivedLatencyOnCardSelection.";
histogram_name += user_is_opted_in ? "OptedIn" : "OptedOut";
SetCreditCardFIDOAuthEnabled(user_is_opted_in);
{
base::HistogramTester histogram_tester;
ResetFetchCreditCard();
credit_card_access_manager().PrepareToFetchCreditCard();
task_environment_.FastForwardBy(base::Seconds(4));
WaitForCallbacks();
credit_card_access_manager().FetchCreditCard(
local_card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
WaitForCallbacks();
histogram_tester.ExpectUniqueSample(
histogram_name,
autofill_metrics::PreflightCallEvent::kDidNotChooseMaskedCard, 1);
}
{
base::HistogramTester histogram_tester;
payments_network_interface().ShouldReturnUnmaskDetailsImmediately(false);
ResetFetchCreditCard();
credit_card_access_manager().PrepareToFetchCreditCard();
credit_card_access_manager().FetchCreditCard(
server_card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
task_environment_.FastForwardBy(base::Seconds(4));
WaitForCallbacks();
histogram_tester.ExpectUniqueSample(
histogram_name,
autofill_metrics::PreflightCallEvent::
kCardChosenBeforePreflightCallReturned,
1);
histogram_tester.ExpectTotalCount(
"Autofill.BetterAuth.UserPerceivedLatencyOnCardSelection.OptedIn."
"Duration",
static_cast<int>(user_is_opted_in));
histogram_tester.ExpectTotalCount(
"Autofill.BetterAuth.UserPerceivedLatencyOnCardSelection.OptedIn."
"TimedOutCvcFallback",
static_cast<int>(user_is_opted_in));
}
{
base::HistogramTester histogram_tester;
payments_network_interface().AllowFidoRegistration(!user_is_opted_in);
ResetFetchCreditCard();
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
credit_card_access_manager().FetchCreditCard(
server_card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
WaitForCallbacks();
histogram_tester.ExpectUniqueSample(
histogram_name,
autofill_metrics::PreflightCallEvent::
kPreflightCallReturnedBeforeCardChosen,
1);
}
}
}
TEST_F(CreditCardAccessManagerTest, Metrics_LoggingTimedOutCvcFallback) {
std::string server_guid = "00000000-0000-0000-0000-000000000001";
CreateServerCard(server_guid, "4594299181086168");
CreditCard* server_card =
personal_data().payments_data_manager().GetCreditCardByGUID(server_guid);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(true);
payments_network_interface().ShouldReturnUnmaskDetailsImmediately(false);
std::string existence_perceived_latency_histogram_name =
"Autofill.BetterAuth.UserPerceivedLatencyOnCardSelection.OptedIn";
std::string perceived_latency_duration_histogram_name =
"Autofill.BetterAuth.UserPerceivedLatencyOnCardSelection.OptedIn."
"Duration";
std::string timeout_cvc_fallback_histogram_name =
"Autofill.BetterAuth.UserPerceivedLatencyOnCardSelection.OptedIn."
"TimedOutCvcFallback";
{
base::HistogramTester histogram_tester;
ResetFetchCreditCard();
credit_card_access_manager().PrepareToFetchCreditCard();
credit_card_access_manager().FetchCreditCard(
server_card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
InvokeDelayedGetUnmaskDetailsResponse();
task_environment_.FastForwardBy(base::Seconds(4));
WaitForCallbacks();
histogram_tester.ExpectUniqueSample(
existence_perceived_latency_histogram_name,
autofill_metrics::PreflightCallEvent::
kCardChosenBeforePreflightCallReturned,
1);
histogram_tester.ExpectTotalCount(perceived_latency_duration_histogram_name,
1);
histogram_tester.ExpectBucketCount(timeout_cvc_fallback_histogram_name,
false, 1);
}
{
base::HistogramTester histogram_tester;
ResetFetchCreditCard();
credit_card_access_manager().PrepareToFetchCreditCard();
credit_card_access_manager().FetchCreditCard(
server_card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
task_environment_.FastForwardBy(base::Seconds(4));
WaitForCallbacks();
histogram_tester.ExpectUniqueSample(
existence_perceived_latency_histogram_name,
autofill_metrics::PreflightCallEvent::
kCardChosenBeforePreflightCallReturned,
1);
histogram_tester.ExpectTotalCount(perceived_latency_duration_histogram_name,
1);
histogram_tester.ExpectBucketCount(timeout_cvc_fallback_histogram_name,
true, 1);
}
}
TEST_F(CreditCardAccessManagerTest, FIDONewCardAuthorization) {
base::HistogramTester histogram_tester;
std::string unmask_decision_histogram_name =
"Autofill.BetterAuth.CardUnmaskTypeDecision";
std::string webauthn_result_histogram_name =
"Autofill.BetterAuth.WebauthnResult.AuthenticationAfterCVC";
std::string flow_events_histogram_name =
"Autofill.BetterAuth.FlowEvents.CvcThenFido";
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
OptUserInToFido();
payments_network_interface().ShouldReturnUnmaskDetailsImmediately(true);
payments_network_interface().SetFidoRequestOptionsInUnmaskDetails(
kCredentialId, kGooglePaymentsRpid);
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
InvokeUnmaskDetailsTimeout();
WaitForCallbacks();
histogram_tester.ExpectUniqueSample(
flow_events_histogram_name,
CreditCardFormEventLogger::UnmaskAuthFlowEvent::kPromptShown, 1);
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber,
TestFidoRequestOptionsType::kNotPresent));
EXPECT_EQ(accessor_->number(), std::u16string());
EXPECT_EQ(accessor_->cvc(), std::u16string());
EXPECT_EQ(CreditCardFidoAuthenticator::Flow::FOLLOWUP_AFTER_CVC_AUTH_FLOW,
GetFIDOAuthenticator()->current_flow());
TestCreditCardFidoAuthenticator::GetAssertion(GetFIDOAuthenticator(),
true);
EXPECT_EQ(kTestNumber16, accessor_->number());
EXPECT_EQ(kTestCvc16, accessor_->cvc());
OptChange(PaymentsRpcResult::kSuccess, true);
histogram_tester.ExpectUniqueSample(
unmask_decision_histogram_name,
autofill_metrics::CardUnmaskTypeDecisionMetric::kCvcThenFido, 1);
histogram_tester.ExpectUniqueSample(
webauthn_result_histogram_name,
autofill_metrics::WebauthnResultMetric::kSuccess, 1);
histogram_tester.ExpectBucketCount(
flow_events_histogram_name,
CreditCardFormEventLogger::UnmaskAuthFlowEvent::kPromptCompleted, 1);
}
TEST_F(CreditCardAccessManagerTest,
FIDONewCardAuthorization_NoRequestOptions_FormFilled) {
CreditCard* card = CreateServerCard(kTestGUID, kTestNumber);
OptUserInToFido();
payments_network_interface().unmask_details()->fido_request_options.clear();
payments_network_interface().ShouldReturnUnmaskDetailsImmediately(true);
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
InvokeUnmaskDetailsTimeout();
WaitForCallbacks();
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber,
TestFidoRequestOptionsType::kNotPresent));
EXPECT_EQ(accessor_->number(), kTestNumber16);
EXPECT_EQ(accessor_->cvc(), kTestCvc16);
}
TEST_F(CreditCardAccessManagerTest,
FIDONewCardAuthorization_InvalidRequestOptions_FormFilled) {
CreditCard* card = CreateServerCard(kTestGUID, kTestNumber);
OptUserInToFido();
payments_network_interface().ShouldReturnUnmaskDetailsImmediately(true);
payments_network_interface().SetFidoRequestOptionsInUnmaskDetails(
"", "");
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
InvokeUnmaskDetailsTimeout();
WaitForCallbacks();
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber,
TestFidoRequestOptionsType::kNotPresent));
EXPECT_EQ(accessor_->number(), kTestNumber16);
EXPECT_EQ(accessor_->cvc(), kTestCvc16);
}
TEST_F(CreditCardAccessManagerTest, FetchExpiredServerCardInvokesCvcPrompt) {
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
card->SetExpirationYearFromString(u"2010");
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(true);
payments_network_interface().AddFidoEligibleCard(
card->server_id(), kCredentialId, kGooglePaymentsRpid);
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
WaitForCallbacks();
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber));
EXPECT_EQ(kTestNumber16, accessor_->number());
EXPECT_EQ(kTestCvc16, accessor_->cvc());
}
#if BUILDFLAG(IS_ANDROID)
TEST_F(CreditCardAccessManagerTest, FIDOOptInSuccess_Android) {
base::HistogramTester histogram_tester;
std::string histogram_name =
"Autofill.BetterAuth.WebauthnResult.CheckoutOptIn";
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(false);
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
InvokeUnmaskDetailsTimeout();
WaitForCallbacks();
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber,
TestFidoRequestOptionsType::kValid));
WaitForCallbacks();
EXPECT_EQ(CreditCardFidoAuthenticator::Flow::OPT_IN_WITH_CHALLENGE_FLOW,
GetFIDOAuthenticator()->current_flow());
EXPECT_EQ(accessor_->number(), std::u16string());
EXPECT_EQ(accessor_->cvc(), std::u16string());
TestCreditCardFidoAuthenticator::GetAssertion(GetFIDOAuthenticator(),
true);
EXPECT_EQ(kTestNumber16, accessor_->number());
EXPECT_EQ(kTestCvc16, accessor_->cvc());
OptChange(PaymentsRpcResult::kSuccess,
true);
EXPECT_EQ(kGooglePaymentsRpid, GetFIDOAuthenticator()->GetRelyingPartyId());
EXPECT_EQ(kTestChallenge,
BytesToBase64(GetFIDOAuthenticator()->GetChallenge()));
EXPECT_TRUE(GetFIDOAuthenticator()->IsUserOptedIn());
histogram_tester.ExpectUniqueSample(
histogram_name, autofill_metrics::WebauthnResultMetric::kSuccess, 1);
}
TEST_F(CreditCardAccessManagerTest,
FIDOOptInFailure_InvalidResponseRequestOptions) {
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(false);
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
InvokeUnmaskDetailsTimeout();
WaitForCallbacks();
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber,
TestFidoRequestOptionsType::kInvalid));
WaitForCallbacks();
EXPECT_EQ(accessor_->number(), kTestNumber16);
EXPECT_EQ(accessor_->cvc(), kTestCvc16);
}
TEST_F(CreditCardAccessManagerTest, FIDOOptInUserVerificationFailure) {
base::HistogramTester histogram_tester;
std::string histogram_name =
"Autofill.BetterAuth.WebauthnResult.CheckoutOptIn";
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(false);
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
InvokeUnmaskDetailsTimeout();
WaitForCallbacks();
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber,
TestFidoRequestOptionsType::kValid));
EXPECT_EQ(CreditCardFidoAuthenticator::Flow::OPT_IN_WITH_CHALLENGE_FLOW,
GetFIDOAuthenticator()->current_flow());
EXPECT_EQ(accessor_->number(), std::u16string());
EXPECT_EQ(accessor_->cvc(), std::u16string());
TestCreditCardFidoAuthenticator::GetAssertion(GetFIDOAuthenticator(),
false);
EXPECT_EQ(kTestNumber16, accessor_->number());
EXPECT_EQ(kTestCvc16, accessor_->cvc());
EXPECT_FALSE(GetFIDOAuthenticator()->IsUserOptedIn());
histogram_tester.ExpectUniqueSample(
histogram_name, autofill_metrics::WebauthnResultMetric::kNotAllowedError,
1);
}
TEST_F(CreditCardAccessManagerTest, FIDOOptInServerFailure) {
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(false);
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
InvokeUnmaskDetailsTimeout();
WaitForCallbacks();
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber,
TestFidoRequestOptionsType::kValid));
EXPECT_EQ(CreditCardFidoAuthenticator::Flow::OPT_IN_WITH_CHALLENGE_FLOW,
GetFIDOAuthenticator()->current_flow());
EXPECT_EQ(accessor_->number(), std::u16string());
EXPECT_EQ(accessor_->cvc(), std::u16string());
TestCreditCardFidoAuthenticator::GetAssertion(GetFIDOAuthenticator(),
true);
EXPECT_EQ(kTestNumber16, accessor_->number());
EXPECT_EQ(kTestCvc16, accessor_->cvc());
OptChange(PaymentsRpcResult::kPermanentFailure, false);
EXPECT_FALSE(GetFIDOAuthenticator()->IsUserOptedIn());
}
TEST_F(CreditCardAccessManagerTest, FIDOOptIn_CheckboxDeclined) {
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(false);
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
InvokeUnmaskDetailsTimeout();
WaitForCallbacks();
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber,
TestFidoRequestOptionsType::kNotPresent));
EXPECT_EQ(kTestNumber16, accessor_->number());
EXPECT_EQ(kTestCvc16, accessor_->cvc());
EXPECT_EQ(CreditCardFidoAuthenticator::Flow::NONE_FLOW,
GetFIDOAuthenticator()->current_flow());
EXPECT_FALSE(GetFIDOAuthenticator()->IsUserOptedIn());
}
TEST_F(CreditCardAccessManagerTest, FIDOSettingsPageOptInSuccess_Android) {
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(true);
payments_network_interface().AllowFidoRegistration(true);
payments_network_interface().ShouldReturnUnmaskDetailsImmediately(true);
credit_card_access_manager().PrepareToFetchCreditCard();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
InvokeUnmaskDetailsTimeout();
WaitForCallbacks();
MockUserResponseForCvcAuth(kTestCvc16, false);
EXPECT_TRUE(payments_network_interface()
.unmask_request()
->user_response.enable_fido_auth);
}
#else
TEST_F(CreditCardAccessManagerTest,
FIDOEnrollmentSuccess_CreationOptions_Desktop) {
base::HistogramTester histogram_tester;
std::string webauthn_result_histogram_name =
"Autofill.BetterAuth.WebauthnResult.CheckoutOptIn";
std::string opt_in_histogram_name =
"Autofill.BetterAuth.OptInCalled.FromCheckoutFlow";
std::string promo_shown_histogram_name =
"Autofill.BetterAuth.OptInPromoShown.FromCheckoutFlow";
std::string promo_user_decision_histogram_name =
"Autofill.BetterAuth.OptInPromoUserDecision.FromCheckoutFlow";
ClearStrikes();
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(false);
payments_network_interface().AllowFidoRegistration(true);
credit_card_access_manager().PrepareToFetchCreditCard();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
WaitForCallbacks();
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber));
AcceptWebauthnOfferDialog(true);
OptChange(PaymentsRpcResult::kSuccess,
false,
true);
EXPECT_EQ(CreditCardFidoAuthenticator::Flow::OPT_IN_WITH_CHALLENGE_FLOW,
GetFIDOAuthenticator()->current_flow());
TestCreditCardFidoAuthenticator::MakeCredential(GetFIDOAuthenticator(),
true);
OptChange(PaymentsRpcResult::kSuccess,
true);
EXPECT_EQ(kGooglePaymentsRpid, GetFIDOAuthenticator()->GetRelyingPartyId());
EXPECT_EQ(kTestChallenge,
BytesToBase64(GetFIDOAuthenticator()->GetChallenge()));
EXPECT_TRUE(GetFIDOAuthenticator()->IsUserOptedIn());
EXPECT_EQ(0, GetStrikes());
histogram_tester.ExpectUniqueSample(
webauthn_result_histogram_name,
autofill_metrics::WebauthnResultMetric::kSuccess, 1);
histogram_tester.ExpectTotalCount(opt_in_histogram_name, 2);
histogram_tester.ExpectBucketCount(
opt_in_histogram_name,
autofill_metrics::WebauthnOptInParameters::kFetchingChallenge, 1);
histogram_tester.ExpectBucketCount(
opt_in_histogram_name,
autofill_metrics::WebauthnOptInParameters::kWithCreationChallenge, 1);
histogram_tester.ExpectTotalCount(promo_shown_histogram_name, 1);
histogram_tester.ExpectUniqueSample(
promo_user_decision_histogram_name,
autofill_metrics::WebauthnOptInPromoUserDecisionMetric::kAccepted, 1);
}
TEST_F(CreditCardAccessManagerTest, FIDOEnrollment_OfferDeclined_Desktop) {
base::HistogramTester histogram_tester;
std::string promo_shown_histogram_name =
"Autofill.BetterAuth.OptInPromoShown.FromCheckoutFlow";
std::string promo_user_decision_histogram_name =
"Autofill.BetterAuth.OptInPromoUserDecision.FromCheckoutFlow";
ClearStrikes();
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(false);
payments_network_interface().AllowFidoRegistration(true);
credit_card_access_manager().PrepareToFetchCreditCard();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
WaitForCallbacks();
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber));
AcceptWebauthnOfferDialog(false);
EXPECT_EQ(
FidoAuthenticationStrikeDatabase::kStrikesToAddWhenOptInOfferDeclined,
GetStrikes());
histogram_tester.ExpectTotalCount(promo_shown_histogram_name, 1);
histogram_tester.ExpectUniqueSample(
promo_user_decision_histogram_name,
autofill_metrics::WebauthnOptInPromoUserDecisionMetric::
kDeclinedImmediately,
1);
}
TEST_F(CreditCardAccessManagerTest,
FIDOEnrollment_OfferDeclinedAfterAccepting_Desktop) {
base::HistogramTester histogram_tester;
std::string promo_shown_histogram_name =
"Autofill.BetterAuth.OptInPromoShown.FromCheckoutFlow";
std::string promo_user_decision_histogram_name =
"Autofill.BetterAuth.OptInPromoUserDecision.FromCheckoutFlow";
ClearStrikes();
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(false);
payments_network_interface().AllowFidoRegistration(true);
credit_card_access_manager().PrepareToFetchCreditCard();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
WaitForCallbacks();
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber));
AcceptWebauthnOfferDialog(true);
AcceptWebauthnOfferDialog(false);
EXPECT_EQ(
FidoAuthenticationStrikeDatabase::kStrikesToAddWhenOptInOfferDeclined,
GetStrikes());
histogram_tester.ExpectTotalCount(promo_shown_histogram_name, 1);
histogram_tester.ExpectUniqueSample(
promo_user_decision_histogram_name,
autofill_metrics::WebauthnOptInPromoUserDecisionMetric::
kDeclinedAfterAccepting,
1);
}
TEST_F(CreditCardAccessManagerTest,
FIDOEnrollment_UserVerificationFailed_Desktop) {
base::HistogramTester histogram_tester;
std::string webauthn_result_histogram_name =
"Autofill.BetterAuth.WebauthnResult.CheckoutOptIn";
std::string opt_in_histogram_name =
"Autofill.BetterAuth.OptInCalled.FromCheckoutFlow";
ClearStrikes();
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(false);
payments_network_interface().AllowFidoRegistration(true);
credit_card_access_manager().PrepareToFetchCreditCard();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
InvokeUnmaskDetailsTimeout();
WaitForCallbacks();
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber));
WaitForCallbacks();
AcceptWebauthnOfferDialog(true);
OptChange(PaymentsRpcResult::kSuccess,
false,
true);
TestCreditCardFidoAuthenticator::MakeCredential(GetFIDOAuthenticator(),
false);
EXPECT_EQ(FidoAuthenticationStrikeDatabase::
kStrikesToAddWhenUserVerificationFailsOnOptInAttempt,
GetStrikes());
histogram_tester.ExpectUniqueSample(
webauthn_result_histogram_name,
autofill_metrics::WebauthnResultMetric::kNotAllowedError, 1);
histogram_tester.ExpectUniqueSample(
opt_in_histogram_name,
autofill_metrics::WebauthnOptInParameters::kFetchingChallenge, 1);
}
TEST_F(CreditCardAccessManagerTest,
FIDOEnrollmentSuccess_RequestOptions_Desktop) {
base::HistogramTester histogram_tester;
std::string webauthn_result_histogram_name =
"Autofill.BetterAuth.WebauthnResult.CheckoutOptIn";
std::string opt_in_histogram_name =
"Autofill.BetterAuth.OptInCalled.FromCheckoutFlow";
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(false);
payments_network_interface().AllowFidoRegistration(true);
credit_card_access_manager().PrepareToFetchCreditCard();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
WaitForCallbacks();
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber));
WaitForCallbacks();
AcceptWebauthnOfferDialog(true);
OptChange(PaymentsRpcResult::kSuccess,
false,
false,
true);
EXPECT_EQ(CreditCardFidoAuthenticator::Flow::OPT_IN_WITH_CHALLENGE_FLOW,
GetFIDOAuthenticator()->current_flow());
TestCreditCardFidoAuthenticator::GetAssertion(GetFIDOAuthenticator(),
true);
OptChange(PaymentsRpcResult::kSuccess,
true);
EXPECT_EQ(kGooglePaymentsRpid, GetFIDOAuthenticator()->GetRelyingPartyId());
EXPECT_EQ(kTestChallenge,
BytesToBase64(GetFIDOAuthenticator()->GetChallenge()));
EXPECT_TRUE(GetFIDOAuthenticator()->IsUserOptedIn());
histogram_tester.ExpectUniqueSample(
webauthn_result_histogram_name,
autofill_metrics::WebauthnResultMetric::kSuccess, 1);
histogram_tester.ExpectTotalCount(opt_in_histogram_name, 2);
histogram_tester.ExpectBucketCount(
opt_in_histogram_name,
autofill_metrics::WebauthnOptInParameters::kFetchingChallenge, 1);
histogram_tester.ExpectBucketCount(
opt_in_histogram_name,
autofill_metrics::WebauthnOptInParameters::kWithRequestChallenge, 1);
}
TEST_F(CreditCardAccessManagerTest, SettingsPage_OptOut) {
base::HistogramTester histogram_tester;
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(true);
EXPECT_TRUE(IsCreditCardFIDOAuthEnabled());
credit_card_access_manager().OnSettingsPageFIDOAuthToggled(false);
EXPECT_TRUE(GetFIDOAuthenticator()->IsOptOutCalled());
OptChange(PaymentsRpcResult::kSuccess,
false);
EXPECT_FALSE(IsCreditCardFIDOAuthEnabled());
}
#endif
class CreditCardAccessManagerBetterAuthOptInLogTest
: public CreditCardAccessManagerTest,
public testing::WithParamInterface<
std::tuple<bool, bool, bool, bool, bool, bool>> {
public:
CreditCardAccessManagerBetterAuthOptInLogTest() = default;
~CreditCardAccessManagerBetterAuthOptInLogTest() override = default;
void SetUp() override {
CreditCardAccessManagerTest::SetUp();
if (MaxStrikesLimitReached()) {
AddMaxStrikes();
} else {
ClearStrikes();
}
CreateServerCard(kTestGUID, kTestNumber);
GetFIDOAuthenticator()->SetUserVerifiable(true);
#if BUILDFLAG(IS_ANDROID)
SetCreditCardFIDOAuthEnabled(HasOptedInFromAndroidSettings());
#else
SetCreditCardFIDOAuthEnabled(false);
#endif
payments_network_interface().AllowFidoRegistration(
UnmaskDetailsOfferFidoOptIn());
if (IsVirtualCard()) {
GetCreditCard()->set_record_type(CreditCard::RecordType::kVirtualCard);
}
if (IsOptedIntoFido()) {
payments_network_interface().AddFidoEligibleCard(
"random_id", kCredentialId, kGooglePaymentsRpid);
}
credit_card_access_manager().PrepareToFetchCreditCard();
credit_card_access_manager().FetchCreditCard(
GetCreditCard(), base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
}
bool IsVirtualCard() { return std::get<0>(GetParam()); }
bool UnmaskDetailsOfferFidoOptIn() { return std::get<1>(GetParam()); }
bool CardAuthorizationTokenPresent() { return std::get<2>(GetParam()); }
bool MaxStrikesLimitReached() { return std::get<3>(GetParam()); }
bool HasOptedInFromAndroidSettings() { return std::get<4>(GetParam()); }
bool IsOptedIntoFido() { return std::get<5>(GetParam()); }
bool ShouldOfferFidoOptIn() {
return !IsOptedIntoFido() && !IsVirtualCard() &&
UnmaskDetailsOfferFidoOptIn() && CardAuthorizationTokenPresent() &&
!MaxStrikesLimitReached();
}
bool ShouldOfferFidoOptInAndroid() {
return !IsOptedIntoFido() && !IsVirtualCard() &&
UnmaskDetailsOfferFidoOptIn() && !HasOptedInFromAndroidSettings();
}
const std::string GetFidoOptInNotOfferedHistogram() {
return fido_opt_in_not_offered_histogram;
}
CreditCard* GetCreditCard() {
return personal_data().payments_data_manager().GetCreditCardByGUID(
kTestGUID);
}
private:
const std::string fido_opt_in_not_offered_histogram =
"Autofill.BetterAuth.OptInPromoNotOfferedReason";
};
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
TEST_P(CreditCardAccessManagerBetterAuthOptInLogTest,
FidoOptInNotShown_Desktop) {
base::HistogramTester histogram_tester;
EXPECT_EQ(test_api(credit_card_access_manager())
.ShouldOfferFidoOptInDialog(
CreditCardCvcAuthenticator::CvcAuthenticationResponse()
.with_did_succeed(true)
.with_card(GetCreditCard())
.with_card_authorization_token(
CardAuthorizationTokenPresent()
? "card_authorization_token"
: "")
.with_cvc(u"123")),
ShouldOfferFidoOptIn());
if (IsOptedIntoFido()) {
histogram_tester.ExpectUniqueSample(
GetFidoOptInNotOfferedHistogram(),
autofill_metrics::WebauthnOptInPromoNotOfferedReason::kAlreadyOptedIn,
1);
} else if (!UnmaskDetailsOfferFidoOptIn()) {
histogram_tester.ExpectUniqueSample(
GetFidoOptInNotOfferedHistogram(),
autofill_metrics::WebauthnOptInPromoNotOfferedReason::
kUnmaskDetailsOfferFidoOptInFalse,
1);
} else if (!CardAuthorizationTokenPresent()) {
histogram_tester.ExpectUniqueSample(
GetFidoOptInNotOfferedHistogram(),
autofill_metrics::WebauthnOptInPromoNotOfferedReason::
kCardAuthorizationTokenEmpty,
1);
} else if (MaxStrikesLimitReached()) {
histogram_tester.ExpectUniqueSample(
GetFidoOptInNotOfferedHistogram(),
autofill_metrics::WebauthnOptInPromoNotOfferedReason::
kBlockedByStrikeDatabase,
1);
} else if (IsVirtualCard()) {
histogram_tester.ExpectUniqueSample(
GetFidoOptInNotOfferedHistogram(),
autofill_metrics::WebauthnOptInPromoNotOfferedReason::kVirtualCard,
1);
} else {
histogram_tester.ExpectTotalCount(GetFidoOptInNotOfferedHistogram(),
0);
}
}
#endif
#if BUILDFLAG(IS_ANDROID)
TEST_P(CreditCardAccessManagerBetterAuthOptInLogTest,
FidoOptInNotShown_Android) {
base::HistogramTester histogram_tester;
EXPECT_EQ(test_api(credit_card_access_manager()).ShouldOfferFidoAuth(),
ShouldOfferFidoOptInAndroid());
if (IsOptedIntoFido()) {
histogram_tester.ExpectUniqueSample(
GetFidoOptInNotOfferedHistogram(),
autofill_metrics::WebauthnOptInPromoNotOfferedReason::kAlreadyOptedIn,
1);
} else if (!UnmaskDetailsOfferFidoOptIn()) {
histogram_tester.ExpectUniqueSample(
GetFidoOptInNotOfferedHistogram(),
autofill_metrics::WebauthnOptInPromoNotOfferedReason::
kUnmaskDetailsOfferFidoOptInFalse,
1);
} else if (HasOptedInFromAndroidSettings()) {
histogram_tester.ExpectUniqueSample(
GetFidoOptInNotOfferedHistogram(),
autofill_metrics::WebauthnOptInPromoNotOfferedReason::
kOptedInFromSettings,
1);
} else if (IsVirtualCard()) {
histogram_tester.ExpectUniqueSample(
GetFidoOptInNotOfferedHistogram(),
autofill_metrics::WebauthnOptInPromoNotOfferedReason::kVirtualCard,
1);
} else {
histogram_tester.ExpectTotalCount(GetFidoOptInNotOfferedHistogram(),
0);
}
}
#endif
INSTANTIATE_TEST_SUITE_P(,
CreditCardAccessManagerBetterAuthOptInLogTest,
testing::Combine(testing::Bool(),
testing::Bool(),
testing::Bool(),
testing::Bool(),
testing::Bool(),
testing::Bool()));
TEST_F(CreditCardAccessManagerTest,
IntentToOptOut_DelayedUnmaskDetailsResponse) {
base::HistogramTester histogram_tester;
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(true);
payments_network_interface().AddFidoEligibleCard(
card->server_id(), kCredentialId, kGooglePaymentsRpid);
SetCreditCardFIDOAuthEnabled(false);
payments_network_interface().ShouldReturnUnmaskDetailsImmediately(false);
credit_card_access_manager().PrepareToFetchCreditCard();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
EXPECT_EQ(GetUnmaskAuthFlowType(), UnmaskAuthFlowType::kCvc);
histogram_tester.ExpectUniqueSample(
"Autofill.BetterAuth.UserPerceivedLatencyOnCardSelection.OptedOut",
autofill_metrics::PreflightCallEvent::
kCardChosenBeforePreflightCallReturned,
1);
histogram_tester.ExpectTotalCount(
"Autofill.BetterAuth.UserPerceivedLatencyOnCardSelection.OptedIn."
"TimedOutCvcFallback",
0);
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber));
EXPECT_FALSE(GetFIDOAuthenticator()->IsOptOutCalled());
EXPECT_FALSE(IsCreditCardFIDOAuthEnabled());
}
TEST_F(CreditCardAccessManagerTest, IntentToOptOut_OptOutAfterUnmaskSucceeds) {
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(true);
payments_network_interface().AddFidoEligibleCard(
card->server_id(), kCredentialId, kGooglePaymentsRpid);
SetCreditCardFIDOAuthEnabled(false);
credit_card_access_manager().PrepareToFetchCreditCard();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
EXPECT_FALSE(IsCreditCardFIDOAuthEnabled());
EXPECT_EQ(GetUnmaskAuthFlowType(), UnmaskAuthFlowType::kCvc);
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber));
WaitForCallbacks();
EXPECT_TRUE(GetFIDOAuthenticator()->IsOptOutCalled());
OptChange(PaymentsRpcResult::kSuccess,
false);
EXPECT_FALSE(IsCreditCardFIDOAuthEnabled());
}
TEST_F(CreditCardAccessManagerTest, IntentToOptOut_OptOutAfterUnmaskFails) {
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(true);
payments_network_interface().AddFidoEligibleCard(
card->server_id(), kCredentialId, kGooglePaymentsRpid);
SetCreditCardFIDOAuthEnabled(false);
credit_card_access_manager().PrepareToFetchCreditCard();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
EXPECT_FALSE(IsCreditCardFIDOAuthEnabled());
EXPECT_EQ(GetUnmaskAuthFlowType(), UnmaskAuthFlowType::kCvc);
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kPermanentFailure,
std::string()));
WaitForCallbacks();
EXPECT_TRUE(GetFIDOAuthenticator()->IsOptOutCalled());
OptChange(PaymentsRpcResult::kSuccess,
false);
EXPECT_FALSE(IsCreditCardFIDOAuthEnabled());
}
TEST_F(CreditCardAccessManagerTest, IntentToOptOut_OptOutFailure) {
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card =
personal_data().payments_data_manager().GetCreditCardByGUID(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetCreditCardFIDOAuthEnabled(true);
payments_network_interface().AddFidoEligibleCard(
card->server_id(), kCredentialId, kGooglePaymentsRpid);
SetCreditCardFIDOAuthEnabled(false);
credit_card_access_manager().PrepareToFetchCreditCard();
credit_card_access_manager().FetchCreditCard(
card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
EXPECT_FALSE(IsCreditCardFIDOAuthEnabled());
EXPECT_EQ(GetUnmaskAuthFlowType(), UnmaskAuthFlowType::kCvc);
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, kTestNumber));
WaitForCallbacks();
OptChange(PaymentsRpcResult::kPermanentFailure, false);
EXPECT_FALSE(IsCreditCardFIDOAuthEnabled());
}
TEST_F(CreditCardAccessManagerTest, FIDOAuthOptChange_OptOut) {
credit_card_access_manager().FIDOAuthOptChange(false);
ASSERT_TRUE(fido_authenticator().IsOptOutCalled());
}
TEST_F(CreditCardAccessManagerTest, FIDOAuthOptChange_OptOut_OffTheRecord) {
autofill_client_.set_is_off_the_record(true);
credit_card_access_manager().FIDOAuthOptChange(false);
ASSERT_FALSE(fido_authenticator().IsOptOutCalled());
}
#if !BUILDFLAG(IS_APPLE)
TEST_F(CreditCardAccessManagerTest, PreflightCallRateLimited) {
base::HistogramTester histogram_tester;
std::string preflight_call_metric =
"Autofill.BetterAuth.CardUnmaskPreflightCalledWithFidoOptInStatus";
ClearCards();
CreateServerCard(kTestGUID, kTestNumber);
GetFIDOAuthenticator()->SetUserVerifiable(true);
ResetFetchCreditCard();
credit_card_access_manager().PrepareToFetchCreditCard();
histogram_tester.ExpectTotalCount(preflight_call_metric, 1);
EXPECT_FALSE(
test_api(credit_card_access_manager()).can_fetch_unmask_details());
credit_card_access_manager().PrepareToFetchCreditCard();
histogram_tester.ExpectTotalCount(preflight_call_metric, 1);
}
#endif
#endif
TEST_F(CreditCardAccessManagerTest,
UnmaskAuthFlowEvent_AlsoLogsServerCardSubhistogram) { … }
TEST_F(CreditCardAccessManagerTest, AuthenticationInProgress) { … }
TEST_F(CreditCardAccessManagerTest, FetchCreditCardUsesUnmaskedCardCache) { … }
TEST_F(CreditCardAccessManagerTest, GetCachedUnmaskedCards) { … }
TEST_F(CreditCardAccessManagerTest, IsCardPresentInUnmaskedCache) { … }
class CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingTest
: public CreditCardAccessManagerTest { … };
TEST_F(CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingTest,
RiskBasedMaskedServerCardUnmasking_Success) { … }
TEST_F(CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingTest,
RiskBasedMaskedServerCardUnmasking_RetrievalError) { … }
TEST_F(CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingTest,
RiskBasedMaskedServerCardUnmasking_FlowCancelled) { … }
TEST_F(
CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingTest,
RiskBasedMaskedServerCardUnmasking_RiskBasedAuthenticationNotInvoked_FeatureDisabled) { … }
TEST_F(
CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingTest,
RiskBasedMaskedServerCardUnmasking_CvcAuthenticationRequired_ContextTokenSetCorrectly) { … }
TEST_F(CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingTest,
RiskBasedMaskedServerCardUnmasking_AuthenticationRequired_CvcOnly) { … }
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID)
TEST_F(CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingTest,
RiskBasedMaskedServerCardUnmasking_AuthenticationRequired_FidoOnly) {
base::HistogramTester histogram_tester;
std::string test_number = "4444333322221111";
CreditCard* masked_server_card =
CreateServerCard(kTestGUID, test_number, kTestServerId);
test_api(credit_card_access_manager()).set_is_user_verifiable(true);
fido_authenticator().set_is_user_opted_in(true);
credit_card_access_manager().FetchCreditCard(
masked_server_card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
EXPECT_TRUE(autofill_client_.GetPaymentsAutofillClient()
->risk_based_authentication_invoked());
EXPECT_TRUE(autofill_client_.GetPaymentsAutofillClient()
->autofill_progress_dialog_shown());
credit_card_access_manager().OnRiskBasedAuthenticationResponseReceived(
CreditCardRiskBasedAuthenticator::RiskBasedAuthenticationResponse()
.with_result(CreditCardRiskBasedAuthenticator::
RiskBasedAuthenticationResponse::Result::
kAuthenticationRequired)
.with_fido_request_options(GetTestRequestOptions())
.with_context_token("fake_context_token"));
histogram_tester.ExpectUniqueSample(
"Autofill.BetterAuth.FlowEvents.Fido",
CreditCardFormEventLogger::UnmaskAuthFlowEvent::kPromptShown, 1);
ASSERT_TRUE(fido_authenticator().authenticate_invoked());
EXPECT_EQ(fido_authenticator().card().number(),
base::UTF8ToUTF16(test_number));
EXPECT_EQ(fido_authenticator().card().record_type(),
CreditCard::RecordType::kMaskedServerCard);
ASSERT_TRUE(fido_authenticator().context_token().has_value());
EXPECT_EQ(fido_authenticator().context_token().value(), "fake_context_token");
EXPECT_FALSE(
test_api(*autofill_client_.GetFormDataImporter())
.payment_method_type_if_non_interactive_authentication_flow_completed()
.has_value());
histogram_tester.ExpectUniqueSample(
"Autofill.BetterAuth.CardUnmaskTypeDecision",
autofill_metrics::CardUnmaskTypeDecisionMetric::kFidoOnly, 1);
}
TEST_F(CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingTest,
RiskBasedMaskedServerCardUnmasking_AuthenticationRequired_CvcThenFido) {
base::HistogramTester histogram_tester;
OptUserInToFido();
std::string test_number = "4444333322221111";
CreditCard* masked_server_card =
CreateServerCard(kTestGUID, test_number, kTestServerId);
payments_network_interface().ShouldReturnUnmaskDetailsImmediately(true);
payments_network_interface().SetFidoRequestOptionsInUnmaskDetails(
kCredentialId, kGooglePaymentsRpid);
credit_card_access_manager().PrepareToFetchCreditCard();
WaitForCallbacks();
MockRiskBasedAuthSucceedsWithoutPanReturned(masked_server_card);
histogram_tester.ExpectUniqueSample(
"Autofill.BetterAuth.FlowEvents.CvcThenFido",
CreditCardFormEventLogger::UnmaskAuthFlowEvent::kPromptShown, 1);
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, test_number,
TestFidoRequestOptionsType::kNotPresent));
EXPECT_EQ(accessor_->number(), std::u16string());
EXPECT_EQ(accessor_->cvc(), std::u16string());
EXPECT_EQ(CreditCardFidoAuthenticator::Flow::FOLLOWUP_AFTER_CVC_AUTH_FLOW,
GetFIDOAuthenticator()->current_flow());
TestCreditCardFidoAuthenticator::GetAssertion(GetFIDOAuthenticator(),
true);
EXPECT_EQ(base::UTF8ToUTF16(test_number), accessor_->number());
EXPECT_EQ(kTestCvc16, accessor_->cvc());
OptChange(PaymentsRpcResult::kSuccess, true);
histogram_tester.ExpectUniqueSample(
"Autofill.BetterAuth.CardUnmaskTypeDecision",
autofill_metrics::CardUnmaskTypeDecisionMetric::kCvcThenFido, 1);
histogram_tester.ExpectUniqueSample(
"Autofill.BetterAuth.WebauthnResult.AuthenticationAfterCVC",
autofill_metrics::WebauthnResultMetric::kSuccess, 1);
histogram_tester.ExpectBucketCount(
"Autofill.BetterAuth.FlowEvents.CvcThenFido",
CreditCardFormEventLogger::UnmaskAuthFlowEvent::kPromptCompleted, 1);
}
TEST_F(
CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingTest,
RiskBasedMaskedServerCardUnmasking_AuthenticationRequired_PreflightCallNotFinished) {
base::HistogramTester histogram_tester;
OptUserInToFido();
std::string test_number = "4444333322221111";
CreditCard* masked_server_card =
CreateServerCard(kTestGUID, test_number, kTestServerId);
payments_network_interface().ShouldReturnUnmaskDetailsImmediately(false);
credit_card_access_manager().PrepareToFetchCreditCard();
MockRiskBasedAuthSucceedsWithoutPanReturned(masked_server_card);
histogram_tester.ExpectUniqueSample(
"Autofill.BetterAuth.FlowEvents.Cvc",
CreditCardFormEventLogger::UnmaskAuthFlowEvent::kPromptShown, 1);
EXPECT_TRUE(GetRealPanForCVCAuth(PaymentsRpcResult::kSuccess, test_number));
EXPECT_EQ(base::UTF8ToUTF16(test_number), accessor_->number());
EXPECT_EQ(kTestCvc16, accessor_->cvc());
EXPECT_FALSE(
test_api(*autofill_client_.GetFormDataImporter())
.payment_method_type_if_non_interactive_authentication_flow_completed()
.has_value());
}
#endif
TEST_F(CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingTest,
LogCvcFilling_RiskBasedMaskedServerCardUnmaskingSuccess) { … }
TEST_F(CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingTest,
DoNotLogCvcFilling_RiskBasedMaskedServerCardUnmaskingSuccess) { … }
TEST_F(
CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingTest,
RiskBasedMaskedServerCardUnmasking_RiskBasedAuthenticationNotInvoked_CardExpired) { … }
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID)
class
CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingPreflightCallReturnedTest
: public CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingTest,
public testing::WithParamInterface<std::tuple<bool, bool>> {
public:
CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingPreflightCallReturnedTest() =
default;
~CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingPreflightCallReturnedTest()
override = default;
bool FidoOptedIn() { return std::get<0>(GetParam()); }
bool PreflightCallReturned() { return std::get<1>(GetParam()); }
};
INSTANTIATE_TEST_SUITE_P(
,
CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingPreflightCallReturnedTest,
testing::Combine(testing::Bool(), testing::Bool()));
TEST_P(
CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingPreflightCallReturnedTest,
Metrics_LogPreflightCallResponseReceivedOnCardSelection) {
base::HistogramTester histogram_tester;
std::string test_number = "4444333322221111";
CreditCard* masked_server_card = CreateServerCard(kTestGUID, test_number);
GetFIDOAuthenticator()->SetUserVerifiable(true);
if (FidoOptedIn()) {
OptUserInToFido();
}
payments_network_interface().ShouldReturnUnmaskDetailsImmediately(
PreflightCallReturned());
std::string histogram_name =
"Autofill.BetterAuth.PreflightCallResponseReceivedOnCardSelection.";
histogram_name += FidoOptedIn() ? "OptedIn." : "OptedOut.";
histogram_name += "ServerCard";
credit_card_access_manager().PrepareToFetchCreditCard();
credit_card_access_manager().FetchCreditCard(
masked_server_card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
WaitForCallbacks();
histogram_tester.ExpectUniqueSample(
histogram_name,
PreflightCallReturned() ? autofill_metrics::PreflightCallEvent::
kPreflightCallReturnedBeforeCardChosen
: autofill_metrics::PreflightCallEvent::
kCardChosenBeforePreflightCallReturned,
1);
}
#endif
TEST_F(CreditCardAccessManagerTest, IsVirtualCardPresentInUnmaskedCache) { … }
TEST_F(CreditCardAccessManagerTest,
RiskBasedVirtualCardUnmasking_Success_VirtualCardsEnabled) { … }
TEST_F(CreditCardAccessManagerTest,
RiskBasedVirtualCardUnmasking_Success_VirtualCardsDisabled) { … }
TEST_F(CreditCardAccessManagerTest,
RiskBasedVirtualCardUnmasking_AuthenticationRequired_OtpOnly) { … }
TEST_F(CreditCardAccessManagerTest,
RiskBasedVirtualCardUnmasking_AuthenticationRequired_CvcOnly) { … }
TEST_F(CreditCardAccessManagerTest,
RiskBasedVirtualCardUnmasking_Only3dsChallengeReturned) { … }
TEST_F(CreditCardAccessManagerTest,
RiskBasedVirtualCardUnmasking_AuthenticationRequired_OtpAndCvcAnd3ds) { … }
#if !BUILDFLAG(IS_IOS)
TEST_F(
CreditCardAccessManagerTest,
RiskBasedVirtualCardUnmasking_CreditCardAccessManagerReset_TriggersOtpAuthenticatorResetOnFlowCancelled) { … }
TEST_F(CreditCardAccessManagerTest,
VirtualCardUnmasking_3dsResponseReceived_Success) { … }
TEST_F(CreditCardAccessManagerTest,
VirtualCardUnmasking_3dsResponseReceived_Error) { … }
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID)
TEST_F(CreditCardAccessManagerTest,
RiskBasedVirtualCardUnmasking_AuthenticationRequired_FidoOnly) {
base::HistogramTester histogram_tester;
CreditCard* masked_server_card =
CreateServerCard(kTestGUID, kTestNumber, kTestServerId);
CreditCard virtual_card = *masked_server_card;
virtual_card.set_record_type(CreditCard::RecordType::kVirtualCard);
test_api(credit_card_access_manager()).set_is_user_verifiable(true);
fido_authenticator().set_is_user_opted_in(true);
credit_card_access_manager().FetchCreditCard(
&virtual_card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
EXPECT_TRUE(autofill_client_.GetPaymentsAutofillClient()
->risk_based_authentication_invoked());
payments::PaymentsNetworkInterface::UnmaskResponseDetails response;
response.context_token = "fake_context_token";
response.fido_request_options = GetTestRequestOptions();
credit_card_access_manager()
.OnVirtualCardRiskBasedAuthenticationResponseReceived(
PaymentsRpcResult::kSuccess, response);
ASSERT_TRUE(fido_authenticator().authenticate_invoked());
EXPECT_EQ(fido_authenticator().card().number(),
base::UTF8ToUTF16(std::string(kTestNumber)));
EXPECT_EQ(fido_authenticator().card().record_type(),
CreditCard::RecordType::kVirtualCard);
ASSERT_TRUE(fido_authenticator().context_token().has_value());
EXPECT_EQ(fido_authenticator().context_token().value(), "fake_context_token");
CreditCardFidoAuthenticator::FidoAuthenticationResponse fido_response;
fido_response.did_succeed = true;
CreditCard card = test::WithCvc(test::GetVirtualCard(), u"234");
fido_response.card = &card;
test_api(credit_card_access_manager())
.OnFIDOAuthenticationComplete(fido_response);
EXPECT_EQ(u"234", accessor_->cvc());
histogram_tester.ExpectUniqueSample(
"Autofill.ServerCardUnmask.VirtualCard.Attempt", true, 1);
histogram_tester.ExpectUniqueSample(
"Autofill.ServerCardUnmask.VirtualCard.Result.Fido",
autofill_metrics::ServerCardUnmaskResult::kAuthenticationUnmasked, 1);
}
TEST_F(
CreditCardAccessManagerTest,
RiskBasedVirtualCardUnmasking_AuthenticationRequired_FidoAndOtp_PrefersFido) {
base::HistogramTester histogram_tester;
CreditCard* masked_server_card =
CreateServerCard(kTestGUID, kTestNumber, kTestServerId);
CreditCard virtual_card = *masked_server_card;
virtual_card.set_record_type(CreditCard::RecordType::kVirtualCard);
test_api(credit_card_access_manager()).set_is_user_verifiable(true);
fido_authenticator().set_is_user_opted_in(true);
credit_card_access_manager().FetchCreditCard(
&virtual_card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
EXPECT_TRUE(autofill_client_.GetPaymentsAutofillClient()
->risk_based_authentication_invoked());
payments::PaymentsNetworkInterface::UnmaskResponseDetails response;
response.context_token = "fake_context_token";
CardUnmaskChallengeOption challenge_option =
test::GetCardUnmaskChallengeOptions(
{CardUnmaskChallengeOptionType::kSmsOtp})[0];
response.card_unmask_challenge_options.emplace_back(challenge_option);
response.fido_request_options = GetTestRequestOptions();
credit_card_access_manager()
.OnVirtualCardRiskBasedAuthenticationResponseReceived(
PaymentsRpcResult::kSuccess, response);
ASSERT_TRUE(fido_authenticator().authenticate_invoked());
EXPECT_EQ(fido_authenticator().card().number(),
base::UTF8ToUTF16(std::string(kTestNumber)));
EXPECT_EQ(fido_authenticator().card().record_type(),
CreditCard::RecordType::kVirtualCard);
ASSERT_TRUE(fido_authenticator().context_token().has_value());
EXPECT_EQ(fido_authenticator().context_token().value(), "fake_context_token");
CreditCardFidoAuthenticator::FidoAuthenticationResponse fido_response;
fido_response.did_succeed = true;
CreditCard card = test::GetVirtualCard();
fido_response.card = &card;
fido_response.cvc = u"123";
test_api(credit_card_access_manager())
.OnFIDOAuthenticationComplete(fido_response);
histogram_tester.ExpectUniqueSample(
"Autofill.ServerCardUnmask.VirtualCard.Attempt", true, 1);
histogram_tester.ExpectUniqueSample(
"Autofill.ServerCardUnmask.VirtualCard.Result.Fido",
autofill_metrics::ServerCardUnmaskResult::kAuthenticationUnmasked, 1);
}
TEST_F(
CreditCardAccessManagerTest,
RiskBasedVirtualCardUnmasking_AuthenticationRequired_FidoAndOtp_FidoNotOptedIn) {
base::HistogramTester histogram_tester;
std::vector<CardUnmaskChallengeOption> challenge_options =
test::GetCardUnmaskChallengeOptions(
{CardUnmaskChallengeOptionType::kSmsOtp});
MockCardUnmaskFlowUpToAuthenticationSelectionDialogAccepted(
false,
true, challenge_options, 0);
CreditCardOtpAuthenticator::OtpAuthenticationResponse otp_response;
otp_response.result =
CreditCardOtpAuthenticator::OtpAuthenticationResponse::Result::kSuccess;
CreditCard card = test::GetCreditCard();
otp_response.card = &card;
otp_response.cvc = u"123";
credit_card_access_manager().OnOtpAuthenticationComplete(otp_response);
histogram_tester.ExpectUniqueSample(
"Autofill.ServerCardUnmask.VirtualCard.Attempt", true, 1);
histogram_tester.ExpectUniqueSample(
"Autofill.ServerCardUnmask.VirtualCard.Result.Otp",
autofill_metrics::ServerCardUnmaskResult::kAuthenticationUnmasked, 1);
}
TEST_F(
CreditCardAccessManagerTest,
RiskBasedVirtualCardUnmasking_AuthenticationRequired_FidoAndOtp_FidoFailedFallBackToOtp) {
base::HistogramTester histogram_tester;
std::vector<CardUnmaskChallengeOption> challenge_options =
test::GetCardUnmaskChallengeOptions(
{CardUnmaskChallengeOptionType::kSmsOtp});
MockCardUnmaskFlowUpToAuthenticationSelectionDialogAccepted(
true,
true, challenge_options, 0);
CreditCardOtpAuthenticator::OtpAuthenticationResponse otp_response;
otp_response.result =
CreditCardOtpAuthenticator::OtpAuthenticationResponse::Result::kSuccess;
CreditCard card = test::GetCreditCard();
otp_response.card = &card;
otp_response.cvc = u"123";
credit_card_access_manager().OnOtpAuthenticationComplete(otp_response);
histogram_tester.ExpectUniqueSample(
"Autofill.ServerCardUnmask.VirtualCard.Attempt", true, 1);
histogram_tester.ExpectUniqueSample(
"Autofill.ServerCardUnmask.VirtualCard.Result.OtpFallbackFromFido",
autofill_metrics::ServerCardUnmaskResult::kAuthenticationUnmasked, 1);
}
TEST_F(
CreditCardAccessManagerTest,
RiskBasedVirtualCardUnmasking_AuthenticationRequired_FidoOnly_FidoNotOptedIn) {
base::HistogramTester histogram_tester;
CreditCard* masked_server_card =
CreateServerCard(kTestGUID, kTestNumber, kTestServerId);
CreditCard virtual_card = *masked_server_card;
virtual_card.set_record_type(CreditCard::RecordType::kVirtualCard);
test_api(credit_card_access_manager()).set_is_user_verifiable(true);
fido_authenticator().set_is_user_opted_in(false);
credit_card_access_manager().FetchCreditCard(
&virtual_card, base::BindOnce(&TestAccessor::OnCreditCardFetched,
accessor_->GetWeakPtr()));
EXPECT_TRUE(autofill_client_.GetPaymentsAutofillClient()
->risk_based_authentication_invoked());
payments::PaymentsNetworkInterface::UnmaskResponseDetails response;
response.context_token = "fake_context_token";
response.fido_request_options = GetTestRequestOptions();
credit_card_access_manager()
.OnVirtualCardRiskBasedAuthenticationResponseReceived(
PaymentsRpcResult::kSuccess, response);
EXPECT_EQ(accessor_->result(), CreditCardFetchResult::kTransientError);
EXPECT_FALSE(otp_authenticator_->on_challenge_option_selected_invoked());
EXPECT_FALSE(fido_authenticator().authenticate_invoked());
histogram_tester.ExpectUniqueSample(
"Autofill.ServerCardUnmask.VirtualCard.Attempt", true, 1);
histogram_tester.ExpectUniqueSample(
"Autofill.ServerCardUnmask.VirtualCard.Result.Fido",
autofill_metrics::ServerCardUnmaskResult::kOnlyFidoAvailableButNotOptedIn,
1);
}
#endif
#endif
TEST_F(CreditCardAccessManagerTest,
RiskBasedVirtualCardUnmasking_Failure_NoOptionReturned) { … }
TEST_F(CreditCardAccessManagerTest,
RiskBasedVirtualCardUnmasking_Failure_VirtualCardRetrievalError) { … }
TEST_F(CreditCardAccessManagerTest,
RiskBasedVirtualCardUnmasking_Failure_MerchantOptedOut) { … }
TEST_F(CreditCardAccessManagerTest,
RiskBasedVirtualCardUnmasking_FlowCancelled) { … }
TEST_F(CreditCardAccessManagerTest, DestructorResetsCardIdentifier) { … }
}