Skip to content

Commit

Permalink
[Secure Payment Confirmation] Enroll metrics
Browse files Browse the repository at this point in the history
PaymentRequest.SecurePaymentConfirmation.Funnel.EnrollDialogShown
0: Could not show, e.g., due to another enrollment dialog already
   showing.
1: Shown, i.e., the user has observed the dialog.

PaymentRequest.SecurePaymentConfirmation.Funnel.EnrollDialogResult
0: Closed by any means except clicking the “Cancel” button.
1: Canceled by clicking the “Cancel” button.
2: Accepted by clicking the "Use Touch ID" or "Use Windows Hello" button
   in the dialog.

PaymentRequest.SecurePaymentConfirmation.Funnel.EnrollSystemPromptResult
0: Failed or cancelled.
1: Succeeded, i.e., the user has approved the system prompt.

Bug: 1183921
Change-Id: Ifac93231a887035ec5f2e0ae7eeaa0c4733a2b23
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2740219
Reviewed-by: Nick Burris <nburris@chromium.org>
Reviewed-by: Robert Kaplow <rkaplow@chromium.org>
Auto-Submit: Rouslan Solomakhin <rouslan@chromium.org>
Commit-Queue: Rouslan Solomakhin <rouslan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#861984}
  • Loading branch information
rsolomakhin authored and Chromium LUCI CQ committed Mar 11, 2021
1 parent a9b158d commit 60fa474
Show file tree
Hide file tree
Showing 10 changed files with 370 additions and 3 deletions.
138 changes: 138 additions & 0 deletions chrome/browser/payments/secure_payment_confirmation_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "components/payments/content/secure_payment_confirmation_app.h"
#include "components/payments/core/journey_logger.h"
#include "components/payments/core/secure_payment_confirmation_instrument.h"
#include "components/payments/core/secure_payment_confirmation_metrics.h"
#include "components/webdata/common/web_data_service_consumer.h"
#include "content/public/browser/authenticator_environment.h"
#include "content/public/common/content_features.h"
Expand Down Expand Up @@ -368,6 +369,59 @@ class SecurePaymentConfirmationCreationTest
return merchant_origin;
}

void ExpectNoEnrollDialogShown() {
histogram_tester_.ExpectTotalCount(
"PaymentRequest.SecurePaymentConfirmation.Funnel.EnrollDialogShown", 0);
}

void ExpectEnrollDialogShown(
SecurePaymentConfirmationEnrollDialogShown result,
int count) {
histogram_tester_.ExpectTotalCount(
"PaymentRequest.SecurePaymentConfirmation.Funnel.EnrollDialogShown",
count);
histogram_tester_.ExpectBucketCount(
"PaymentRequest.SecurePaymentConfirmation.Funnel.EnrollDialogShown",
result, count);
}

void ExpectNoEnrollDialogResult() {
histogram_tester_.ExpectTotalCount(
"PaymentRequest.SecurePaymentConfirmation.Funnel.EnrollDialogResult",
0);
}

void ExpectEnrollDialogResult(
SecurePaymentConfirmationEnrollDialogResult result,
int count) {
histogram_tester_.ExpectTotalCount(
"PaymentRequest.SecurePaymentConfirmation.Funnel.EnrollDialogResult",
count);
histogram_tester_.ExpectBucketCount(
"PaymentRequest.SecurePaymentConfirmation.Funnel.EnrollDialogResult",
result, count);
}

void ExpectNoEnrollSystemPromptResult() {
histogram_tester_.ExpectTotalCount(
"PaymentRequest.SecurePaymentConfirmation.Funnel."
"EnrollSystemPromptResult",
0);
}

void ExpectEnrollSystemPromptResult(
SecurePaymentConfirmationEnrollSystemPromptResult result,
int count) {
histogram_tester_.ExpectTotalCount(
"PaymentRequest.SecurePaymentConfirmation.Funnel."
"EnrollSystemPromptResult",
count);
histogram_tester_.ExpectBucketCount(
"PaymentRequest.SecurePaymentConfirmation.Funnel."
"EnrollSystemPromptResult",
result, count);
}

