File: active_session_auth_metrics_recorder.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (185 lines) | stat: -rw-r--r-- 6,803 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/auth/active_session_auth_metrics_recorder.h"

#include <optional>

#include "ash/ash_export.h"
#include "ash/auth/views/auth_common.h"
#include "ash/public/cpp/auth/active_session_auth_controller.h"
#include "base/check.h"
#include "base/check_op.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/notreached.h"
#include "base/timer/elapsed_timer.h"

namespace ash {

namespace {

// Constants for histograms.
constexpr char kShowReasonHistogram[] = "Ash.Auth.ActiveSessionShowReason";
constexpr char kAuthStartedHistogram[] = "Ash.Auth.ActiveSessionAuthStart";
constexpr char kAuthFailedHistogram[] = "Ash.Auth.ActiveSessionAuthFailed";
constexpr char kAuthSucceededHistogram[] =
    "Ash.Auth.ActiveSessionAuthSucceeded";
constexpr char kClosedWithSuccessHistogram[] =
    "Ash.Auth.ActiveSessionAuthClosedWithSuccess";
constexpr char kClosedDuringAuthHistogram[] =
    "Ash.Auth.ActiveSessionAuthClosedDuringAuth";
constexpr char kOpenDurationHistogram[] =
    "Ash.Auth.ActiveSessionAuthOpenDuration";
constexpr char kNumberOfPinAttemptHistogram[] =
    "Ash.Auth.ActiveSessionAuthPinAttempt";
constexpr char kNumberOfPasswordAttemptHistogram[] =
    "Ash.Auth.ActiveSessionAuthPasswordAttempt";
constexpr char kNumberOfFingerprintAttemptHistogram[] =
    "Ash.Auth.ActiveSessionAuthFingerprintAttempt";
constexpr char kClosedPasswordlessUserWithSuccessHistogram[] =
    "Ash.Auth.ActiveSessionPasswordlessAuthClosedWithSuccess";

// The ceiling to use when clamping the number of PIN attempts that can be
// recorded for UMA collection.
constexpr int kMaxRecordedPinAttempts = 20;

// The ceiling to use when clamping the number of Password attempts that can be
// recorded for UMA collection.
constexpr int kMaxRecordedPasswordAttempts = 20;

// The ceiling to use when clamping the number of Fingerprint attempts that can
// be recorded for UMA collection.
constexpr int kMaxRecordedFingerprintAttempts = 20;

}  // namespace

ActiveSessionAuthMetricsRecorder::ActiveSessionAuthMetricsRecorder() = default;

ActiveSessionAuthMetricsRecorder::~ActiveSessionAuthMetricsRecorder() = default;

void ActiveSessionAuthMetricsRecorder::RecordShow(
    AuthRequest::Reason reason,
    AuthFactorSet available_factors) {
  CHECK(!open_reason_.has_value());
  CHECK(!open_timer_.has_value());

  // Record to metric the reason when the ActiveSessionAuthWidget is shown.
  base::UmaHistogramEnumeration(kShowReasonHistogram, reason);

  open_reason_ = reason;
  available_factors_ = available_factors;
  open_timer_.emplace(base::ElapsedTimer());
}

void ActiveSessionAuthMetricsRecorder::RecordClose() {
  CHECK(open_reason_.has_value());
  CHECK(open_timer_.has_value());

  // Record to metric the dialog was closed after authentication succeeded or
  // not.
  base::UmaHistogramBoolean(kClosedWithSuccessHistogram, auth_succeeded_);

  if (!available_factors_.Has(AuthInputType::kPassword)) {
    base::UmaHistogramBoolean(kClosedPasswordlessUserWithSuccessHistogram,
                              auth_succeeded_);
  }

  // Record to metric the dialog was closed during authentication or not.
  base::UmaHistogramBoolean(kClosedDuringAuthHistogram,
                            started_auth_type_.has_value());

  // Record to metric how long was the dialog opened.
  base::UmaHistogramMediumTimes(kOpenDurationHistogram, open_timer_->Elapsed());

  // Record to metric the number of pin attempts.
  base::UmaHistogramExactLinear(kNumberOfPinAttemptHistogram,
                                pin_attempt_counter_, kMaxRecordedPinAttempts);

  // Record to metric the number of password attempts.
  base::UmaHistogramExactLinear(kNumberOfPasswordAttemptHistogram,
                                password_attempt_counter_,
                                kMaxRecordedPasswordAttempts);

  // Record to metric the number of fingerprint attempts.
  base::UmaHistogramExactLinear(kNumberOfFingerprintAttemptHistogram,
                                fingerprint_attempt_counter_,
                                kMaxRecordedFingerprintAttempts);

  // Reset the state.
  auth_succeeded_ = false;
  available_factors_.Clear();
  pin_attempt_counter_ = 0;
  password_attempt_counter_ = 0;
  fingerprint_attempt_counter_ = 0;
  started_auth_type_.reset();
  open_reason_.reset();
  open_timer_.reset();
}

void ActiveSessionAuthMetricsRecorder::RecordAuthStarted(
    AuthInputType input_type) {
  CHECK(!started_auth_type_.has_value());
  switch (input_type) {
    case AuthInputType::kPassword:
      ++password_attempt_counter_;
      break;
    case AuthInputType::kPin:
      ++pin_attempt_counter_;
      break;
    case AuthInputType::kFingerprint:
      // Fingerprint authentication begins when the authentication dialog is
      // shown and the user has fingerprint record(s) and the policy doesn't
      // prevent its use. The fingerprint session remains active until
      // explicitly terminated, so even after a failed scan attempt, there's no
      // need to restart it. This session runs concurrently with password/PIN
      // authentication attempts. Therefore, we are not tracking "Authentication
      // Started" events for fingerprint specifically, but rather focusing on
      // the count of successful and failed attempts.
      NOTREACHED();
    default:
      NOTREACHED();
  }
  started_auth_type_ = input_type;

  // Record to metric the auth input type when an authentication started.
  base::UmaHistogramEnumeration(kAuthStartedHistogram, input_type);
}

void ActiveSessionAuthMetricsRecorder::RecordAuthFailed(
    AuthInputType input_type) {
  // Fingerprint authentication can occur concurrently with other
  // AuthInputType's.
  if (input_type == AuthInputType::kFingerprint) {
    ++fingerprint_attempt_counter_;
  } else {
    CHECK(started_auth_type_.has_value());
    CHECK_EQ(started_auth_type_.value(), input_type);

    started_auth_type_.reset();
  }

  // Record to metric the failed authentication type.
  base::UmaHistogramEnumeration(kAuthFailedHistogram, input_type);
}

void ActiveSessionAuthMetricsRecorder::RecordAuthSucceeded(
    AuthInputType input_type) {
  // Fingerprint authentication can occur concurrently with other
  // AuthInputType's.
  if (input_type == AuthInputType::kFingerprint) {
    ++fingerprint_attempt_counter_;
  } else {
    CHECK(started_auth_type_.has_value());
    CHECK_EQ(started_auth_type_.value(), input_type);
  }

  // Record to metric the succeeded authentication type.
  base::UmaHistogramEnumeration(kAuthSucceededHistogram, input_type);

  started_auth_type_.reset();
  auth_succeeded_ = true;
}

}  // namespace ash