blob: 62ca71afa7ffcc009b170a7fcf187d1ca5d79668 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/webid/fedcm_metrics.h"
#include "base/metrics/histogram_functions.h"
#include "base/types/pass_key.h"
#include "content/browser/webid/flags.h"
#include "services/metrics/public/cpp/metrics_utils.h"
#include "url/gurl.h"
namespace content {
FedCmMetrics::FedCmMetrics(const GURL& provider,
ukm::SourceId page_source_id,
int session_id,
bool is_disabled)
: page_source_id_(page_source_id),
provider_source_id_(ukm::UkmRecorder::GetSourceIdForWebIdentityFromScope(
base::PassKey<FedCmMetrics>(),
provider)),
session_id_(session_id),
is_disabled_(is_disabled) {}
void FedCmMetrics::RecordShowAccountsDialogTime(base::TimeDelta duration) {
if (is_disabled_)
return;
auto RecordUkm = [&](auto& ukm_builder) {
ukm_builder.SetTiming_ShowAccountsDialog(
ukm::GetExponentialBucketMinForUserTiming(duration.InMilliseconds()));
ukm_builder.SetFedCmSessionID(session_id_);
ukm_builder.Record(ukm::UkmRecorder::Get());
};
ukm::builders::Blink_FedCm fedcm_builder(page_source_id_);
RecordUkm(fedcm_builder);
ukm::builders::Blink_FedCmIdp fedcm_idp_builder(provider_source_id_);
RecordUkm(fedcm_idp_builder);
base::UmaHistogramMediumTimes("Blink.FedCm.Timing.ShowAccountsDialog",
duration);
}
void FedCmMetrics::RecordContinueOnDialogTime(base::TimeDelta duration) {
if (is_disabled_)
return;
auto RecordUkm = [&](auto& ukm_builder) {
ukm_builder.SetTiming_ContinueOnDialog(
ukm::GetExponentialBucketMinForUserTiming(duration.InMilliseconds()));
ukm_builder.SetFedCmSessionID(session_id_);
ukm_builder.Record(ukm::UkmRecorder::Get());
};
ukm::builders::Blink_FedCm fedcm_builder(page_source_id_);
RecordUkm(fedcm_builder);
ukm::builders::Blink_FedCmIdp fedcm_idp_builder(provider_source_id_);
RecordUkm(fedcm_idp_builder);
base::UmaHistogramMediumTimes("Blink.FedCm.Timing.ContinueOnDialog",
duration);
}
void FedCmMetrics::RecordCancelOnDialogTime(base::TimeDelta duration) {
if (is_disabled_)
return;
auto RecordUkm = [&](auto& ukm_builder) {
ukm_builder.SetTiming_CancelOnDialog(
ukm::GetExponentialBucketMinForUserTiming(duration.InMilliseconds()));
ukm_builder.SetFedCmSessionID(session_id_);
ukm_builder.Record(ukm::UkmRecorder::Get());
};
ukm::builders::Blink_FedCm fedcm_builder(page_source_id_);
RecordUkm(fedcm_builder);
ukm::builders::Blink_FedCmIdp fedcm_idp_builder(provider_source_id_);
RecordUkm(fedcm_idp_builder);
base::UmaHistogramMediumTimes("Blink.FedCm.Timing.CancelOnDialog", duration);
}
void FedCmMetrics::RecordCancelReason(
IdentityRequestDialogController::DismissReason dismiss_reason) {
if (is_disabled_)
return;
base::UmaHistogramEnumeration("Blink.FedCm.CancelReason", dismiss_reason);
}
void FedCmMetrics::RecordTokenResponseAndTurnaroundTime(
base::TimeDelta token_response_time,
base::TimeDelta turnaround_time) {
if (is_disabled_)
return;
auto RecordUkm = [&](auto& ukm_builder) {
ukm_builder
.SetTiming_IdTokenResponse(ukm::GetExponentialBucketMinForUserTiming(
token_response_time.InMilliseconds()))
.SetTiming_TurnaroundTime(ukm::GetExponentialBucketMinForUserTiming(
turnaround_time.InMilliseconds()));
ukm_builder.SetFedCmSessionID(session_id_);
ukm_builder.Record(ukm::UkmRecorder::Get());
};
ukm::builders::Blink_FedCm fedcm_builder(page_source_id_);
RecordUkm(fedcm_builder);
ukm::builders::Blink_FedCmIdp fedcm_idp_builder(provider_source_id_);
RecordUkm(fedcm_idp_builder);
base::UmaHistogramMediumTimes("Blink.FedCm.Timing.IdTokenResponse",
token_response_time);
base::UmaHistogramMediumTimes("Blink.FedCm.Timing.TurnaroundTime",
turnaround_time);
}
void FedCmMetrics::RecordRequestTokenStatus(FedCmRequestIdTokenStatus status) {
if (is_disabled_)
return;
// If the request has failed but we have not yet rejected the promise,
// e.g. when the user has declined the permission or the API is disabled
// etc., we have already recorded a RequestTokenStatus. i.e.
// `request_token_status_recorded_` would be true. In this case, we
// shouldn't record another RequestTokenStatus.
if (request_token_status_recorded_) {
return;
}
request_token_status_recorded_ = true;
auto RecordUkm = [&](auto& ukm_builder) {
ukm_builder.SetStatus_RequestIdToken(static_cast<int>(status));
ukm_builder.SetFedCmSessionID(session_id_);
ukm_builder.Record(ukm::UkmRecorder::Get());
};
ukm::builders::Blink_FedCm fedcm_builder(page_source_id_);
RecordUkm(fedcm_builder);
ukm::builders::Blink_FedCmIdp fedcm_idp_builder(provider_source_id_);
RecordUkm(fedcm_idp_builder);
base::UmaHistogramEnumeration("Blink.FedCm.Status.RequestIdToken", status);
}
void FedCmMetrics::RecordSignInStateMatchStatus(
FedCmSignInStateMatchStatus status) {
if (is_disabled_)
return;
auto RecordUkm = [&](auto& ukm_builder) {
ukm_builder.SetStatus_SignInStateMatch(static_cast<int>(status));
ukm_builder.SetFedCmSessionID(session_id_);
ukm_builder.Record(ukm::UkmRecorder::Get());
};
ukm::builders::Blink_FedCmIdp fedcm_idp_builder(provider_source_id_);
RecordUkm(fedcm_idp_builder);
base::UmaHistogramEnumeration("Blink.FedCm.Status.SignInStateMatch", status);
}
void FedCmMetrics::RecordIdpSigninMatchStatus(
absl::optional<bool> idp_signin_status,
IdpNetworkRequestManager::ParseStatus accounts_endpoint_status) {
if (is_disabled_)
return;
FedCmIdpSigninMatchStatus match_status = FedCmIdpSigninMatchStatus::kMaxValue;
if (!idp_signin_status.has_value()) {
match_status =
(accounts_endpoint_status ==
IdpNetworkRequestManager::ParseStatus::kSuccess)
? FedCmIdpSigninMatchStatus::kUnknownStatusWithAccounts
: FedCmIdpSigninMatchStatus::kUnknownStatusWithoutAccounts;
} else if (idp_signin_status.value()) {
switch (accounts_endpoint_status) {
case IdpNetworkRequestManager::ParseStatus::kHttpNotFoundError:
match_status = FedCmIdpSigninMatchStatus::kMismatchWithNetworkError;
break;
case IdpNetworkRequestManager::ParseStatus::kNoResponseError:
match_status = FedCmIdpSigninMatchStatus::kMismatchWithNoContent;
break;
case IdpNetworkRequestManager::ParseStatus::kInvalidResponseError:
match_status = FedCmIdpSigninMatchStatus::kMismatchWithInvalidResponse;
break;
case IdpNetworkRequestManager::ParseStatus::kEmptyListError:
match_status = FedCmIdpSigninMatchStatus::kMismatchWithNoContent;
break;
case IdpNetworkRequestManager::ParseStatus::kSuccess:
match_status = FedCmIdpSigninMatchStatus::kMatchWithAccounts;
break;
}
} else {
match_status =
(accounts_endpoint_status ==
IdpNetworkRequestManager::ParseStatus::kSuccess)
? FedCmIdpSigninMatchStatus::kMismatchWithUnexpectedAccounts
: FedCmIdpSigninMatchStatus::kMatchWithoutAccounts;
}
base::UmaHistogramEnumeration("Blink.FedCm.Status.IdpSigninMatch",
match_status);
}
void FedCmMetrics::RecordIsSignInUser(bool is_sign_in) {
if (is_disabled_)
return;
base::UmaHistogramBoolean("Blink.FedCm.IsSignInUser", is_sign_in);
}
void FedCmMetrics::RecordWebContentsVisibilityUponReadyToShowDialog(
bool is_visible) {
if (is_disabled_)
return;
base::UmaHistogramBoolean("Blink.FedCm.WebContentsVisible", is_visible);
}
void FedCmMetrics::RecordAutoReauthnMetrics(
bool has_single_returning_account,
const IdentityRequestAccount* auto_signin_account,
bool auto_reauthn_success,
bool is_auto_reauthn_setting_blocked,
bool is_auto_reauthn_embargoed,
absl::optional<base::TimeDelta> time_from_embargo) {
NumReturningAccounts num_returning_accounts = NumReturningAccounts::kZero;
if (has_single_returning_account) {
num_returning_accounts = NumReturningAccounts::kOne;
} else if (auto_signin_account) {
num_returning_accounts = NumReturningAccounts::kMultiple;
}
base::UmaHistogramEnumeration("Blink.FedCm.AutoReauthn.ReturningAccounts",
num_returning_accounts);
base::UmaHistogramBoolean("Blink.FedCm.AutoReauthn.Succeeded",
auto_reauthn_success);
base::UmaHistogramBoolean("Blink.FedCm.AutoReauthn.BlockedByContentSettings",
is_auto_reauthn_setting_blocked);
base::UmaHistogramBoolean("Blink.FedCm.AutoReauthn.BlockedByEmbargo",
is_auto_reauthn_embargoed);
ukm::builders::Blink_FedCm ukm_builder(page_source_id_);
if (time_from_embargo) {
// Use a custom histogram with the default number of buckets so that we set
// the maximum to the permission embargo duration: 10 minutes. See
// `kFederatedIdentityAutoReauthnEmbargoDuration`.
base::UmaHistogramCustomTimes(
"Blink.FedCm.AutoReauthn.TimeFromEmbargoWhenBlocked",
*time_from_embargo, base::Milliseconds(10), base::Minutes(10),
/*buckets=*/50);
ukm_builder.SetAutoReauthn_TimeFromEmbargoWhenBlocked(
ukm::GetExponentialBucketMinForUserTiming(
time_from_embargo->InMilliseconds()));
}
ukm_builder.SetAutoReauthn_ReturningAccounts(
static_cast<int>(num_returning_accounts));
ukm_builder.SetAutoReauthn_Succeeded(auto_reauthn_success);
ukm_builder.SetAutoReauthn_BlockedByContentSettings(
is_auto_reauthn_setting_blocked);
ukm_builder.SetAutoReauthn_BlockedByEmbargo(is_auto_reauthn_embargoed);
ukm_builder.SetFedCmSessionID(session_id_);
ukm_builder.Record(ukm::UkmRecorder::Get());
}
void RecordApprovedClientsExistence(bool has_approved_clients) {
if (IsFedCmMultipleIdentityProvidersEnabled())
return;
base::UmaHistogramBoolean("Blink.FedCm.ApprovedClientsExistence",
has_approved_clients);
}
void RecordApprovedClientsSize(int size) {
if (IsFedCmMultipleIdentityProvidersEnabled())
return;
base::UmaHistogramCounts10000("Blink.FedCm.ApprovedClientsSize", size);
}
} // namespace content