void ExpectNoFunnelCount() {
histogram_tester_.ExpectTotalCount(
"PaymentRequest.SecurePaymentConfirmation.Funnel."
Expand Down Expand Up @@ -426,6 +480,11 @@ IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationCreationTest, UserCancel) {
content::EvalJs(GetActiveWebContents(),
content::JsReplace("createPaymentCredential($1)",
GetDefaultIconURL())));
ExpectEnrollDialogShown(SecurePaymentConfirmationEnrollDialogShown::kShown,
1);
ExpectEnrollDialogResult(
SecurePaymentConfirmationEnrollDialogResult::kCanceled, 1);
ExpectNoEnrollSystemPromptResult();
ExpectNoFunnelCount();
ExpectJourneyLoggerEvent(/*spc_confirm_logged=*/false);
}
Expand All @@ -444,6 +503,12 @@ IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationCreationTest,
// Verify that credential id size gets recorded.
histogram_tester_.ExpectTotalCount(
"PaymentRequest.SecurePaymentConfirmationCredentialIdSizeInBytes", 1U);
ExpectEnrollDialogShown(SecurePaymentConfirmationEnrollDialogShown::kShown,
1);
ExpectEnrollDialogResult(
SecurePaymentConfirmationEnrollDialogResult::kAccepted, 1);
ExpectEnrollSystemPromptResult(
SecurePaymentConfirmationEnrollSystemPromptResult::kAccepted, 1);
ExpectNoFunnelCount();
ExpectJourneyLoggerEvent(/*spc_confirm_logged=*/false);
}
Expand Down Expand Up @@ -475,6 +540,12 @@ IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationCreationTest,
EXPECT_EQ(1u, test_controller()->app_descriptions().size());
EXPECT_EQ("display_name_for_instrument",
test_controller()->app_descriptions().front().label);
ExpectEnrollDialogShown(SecurePaymentConfirmationEnrollDialogShown::kShown,
1);
ExpectEnrollDialogResult(
SecurePaymentConfirmationEnrollDialogResult::kAccepted, 1);
ExpectEnrollSystemPromptResult(
SecurePaymentConfirmationEnrollSystemPromptResult::kAccepted, 1);
ExpectNoFunnelCount();
ExpectJourneyLoggerEvent(/*spc_confirm_logged=*/false);
}
Expand Down Expand Up @@ -503,6 +574,12 @@ IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationCreationTest,
"postToIframe($1, $2);",
https_server()->GetURL("c.com", "/iframe_receiver.html").spec(),
credentialIdentifier)));
ExpectEnrollDialogShown(SecurePaymentConfirmationEnrollDialogShown::kShown,
1);
ExpectEnrollDialogResult(
SecurePaymentConfirmationEnrollDialogResult::kAccepted, 1);
ExpectEnrollSystemPromptResult(
SecurePaymentConfirmationEnrollSystemPromptResult::kAccepted, 1);
ExpectFunnelCount(SecurePaymentConfirmationSystemPromptResult::kAccepted, 1);
ExpectJourneyLoggerEvent(/*spc_confirm_logged=*/true);
}
Expand Down Expand Up @@ -564,6 +641,12 @@ IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationCreationTest,
content::JsReplace("getChallengeWithModifierAndShowPromise($1, $2);",
credentialIdentifier, "0.04")));

ExpectEnrollDialogShown(SecurePaymentConfirmationEnrollDialogShown::kShown,
1);
ExpectEnrollDialogResult(
SecurePaymentConfirmationEnrollDialogResult::kAccepted, 1);
ExpectEnrollSystemPromptResult(
SecurePaymentConfirmationEnrollSystemPromptResult::kAccepted, 1);
ExpectFunnelCount(SecurePaymentConfirmationSystemPromptResult::kAccepted, 4);
ExpectJourneyLoggerEvent(/*spc_confirm_logged=*/true);
}
Expand Down Expand Up @@ -592,6 +675,12 @@ IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationCreationTest,
content::JsReplace("getChallenge($1, $2);",
credentialIdentifier, "0.01")));

ExpectEnrollDialogShown(SecurePaymentConfirmationEnrollDialogShown::kShown,
1);
ExpectEnrollDialogResult(
SecurePaymentConfirmationEnrollDialogResult::kAccepted, 1);
ExpectEnrollSystemPromptResult(
SecurePaymentConfirmationEnrollSystemPromptResult::kAccepted, 1);
ExpectFunnelCount(SecurePaymentConfirmationSystemPromptResult::kCanceled, 1);
ExpectJourneyLoggerEvent(/*spc_confirm_logged=*/true);
}
Expand All @@ -609,6 +698,11 @@ IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationCreationTest, NonexistentIcon) {
"createCredentialAndReturnItsIdentifier($1)",
https_server()->GetURL("a.com", "/nonexistent.png").spec()))
.error);

ExpectEnrollDialogShown(
SecurePaymentConfirmationEnrollDialogShown::kCouldNotShow, 1);
ExpectNoEnrollDialogResult();
ExpectNoEnrollSystemPromptResult();
ExpectNoFunnelCount();
ExpectJourneyLoggerEvent(/*spc_confirm_logged=*/false);
}
Expand All @@ -630,6 +724,9 @@ IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationCreationTest, InsecureIcon) {
content::JsReplace("createCredentialAndReturnItsIdentifier($1)",
icon_url))
.error);
ExpectNoEnrollDialogShown();
ExpectNoEnrollDialogResult();
ExpectNoEnrollSystemPromptResult();
ExpectNoFunnelCount();
ExpectJourneyLoggerEvent(/*spc_confirm_logged=*/false);
}
Expand All @@ -653,6 +750,13 @@ IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationCreationTest,
// Verify that credential id size gets recorded.
histogram_tester_.ExpectTotalCount(
"PaymentRequest.SecurePaymentConfirmationCredentialIdSizeInBytes", 2U);

