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

Side by Side Diff: chrome/browser/engagement/site_engagement_helper.cc

Issue 1427913002: Implement media playing engagement detection for the site engagement service. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@user-input-event
Patch Set: Addressing nits Created 5 years, 1 month 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/engagement/site_engagement_helper.h" 5 #include "chrome/browser/engagement/site_engagement_helper.h"
6 6
7 #include "base/time/time.h" 7 #include "base/time/time.h"
8 #include "base/trace_event/trace_event.h" 8 #include "base/trace_event/trace_event.h"
9 #include "chrome/browser/engagement/site_engagement_service.h" 9 #include "chrome/browser/engagement/site_engagement_service.h"
10 #include "chrome/browser/engagement/site_engagement_service_factory.h" 10 #include "chrome/browser/engagement/site_engagement_service_factory.h"
11 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/browser/profiles/profile.h"
12 #include "content/public/browser/navigation_entry.h" 12 #include "content/public/browser/navigation_entry.h"
13 #include "content/public/browser/web_contents.h" 13 #include "content/public/browser/web_contents.h"
14 14
15 namespace { 15 namespace {
16 16
17 int g_seconds_between_user_input_check = 10; 17 int g_seconds_to_pause_engagement_detection = 10;
18 int g_seconds_tracking_delay_after_navigation = 10; 18 int g_seconds_delay_after_navigation = 10;
19 int g_seconds_tracking_delay_after_show = 5; 19 int g_seconds_delay_after_show = 5;
20 20
21 } // anonymous namespace 21 } // anonymous namespace
22 22
23 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SiteEngagementHelper); 23 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SiteEngagementHelper);
24 24
25 SiteEngagementHelper::InputTracker::InputTracker( 25 SiteEngagementHelper::PeriodicTracker::PeriodicTracker(
26 content::WebContents* web_contents,
27 SiteEngagementHelper* helper) 26 SiteEngagementHelper* helper)
28 : WebContentsObserver(web_contents), 27 : helper_(helper), pause_timer_(new base::Timer(true, false)) {}
29 helper_(helper),
30 pause_timer_(new base::Timer(true, false)),
31 is_tracking_(false) {}
32 28
33 SiteEngagementHelper::InputTracker::~InputTracker() {} 29 SiteEngagementHelper::PeriodicTracker::~PeriodicTracker() {}
34 30
35 void SiteEngagementHelper::InputTracker::Start(base::TimeDelta initial_delay) { 31 void SiteEngagementHelper::PeriodicTracker::Start(
32 base::TimeDelta initial_delay) {
36 StartTimer(initial_delay); 33 StartTimer(initial_delay);
37 } 34 }
38 35
39 void SiteEngagementHelper::InputTracker::Pause() { 36 void SiteEngagementHelper::PeriodicTracker::Pause() {
40 is_tracking_ = false; 37 TrackingStopped();
41 StartTimer(base::TimeDelta::FromSeconds(g_seconds_between_user_input_check)); 38 StartTimer(
39 base::TimeDelta::FromSeconds(g_seconds_to_pause_engagement_detection));
42 } 40 }
43 41
44 void SiteEngagementHelper::InputTracker::Stop() { 42 void SiteEngagementHelper::PeriodicTracker::Stop() {
45 is_tracking_ = false; 43 TrackingStopped();
46 pause_timer_->Stop(); 44 pause_timer_->Stop();
47 } 45 }
48 46
49 void SiteEngagementHelper::InputTracker::SetPauseTimerForTesting( 47 void SiteEngagementHelper::PeriodicTracker::SetPauseTimerForTesting(
50 scoped_ptr<base::Timer> timer) { 48 scoped_ptr<base::Timer> timer) {
51 pause_timer_ = timer.Pass(); 49 pause_timer_ = timer.Pass();
52 } 50 }
53 51
54 void SiteEngagementHelper::InputTracker::StartTimer(base::TimeDelta delay) { 52 void SiteEngagementHelper::PeriodicTracker::StartTimer(
53 base::TimeDelta delay) {
55 pause_timer_->Start( 54 pause_timer_->Start(
56 FROM_HERE, delay, 55 FROM_HERE, delay,
57 base::Bind(&SiteEngagementHelper::InputTracker::StartTracking, 56 base::Bind(&SiteEngagementHelper::PeriodicTracker::TrackingStarted,
58 base::Unretained(this))); 57 base::Unretained(this)));
59 } 58 }
60 59
61 void SiteEngagementHelper::InputTracker::StartTracking() { 60 SiteEngagementHelper::InputTracker::InputTracker(
61 SiteEngagementHelper* helper,
62 content::WebContents* web_contents)
63 : PeriodicTracker(helper), content::WebContentsObserver(web_contents) {}
64
65 void SiteEngagementHelper::InputTracker::TrackingStarted() {
62 is_tracking_ = true; 66 is_tracking_ = true;
63 } 67 }
64 68
69 void SiteEngagementHelper::InputTracker::TrackingStopped() {
70 is_tracking_ = false;
71 }
72
65 // Record that there was some user input, and defer handling of the input event. 73 // Record that there was some user input, and defer handling of the input event.
66 // Once the timer finishes running, the callbacks detecting user input will be 74 // Once the timer finishes running, the callbacks detecting user input will be
67 // registered again. 75 // registered again.
68 void SiteEngagementHelper::InputTracker::DidGetUserInteraction( 76 void SiteEngagementHelper::InputTracker::DidGetUserInteraction(
69 const blink::WebInputEvent::Type type) { 77 const blink::WebInputEvent::Type type) {
70 // Only respond to raw key down to avoid multiple triggering on a single input 78 // Only respond to raw key down to avoid multiple triggering on a single input
71 // (e.g. keypress is a key down then key up). 79 // (e.g. keypress is a key down then key up).
72 if (!is_tracking_) 80 if (!is_tracking_)
73 return; 81 return;
74 82
75 // This switch has a default NOTREACHED case because it will not test all 83 // This switch has a default NOTREACHED case because it will not test all
76 // of the values of the WebInputEvent::Type enum (hence it won't require the 84 // of the values of the WebInputEvent::Type enum (hence it won't require the
77 // compiler verifying that all cases are covered). 85 // compiler verifying that all cases are covered).
78 switch (type) { 86 switch (type) {
79 case blink::WebInputEvent::RawKeyDown: 87 case blink::WebInputEvent::RawKeyDown:
80 helper_->RecordUserInput(SiteEngagementMetrics::ENGAGEMENT_KEYPRESS); 88 helper()->RecordUserInput(SiteEngagementMetrics::ENGAGEMENT_KEYPRESS);
81 break; 89 break;
82 case blink::WebInputEvent::MouseDown: 90 case blink::WebInputEvent::MouseDown:
83 helper_->RecordUserInput(SiteEngagementMetrics::ENGAGEMENT_MOUSE); 91 helper()->RecordUserInput(SiteEngagementMetrics::ENGAGEMENT_MOUSE);
84 break; 92 break;
85 case blink::WebInputEvent::GestureTapDown: 93 case blink::WebInputEvent::GestureTapDown:
86 helper_->RecordUserInput(SiteEngagementMetrics::ENGAGEMENT_TOUCH_GESTURE); 94 helper()->RecordUserInput(
95 SiteEngagementMetrics::ENGAGEMENT_TOUCH_GESTURE);
87 break; 96 break;
88 case blink::WebInputEvent::MouseWheel: 97 case blink::WebInputEvent::MouseWheel:
89 helper_->RecordUserInput(SiteEngagementMetrics::ENGAGEMENT_WHEEL); 98 helper()->RecordUserInput(SiteEngagementMetrics::ENGAGEMENT_WHEEL);
90 break; 99 break;
91 default: 100 default:
92 NOTREACHED(); 101 NOTREACHED();
93 } 102 }
94 Pause(); 103 Pause();
95 } 104 }
96 105
106 SiteEngagementHelper::MediaTracker::MediaTracker(
107 SiteEngagementHelper* helper,
108 content::WebContents* web_contents)
109 : PeriodicTracker(helper), content::WebContentsObserver(web_contents),
110 is_hidden_(false),
111 is_playing_(false) {}
112
113 void SiteEngagementHelper::MediaTracker::TrackingStarted() {
114 if (is_playing_)
115 helper()->RecordMediaPlaying(is_hidden_);
116
117 Pause();
118 }
119
120 void SiteEngagementHelper::MediaTracker::MediaStartedPlaying() {
121 is_playing_ = true;
122 }
123
124 void SiteEngagementHelper::MediaTracker::MediaPaused() {
125 is_playing_ = false;
126 }
127
128 void SiteEngagementHelper::MediaTracker::WasShown() {
129 is_hidden_ = false;
130 }
131
132 void SiteEngagementHelper::MediaTracker::WasHidden() {
133 is_hidden_ = true;
134 }
135
97 SiteEngagementHelper::~SiteEngagementHelper() { 136 SiteEngagementHelper::~SiteEngagementHelper() {
98 content::WebContents* contents = web_contents(); 137 content::WebContents* contents = web_contents();
99 if (contents) 138 if (contents) {
100 input_tracker_.Stop(); 139 input_tracker_.Stop();
140 media_tracker_.Stop();
141 }
101 } 142 }
102 143
103 SiteEngagementHelper::SiteEngagementHelper(content::WebContents* web_contents) 144 SiteEngagementHelper::SiteEngagementHelper(content::WebContents* web_contents)
104 : content::WebContentsObserver(web_contents), 145 : content::WebContentsObserver(web_contents),
105 input_tracker_(web_contents, this), 146 input_tracker_(this, web_contents),
147 media_tracker_(this, web_contents),
106 record_engagement_(false) {} 148 record_engagement_(false) {}
107 149
108 void SiteEngagementHelper::RecordUserInput( 150 void SiteEngagementHelper::RecordUserInput(
109 SiteEngagementMetrics::EngagementType type) { 151 SiteEngagementMetrics::EngagementType type) {
110 TRACE_EVENT0("SiteEngagement", "RecordUserInput"); 152 TRACE_EVENT0("SiteEngagement", "RecordUserInput");
111 content::WebContents* contents = web_contents(); 153 content::WebContents* contents = web_contents();
112 if (contents) { 154 if (contents) {
113 Profile* profile = 155 Profile* profile =
114 Profile::FromBrowserContext(contents->GetBrowserContext()); 156 Profile::FromBrowserContext(contents->GetBrowserContext());
115 SiteEngagementService* service = 157 SiteEngagementService* service =
116 SiteEngagementServiceFactory::GetForProfile(profile); 158 SiteEngagementServiceFactory::GetForProfile(profile);
117 159
118 // Service is null in incognito. 160 // Service is null in incognito.
119 if (service) 161 if (service)
120 service->HandleUserInput(contents->GetVisibleURL(), type); 162 service->HandleUserInput(contents->GetVisibleURL(), type);
121 } 163 }
122 } 164 }
123 165
166 void SiteEngagementHelper::RecordMediaPlaying(bool is_hidden) {
167 content::WebContents* contents = web_contents();
168 if (contents) {
169 Profile* profile =
170 Profile::FromBrowserContext(contents->GetBrowserContext());
171 SiteEngagementService* service =
172 SiteEngagementServiceFactory::GetForProfile(profile);
173
174 if (service)
175 service->HandleMediaPlaying(contents->GetVisibleURL(), is_hidden);
176 }
177 }
178
124 void SiteEngagementHelper::DidNavigateMainFrame( 179 void SiteEngagementHelper::DidNavigateMainFrame(
125 const content::LoadCommittedDetails& details, 180 const content::LoadCommittedDetails& details,
126 const content::FrameNavigateParams& params) { 181 const content::FrameNavigateParams& params) {
127 input_tracker_.Stop(); 182 input_tracker_.Stop();
183 media_tracker_.Stop();
128 184
129 record_engagement_ = params.url.SchemeIsHTTPOrHTTPS(); 185 record_engagement_ = params.url.SchemeIsHTTPOrHTTPS();
130 186
131 // Ignore all schemes except HTTP and HTTPS. 187 // Ignore all schemes except HTTP and HTTPS.
132 if (!record_engagement_) 188 if (!record_engagement_)
133 return; 189 return;
134 190
135 Profile* profile = 191 Profile* profile =
136 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); 192 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
137 SiteEngagementService* service = 193 SiteEngagementService* service =
138 SiteEngagementServiceFactory::GetForProfile(profile); 194 SiteEngagementServiceFactory::GetForProfile(profile);
139 195
140 if (service) 196 if (service)
141 service->HandleNavigation(params.url, params.transition); 197 service->HandleNavigation(params.url, params.transition);
142 198
143 input_tracker_.Start( 199 base::TimeDelta delay =
144 base::TimeDelta::FromSeconds(g_seconds_tracking_delay_after_navigation)); 200 base::TimeDelta::FromSeconds(g_seconds_delay_after_navigation);
201 input_tracker_.Start(delay);
202 media_tracker_.Start(delay);
145 } 203 }
146 204
147 void SiteEngagementHelper::WasShown() { 205 void SiteEngagementHelper::WasShown() {
148 // Ensure that the input callbacks are registered when we come into view. 206 // Ensure that the input callbacks are registered when we come into view.
149 if (record_engagement_) { 207 if (record_engagement_) {
150 input_tracker_.Start( 208 base::TimeDelta delay =
151 base::TimeDelta::FromSeconds(g_seconds_tracking_delay_after_show)); 209 base::TimeDelta::FromSeconds(g_seconds_delay_after_show);
210 input_tracker_.Start(delay);
211 media_tracker_.Start(delay);
152 } 212 }
153 } 213 }
154 214
155 void SiteEngagementHelper::WasHidden() { 215 void SiteEngagementHelper::WasHidden() {
156 // Ensure that the input callbacks are not registered when hidden. 216 // Ensure that the input callbacks are not registered when hidden.
157 input_tracker_.Stop(); 217 input_tracker_.Stop();
158 } 218 }
159 219
160 // static 220 // static
161 void SiteEngagementHelper::SetSecondsBetweenUserInputCheck(int seconds) { 221 void SiteEngagementHelper::SetSecondsBetweenUserInputCheck(int seconds) {
162 g_seconds_between_user_input_check = seconds; 222 g_seconds_to_pause_engagement_detection = seconds;
163 } 223 }
164 224
165 // static 225 // static
166 void SiteEngagementHelper::SetSecondsTrackingDelayAfterNavigation(int seconds) { 226 void SiteEngagementHelper::SetSecondsTrackingDelayAfterNavigation(int seconds) {
167 g_seconds_tracking_delay_after_navigation = seconds; 227 g_seconds_delay_after_navigation = seconds;
168 } 228 }
169 229
170 // static 230 // static
171 void SiteEngagementHelper::SetSecondsTrackingDelayAfterShow(int seconds) { 231 void SiteEngagementHelper::SetSecondsTrackingDelayAfterShow(int seconds) {
172 g_seconds_tracking_delay_after_show = seconds; 232 g_seconds_delay_after_show = seconds;
173 } 233 }
OLDNEW
« no previous file with comments | « chrome/browser/engagement/site_engagement_helper.h ('k') | chrome/browser/engagement/site_engagement_helper_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698