1 // Copyright 2020 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/supervised_user/supervised_user_extensions_metrics_recorder.h"
6 
7 #include "base/check.h"
8 #include "base/metrics/histogram_functions.h"
9 #include "base/metrics/user_metrics.h"
10 #include "base/time/default_tick_clock.h"
11 
12 // static
13 const char SupervisedUserExtensionsMetricsRecorder::kExtensionsHistogramName[] =
14     "SupervisedUsers.Extensions2";
15 const char
16     SupervisedUserExtensionsMetricsRecorder::kApprovalGrantedActionName[] =
17         "SupervisedUsers_Extensions_ApprovalGranted";
18 const char SupervisedUserExtensionsMetricsRecorder::
19     kPermissionsIncreaseGrantedActionName[] =
20         "SupervisedUsers_Extensions_PermissionsIncreaseGranted";
21 const char
22     SupervisedUserExtensionsMetricsRecorder::kApprovalRemovedActionName[] =
23         "SupervisedUsers_Extensions_ApprovalRemoved";
24 // Extension Install Dialog.
25 const char SupervisedUserExtensionsMetricsRecorder::
26     kExtensionInstallDialogHistogramName[] =
27         "SupervisedUsers.ExtensionInstallDialog";
28 const char SupervisedUserExtensionsMetricsRecorder::
29     kExtensionInstallDialogAskedParentTimeHistogramName[] =
30         "SupervisedUsers.ExtensionInstallDialog.AskedParentUserTime";
31 const char SupervisedUserExtensionsMetricsRecorder::
32     kExtensionInstallDialogChildCanceledTimeHistogramName[] =
33         "SupervisedUsers.ExtensionInstallDialog.ChildCanceledUserTime";
34 const char SupervisedUserExtensionsMetricsRecorder::
35     kExtensionInstallDialogOpenedActionName[] =
36         "SupervisedUsers_Extensions_ExtensionInstallDialog_Opened";
37 const char SupervisedUserExtensionsMetricsRecorder::
38     kExtensionInstallDialogAskedParentActionName[] =
39         "SupervisedUsers_Extensions_ExtensionInstallDialog_AskedParent";
40 const char SupervisedUserExtensionsMetricsRecorder::
41     kExtensionInstallDialogChildCanceledActionName[] =
42         "SupervisedUsers_Extensions_ExtensionInstallDialog_ChildCanceled";
43 // Parent Permission Dialog.
44 const char SupervisedUserExtensionsMetricsRecorder::
45     kParentPermissionDialogHistogramName[] =
46         "SupervisedUsers.ParentPermissionDialog";
47 const char SupervisedUserExtensionsMetricsRecorder::
48     kParentPermissionDialogParentApprovedTimeHistogramName[] =
49         "SupervisedUsers.ParentPermissionDialog.ParentApprovedUserTime";
50 const char SupervisedUserExtensionsMetricsRecorder::
51     kParentPermissionDialogParentCanceledTimeHistogramName[] =
52         "SupervisedUsers.ParentPermissionDialog.ParentCanceledUserTime";
53 const char SupervisedUserExtensionsMetricsRecorder::
54     kParentPermissionDialogFailedTimeHistogramName[] =
55         "SupervisedUsers.ParentPermissionDialog.FailedUserTime";
56 const char SupervisedUserExtensionsMetricsRecorder::
57     kParentPermissionDialogOpenedActionName[] =
58         "SupervisedUsers_Extensions_ParentPermissionDialog_Opened";
59 const char SupervisedUserExtensionsMetricsRecorder::
60     kParentPermissionDialogParentApprovedActionName[] =
61         "SupervisedUsers_Extensions_ParentPermissionDialog_ParentApproved";
62 const char SupervisedUserExtensionsMetricsRecorder::
63     kParentPermissionDialogParentCanceledActionName[] =
64         "SupervisedUsers_Extensions_ParentPermissionDialog_ParentCanceled";
65 // Enabling and disabling extensions.
66 const char SupervisedUserExtensionsMetricsRecorder::kEnablementHistogramName[] =
67     "SupervisedUsers.ExtensionEnablement";
68 const char SupervisedUserExtensionsMetricsRecorder::kEnabledActionName[] =
69     "SupervisedUsers_Extensions_Enabled";
70 const char SupervisedUserExtensionsMetricsRecorder::kDisabledActionName[] =
71     "SupervisedUsers_Extensions_Disabled";
72 const char
73     SupervisedUserExtensionsMetricsRecorder::kFailedToEnableActionName[] =
74         "SupervisedUsers_Extensions_FailedToEnable";
75 
76 SupervisedUserExtensionsMetricsRecorder::
SupervisedUserExtensionsMetricsRecorder()77     SupervisedUserExtensionsMetricsRecorder()
78     : clock_(base::DefaultTickClock::GetInstance()) {}
79 
OnDialogOpened()80 void SupervisedUserExtensionsMetricsRecorder::OnDialogOpened() {
81   RecordExtensionInstallDialogUmaMetrics(ExtensionInstallDialogState::kOpened);
82 }
83 
OnDialogAccepted()84 void SupervisedUserExtensionsMetricsRecorder::OnDialogAccepted() {
85   RecordExtensionInstallDialogUmaMetrics(
86       ExtensionInstallDialogState::kAskedParent);
87 }
88 
OnDialogCanceled()89 void SupervisedUserExtensionsMetricsRecorder::OnDialogCanceled() {
90   RecordExtensionInstallDialogUmaMetrics(
91       ExtensionInstallDialogState::kChildCanceled);
92 }
93 
94 // static
RecordExtensionsUmaMetrics(UmaExtensionState state)95 void SupervisedUserExtensionsMetricsRecorder::RecordExtensionsUmaMetrics(
96     UmaExtensionState state) {
97   base::UmaHistogramEnumeration(kExtensionsHistogramName, state);
98   switch (state) {
99     case UmaExtensionState::kApprovalGranted:
100       // Record UMA metrics for custodian approval for a new extension.
101       base::RecordAction(base::UserMetricsAction(kApprovalGrantedActionName));
102       break;
103     case UmaExtensionState::kPermissionsIncreaseGranted:
104       // Record UMA metrics for child approval for a newer version of an
105       // existing extension with increased permissions.
106       base::RecordAction(
107           base::UserMetricsAction(kPermissionsIncreaseGrantedActionName));
108       break;
109     case UmaExtensionState::kApprovalRemoved:
110       // Record UMA metrics for removing an extension.
111       base::RecordAction(base::UserMetricsAction(kApprovalRemovedActionName));
112       break;
113   }
114 }
115 
116 void SupervisedUserExtensionsMetricsRecorder::
RecordExtensionInstallDialogUmaMetrics(ExtensionInstallDialogState state)117     RecordExtensionInstallDialogUmaMetrics(ExtensionInstallDialogState state) {
118   base::UmaHistogramEnumeration(kExtensionInstallDialogHistogramName, state);
119   switch (state) {
120     case ExtensionInstallDialogState::kOpened:
121       base::RecordAction(
122           base::UserMetricsAction(kExtensionInstallDialogOpenedActionName));
123       start_time_ = clock_->NowTicks();
124       break;
125     case ExtensionInstallDialogState::kAskedParent:
126       base::RecordAction(base::UserMetricsAction(
127           kExtensionInstallDialogAskedParentActionName));
128       RecordUserTime(kExtensionInstallDialogAskedParentTimeHistogramName);
129       break;
130     case ExtensionInstallDialogState::kChildCanceled:
131       base::RecordAction(base::UserMetricsAction(
132           kExtensionInstallDialogChildCanceledActionName));
133       RecordUserTime(kExtensionInstallDialogChildCanceledTimeHistogramName);
134       break;
135   }
136 }
137 
138 void SupervisedUserExtensionsMetricsRecorder::
RecordParentPermissionDialogUmaMetrics(ParentPermissionDialogState state)139     RecordParentPermissionDialogUmaMetrics(ParentPermissionDialogState state) {
140   base::UmaHistogramEnumeration(kParentPermissionDialogHistogramName, state);
141   switch (state) {
142     case ParentPermissionDialogState::kOpened:
143       base::RecordAction(
144           base::UserMetricsAction(kParentPermissionDialogOpenedActionName));
145       start_time_ = clock_->NowTicks();
146       break;
147     case ParentPermissionDialogState::kParentApproved:
148       base::RecordAction(base::UserMetricsAction(
149           kParentPermissionDialogParentApprovedActionName));
150       RecordUserTime(kParentPermissionDialogParentApprovedTimeHistogramName);
151       break;
152     case ParentPermissionDialogState::kParentCanceled:
153       base::RecordAction(base::UserMetricsAction(
154           kParentPermissionDialogParentCanceledActionName));
155       RecordUserTime(kParentPermissionDialogParentCanceledTimeHistogramName);
156       break;
157     case ParentPermissionDialogState::kFailed:
158       RecordUserTime(kParentPermissionDialogFailedTimeHistogramName);
159       break;
160     case ParentPermissionDialogState::kNoParentError:
161       // Nothing to do here.
162       break;
163   }
164 }
165 
166 // static
RecordEnablementUmaMetrics(EnablementState state)167 void SupervisedUserExtensionsMetricsRecorder::RecordEnablementUmaMetrics(
168     EnablementState state) {
169   base::UmaHistogramEnumeration(kEnablementHistogramName, state);
170   switch (state) {
171     case EnablementState::kEnabled:
172       base::RecordAction(base::UserMetricsAction(kEnabledActionName));
173       break;
174     case EnablementState::kDisabled:
175       base::RecordAction(base::UserMetricsAction(kDisabledActionName));
176       break;
177     case EnablementState::kFailedToEnable:
178       base::RecordAction(base::UserMetricsAction(kFailedToEnableActionName));
179       break;
180   }
181 }
182 
SetClockForTesting(const base::TickClock * tick_clock)183 void SupervisedUserExtensionsMetricsRecorder::SetClockForTesting(
184     const base::TickClock* tick_clock) {
185   clock_ = tick_clock;
186 }
187 
RecordUserTime(const std::string & metric_name) const188 void SupervisedUserExtensionsMetricsRecorder::RecordUserTime(
189     const std::string& metric_name) const {
190   DCHECK(!start_time_.is_null()) << "start_time_ has not been initialized.";
191   base::TimeDelta duration = clock_->NowTicks() - start_time_;
192   base::UmaHistogramLongTimes(metric_name, duration);
193 }
194