ExpectEnrollDialogShown(SecurePaymentConfirmationEnrollDialogShown::kShown,
2);
ExpectEnrollDialogResult(
SecurePaymentConfirmationEnrollDialogResult::kAccepted, 2);
ExpectEnrollSystemPromptResult(
SecurePaymentConfirmationEnrollSystemPromptResult::kAccepted, 2);
ExpectNoFunnelCount();
ExpectJourneyLoggerEvent(/*spc_confirm_logged=*/false);
}
Expand All @@ -674,6 +778,12 @@ IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationCreationTest,
GetActiveWebContents()->Close();
event_waiter_->Wait();

ExpectEnrollDialogShown(SecurePaymentConfirmationEnrollDialogShown::kShown,
1);
ExpectEnrollDialogResult(
SecurePaymentConfirmationEnrollDialogResult::kAccepted, 1);
ExpectEnrollSystemPromptResult(
SecurePaymentConfirmationEnrollSystemPromptResult::kCanceled, 1);
ExpectNoFunnelCount();
ExpectJourneyLoggerEvent(/*spc_confirm_logged=*/false);
}
Expand All @@ -694,6 +804,13 @@ IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationCreationTest,
GetDefaultIconURL()))
.error);

ExpectEnrollDialogShown(SecurePaymentConfirmationEnrollDialogShown::kShown,
1);
ExpectEnrollDialogResult(
SecurePaymentConfirmationEnrollDialogResult::kAccepted, 1);
ExpectEnrollSystemPromptResult(
SecurePaymentConfirmationEnrollSystemPromptResult::kCanceled, 1);

ReplaceFidoDiscoveryFactory(/*should_succeed=*/true);
std::string credentialIdentifier =
content::EvalJs(
Expand All @@ -716,6 +833,23 @@ IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationCreationTest,
content::JsReplace("getChallenge($1, $2);",
credentialIdentifier, "0.01")));

ExpectEnrollDialogShown(SecurePaymentConfirmationEnrollDialogShown::kShown,
2);
ExpectEnrollDialogResult(
SecurePaymentConfirmationEnrollDialogResult::kAccepted, 2);
histogram_tester_.ExpectTotalCount(
"PaymentRequest.SecurePaymentConfirmation.Funnel."
"EnrollSystemPromptResult",
2);
histogram_tester_.ExpectBucketCount(
"PaymentRequest.SecurePaymentConfirmation.Funnel."
"EnrollSystemPromptResult",
SecurePaymentConfirmationEnrollSystemPromptResult::kCanceled, 1);
histogram_tester_.ExpectBucketCount(
"PaymentRequest.SecurePaymentConfirmation.Funnel."
"EnrollSystemPromptResult",
SecurePaymentConfirmationEnrollSystemPromptResult::kAccepted, 1);

ExpectFunnelCount(SecurePaymentConfirmationSystemPromptResult::kAccepted, 1);
ExpectJourneyLoggerEvent(/*spc_confirm_logged=*/true);
}
Expand Down Expand Up @@ -754,6 +888,10 @@ IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationCreationTest,
GetActiveWebContents()->Close();
event_waiter_->Wait();

ExpectEnrollDialogShown(
SecurePaymentConfirmationEnrollDialogShown::kCouldNotShow, 1);
ExpectNoEnrollDialogResult();
ExpectNoEnrollSystemPromptResult();
ExpectNoFunnelCount();
ExpectJourneyLoggerEvent(/*spc_confirm_logged=*/false);
}
Expand Down
51 changes: 48 additions & 3 deletions components/payments/content/payment_credential.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ void PaymentCredential::DownloadIconAndShowUserPrompt(
if (state_ != State::kIdle || !IsCurrentStateValid() || !instrument ||
instrument->display_name.empty() ||
!UrlUtil::IsOriginAllowedToUseWebPaymentApis(instrument->icon)) {
RecordFirstDialogShown(
SecurePaymentConfirmationEnrollDialogShown::kCouldNotShow);
Reset();
std::move(callback).Run(
mojom::PaymentCredentialUserPromptStatus::FAILED_TO_DOWNLOAD_ICON);
Expand All @@ -67,6 +69,8 @@ void PaymentCredential::DownloadIconAndShowUserPrompt(
->GetWeakPtr();
ui_controller_token_ = ui_controller_->GetTokenIfAvailable();
if (!ui_controller_token_) {
RecordFirstDialogShown(
SecurePaymentConfirmationEnrollDialogShown::kCouldNotShow);
Reset();
std::move(callback).Run(
mojom::PaymentCredentialUserPromptStatus::FAILED_TO_DOWNLOAD_ICON);
Expand Down Expand Up @@ -101,6 +105,9 @@ void PaymentCredential::StorePaymentCredentialAndHideUserPrompt(
return;
}

RecordFirstSystemPromptResult(
SecurePaymentConfirmationEnrollSystemPromptResult::kAccepted);

storage_callback_ = std::move(callback);
state_ = State::kStoringCredential;
data_service_request_handle_ =
Expand All @@ -112,7 +119,12 @@ void PaymentCredential::StorePaymentCredentialAndHideUserPrompt(
}

void PaymentCredential::HideUserPrompt(HideUserPromptCallback callback) {
DCHECK_EQ(State::kMakingCredential, state_);
if (state_ == State::kMakingCredential) {
RecordFirstSystemPromptResult(
SecurePaymentConfirmationEnrollSystemPromptResult::kCanceled);
} else {
NOTREACHED();
}
DCHECK(IsCurrentStateValid());

Reset();
Expand All @@ -130,6 +142,7 @@ void PaymentCredential::OnWebDataServiceRequestDone(

auto callback = std::move(storage_callback_);
Reset();

std::move(callback).Run(
static_cast<WDResult<bool>*>(result.get())->GetValue()
? mojom::PaymentCredentialStorageStatus::SUCCESS
Expand Down Expand Up @@ -213,6 +226,8 @@ void PaymentCredential::DidDownloadIcon(
instrument_name.empty() ||
request_id != pending_icon_download_request_id_.value() ||
bitmaps.empty()) {
RecordFirstDialogShown(
SecurePaymentConfirmationEnrollDialogShown::kCouldNotShow);
Reset();
return;
}
Expand All @@ -227,6 +242,7 @@ void PaymentCredential::DidDownloadIcon(
encoded_icon_ =
std::vector<uint8_t>(raw_data->front_as<uint8_t>(),
raw_data->front_as<uint8_t>() + raw_data->size());
RecordFirstDialogShown(SecurePaymentConfirmationEnrollDialogShown::kShown);

state_ = State::kShowingUserPrompt;
ui_controller_->ShowDialog(
Expand All @@ -236,8 +252,7 @@ void PaymentCredential::DidDownloadIcon(
weak_ptr_factory_.GetWeakPtr()));
}

void PaymentCredential::OnUserResponseFromUI(
bool user_confirm_from_ui) {
void PaymentCredential::OnUserResponseFromUI(bool user_confirm_from_ui) {
if (state_ != State::kShowingUserPrompt || !IsCurrentStateValid() ||
!user_confirm_from_ui) {
Reset();
Expand All @@ -249,6 +264,22 @@ void PaymentCredential::OnUserResponseFromUI(
.Run(mojom::PaymentCredentialUserPromptStatus::USER_CONFIRM_FROM_UI);
}

void PaymentCredential::RecordFirstDialogShown(
SecurePaymentConfirmationEnrollDialogShown shown) {
if (!is_dialog_shown_recorded_) {
is_dialog_shown_recorded_ = true;
RecordEnrollDialogShown(shown);
}
}

void PaymentCredential::RecordFirstSystemPromptResult(
SecurePaymentConfirmationEnrollSystemPromptResult result) {
if (!is_system_prompt_result_recorded_) {
is_system_prompt_result_recorded_ = true;
RecordEnrollSystemPromptResult(result);
}
}

void PaymentCredential::Reset() {
// Callbacks must either be run or disconnected before being destroyed, so
// run them if they are still connected.
Expand All @@ -267,16 +298,30 @@ void PaymentCredential::Reset() {
FAILED_TO_DOWNLOAD_ICON);
}
}

if (web_data_service_ && data_service_request_handle_) {
web_data_service_->CancelRequest(data_service_request_handle_.value());
}

if (state_ == State::kDownloadingIcon) {
RecordFirstDialogShown(
SecurePaymentConfirmationEnrollDialogShown::kCouldNotShow);
}

if (state_ == State::kMakingCredential) {
RecordFirstSystemPromptResult(
SecurePaymentConfirmationEnrollSystemPromptResult::kCanceled);
}

data_service_request_handle_.reset();
encoded_icon_.clear();
pending_icon_download_request_id_.reset();
ui_controller_token_.reset();
if (ui_controller_)
ui_controller_->CloseDialog();
ui_controller_.reset();
is_dialog_shown_recorded_ = false;
is_system_prompt_result_recorded_ = false;
state_ = State::kIdle;
}

Expand Down
Loading

0 comments on commit 60fa474

Please sign in to comment.