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

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

Issue 2127143002: Integrate audible tab tracking into desktop engagement service. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 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
« no previous file with comments | « chrome/browser/metrics/desktop_engagement_service.h ('k') | chrome/browser/ui/browser_list.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 = 1;
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 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 };
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_) {
80 OnUserEvent();
81 } else if (in_session_ && !is_audio_playing_) {
82 DLOG(ERROR) << "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 DLOG(ERROR) << "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 DLOG(ERROR) << "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 DLOG(ERROR) << "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 StartSession();
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 = base::TimeTicks::Now() - last_user_event_;
132 if (remaining < base::TimeDelta::FromMinutes(kActivityIntervalMinutes)) {
133 StartTimer(remaining);
134 return;
135 }
136
137 // No user events happened in the last 5 min. Terminate the session now.
138 if (!is_audio_playing_) {
139 DLOG(ERROR) << "Ending session after delay";
140 EndSession();
141 }
142 }
143
144 void DesktopEngagementService::StartSession() {
145 in_session_ = true;
146 session_start_ = base::TimeTicks::Now();
147 StartTimer(base::TimeDelta::FromMinutes(kActivityIntervalMinutes));
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 DLOG(ERROR) << "Logging session length of " << delta.InSeconds()
156 << " seconds.";
157 UMA_HISTOGRAM_CUSTOM_TIMES("Session.TotalDuration", delta,
158 base::TimeDelta::FromMilliseconds(1),
159 base::TimeDelta::FromHours(24), kNumTimeSlices);
160 }
OLDNEW
« no previous file with comments | « chrome/browser/metrics/desktop_engagement_service.h ('k') | chrome/browser/ui/browser_list.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698