1// Copyright 2019 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/media/webrtc/system_media_capture_permissions_stats_mac.h"
6
7#include "base/metrics/histogram_functions.h"
8#include "chrome/browser/browser_process.h"
9#include "chrome/browser/media/webrtc/system_media_capture_permissions_mac.h"
10#include "components/prefs/pref_registry_simple.h"
11#include "components/prefs/pref_service.h"
12
13namespace system_media_permissions {
14
15namespace {
16
17const char kSystemPermissionMicFirstBlockedTimePref[] =
18    "system_permission.mic.first_blocked_time";
19const char kSystemPermissionMicLastBlockedTimePref[] =
20    "system_permission.mic.last_blocked_time";
21const char kSystemPermissionCameraFirstBlockedTimePref[] =
22    "system_permission.camera.first_blocked_time";
23const char kSystemPermissionCameraLastBlockedTimePref[] =
24    "system_permission.camera.last_blocked_time";
25
26void LogStartupMicSystemPermission(SystemPermission permission) {
27  base::UmaHistogramEnumeration(
28      "Media.Audio.Capture.Mac.MicSystemPermission.Startup", permission);
29}
30
31void LogStartupCameraSystemPermission(SystemPermission permission) {
32  base::UmaHistogramEnumeration(
33      "Media.Video.Capture.Mac.CameraSystemPermission.Startup", permission);
34}
35
36void MaybeLogAdditionalMicSystemPermissionStats(SystemPermission permission) {
37  PrefService* prefs = g_browser_process->local_state();
38
39  if (!prefs->HasPrefPath(kSystemPermissionMicFirstBlockedTimePref)) {
40    DCHECK(!prefs->HasPrefPath(kSystemPermissionMicLastBlockedTimePref));
41    return;
42  }
43
44  // A pref exists, so there was a failure accessing the mic due to blocked
45  // system permission before the last restart. Log additional stats.
46
47  DCHECK(prefs->HasPrefPath(kSystemPermissionMicLastBlockedTimePref));
48  base::UmaHistogramEnumeration("Media.Audio.Capture.Mac.MicSystemPermission."
49                                "StartupAfterFailure",
50                                permission);
51
52  // If the state has changed to allowed, log the time it took since first
53  // and last failure before restart. Check for positive time delta, since
54  // the system clock may change at any time.
55  if (permission == SystemPermission::kAllowed) {
56    base::Time stored_time =
57        prefs->GetTime(kSystemPermissionMicFirstBlockedTimePref);
58    base::TimeDelta time_delta = base::Time::Now() - stored_time;
59    if (time_delta > base::TimeDelta()) {
60      base::UmaHistogramCustomTimes(
61          "Media.Audio.Capture.Mac.MicSystemPermission."
62          "FixedTime.SinceFirstFailure",
63          time_delta, base::TimeDelta::FromSeconds(1),
64          base::TimeDelta::FromHours(1), 50);
65    }
66
67    stored_time = prefs->GetTime(kSystemPermissionMicLastBlockedTimePref);
68    time_delta = base::Time::Now() - stored_time;
69    if (time_delta > base::TimeDelta()) {
70      base::UmaHistogramCustomTimes(
71          "Media.Audio.Capture.Mac.MicSystemPermission."
72          "FixedTime.SinceLastFailure",
73          time_delta, base::TimeDelta::FromSeconds(1),
74          base::TimeDelta::FromHours(1), 50);
75    }
76  }
77
78  prefs->ClearPref(kSystemPermissionMicFirstBlockedTimePref);
79  prefs->ClearPref(kSystemPermissionMicLastBlockedTimePref);
80}
81
82void MaybeLogAdditionalCameraSystemPermissionStats(
83    SystemPermission permission) {
84  PrefService* prefs = g_browser_process->local_state();
85
86  if (!prefs->HasPrefPath(kSystemPermissionCameraFirstBlockedTimePref)) {
87    DCHECK(!prefs->HasPrefPath(kSystemPermissionCameraLastBlockedTimePref));
88    return;
89  }
90
91  // A pref exists, so there was a failure accessing the camera due to blocked
92  // system permission before the last restart. Log additional stats.
93
94  DCHECK(prefs->HasPrefPath(kSystemPermissionCameraLastBlockedTimePref));
95  base::UmaHistogramEnumeration(
96      "Media.Video.Capture.Mac.CameraSystemPermission."
97      "StartupAfterFailure",
98      permission);
99
100  // If the state has changed to allowed, log the time it took since first
101  // and last failure before restart. Check for positive time delta, since
102  // the system clock may change at any time.
103  if (permission == SystemPermission::kAllowed) {
104    base::Time stored_time =
105        prefs->GetTime(kSystemPermissionCameraFirstBlockedTimePref);
106    base::TimeDelta time_delta = base::Time::Now() - stored_time;
107    if (time_delta > base::TimeDelta()) {
108      base::UmaHistogramCustomTimes(
109          "Media.Video.Capture.Mac.CameraSystemPermission.FixedTime."
110          "SinceFirstFailure",
111          time_delta, base::TimeDelta::FromSeconds(1),
112          base::TimeDelta::FromHours(1), 50);
113    }
114
115    stored_time = prefs->GetTime(kSystemPermissionCameraLastBlockedTimePref);
116    time_delta = base::Time::Now() - stored_time;
117    if (time_delta > base::TimeDelta()) {
118      base::UmaHistogramCustomTimes(
119          "Media.Video.Capture.Mac.CameraSystemPermission.FixedTime."
120          "SinceLastFailure",
121          time_delta, base::TimeDelta::FromSeconds(1),
122          base::TimeDelta::FromHours(1), 50);
123    }
124  }
125
126  prefs->ClearPref(kSystemPermissionCameraFirstBlockedTimePref);
127  prefs->ClearPref(kSystemPermissionCameraLastBlockedTimePref);
128}
129
130}  // namespace
131
132void RegisterSystemMediaPermissionStatesPrefs(PrefRegistrySimple* registry) {
133  if (@available(macOS 10.14, *)) {
134    registry->RegisterTimePref(kSystemPermissionMicFirstBlockedTimePref,
135                               base::Time());
136    registry->RegisterTimePref(kSystemPermissionMicLastBlockedTimePref,
137                               base::Time());
138    registry->RegisterTimePref(kSystemPermissionCameraFirstBlockedTimePref,
139                               base::Time());
140    registry->RegisterTimePref(kSystemPermissionCameraLastBlockedTimePref,
141                               base::Time());
142  }
143}
144
145void LogSystemMediaPermissionsStartupStats() {
146  if (@available(macOS 10.14, *)) {
147    const SystemPermission audio_permission =
148        CheckSystemAudioCapturePermission();
149    LogStartupMicSystemPermission(audio_permission);
150    MaybeLogAdditionalMicSystemPermissionStats(audio_permission);
151
152    const SystemPermission video_permission =
153        CheckSystemVideoCapturePermission();
154    LogStartupCameraSystemPermission(video_permission);
155    MaybeLogAdditionalCameraSystemPermissionStats(video_permission);
156  }  // (@available(macOS 10.14, *))
157}
158
159void SystemAudioCapturePermissionDetermined(SystemPermission permission) {
160  if (@available(macOS 10.14, *)) {
161    DCHECK_NE(permission, SystemPermission::kNotDetermined);
162    LogStartupMicSystemPermission(permission);
163  }
164}
165
166void SystemVideoCapturePermissionDetermined(SystemPermission permission) {
167  if (@available(macOS 10.14, *)) {
168    DCHECK_NE(permission, SystemPermission::kNotDetermined);
169    LogStartupCameraSystemPermission(permission);
170  }
171}
172
173void SystemAudioCapturePermissionBlocked() {
174  if (@available(macOS 10.14, *)) {
175    PrefService* prefs = g_browser_process->local_state();
176    if (!prefs->HasPrefPath(kSystemPermissionMicFirstBlockedTimePref)) {
177      prefs->SetTime(kSystemPermissionMicFirstBlockedTimePref,
178                     base::Time::Now());
179    }
180    prefs->SetTime(kSystemPermissionMicLastBlockedTimePref, base::Time::Now());
181  }
182}
183
184void SystemVideoCapturePermissionBlocked() {
185  if (@available(macOS 10.14, *)) {
186    PrefService* prefs = g_browser_process->local_state();
187    if (!prefs->HasPrefPath(kSystemPermissionCameraFirstBlockedTimePref)) {
188      prefs->SetTime(kSystemPermissionCameraFirstBlockedTimePref,
189                     base::Time::Now());
190    }
191    prefs->SetTime(kSystemPermissionCameraLastBlockedTimePref,
192                   base::Time::Now());
193  }
194}
195
196}  // namespace system_media_permissions
197