Commit 62fa13ed authored by Jared Saul's avatar Jared Saul Committed by Commit Bot

Log UMA metric for checking if full server cards have expired

Bug: 
Change-Id: Id8c07997ba50f6d5592f54148f423cfeb920426f
Reviewed-on: https://chromium-review.googlesource.com/580071
Commit-Queue: Jared Saul <jsaul@google.com>
Reviewed-by: default avatarIlya Sherman <isherman@chromium.org>
Reviewed-by: default avatarMathieu Perreault <mathp@chromium.org>
Reviewed-by: default avatarSebastien Seguin-Gagnon <sebsg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#488435}
parent 9ff42baa
...@@ -512,6 +512,15 @@ void LogPredictionQualityMetrics( ...@@ -512,6 +512,15 @@ void LogPredictionQualityMetrics(
} // namespace } // namespace
// static
void AutofillMetrics::LogSubmittedServerCardExpirationStatusMetric(
SubmittedServerCardExpirationStatusMetric metric) {
DCHECK_LT(metric, NUM_SUBMITTED_SERVER_CARD_EXPIRATION_STATUS_METRICS);
UMA_HISTOGRAM_ENUMERATION(
"Autofill.SubmittedServerCardExpirationStatus", metric,
NUM_SUBMITTED_SERVER_CARD_EXPIRATION_STATUS_METRICS);
}
// static // static
void AutofillMetrics::LogCardUploadDecisionMetrics( void AutofillMetrics::LogCardUploadDecisionMetrics(
int upload_decision_metrics) { int upload_decision_metrics) {
......
...@@ -302,6 +302,26 @@ class AutofillMetrics { ...@@ -302,6 +302,26 @@ class AutofillMetrics {
NUM_INFO_BAR_METRICS, NUM_INFO_BAR_METRICS,
}; };
// Metric to measure if a submitted card's expiration date matches the same
// server card's expiration date (unmasked or not). Cards are considered to
// be the same if they have the same card number (if unmasked) or if they have
// the same network and last four digits (if masked).
enum SubmittedServerCardExpirationStatusMetric {
// The submitted card and the unmasked server card had the same expiration
// date.
FULL_SERVER_CARD_EXPIRATION_DATE_MATCHED,
// The submitted card and the unmasked server card had different expiration
// dates.
FULL_SERVER_CARD_EXPIRATION_DATE_DID_NOT_MATCH,
// The submitted card and the masked server card had the same expiration
// date.
MASKED_SERVER_CARD_EXPIRATION_DATE_MATCHED,
// The submitted card and the masked server card had different expiration
// dates.
MASKED_SERVER_CARD_EXPIRATION_DATE_DID_NOT_MATCH,
NUM_SUBMITTED_SERVER_CARD_EXPIRATION_STATUS_METRICS,
};
// Metrics to measure user interaction with the save credit card prompt. // Metrics to measure user interaction with the save credit card prompt.
// //
// SAVE_CARD_PROMPT_DISMISS_FOCUS is not stored explicitly, but can be // SAVE_CARD_PROMPT_DISMISS_FOCUS is not stored explicitly, but can be
...@@ -772,6 +792,12 @@ class AutofillMetrics { ...@@ -772,6 +792,12 @@ class AutofillMetrics {
DISALLOW_IMPLICIT_CONSTRUCTORS(UkmTimestampPin); DISALLOW_IMPLICIT_CONSTRUCTORS(UkmTimestampPin);
}; };
// If a credit card that matches a server card (unmasked or not) was submitted
// on a form, logs whether the submitted card's expiration date matched the
// server card's known expiration date.
static void LogSubmittedServerCardExpirationStatusMetric(
SubmittedServerCardExpirationStatusMetric metric);
// |upload_decision_metrics| is a bitmask of |CardUploadDecisionMetric|. // |upload_decision_metrics| is a bitmask of |CardUploadDecisionMetric|.
static void LogCardUploadDecisionMetrics(int upload_decision_metrics); static void LogCardUploadDecisionMetrics(int upload_decision_metrics);
static void LogCreditCardInfoBarMetric( static void LogCreditCardInfoBarMetric(
......
...@@ -1639,6 +1639,23 @@ bool PersonalDataManager::ImportCreditCard( ...@@ -1639,6 +1639,23 @@ bool PersonalDataManager::ImportCreditCard(
// can enter the full card number without having to unmask the card. // can enter the full card number without having to unmask the card.
for (const auto& card : server_credit_cards_) { for (const auto& card : server_credit_cards_) {
if (candidate_credit_card.HasSameNumberAs(*card)) { if (candidate_credit_card.HasSameNumberAs(*card)) {
// Record metric on whether expiration dates matched.
if (candidate_credit_card.expiration_month() ==
card->expiration_month() &&
candidate_credit_card.expiration_year() == card->expiration_year()) {
AutofillMetrics::LogSubmittedServerCardExpirationStatusMetric(
card->record_type() == CreditCard::FULL_SERVER_CARD
? AutofillMetrics::FULL_SERVER_CARD_EXPIRATION_DATE_MATCHED
: AutofillMetrics::MASKED_SERVER_CARD_EXPIRATION_DATE_MATCHED);
} else {
AutofillMetrics::LogSubmittedServerCardExpirationStatusMetric(
card->record_type() == CreditCard::FULL_SERVER_CARD
? AutofillMetrics::
FULL_SERVER_CARD_EXPIRATION_DATE_DID_NOT_MATCH
: AutofillMetrics::
MASKED_SERVER_CARD_EXPIRATION_DATE_DID_NOT_MATCH);
}
if (card->record_type() == CreditCard::FULL_SERVER_CARD) if (card->record_type() == CreditCard::FULL_SERVER_CARD)
return false; return false;
DCHECK_EQ(card->record_type(), CreditCard::MASKED_SERVER_CARD); DCHECK_EQ(card->record_type(), CreditCard::MASKED_SERVER_CARD);
......
...@@ -4461,6 +4461,190 @@ TEST_F(PersonalDataManagerTest, DontDuplicateFullServerCard) { ...@@ -4461,6 +4461,190 @@ TEST_F(PersonalDataManagerTest, DontDuplicateFullServerCard) {
EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card); EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
} }
TEST_F(PersonalDataManagerTest,
Metrics_SubmittedServerCardExpirationStatus_FullServerCardMatch) {
EnableWalletCardImport();
std::vector<CreditCard> server_cards;
server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "c789"));
test::SetCreditCardInfo(&server_cards.back(), "Clyde Barrow",
"4444333322221111" /* Visa */, "04", "2111", "1");
test::SetServerCreditCards(autofill_table_, server_cards);
personal_data_->Refresh();
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::RunLoop().Run();
// A user fills/enters the card's information on a checkout form. Ensure that
// an expiration date match is recorded.
FormData form;
FormFieldData field;
test::CreateTestFormField("Name on card:", "name_on_card", "Clyde Barrow",
"text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Card Number:", "card_number", "4444333322221111",
"text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Exp Month:", "exp_month", "04", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Exp Year:", "exp_year", "2111", "text", &field);
form.fields.push_back(field);
base::HistogramTester histogram_tester;
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_FALSE(personal_data_->ImportFormData(
form_structure, false, &imported_credit_card,
&imported_credit_card_matches_masked_server_credit_card));
EXPECT_FALSE(imported_credit_card);
EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
histogram_tester.ExpectUniqueSample(
"Autofill.SubmittedServerCardExpirationStatus",
AutofillMetrics::FULL_SERVER_CARD_EXPIRATION_DATE_MATCHED, 1);
}
TEST_F(PersonalDataManagerTest,
Metrics_SubmittedServerCardExpirationStatus_FullServerCardMismatch) {
EnableWalletCardImport();
std::vector<CreditCard> server_cards;
server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "c789"));
test::SetCreditCardInfo(&server_cards.back(), "Clyde Barrow",
"4444333322221111" /* Visa */, "04", "2111", "1");
test::SetServerCreditCards(autofill_table_, server_cards);
personal_data_->Refresh();
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::RunLoop().Run();
// A user fills/enters the card's information on a checkout form but changes
// the expiration date of the card. Ensure that an expiration date mismatch
// is recorded.
FormData form;
FormFieldData field;
test::CreateTestFormField("Name on card:", "name_on_card", "Clyde Barrow",
"text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Card Number:", "card_number", "4444333322221111",
"text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Exp Month:", "exp_month", "04", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Exp Year:", "exp_year", "2345", "text", &field);
form.fields.push_back(field);
base::HistogramTester histogram_tester;
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_FALSE(personal_data_->ImportFormData(
form_structure, false, &imported_credit_card,
&imported_credit_card_matches_masked_server_credit_card));
EXPECT_FALSE(imported_credit_card);
EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
histogram_tester.ExpectUniqueSample(
"Autofill.SubmittedServerCardExpirationStatus",
AutofillMetrics::FULL_SERVER_CARD_EXPIRATION_DATE_DID_NOT_MATCH, 1);
}
TEST_F(PersonalDataManagerTest,
Metrics_SubmittedServerCardExpirationStatus_MaskedServerCardMatch) {
EnableWalletCardImport();
std::vector<CreditCard> server_cards;
server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "a123"));
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"1111" /* Visa */, "01", "2111", "");
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
test::SetServerCreditCards(autofill_table_, server_cards);
personal_data_->Refresh();
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::RunLoop().Run();
// A user fills/enters the card's information on a checkout form. Ensure that
// an expiration date match is recorded.
FormData form;
FormFieldData field;
test::CreateTestFormField("Name on card:", "name_on_card", "Clyde Barrow",
"text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Card Number:", "card_number", "4444333322221111",
"text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Exp Month:", "exp_month", "01", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Exp Year:", "exp_year", "2111", "text", &field);
form.fields.push_back(field);
base::HistogramTester histogram_tester;
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_TRUE(personal_data_->ImportFormData(
form_structure, false, &imported_credit_card,
&imported_credit_card_matches_masked_server_credit_card));
EXPECT_TRUE(imported_credit_card);
EXPECT_TRUE(imported_credit_card_matches_masked_server_credit_card);
histogram_tester.ExpectUniqueSample(
"Autofill.SubmittedServerCardExpirationStatus",
AutofillMetrics::MASKED_SERVER_CARD_EXPIRATION_DATE_MATCHED, 1);
}
TEST_F(PersonalDataManagerTest,
Metrics_SubmittedServerCardExpirationStatus_MaskedServerCardMismatch) {
EnableWalletCardImport();
std::vector<CreditCard> server_cards;
server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "a123"));
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"1111" /* Visa */, "01", "2111", "");
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
test::SetServerCreditCards(autofill_table_, server_cards);
personal_data_->Refresh();
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::RunLoop().Run();
// A user fills/enters the card's information on a checkout form but changes
// the expiration date of the card. Ensure that an expiration date mismatch
// is recorded.
FormData form;
FormFieldData field;
test::CreateTestFormField("Name on card:", "name_on_card", "Clyde Barrow",
"text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Card Number:", "card_number", "4444333322221111",
"text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Exp Month:", "exp_month", "04", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Exp Year:", "exp_year", "2345", "text", &field);
form.fields.push_back(field);
base::HistogramTester histogram_tester;
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_TRUE(personal_data_->ImportFormData(
form_structure, false, &imported_credit_card,
&imported_credit_card_matches_masked_server_credit_card));
EXPECT_TRUE(imported_credit_card);
EXPECT_TRUE(imported_credit_card_matches_masked_server_credit_card);
histogram_tester.ExpectUniqueSample(
"Autofill.SubmittedServerCardExpirationStatus",
AutofillMetrics::MASKED_SERVER_CARD_EXPIRATION_DATE_DID_NOT_MATCH, 1);
}
// Tests the SaveImportedProfile method with different profiles to make sure the // Tests the SaveImportedProfile method with different profiles to make sure the
// merge logic works correctly. // merge logic works correctly.
typedef struct { typedef struct {
......
...@@ -2166,6 +2166,13 @@ uploading your change for review. These are checked by presubmit scripts. ...@@ -2166,6 +2166,13 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="2" label="Some other item selected"/> <int value="2" label="Some other item selected"/>
</enum> </enum>
<enum name="AutofillSubmittedServerCardExpirationStatus">
<int value="0" label="Expiration date matched, full server card"/>
<int value="1" label="Expiration date did not match, full server card"/>
<int value="2" label="Expiration date matched, masked server card"/>
<int value="3" label="Expiration date did not match, masked server card"/>
</enum>
<enum name="AutofillTypeQuality"> <enum name="AutofillTypeQuality">
<int value="0" label="Unknown"/> <int value="0" label="Unknown"/>
<int value="1" label="Match"/> <int value="1" label="Match"/>
...@@ -4710,6 +4710,17 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries. ...@@ -4710,6 +4710,17 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
</summary> </summary>
</histogram> </histogram>
<histogram name="Autofill.SubmittedServerCardExpirationStatus"
enum="AutofillSubmittedServerCardExpirationStatus">
<owner>jsaul@google.com</owner>
<summary>
Metric to measure if a submitted card's expiration date matches the same
server card's expiration date (unmasked or not). Cards are considered to be
the same if they have the same card number (if unmasked) or if they have the
same network and last four digits (if masked).
</summary>
</histogram>
<histogram name="Autofill.SuggestionAcceptedIndex" units="position"> <histogram name="Autofill.SuggestionAcceptedIndex" units="position">
<owner>mathp@chromium.org</owner> <owner>mathp@chromium.org</owner>
<summary>The index of the accepted Autofill suggestion in the popup.</summary> <summary>The index of the accepted Autofill suggestion in the popup.</summary>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment