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

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

Issue 1338603002: Implement a site engagement score based on time-on-site. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: More web contents validity checking Created 5 years, 3 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
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 "chrome/browser/engagement/site_engagement_service.h" 8 #include "chrome/browser/engagement/site_engagement_service.h"
8 #include "chrome/browser/engagement/site_engagement_service_factory.h" 9 #include "chrome/browser/engagement/site_engagement_service_factory.h"
9 #include "chrome/browser/prerender/prerender_contents.h" 10 #include "chrome/browser/prerender/prerender_contents.h"
10 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/browser/profiles/profile.h"
11 #include "content/public/browser/navigation_entry.h" 12 #include "content/public/browser/navigation_entry.h"
12 #include "content/public/browser/web_contents.h" 13 #include "content/public/browser/web_contents.h"
13 14
15 namespace {
16
17 const int kSecondsBetweenUserInputCheck = 10;
18
19 } // anonymous namespace
20
14 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SiteEngagementHelper); 21 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SiteEngagementHelper);
15 22
16 SiteEngagementHelper::~SiteEngagementHelper() { 23 SiteEngagementHelper::~SiteEngagementHelper() {
24 timer_.Stop();
25 content::WebContents* contents = web_contents();
26 if (contents)
27 RemoveInputCallbacks(contents->GetRenderViewHost());
17 } 28 }
18 29
19 SiteEngagementHelper::SiteEngagementHelper(content::WebContents* web_contents) 30 SiteEngagementHelper::SiteEngagementHelper(content::WebContents* web_contents)
20 : content::WebContentsObserver(web_contents) { 31 : content::WebContentsObserver(web_contents),
32 user_input_recorded_(false),
33 callbacks_added_(false),
34 ignore_page_(false) {
35 key_press_event_callback_ = base::Bind(
36 &SiteEngagementHelper::HandleKeyPressEvent, base::Unretained(this));
37 mouse_event_callback_ = base::Bind(&SiteEngagementHelper::HandleMouseEvent,
38 base::Unretained(this));
39 RegisterInputCallbacks(web_contents->GetRenderViewHost());
benwells 2015/09/16 00:23:32 Should the callbacks be registered here? Won't the
dominickn 2015/09/18 06:05:27 There isn't a strong relationship between timer ru
40 }
41
42 // Record that there was some user input, and defer handling of the input event.
43 // web_contents() will return nullptr if the observed contents have been
44 // deleted.
45 bool SiteEngagementHelper::HandleKeyPressEvent(
46 const content::NativeWebKeyboardEvent& event) {
47 user_input_recorded_ = true;
48 content::WebContents* contents = web_contents();
49 if (contents)
50 RemoveInputCallbacks(contents->GetRenderViewHost());
51 return false;
52 }
53
54 bool SiteEngagementHelper::HandleMouseEvent(const blink::WebMouseEvent& event) {
55 user_input_recorded_ = true;
56 content::WebContents* contents = web_contents();
57 if (contents)
58 RemoveInputCallbacks(contents->GetRenderViewHost());
59 return false;
60 }
61
62 void SiteEngagementHelper::RegisterInputCallbacks(
63 content::RenderViewHost* host) {
64 if (!callbacks_added_) {
benwells 2015/09/16 00:23:32 I wonder if this could be encapsulated into some s
dominickn 2015/09/18 06:05:27 I'm concerned whether the additional clarity comes
65 host->AddKeyPressEventCallback(key_press_event_callback_);
66 host->AddMouseEventCallback(mouse_event_callback_);
67 callbacks_added_ = true;
68 }
69 }
70
71 void SiteEngagementHelper::RemoveInputCallbacks(
72 content::RenderViewHost* host) {
73 if (callbacks_added_) {
74 host->RemoveKeyPressEventCallback(key_press_event_callback_);
75 host->RemoveMouseEventCallback(mouse_event_callback_);
76 callbacks_added_ = false;
77 }
78 }
79
80 void SiteEngagementHelper::StartTimer() {
81 timer_.Start(FROM_HERE,
82 base::TimeDelta::FromSeconds(kSecondsBetweenUserInputCheck),
83 this, &SiteEngagementHelper::TimerFired);
21 } 84 }
22 85
23 void SiteEngagementHelper::DidStartNavigationToPendingEntry( 86 void SiteEngagementHelper::DidStartNavigationToPendingEntry(
24 const GURL& url, 87 const GURL& url,
25 content::NavigationController::ReloadType reload_type) { 88 content::NavigationController::ReloadType reload_type) {
89 content::WebContents* contents = web_contents();
26 prerender::PrerenderContents* prerender_contents = 90 prerender::PrerenderContents* prerender_contents =
27 prerender::PrerenderContents::FromWebContents(web_contents()); 91 prerender::PrerenderContents::FromWebContents(contents);
28 92
29 // Ignore pre-render loads. 93 // Ignore pre-render loads and all schemes except HTTP and HTTPS.
30 if (prerender_contents != NULL) 94 ignore_page_ = (prerender_contents != NULL || !url.SchemeIsHTTPOrHTTPS());
95 }
96
97 void SiteEngagementHelper::TimerFired() {
98 if (ignore_page_)
benwells 2015/09/16 00:23:32 I don't really like having this timer running all
dominickn 2015/09/18 06:05:27 I have changed this design such that the timer is
31 return; 99 return;
100 content::WebContents* contents = web_contents();
101 if (contents) {
102 GURL url = contents->GetVisibleURL();
103 if (user_input_recorded_) {
104 Profile* profile =
105 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
106 SiteEngagementService* service =
107 SiteEngagementServiceFactory::GetForProfile(profile);
32 108
33 // Ignore all schemes except HTTP and HTTPS. 109 // Service is null in incognito.
34 if (!url.SchemeIsHTTPOrHTTPS()) 110 if (service)
35 return; 111 service->HandleUserInput(url);
112 RegisterInputCallbacks(contents->GetRenderViewHost());
113 }
114 }
115 user_input_recorded_ = false;
116 }
36 117
37 Profile* profile = 118 void SiteEngagementHelper::RenderViewHostChanged(
38 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); 119 content::RenderViewHost* old_host,
39 SiteEngagementService* service = 120 content::RenderViewHost* new_host) {
40 SiteEngagementServiceFactory::GetForProfile(profile); 121 // On changing the render view host, we need to re-register the callbacks
41 // Service is null in incognito. 122 // listening for user input.
42 if (!service) 123 if (old_host)
43 return; 124 RemoveInputCallbacks(old_host);
125 RegisterInputCallbacks(new_host);
126 }
44 127
45 service->HandleNavigation(url); 128 void SiteEngagementHelper::WasShown() {
benwells 2015/09/16 00:23:32 Why is this now removed? I am guessing you're equa
dominickn 2015/09/18 06:05:27 calamity@ wanted to remove navigation tracking ent
129 // When we come back into view, ensure that the input listening callbacks are
130 // registered.
131 user_input_recorded_ = false;
132 RegisterInputCallbacks(web_contents()->GetRenderViewHost());
133 StartTimer();
46 } 134 }
135
136 void SiteEngagementHelper::WasHidden() {
137 // Ensure that we are not recording user events for hidden web contents.
138 timer_.Stop();
139 user_input_recorded_ = false;
140 content::WebContents* contents = web_contents();
141 if (contents)
142 RemoveInputCallbacks(contents->GetRenderViewHost());
143 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698