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

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

Issue 2142983002: Add desktop engagement metrics. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address comments and fix mac bot Created 4 years, 4 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/desktop_engagement_service.h "
6
7 #include "base/bind.h"
8 #include "base/metrics/histogram_macros.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "chrome/browser/metrics/desktop_engagement/audible_contents_tracker.h"
11 #include "chrome/browser/metrics/desktop_engagement/chrome_visibility_observer.h "
12 #include "components/variations/variations_associated_data.h"
13
14 namespace {
15
16 DesktopEngagementService* g_instance = nullptr;
17
18 // Small adapter for observing AudibleContentsTracker notifications and
19 // dispatching them to the DesktopEngagementService.
20 class AudibleContentsObserver
21 : public metrics::AudibleContentsTracker::Observer {
Alexei Svitkine (slow) 2016/07/26 22:00:40 Please make things consistent re: using metrics na
gayane -on leave until 09-2017 2016/07/27 21:10:25 Done.
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 DCHECK(!tracker_);
30 DCHECK(!observer_);
31 observer_ = new AudibleContentsObserver();
32 tracker_ = new metrics::AudibleContentsTracker(observer_);
33 }
34
35 // AudibleContentsTracker::Observer:
36 void OnAudioStart() override { g_instance->OnAudioStart(); }
37 void OnAudioEnd() override { g_instance->OnAudioEnd(); }
38
39 private:
40 // Singletons for performing the tracking and observing state changes. These
41 // are deliberately leaked at shutdown.
42 static metrics::AudibleContentsTracker* tracker_;
43 static AudibleContentsObserver* observer_;
44
45 DISALLOW_COPY_AND_ASSIGN(AudibleContentsObserver);
46 };
Alexei Svitkine (slow) 2016/07/26 22:00:40 This seems overly complicated. Why not just have D
gayane -on leave until 09-2017 2016/07/27 21:10:25 Moved this implementation to AudibleContentsTracke
47
48 metrics::AudibleContentsTracker* AudibleContentsObserver::tracker_ = nullptr;
49 AudibleContentsObserver* AudibleContentsObserver::observer_ = nullptr;
50
51 } // namespace
52
53 // static
54 void DesktopEngagementService::Initialize() {
55 g_instance = new DesktopEngagementService;
56 AudibleContentsObserver::Initialize();
57 metrics::ChromeVisibilityObserver::Initialize();
58 }
59
60 // static
61 bool DesktopEngagementService::IsInitialized() {
62 return g_instance != nullptr;
63 }
64
65 // static
66 DesktopEngagementService* DesktopEngagementService::Get() {
67 DCHECK(g_instance);
68 return g_instance;
69 }
70
71 void DesktopEngagementService::StartTimer(base::TimeDelta duration) {
72 timer_.Start(FROM_HERE, duration,
73 base::Bind(&DesktopEngagementService::OnTimerFired,
74 weak_factory_.GetWeakPtr()));
75 }
76
77 void DesktopEngagementService::OnVisibilityChanged(bool visible) {
78 is_visible_ = visible;
79 if (is_visible_ && !is_first_session_) {
80 OnUserEvent();
81 } else if (in_session_ && !is_audio_playing_) {
82 DVLOG(4) << "Ending session due to visibility change";
83 EndSession();
84 }
85 }
86
87 void DesktopEngagementService::OnUserEvent() {
88 if (!is_visible_)
89 return;
90
91 last_user_event_ = base::TimeTicks::Now();
92 // This may start session.
93 if (!in_session_) {
94 DVLOG(4) << "Starting session due to user event";
95 StartSession();
96 }
97 }
98
99 void DesktopEngagementService::OnAudioStart() {
100 // This may start session.
101 is_audio_playing_ = true;
102 if (!in_session_) {
103 DVLOG(4) << "Starting session due to audio start";
104 StartSession();
105 }
106 }
107
108 void DesktopEngagementService::OnAudioEnd() {
109 is_audio_playing_ = false;
110
111 // If the timer is not running, this means that no user events happened in the
112 // last 5 minutes so the session can be terminated.
113 if (!timer_.IsRunning()) {
114 DVLOG(4) << "Ending session due to audio ending";
115 EndSession();
116 }
117 }
118
119 DesktopEngagementService::DesktopEngagementService()
120 : session_start_(base::TimeTicks::Now()),
121 last_user_event_(session_start_),
122 weak_factory_(this) {
123 InitInactivityTimeout();
124 }
125
126 DesktopEngagementService::~DesktopEngagementService() {}
127
128 void DesktopEngagementService::OnTimerFired() {
129 base::TimeDelta remaining =
130 inactivity_timeout_ - (base::TimeTicks::Now() - last_user_event_);
131 if (remaining.ToInternalValue() > 0) {
132 StartTimer(remaining);
133 return;
134 }
135
136 // No user events happened in the last 5 min. Terminate the session now.
137 if (!is_audio_playing_) {
138 DVLOG(4) << "Ending session after delay";
139 EndSession();
140 }
141 }
142
143 void DesktopEngagementService::StartSession() {
144 in_session_ = true;
145 is_first_session_ = false;
146 session_start_ = base::TimeTicks::Now();
147 StartTimer(inactivity_timeout_);
148 }
149
150 void DesktopEngagementService::EndSession() {
151 in_session_ = false;
152 base::TimeDelta delta = base::TimeTicks::Now() - session_start_;
153
154 constexpr unsigned kNumTimeSlices = 60 / 5 * 24;
155 DVLOG(4) << "Logging session length of " << delta.InSeconds()
156 << " seconds.";
Alexei Svitkine (slow) 2016/07/26 22:00:40 Nit: Align <<'s Or just git cl format, which I th
gayane -on leave until 09-2017 2016/07/27 21:10:25 Done.
157 UMA_HISTOGRAM_CUSTOM_TIMES("Session.TotalDuration", delta,
158 base::TimeDelta::FromMilliseconds(1),
159 base::TimeDelta::FromHours(24), kNumTimeSlices);
Alexei Svitkine (slow) 2016/07/26 22:00:41 Looks like the metric on android uses a different
gayane -on leave until 09-2017 2016/07/27 21:10:25 Done.
160 }
161
162 void DesktopEngagementService::InitInactivityTimeout() {
163 const int kDefaultInactivityTimeoutMinutes = 5;
164
165 int timeout_minutes = kDefaultInactivityTimeoutMinutes;
166 std::string param_value = variations::GetVariationParamValue(
167 "DesktopEngagement", "inactivity_timeout");
168 if (!param_value.empty())
169 base::StringToInt(param_value, &timeout_minutes);
170
171 inactivity_timeout_ = base::TimeDelta::FromMinutes(timeout_minutes);
172 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698