1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/login/enterprise_user_session_metrics.h"
6
7 #include <algorithm>
8
9 #include "base/check.h"
10 #include "base/metrics/histogram_functions.h"
11 #include "base/metrics/histogram_macros.h"
12 #include "base/notreached.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/browser_process_platform_part.h"
15 #include "chrome/browser/chromeos/login/demo_mode/demo_session.h"
16 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
17 #include "chrome/common/pref_names.h"
18 #include "chromeos/login/auth/user_context.h"
19 #include "components/prefs/pref_registry_simple.h"
20 #include "components/prefs/pref_service.h"
21
22 namespace {
23
24 // Returns true if the device is enterprise managed, false otherwise.
IsEnterpriseManaged()25 bool IsEnterpriseManaged() {
26 return g_browser_process->platform_part()
27 ->browser_policy_connector_chromeos()
28 ->IsEnterpriseManaged();
29 }
30
31 // Returns the duration in minutes, capped at `max_duration` and rounded down to
32 // the nearest `bucket_size` minutes.
GetMinutesToReport(base::TimeDelta duration,int bucket_size,base::TimeDelta max_duration)33 int GetMinutesToReport(base::TimeDelta duration,
34 int bucket_size,
35 base::TimeDelta max_duration) {
36 int minutes = std::min(duration.InMinutes(), max_duration.InMinutes());
37 return minutes / bucket_size * bucket_size;
38 }
39
40 } // namespace
41
42 namespace chromeos {
43 namespace enterprise_user_session_metrics {
44
RegisterPrefs(PrefRegistrySimple * registry)45 void RegisterPrefs(PrefRegistrySimple* registry) {
46 registry->RegisterIntegerPref(prefs::kLastSessionType, 0);
47 registry->RegisterInt64Pref(prefs::kLastSessionLength, 0);
48 }
49
RecordSignInEvent(SignInEventType sign_in_event_type)50 void RecordSignInEvent(SignInEventType sign_in_event_type) {
51 DCHECK(IsEnterpriseManaged());
52
53 UMA_HISTOGRAM_ENUMERATION(
54 "Enterprise.UserSession.Logins", static_cast<int>(sign_in_event_type),
55 static_cast<int>(SignInEventType::SIGN_IN_EVENT_COUNT));
56 }
57
RecordSignInEvent(const UserContext & user_context,bool is_auto_login)58 void RecordSignInEvent(const UserContext& user_context, bool is_auto_login) {
59 DCHECK(IsEnterpriseManaged());
60
61 const user_manager::UserType session_type = user_context.GetUserType();
62 if (session_type == user_manager::USER_TYPE_REGULAR) {
63 RecordSignInEvent(SignInEventType::REGULAR_USER);
64 } else if (session_type == user_manager::USER_TYPE_PUBLIC_ACCOUNT) {
65 RecordSignInEvent(is_auto_login ? SignInEventType::AUTOMATIC_PUBLIC_SESSION
66 : SignInEventType::MANUAL_PUBLIC_SESSION);
67 }
68
69 // Kiosk sign-ins are handled separately in AppLaunchController and other
70 // session types are ignored for now.
71 }
72
StoreSessionLength(user_manager::UserType session_type,const base::TimeDelta & session_length)73 void StoreSessionLength(user_manager::UserType session_type,
74 const base::TimeDelta& session_length) {
75 DCHECK(IsEnterpriseManaged());
76
77 if (session_type != user_manager::USER_TYPE_REGULAR &&
78 session_type != user_manager::USER_TYPE_PUBLIC_ACCOUNT) {
79 // No session length metric for other session types.
80 return;
81 }
82
83 PrefService* local_state = g_browser_process->local_state();
84 local_state->SetInteger(prefs::kLastSessionType, session_type);
85 local_state->SetInt64(prefs::kLastSessionLength,
86 session_length.ToInternalValue());
87 local_state->CommitPendingWrite();
88 }
89
RecordStoredSessionLength()90 void RecordStoredSessionLength() {
91 DCHECK(IsEnterpriseManaged());
92
93 PrefService* local_state = g_browser_process->local_state();
94 if (!local_state->HasPrefPath(prefs::kLastSessionType) ||
95 !local_state->HasPrefPath(prefs::kLastSessionLength)) {
96 return;
97 }
98
99 const user_manager::UserType session_type =
100 static_cast<user_manager::UserType>(
101 local_state->GetInteger(prefs::kLastSessionType));
102 const base::TimeDelta session_length = base::TimeDelta::FromInternalValue(
103 local_state->GetInt64(prefs::kLastSessionLength));
104
105 local_state->ClearPref(prefs::kLastSessionType);
106 local_state->ClearPref(prefs::kLastSessionLength);
107
108 if (session_length.is_zero())
109 return;
110
111 std::string metric_name;
112 if (session_type == user_manager::USER_TYPE_REGULAR) {
113 metric_name = "Enterprise.RegularUserSession.SessionLength";
114 } else if (session_type == user_manager::USER_TYPE_PUBLIC_ACCOUNT) {
115 metric_name = "Enterprise.PublicSession.SessionLength";
116 } else {
117 // NOTREACHED() since session length for other session types should not
118 // be recorded.
119 NOTREACHED();
120 return;
121 }
122
123 // Report session duration for the first 24 hours, split into 144 buckets
124 // (i.e. every 10 minute). Note that sparse histogram is used here. It is
125 // important to limit the number of buckets to something reasonable.
126 base::UmaHistogramSparse(
127 metric_name,
128 GetMinutesToReport(session_length, 10, base::TimeDelta::FromHours(24)));
129
130 if (chromeos::DemoSession::IsDeviceInDemoMode()) {
131 // Demo mode sessions will have shorter durations. Report session length
132 // rounded down to the nearest minute, up to two hours.
133 base::UmaHistogramSparse(
134 "DemoMode.SessionLength",
135 GetMinutesToReport(session_length, 1, base::TimeDelta::FromHours(2)));
136 }
137 }
138
139 } // namespace enterprise_user_session_metrics
140 } // namespace chromeos
141