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

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

Issue 1388293002: Notify WebContentsObservers of user interactions. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Refactoring site engagement to use DidGetUserInteraction 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/prerender/prerender_contents.h"
12 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/browser/profiles/profile.h"
13 #include "content/public/browser/navigation_entry.h" 12 #include "content/public/browser/navigation_entry.h"
14 #include "content/public/browser/web_contents.h" 13 #include "content/public/browser/web_contents.h"
15 14
16 namespace { 15 namespace {
17 16
18 int g_seconds_between_user_input_check = 10; 17 int g_seconds_between_user_input_check = 10;
19 int g_seconds_tracking_delay_after_navigation = 10; 18 int g_seconds_tracking_delay_after_navigation = 10;
20 int g_seconds_tracking_delay_after_show = 5; 19 int g_seconds_tracking_delay_after_show = 5;
21 20
22 } // anonymous namespace 21 } // anonymous namespace
23 22
24 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SiteEngagementHelper); 23 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SiteEngagementHelper);
25 24
26 SiteEngagementHelper::InputTracker::InputTracker(SiteEngagementHelper* helper) 25 SiteEngagementHelper::InputTracker::InputTracker(
27 : helper_(helper), 26 content::WebContents* web_contents,
27 SiteEngagementHelper* helper)
28 : WebContentsObserver(web_contents),
29 helper_(helper),
28 pause_timer_(new base::Timer(true, false)), 30 pause_timer_(new base::Timer(true, false)),
29 host_(nullptr), 31 is_tracking_(false) {}
30 is_tracking_(false) {
31 key_press_event_callback_ =
32 base::Bind(&SiteEngagementHelper::InputTracker::HandleKeyPressEvent,
33 base::Unretained(this));
34 mouse_event_callback_ =
35 base::Bind(&SiteEngagementHelper::InputTracker::HandleMouseEvent,
36 base::Unretained(this));
37 }
38 32
39 SiteEngagementHelper::InputTracker::~InputTracker() {} 33 SiteEngagementHelper::InputTracker::~InputTracker() {}
40 34
41 // Record that there was some user input, and defer handling of the input event. 35 void SiteEngagementHelper::InputTracker::Start(base::TimeDelta initial_delay) {
42 // web_contents() will return nullptr if the observed contents have been
43 // deleted; if the contents exist, record engagement for the site. Once the
44 // timer finishes running, the callbacks detecting user input will be registered
45 // again.
46 bool SiteEngagementHelper::InputTracker::HandleKeyPressEvent(
47 const content::NativeWebKeyboardEvent& event) {
48 // Only respond to raw key down to avoid multiple triggering on a single input
49 // (e.g. keypress is a key down then key up).
50 if (event.type == blink::WebInputEvent::RawKeyDown) {
51 Pause();
52 helper_->RecordUserInput(SiteEngagementMetrics::ENGAGEMENT_KEYPRESS);
53 }
54 return false;
55 }
56
57 bool SiteEngagementHelper::InputTracker::HandleMouseEvent(
58 const blink::WebMouseEvent& event) {
59 // Only respond to mouse down with a button or mouse move events (e.g. a click
60 // is a mouse down and mouse up) to avoid cases where multiple events come in
61 // before we can pause tracking.
62 if ((event.button != blink::WebMouseEvent::ButtonNone &&
63 event.type == blink::WebInputEvent::MouseDown) ||
64 event.type == blink::WebInputEvent::MouseWheel) {
65 Pause();
66 helper_->RecordUserInput(SiteEngagementMetrics::ENGAGEMENT_MOUSE);
67 }
68 return false;
69 }
70
71 void SiteEngagementHelper::InputTracker::Start(content::RenderViewHost* host,
72 base::TimeDelta initial_delay) {
73 DCHECK(!host_);
74 DCHECK(host);
75 host_ = host;
76 StartTimer(initial_delay); 36 StartTimer(initial_delay);
77 } 37 }
78 38
79 void SiteEngagementHelper::InputTracker::Pause() { 39 void SiteEngagementHelper::InputTracker::Pause() {
80 RemoveCallbacks(); 40 is_tracking_ = false;
81 StartTimer(base::TimeDelta::FromSeconds(g_seconds_between_user_input_check)); 41 StartTimer(base::TimeDelta::FromSeconds(g_seconds_between_user_input_check));
82 } 42 }
83 43
84 void SiteEngagementHelper::InputTracker::SwitchRenderViewHost(
85 content::RenderViewHost* old_host,
86 content::RenderViewHost* new_host) {
87 DCHECK(host_);
88 DCHECK(new_host);
89
90 bool was_tracking = is_tracking_;
91 if (old_host) {
92 DCHECK_EQ(host_, old_host);
93 RemoveCallbacks();
94 }
95
96 host_ = new_host;
97
98 if (was_tracking)
99 AddCallbacks();
100 }
101
102 void SiteEngagementHelper::InputTracker::Stop() { 44 void SiteEngagementHelper::InputTracker::Stop() {
45 is_tracking_ = false;
103 pause_timer_->Stop(); 46 pause_timer_->Stop();
104 RemoveCallbacks();
105 host_ = nullptr;
106 }
107
108 bool SiteEngagementHelper::InputTracker::IsActive() const {
109 return host_ != nullptr;
110 } 47 }
111 48
112 void SiteEngagementHelper::InputTracker::SetPauseTimerForTesting( 49 void SiteEngagementHelper::InputTracker::SetPauseTimerForTesting(
113 scoped_ptr<base::Timer> timer) { 50 scoped_ptr<base::Timer> timer) {
114 pause_timer_ = timer.Pass(); 51 pause_timer_ = timer.Pass();
115 } 52 }
116 53
117 void SiteEngagementHelper::InputTracker::StartTimer(base::TimeDelta delay) { 54 void SiteEngagementHelper::InputTracker::StartTimer(base::TimeDelta delay) {
118 pause_timer_->Start( 55 pause_timer_->Start(
119 FROM_HERE, delay, 56 FROM_HERE, delay,
120 base::Bind(&SiteEngagementHelper::InputTracker::AddCallbacks, 57 base::Bind(&SiteEngagementHelper::InputTracker::StartTracking,
121 base::Unretained(this))); 58 base::Unretained(this)));
122 } 59 }
123 60
124 void SiteEngagementHelper::InputTracker::AddCallbacks() { 61 void SiteEngagementHelper::InputTracker::StartTracking() {
125 content::WebContents* contents = helper_->web_contents();
126 if (!contents)
127 return;
128
129 host_->GetWidget()->AddKeyPressEventCallback(key_press_event_callback_);
130 host_->GetWidget()->AddMouseEventCallback(mouse_event_callback_);
131 is_tracking_ = true; 62 is_tracking_ = true;
132 } 63 }
133 64
134 void SiteEngagementHelper::InputTracker::RemoveCallbacks() { 65 // 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
67 // registered again.
68 void SiteEngagementHelper::InputTracker::DidGetUserInteraction(
69 const blink::WebInputEvent::Type type) {
70 // 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).
135 if (is_tracking_) { 72 if (is_tracking_) {
136 host_->GetWidget()->RemoveKeyPressEventCallback(key_press_event_callback_); 73 if (type == blink::WebInputEvent::RawKeyDown) {
137 host_->GetWidget()->RemoveMouseEventCallback(mouse_event_callback_); 74 helper_->RecordUserInput(SiteEngagementMetrics::ENGAGEMENT_KEYPRESS);
138 is_tracking_ = false; 75 } else if (type == blink::WebInputEvent::MouseDown) {
76 helper_->RecordUserInput(SiteEngagementMetrics::ENGAGEMENT_MOUSE);
77 } else if (type == blink::WebInputEvent::MouseWheel) {
78 helper_->RecordUserInput(SiteEngagementMetrics::ENGAGEMENT_WHEEL);
79 } else if (type == blink::WebInputEvent::GestureTapDown) {
80 helper_->RecordUserInput(SiteEngagementMetrics::ENGAGEMENT_GESTURE);
81 } else {
82 NOTREACHED();
83 }
84 Pause();
139 } 85 }
140 } 86 }
141 87
142 SiteEngagementHelper::~SiteEngagementHelper() { 88 SiteEngagementHelper::~SiteEngagementHelper() {
143 content::WebContents* contents = web_contents(); 89 content::WebContents* contents = web_contents();
144 if (contents) 90 if (contents)
145 input_tracker_.Stop(); 91 input_tracker_.Stop();
146 } 92 }
147 93
148 SiteEngagementHelper::SiteEngagementHelper(content::WebContents* contents) 94 SiteEngagementHelper::SiteEngagementHelper(content::WebContents* web_contents)
149 : content::WebContentsObserver(contents), 95 : content::WebContentsObserver(web_contents),
150 input_tracker_(this), 96 input_tracker_(web_contents, this),
151 record_engagement_(false) {} 97 record_engagement_(false) {}
152 98
153 void SiteEngagementHelper::RecordUserInput( 99 void SiteEngagementHelper::RecordUserInput(
154 SiteEngagementMetrics::EngagementType type) { 100 SiteEngagementMetrics::EngagementType type) {
155 TRACE_EVENT0("SiteEngagement", "RecordUserInput"); 101 TRACE_EVENT0("SiteEngagement", "RecordUserInput");
156 content::WebContents* contents = web_contents(); 102 content::WebContents* contents = web_contents();
157 if (contents) { 103 if (contents) {
158 Profile* profile = 104 Profile* profile =
159 Profile::FromBrowserContext(contents->GetBrowserContext()); 105 Profile::FromBrowserContext(contents->GetBrowserContext());
160 SiteEngagementService* service = 106 SiteEngagementService* service =
(...skipping 18 matching lines...) Expand all
179 125
180 Profile* profile = 126 Profile* profile =
181 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); 127 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
182 SiteEngagementService* service = 128 SiteEngagementService* service =
183 SiteEngagementServiceFactory::GetForProfile(profile); 129 SiteEngagementServiceFactory::GetForProfile(profile);
184 130
185 if (service) 131 if (service)
186 service->HandleNavigation(params.url, params.transition); 132 service->HandleNavigation(params.url, params.transition);
187 133
188 input_tracker_.Start( 134 input_tracker_.Start(
189 web_contents()->GetRenderViewHost(),
190 base::TimeDelta::FromSeconds(g_seconds_tracking_delay_after_navigation)); 135 base::TimeDelta::FromSeconds(g_seconds_tracking_delay_after_navigation));
191 } 136 }
192 137
193 void SiteEngagementHelper::RenderViewHostChanged(
194 content::RenderViewHost* old_host,
195 content::RenderViewHost* new_host) {
196 // On changing the render view host, we need to re-register the callbacks
197 // listening for user input.
198 if (input_tracker_.IsActive()) {
199 input_tracker_.SwitchRenderViewHost(old_host, new_host);
200 }
201 }
202
203 void SiteEngagementHelper::WasShown() { 138 void SiteEngagementHelper::WasShown() {
204 // Ensure that the input callbacks are registered when we come into view. 139 // Ensure that the input callbacks are registered when we come into view.
205 if (record_engagement_) { 140 if (record_engagement_) {
206 input_tracker_.Start( 141 input_tracker_.Start(
207 web_contents()->GetRenderViewHost(),
208 base::TimeDelta::FromSeconds(g_seconds_tracking_delay_after_show)); 142 base::TimeDelta::FromSeconds(g_seconds_tracking_delay_after_show));
209 } 143 }
210 } 144 }
211 145
212 void SiteEngagementHelper::WasHidden() { 146 void SiteEngagementHelper::WasHidden() {
213 // Ensure that the input callbacks are not registered when hidden. 147 // Ensure that the input callbacks are not registered when hidden.
214 input_tracker_.Stop(); 148 input_tracker_.Stop();
215 } 149 }
216 150
217 // static 151 // static
218 void SiteEngagementHelper::SetSecondsBetweenUserInputCheck(int seconds) { 152 void SiteEngagementHelper::SetSecondsBetweenUserInputCheck(int seconds) {
219 g_seconds_between_user_input_check = seconds; 153 g_seconds_between_user_input_check = seconds;
220 } 154 }
221 155
222 // static 156 // static
223 void SiteEngagementHelper::SetSecondsTrackingDelayAfterNavigation(int seconds) { 157 void SiteEngagementHelper::SetSecondsTrackingDelayAfterNavigation(int seconds) {
224 g_seconds_tracking_delay_after_navigation = seconds; 158 g_seconds_tracking_delay_after_navigation = seconds;
225 } 159 }
226 160
227 // static 161 // static
228 void SiteEngagementHelper::SetSecondsTrackingDelayAfterShow(int seconds) { 162 void SiteEngagementHelper::SetSecondsTrackingDelayAfterShow(int seconds) {
229 g_seconds_tracking_delay_after_show = seconds; 163 g_seconds_tracking_delay_after_show = seconds;
230 } 164 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698