1 // Copyright 2013 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 "ash/metrics/user_metrics_recorder.h"
6 
7 #include <memory>
8 #include <vector>
9 
10 #include "ash/login/ui/lock_screen.h"
11 #include "ash/metrics/demo_session_metrics_recorder.h"
12 #include "ash/metrics/desktop_task_switch_metric_recorder.h"
13 #include "ash/metrics/pointer_metrics_recorder.h"
14 #include "ash/public/cpp/accessibility_controller_enums.h"
15 #include "ash/public/cpp/shelf_item.h"
16 #include "ash/public/cpp/shelf_model.h"
17 #include "ash/public/cpp/shell_window_ids.h"
18 #include "ash/session/session_controller_impl.h"
19 #include "ash/shelf/shelf.h"
20 #include "ash/shelf/shelf_view.h"
21 #include "ash/shell.h"
22 #include "ash/wm/desks/desks_util.h"
23 #include "ash/wm/window_state.h"
24 #include "base/metrics/histogram_macros.h"
25 #include "base/metrics/user_metrics.h"
26 #include "ui/aura/window.h"
27 
28 namespace ash {
29 
30 namespace {
31 
32 using ::chromeos::WindowStateType;
33 
34 // Time in seconds between calls to "RecordPeriodicMetrics".
35 const int kAshPeriodicMetricsTimeInSeconds = 30 * 60;
36 
37 enum ActiveWindowStateType {
38   ACTIVE_WINDOW_STATE_TYPE_NO_ACTIVE_WINDOW,
39   ACTIVE_WINDOW_STATE_TYPE_OTHER,
40   ACTIVE_WINDOW_STATE_TYPE_MAXIMIZED,
41   ACTIVE_WINDOW_STATE_TYPE_FULLSCREEN,
42   ACTIVE_WINDOW_STATE_TYPE_SNAPPED,
43   ACTIVE_WINDOW_STATE_TYPE_PINNED,
44   ACTIVE_WINDOW_STATE_TYPE_TRUSTED_PINNED,
45   ACTIVE_WINDOW_STATE_TYPE_PIP,
46   ACTIVE_WINDOW_STATE_TYPE_COUNT,
47 };
48 
GetActiveWindowState()49 ActiveWindowStateType GetActiveWindowState() {
50   ActiveWindowStateType active_window_state_type =
51       ACTIVE_WINDOW_STATE_TYPE_NO_ACTIVE_WINDOW;
52   WindowState* active_window_state = WindowState::ForActiveWindow();
53   if (active_window_state) {
54     switch (active_window_state->GetStateType()) {
55       case WindowStateType::kMaximized:
56         active_window_state_type = ACTIVE_WINDOW_STATE_TYPE_MAXIMIZED;
57         break;
58       case WindowStateType::kFullscreen:
59         active_window_state_type = ACTIVE_WINDOW_STATE_TYPE_FULLSCREEN;
60         break;
61       case WindowStateType::kLeftSnapped:
62       case WindowStateType::kRightSnapped:
63         active_window_state_type = ACTIVE_WINDOW_STATE_TYPE_SNAPPED;
64         break;
65       case WindowStateType::kPinned:
66         active_window_state_type = ACTIVE_WINDOW_STATE_TYPE_PINNED;
67         break;
68       case WindowStateType::kTrustedPinned:
69         active_window_state_type = ACTIVE_WINDOW_STATE_TYPE_TRUSTED_PINNED;
70         break;
71       case WindowStateType::kPip:
72         active_window_state_type = ACTIVE_WINDOW_STATE_TYPE_PIP;
73         break;
74       case WindowStateType::kDefault:
75       case WindowStateType::kNormal:
76       case WindowStateType::kMinimized:
77       case WindowStateType::kInactive:
78       case WindowStateType::kAutoPositioned:
79         active_window_state_type = ACTIVE_WINDOW_STATE_TYPE_OTHER;
80         break;
81     }
82   }
83   return active_window_state_type;
84 }
85 
86 // Returns true if kiosk mode is active.
IsKioskModeActive()87 bool IsKioskModeActive() {
88   return Shell::Get()->session_controller()->login_status() ==
89          LoginStatus::KIOSK_APP;
90 }
91 
92 // Returns true if there is an active user and their session isn't currently
93 // locked.
IsUserActive()94 bool IsUserActive() {
95   SessionControllerImpl* session = Shell::Get()->session_controller();
96   return session->IsActiveUserSessionStarted() && !session->IsScreenLocked();
97 }
98 
99 // Returns a list of window container ids that contain visible windows to be
100 // counted for UMA statistics. Note the containers are ordered from top most
101 // visible container to the lowest to allow the |GetNumVisibleWindows| method to
102 // short circuit when processing a maximized or fullscreen window.
GetVisibleWindowContainerIds()103 std::vector<int> GetVisibleWindowContainerIds() {
104   std::vector<int> ids{kShellWindowId_PipContainer,
105                        kShellWindowId_AlwaysOnTopContainer};
106   // TODO(afakhry): Add metrics for the inactive desks.
107   ids.emplace_back(desks_util::GetActiveDeskContainerId());
108   return ids;
109 }
110 
111 // Returns an approximate count of how many windows are currently visible in the
112 // primary root window.
GetNumVisibleWindowsInPrimaryDisplay()113 int GetNumVisibleWindowsInPrimaryDisplay() {
114   int visible_window_count = 0;
115   bool maximized_or_fullscreen_window_present = false;
116 
117   for (const int& current_container_id : GetVisibleWindowContainerIds()) {
118     if (maximized_or_fullscreen_window_present)
119       break;
120 
121     const aura::Window::Windows& children =
122         Shell::GetContainer(Shell::Get()->GetPrimaryRootWindow(),
123                             current_container_id)
124             ->children();
125     // Reverse iterate over the child windows so that they are processed in
126     // visible stacking order.
127     for (aura::Window::Windows::const_reverse_iterator it = children.rbegin(),
128                                                        rend = children.rend();
129          it != rend; ++it) {
130       const aura::Window* child_window = *it;
131       const WindowState* child_window_state = WindowState::Get(child_window);
132 
133       if (!child_window->IsVisible() || child_window_state->IsMinimized())
134         continue;
135 
136       // Only count activatable windows for 1 reason:
137       //  - Ensures that a browser window and its transient, modal child will
138       //    only count as 1 visible window.
139       if (child_window_state->CanActivate())
140         ++visible_window_count;
141 
142       // Stop counting windows that will be hidden by maximized or fullscreen
143       // windows. Only windows in the active desk container and
144       // kShellWindowId_AlwaysOnTopContainer can be maximized or fullscreened
145       // and completely obscure windows beneath them.
146       if (child_window_state->IsMaximizedOrFullscreenOrPinned()) {
147         maximized_or_fullscreen_window_present = true;
148         break;
149       }
150     }
151   }
152   return visible_window_count;
153 }
154 
155 // Records the number of items in the shelf as an UMA statistic.
RecordShelfItemCounts()156 void RecordShelfItemCounts() {
157   int pinned_item_count = 0;
158   int unpinned_item_count = 0;
159   for (const ShelfItem& item : ShelfModel::Get()->items()) {
160     if (item.type == TYPE_PINNED_APP || item.type == TYPE_BROWSER_SHORTCUT)
161       ++pinned_item_count;
162     else
163       ++unpinned_item_count;
164   }
165 
166   UMA_HISTOGRAM_COUNTS_100("Ash.Shelf.NumberOfItems",
167                            pinned_item_count + unpinned_item_count);
168   UMA_HISTOGRAM_COUNTS_100("Ash.Shelf.NumberOfPinnedItems", pinned_item_count);
169   UMA_HISTOGRAM_COUNTS_100("Ash.Shelf.NumberOfUnpinnedItems",
170                            unpinned_item_count);
171 }
172 
173 }  // namespace
174 
UserMetricsRecorder()175 UserMetricsRecorder::UserMetricsRecorder() {
176   StartTimer();
177   login_metrics_recorder_ = std::make_unique<LoginMetricsRecorder>();
178 }
179 
UserMetricsRecorder(bool record_periodic_metrics)180 UserMetricsRecorder::UserMetricsRecorder(bool record_periodic_metrics) {
181   if (record_periodic_metrics)
182     StartTimer();
183 }
184 
~UserMetricsRecorder()185 UserMetricsRecorder::~UserMetricsRecorder() {
186   timer_.Stop();
187 }
188 
189 // static
RecordUserClickOnTray(LoginMetricsRecorder::TrayClickTarget target)190 void UserMetricsRecorder::RecordUserClickOnTray(
191     LoginMetricsRecorder::TrayClickTarget target) {
192   LoginMetricsRecorder* recorder =
193       Shell::Get()->metrics()->login_metrics_recorder();
194   recorder->RecordUserTrayClick(target);
195 }
196 
197 // static
RecordUserClickOnShelfButton(LoginMetricsRecorder::ShelfButtonClickTarget target)198 void UserMetricsRecorder::RecordUserClickOnShelfButton(
199     LoginMetricsRecorder::ShelfButtonClickTarget target) {
200   LoginMetricsRecorder* recorder =
201       Shell::Get()->metrics()->login_metrics_recorder();
202   recorder->RecordUserShelfButtonClick(target);
203 }
204 
205 // static
RecordUserToggleDictation(DictationToggleSource source)206 void UserMetricsRecorder::RecordUserToggleDictation(
207     DictationToggleSource source) {
208   UMA_HISTOGRAM_ENUMERATION("Accessibility.CrosDictation.ToggleDictationMethod",
209                             source);
210 }
211 
RecordUserMetricsAction(UserMetricsAction action)212 void UserMetricsRecorder::RecordUserMetricsAction(UserMetricsAction action) {
213   using base::RecordAction;
214   using base::UserMetricsAction;
215 
216   switch (action) {
217     case UMA_DESKTOP_SWITCH_TASK:
218       RecordAction(UserMetricsAction("Desktop_SwitchTask"));
219       task_switch_metrics_recorder_.OnTaskSwitch(TaskSwitchSource::DESKTOP);
220       break;
221     case UMA_LAUNCHER_BUTTON_PRESSED_WITH_MOUSE:
222       RecordAction(UserMetricsAction("Launcher_ButtonPressed_Mouse"));
223       break;
224     case UMA_LAUNCHER_BUTTON_PRESSED_WITH_TOUCH:
225       RecordAction(UserMetricsAction("Launcher_ButtonPressed_Touch"));
226       break;
227     case UMA_LAUNCHER_CLICK_ON_APP:
228       RecordAction(UserMetricsAction("Launcher_ClickOnApp"));
229       break;
230     case UMA_LAUNCHER_CLICK_ON_APPLIST_BUTTON:
231       RecordAction(UserMetricsAction("Launcher_ClickOnApplistButton"));
232       break;
233     case UMA_LAUNCHER_LAUNCH_TASK:
234       RecordAction(UserMetricsAction("Launcher_LaunchTask"));
235       task_switch_metrics_recorder_.OnTaskSwitch(TaskSwitchSource::SHELF);
236       break;
237     case UMA_LAUNCHER_MINIMIZE_TASK:
238       RecordAction(UserMetricsAction("Launcher_MinimizeTask"));
239       break;
240     case UMA_LAUNCHER_SWITCH_TASK:
241       RecordAction(UserMetricsAction("Launcher_SwitchTask"));
242       task_switch_metrics_recorder_.OnTaskSwitch(TaskSwitchSource::SHELF);
243       break;
244     case UMA_SHELF_ALIGNMENT_SET_BOTTOM:
245       RecordAction(UserMetricsAction("Shelf_AlignmentSetBottom"));
246       break;
247     case UMA_SHELF_ALIGNMENT_SET_LEFT:
248       RecordAction(UserMetricsAction("Shelf_AlignmentSetLeft"));
249       break;
250     case UMA_SHELF_ALIGNMENT_SET_RIGHT:
251       RecordAction(UserMetricsAction("Shelf_AlignmentSetRight"));
252       break;
253     case UMA_STATUS_AREA_AUDIO_CURRENT_INPUT_DEVICE:
254       RecordAction(UserMetricsAction("StatusArea_Audio_CurrentInputDevice"));
255       break;
256     case UMA_STATUS_AREA_AUDIO_CURRENT_OUTPUT_DEVICE:
257       RecordAction(UserMetricsAction("StatusArea_Audio_CurrentOutputDevice"));
258       break;
259     case UMA_STATUS_AREA_AUDIO_SWITCH_INPUT_DEVICE:
260       RecordAction(UserMetricsAction("StatusArea_Audio_SwitchInputDevice"));
261       break;
262     case UMA_STATUS_AREA_AUDIO_SWITCH_OUTPUT_DEVICE:
263       RecordAction(UserMetricsAction("StatusArea_Audio_SwitchOutputDevice"));
264       break;
265     case UMA_STATUS_AREA_BRIGHTNESS_CHANGED:
266       RecordAction(UserMetricsAction("StatusArea_BrightnessChanged"));
267       break;
268     case UMA_STATUS_AREA_BLUETOOTH_DISABLED:
269       RecordAction(UserMetricsAction("StatusArea_Bluetooth_Disabled"));
270       break;
271     case UMA_STATUS_AREA_BLUETOOTH_ENABLED:
272       RecordAction(UserMetricsAction("StatusArea_Bluetooth_Enabled"));
273       break;
274     case UMA_STATUS_AREA_CAPS_LOCK_DETAILED:
275       RecordAction(UserMetricsAction("StatusArea_CapsLock_Detailed"));
276       break;
277     case UMA_STATUS_AREA_CAPS_LOCK_DISABLED_BY_CLICK:
278       RecordAction(UserMetricsAction("StatusArea_CapsLock_DisabledByClick"));
279       break;
280     case UMA_STATUS_AREA_CAPS_LOCK_ENABLED_BY_CLICK:
281       RecordAction(UserMetricsAction("StatusArea_CapsLock_EnabledByClick"));
282       break;
283     case UMA_STATUS_AREA_CAPS_LOCK_POPUP:
284       RecordAction(UserMetricsAction("StatusArea_CapsLock_Popup"));
285       break;
286     case UMA_STATUS_AREA_CAST_STOP_CAST:
287       RecordAction(UserMetricsAction("StatusArea_Cast_StopCast"));
288       break;
289     case UMA_STATUS_AREA_CONNECT_TO_CONFIGURED_NETWORK:
290       RecordAction(UserMetricsAction("StatusArea_Network_ConnectConfigured"));
291       break;
292     case UMA_STATUS_AREA_CONNECT_TO_UNCONFIGURED_NETWORK:
293       RecordAction(UserMetricsAction("StatusArea_Network_ConnectUnconfigured"));
294       break;
295     case UMA_STATUS_AREA_CONNECT_TO_VPN:
296       RecordAction(UserMetricsAction("StatusArea_VPN_ConnectToNetwork"));
297       break;
298     case UMA_STATUS_AREA_CHANGED_VOLUME_MENU:
299       RecordAction(UserMetricsAction("StatusArea_Volume_ChangedMenu"));
300       break;
301     case UMA_STATUS_AREA_CHANGED_VOLUME_POPUP:
302       RecordAction(UserMetricsAction("StatusArea_Volume_ChangedPopup"));
303       break;
304     case UMA_STATUS_AREA_DETAILED_ACCESSIBILITY:
305       RecordAction(UserMetricsAction("StatusArea_Accessability_DetailedView"));
306       break;
307     case UMA_STATUS_AREA_DETAILED_AUDIO_VIEW:
308       RecordAction(UserMetricsAction("StatusArea_Audio_Detailed"));
309       break;
310     case UMA_STATUS_AREA_DETAILED_BLUETOOTH_VIEW:
311       RecordAction(UserMetricsAction("StatusArea_Bluetooth_Detailed"));
312       break;
313     case UMA_STATUS_AREA_DETAILED_BRIGHTNESS_VIEW:
314       RecordAction(UserMetricsAction("StatusArea_Brightness_Detailed"));
315       break;
316     case UMA_STATUS_AREA_DETAILED_CAST_VIEW:
317       RecordAction(UserMetricsAction("StatusArea_Cast_Detailed"));
318       break;
319     case UMA_STATUS_AREA_DETAILED_CAST_VIEW_LAUNCH_CAST:
320       RecordAction(UserMetricsAction("StatusArea_Cast_Detailed_Launch_Cast"));
321       break;
322     case UMA_STATUS_AREA_DETAILED_DRIVE_VIEW:
323       RecordAction(UserMetricsAction("StatusArea_Drive_Detailed"));
324       break;
325     case UMA_STATUS_AREA_DETAILED_NETWORK_VIEW:
326       RecordAction(UserMetricsAction("StatusArea_Network_Detailed"));
327       break;
328     case UMA_STATUS_AREA_DETAILED_SMS_VIEW:
329       RecordAction(UserMetricsAction("StatusArea_SMS_Detailed"));
330       break;
331     case UMA_STATUS_AREA_DETAILED_VPN_VIEW:
332       RecordAction(UserMetricsAction("StatusArea_VPN_Detailed"));
333       break;
334     case UMA_STATUS_AREA_DISPLAY_DEFAULT_SELECTED:
335       RecordAction(UserMetricsAction("StatusArea_Display_Default_Selected"));
336       break;
337     case UMA_STATUS_AREA_DISPLAY_DEFAULT_SHOW_SETTINGS:
338       RecordAction(
339           UserMetricsAction("StatusArea_Display_Default_ShowSettings"));
340       break;
341     case UMA_STATUS_AREA_DISPLAY_NOTIFICATION_CREATED:
342       RecordAction(
343           UserMetricsAction("StatusArea_Display_Notification_Created"));
344       break;
345     case UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SELECTED:
346       RecordAction(
347           UserMetricsAction("StatusArea_Display_Notification_Selected"));
348       break;
349     case UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SHOW_SETTINGS:
350       RecordAction(
351           UserMetricsAction("StatusArea_Display_Notification_Show_Settings"));
352       break;
353     case UMA_STATUS_AREA_DISABLE_WIFI:
354       RecordAction(UserMetricsAction("StatusArea_Network_WifiDisabled"));
355       break;
356     case UMA_STATUS_AREA_DRIVE_CANCEL_OPERATION:
357       RecordAction(UserMetricsAction("StatusArea_Drive_CancelOperation"));
358       break;
359     case UMA_STATUS_AREA_DRIVE_SETTINGS:
360       RecordAction(UserMetricsAction("StatusArea_Drive_Settings"));
361       break;
362     case UMA_STATUS_AREA_ENABLE_WIFI:
363       RecordAction(UserMetricsAction("StatusArea_Network_WifiEnabled"));
364       break;
365     case UMA_STATUS_AREA_MENU_OPENED:
366       RecordAction(UserMetricsAction("StatusArea_MenuOpened"));
367       break;
368     case UMA_STATUS_AREA_NETWORK_JOIN_OTHER_CLICKED:
369       RecordAction(UserMetricsAction("StatusArea_Network_JoinOther"));
370       break;
371     case UMA_STATUS_AREA_NETWORK_SETTINGS_OPENED:
372       RecordAction(UserMetricsAction("StatusArea_Network_Settings"));
373       break;
374     case UMA_STATUS_AREA_OS_UPDATE_DEFAULT_SELECTED:
375       RecordAction(UserMetricsAction("StatusArea_OS_Update_Default_Selected"));
376       break;
377     case UMA_STATUS_AREA_SCREEN_CAPTURE_CHANGE_SOURCE:
378       RecordAction(UserMetricsAction("StatusArea_ScreenCapture_Change_Source"));
379       break;
380     case UMA_STATUS_AREA_SCREEN_CAPTURE_DEFAULT_STOP:
381       RecordAction(UserMetricsAction("StatusArea_ScreenCapture_Default_Stop"));
382       break;
383     case UMA_STATUS_AREA_SCREEN_CAPTURE_NOTIFICATION_STOP:
384       RecordAction(
385           UserMetricsAction("StatusArea_ScreenCapture_Notification_Stop"));
386       break;
387     case UMA_STATUS_AREA_SHOW_NETWORK_CONNECTION_DETAILS:
388       RecordAction(UserMetricsAction("StatusArea_Network_ConnectionDetails"));
389       break;
390     case UMA_STATUS_AREA_SHOW_VPN_CONNECTION_DETAILS:
391       RecordAction(UserMetricsAction("StatusArea_VPN_ConnectionDetails"));
392       break;
393     case UMA_STATUS_AREA_SIGN_OUT:
394       RecordAction(UserMetricsAction("StatusArea_SignOut"));
395       break;
396     case UMA_STATUS_AREA_SMS_DETAILED_DISMISS_MSG:
397       RecordAction(UserMetricsAction("StatusArea_SMS_Detailed_DismissMsg"));
398       break;
399     case UMA_STATUS_AREA_SMS_NOTIFICATION_DISMISS_MSG:
400       RecordAction(UserMetricsAction("StatusArea_SMS_Notification_DismissMsg"));
401       break;
402     case UMA_STATUS_AREA_TRACING_DEFAULT_SELECTED:
403       RecordAction(UserMetricsAction("StatusArea_Tracing_Default_Selected"));
404       break;
405     case UMA_STATUS_AREA_VPN_ADD_BUILT_IN_CLICKED:
406       RecordAction(UserMetricsAction("StatusArea_VPN_AddBuiltIn"));
407       break;
408     case UMA_STATUS_AREA_VPN_ADD_THIRD_PARTY_CLICKED:
409       RecordAction(UserMetricsAction("StatusArea_VPN_AddThirdParty"));
410       break;
411     case UMA_STATUS_AREA_VPN_DISCONNECT_CLICKED:
412       RecordAction(UserMetricsAction("StatusArea_VPN_Disconnect"));
413       break;
414     case UMA_STATUS_AREA_VPN_SETTINGS_OPENED:
415       RecordAction(UserMetricsAction("StatusArea_VPN_Settings"));
416       break;
417     case UMA_TRAY_HELP:
418       RecordAction(UserMetricsAction("Tray_Help"));
419       break;
420     case UMA_TRAY_LOCK_SCREEN:
421       RecordAction(UserMetricsAction("Tray_LockScreen"));
422       break;
423     case UMA_TRAY_NIGHT_LIGHT:
424       RecordAction(UserMetricsAction("Tray_NightLight"));
425       break;
426     case UMA_TRAY_OVERVIEW:
427       RecordAction(UserMetricsAction("Tray_Overview"));
428       break;
429     case UMA_TRAY_SETTINGS:
430       RecordAction(UserMetricsAction("Tray_Settings"));
431       break;
432     case UMA_TRAY_SHUT_DOWN:
433       RecordAction(UserMetricsAction("Tray_ShutDown"));
434       break;
435   }
436 }
437 
StartDemoSessionMetricsRecording()438 void UserMetricsRecorder::StartDemoSessionMetricsRecording() {
439   demo_session_metrics_recorder_ =
440       std::make_unique<DemoSessionMetricsRecorder>();
441 }
442 
OnShellInitialized()443 void UserMetricsRecorder::OnShellInitialized() {
444   // Lazy creation of the DesktopTaskSwitchMetricRecorder because it accesses
445   // Shell::Get() which is not available when |this| is instantiated.
446   if (!desktop_task_switch_metric_recorder_) {
447     desktop_task_switch_metric_recorder_.reset(
448         new DesktopTaskSwitchMetricRecorder());
449   }
450   pointer_metrics_recorder_ = std::make_unique<PointerMetricsRecorder>();
451 }
452 
OnShellShuttingDown()453 void UserMetricsRecorder::OnShellShuttingDown() {
454   demo_session_metrics_recorder_.reset();
455   desktop_task_switch_metric_recorder_.reset();
456 
457   // To clean up pointer_metrics_recorder_ properly, a valid shell instance is
458   // required, so explicitly delete it before the shell instance becomes
459   // invalid.
460   pointer_metrics_recorder_.reset();
461 }
462 
RecordPeriodicMetrics()463 void UserMetricsRecorder::RecordPeriodicMetrics() {
464   Shelf* shelf = Shelf::ForWindow(Shell::GetPrimaryRootWindow());
465   // TODO(bruthig): Investigating whether the check for |manager| is necessary
466   // and add tests if it is.
467   if (shelf) {
468     // TODO(bruthig): Consider tracking the time spent in each alignment.
469     UMA_HISTOGRAM_ENUMERATION("Ash.ShelfAlignmentOverTime",
470                               static_cast<ShelfAlignmentUmaEnumValue>(
471                                   shelf->SelectValueForShelfAlignment(
472                                       SHELF_ALIGNMENT_UMA_ENUM_VALUE_BOTTOM,
473                                       SHELF_ALIGNMENT_UMA_ENUM_VALUE_LEFT,
474                                       SHELF_ALIGNMENT_UMA_ENUM_VALUE_RIGHT)),
475                               SHELF_ALIGNMENT_UMA_ENUM_VALUE_COUNT);
476   }
477 
478   if (IsUserInActiveDesktopEnvironment()) {
479     RecordShelfItemCounts();
480     UMA_HISTOGRAM_COUNTS_100("Ash.NumberOfVisibleWindowsInPrimaryDisplay",
481                              GetNumVisibleWindowsInPrimaryDisplay());
482   }
483 
484   // TODO(bruthig): Find out if this should only be logged when the user is
485   // active.
486   // TODO(bruthig): Consider tracking how long a particular type of window is
487   // active at a time.
488   UMA_HISTOGRAM_ENUMERATION("Ash.ActiveWindowShowTypeOverTime",
489                             GetActiveWindowState(),
490                             ACTIVE_WINDOW_STATE_TYPE_COUNT);
491 }
492 
IsUserInActiveDesktopEnvironment() const493 bool UserMetricsRecorder::IsUserInActiveDesktopEnvironment() const {
494   return IsUserActive() && !IsKioskModeActive();
495 }
496 
StartTimer()497 void UserMetricsRecorder::StartTimer() {
498   timer_.Start(FROM_HERE,
499                base::TimeDelta::FromSeconds(kAshPeriodicMetricsTimeInSeconds),
500                this, &UserMetricsRecorder::RecordPeriodicMetrics);
501 }
502 
503 }  // namespace ash
504