Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(758)

Side by Side Diff: chrome/browser/metrics/desktop_engagement_service.cc

Issue 2142983002: Add desktop engagement metrics. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix unittests Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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/metrics/desktop_engagement_service.h"
6
7 #include "base/bind.h"
8 #include "base/metrics/histogram_macros.h"
9 #include "chrome/browser/metrics/audible_contents_tracker.h"
10 #include "chrome/browser/metrics/chrome_visibility_observer.h"
11
12 namespace {
13
14 DesktopEngagementService* g_instance = nullptr;
15
16 const int kActivityIntervalMinutes = 5;
Patrick Monette 2016/07/13 16:06:24 Same.
gayane -on leave until 09-2017 2016/07/20 20:22:02 I have changed this logic a bit. Please have a loo
17
18 // Small adapter for observing AudibleContentsTracker notifications and
19 // dispatching them to the DesktopEngagementService.
20 class AudibleContentsObserver
21 : public metrics::AudibleContentsTracker::Observer {
22 public:
23 AudibleContentsObserver() {}
24
25 // A one way initialization function. This causes a tracker/observer pair to
26 // be created, which live for the lifetime of the browser. They are
27 // deliberately leaked at shutdown.
28 static void Initialize() {
29
30 DCHECK(!tracker_);
31 DCHECK(!observer_);
32 observer_ = new AudibleContentsObserver();
33 tracker_ = new metrics::AudibleContentsTracker(observer_);
34 }
35
36 // AudibleContentsTracker::Observer:
37 void OnAudioStart() override { g_instance->OnAudioStart(); }
38 void OnAudioEnd() override { g_instance->OnAudioEnd(); }
39
40 private:
41 // Singletons for performing the tracking and observing state changes. These
42 // are deliberately leaked at shutdown.
43 static metrics::AudibleContentsTracker* tracker_;
44 static AudibleContentsObserver* observer_;
45
46 DISALLOW_COPY_AND_ASSIGN(AudibleContentsObserver);
47 };
48
49 metrics::AudibleContentsTracker* AudibleContentsObserver::tracker_ = nullptr;
50 AudibleContentsObserver* AudibleContentsObserver::observer_ = nullptr;
51
52 } // namespace
53
54 // static
55 void DesktopEngagementService::Initialize() {
56 g_instance = new DesktopEngagementService;
57 AudibleContentsObserver::Initialize();
58 metrics::ChromeVisibilityObserver::Initialize();
59 }
60
61 // static
62 bool DesktopEngagementService::IsInitialized() {
63 return g_instance != nullptr;
64 }
65
66 // static
67 DesktopEngagementService* DesktopEngagementService::Get() {
68 DCHECK(g_instance);
69 return g_instance;
70 }
71
72 void DesktopEngagementService::StartTimer(base::TimeDelta duration) {
73 timer_.Start(FROM_HERE, duration,
74 base::Bind(&DesktopEngagementService::OnTimerFired,
75 weak_factory_.GetWeakPtr()));
76 }
77
78 void DesktopEngagementService::OnVisibilityChanged(bool visible) {
79 is_visible_ = visible;
80 if (is_visible_ && !is_first_session_) {
81 OnUserEvent();
82 } else if (in_session_ && !is_audio_playing_) {
83 DLOG(ERROR) << "Ending session due to visibility change";
84 EndSession();
85 }
86 }
87
88 void DesktopEngagementService::OnUserEvent() {
89 if (!is_visible_)
90 return;
91
92 last_user_event_ = base::TimeTicks::Now();
93 // This may start session.
94 if (!in_session_) {
95 DLOG(ERROR) << "Starting session due to user event";
96 StartSession();
97 }
98 }
99
100 void DesktopEngagementService::OnAudioStart() {
101 // This may start session.
102 is_audio_playing_ = true;
103 if (!in_session_) {
104 DLOG(ERROR) << "Starting session due to audio start";
105 StartSession();
106 }
107 }
108
109 void DesktopEngagementService::OnAudioEnd() {
110 is_audio_playing_ = false;
111
112 // If the timer is not running, this means that no user events happened in the
113 // last 5 minutes so the session can be terminated.
114 if (!timer_.IsRunning()) {
115 DLOG(ERROR) << "Ending session due to audio ending";
116 EndSession();
117 }
118 }
119
120 DesktopEngagementService::DesktopEngagementService()
121 : session_start_(base::TimeTicks::Now()),
122 last_user_event_(session_start_),
123 weak_factory_(this) {
124 // TODO: Add user events observers here, or add a static Get() method to
125 // DesktopEngagementService.
126 }
127
128 DesktopEngagementService::~DesktopEngagementService() {}
129
130 void DesktopEngagementService::OnTimerFired() {
131 base::TimeDelta remaining =
132 GetActivityInterval() - (base::TimeTicks::Now() - last_user_event_);
133 if (remaining.ToInternalValue() > 0) {
134 StartTimer(remaining);
135 return;
136 }
137
138 // No user events happened in the last 5 min. Terminate the session now.
139 if (!is_audio_playing_) {
140 DLOG(ERROR) << "Ending session after delay";
141 EndSession();
142 }
143 }
144
145 void DesktopEngagementService::StartSession() {
146 in_session_ = true;
147 is_first_session_ = false;
148 session_start_ = base::TimeTicks::Now();
149 StartTimer(GetActivityInterval());
150 }
151
152 void DesktopEngagementService::EndSession() {
153 in_session_ = false;
154 base::TimeDelta delta = base::TimeTicks::Now() - session_start_;
155
156 constexpr unsigned kNumTimeSlices = 60 / 5 * 24;
157 DLOG(ERROR) << "Logging session length of " << delta.InSeconds()
158 << " seconds.";
159 UMA_HISTOGRAM_CUSTOM_TIMES("Session.TotalDuration", delta,
160 base::TimeDelta::FromMilliseconds(1),
161 base::TimeDelta::FromHours(24), kNumTimeSlices);
162 }
163
164 base::TimeDelta DesktopEngagementService::GetActivityInterval() {
165 if (activity_interval_seconds_testing_ != 0)
166 return base::TimeDelta::FromSeconds(activity_interval_seconds_testing_);
167 return base::TimeDelta::FromMinutes(kActivityIntervalMinutes);
168 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698