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

Side by Side Diff: chrome/browser/ui/webui/ntp/ntp_user_data_logger.cc

Issue 2124903003: Record impressions/navigations only once per tile. (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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/ui/webui/ntp/ntp_user_data_logger.h" 5 #include "chrome/browser/ui/webui/ntp/ntp_user_data_logger.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 9
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 NTPUserDataLogger* NTPUserDataLogger::GetOrCreateFromWebContents( 82 NTPUserDataLogger* NTPUserDataLogger::GetOrCreateFromWebContents(
83 content::WebContents* content) { 83 content::WebContents* content) {
84 // Calling CreateForWebContents when an instance is already attached has no 84 // Calling CreateForWebContents when an instance is already attached has no
85 // effect, so we can do this. 85 // effect, so we can do this.
86 NTPUserDataLogger::CreateForWebContents(content); 86 NTPUserDataLogger::CreateForWebContents(content);
87 NTPUserDataLogger* logger = NTPUserDataLogger::FromWebContents(content); 87 NTPUserDataLogger* logger = NTPUserDataLogger::FromWebContents(content);
88 88
89 // We record the URL of this NTP in order to identify navigations that 89 // We record the URL of this NTP in order to identify navigations that
90 // originate from it. We use the NavigationController's URL since it might 90 // originate from it. We use the NavigationController's URL since it might
91 // differ from the WebContents URL which is usually chrome://newtab/. 91 // differ from the WebContents URL which is usually chrome://newtab/.
92 //
93 // We update the NTP URL every time this function is called, because the NTP
94 // URL sometimes changes while it is open, and we care about the final one for
95 // detecting when the user leaves or returns to the NTP.
Marc Treib 2016/07/12 08:17:46 ...wait, what? It can change while the NTP is open
sfiera 2016/07/12 08:37:33 Yep. Reproduction: 1. Start Chromium with a clean
Marc Treib 2016/07/12 08:58:47 The *tiles* can change, but the NTP URL? I guess i
sfiera 2016/07/12 09:08:58 Oh, misread that. But still yes. On first launch,
Marc Treib 2016/07/14 14:40:52 On subsequent runs, the Google TLD doesn't change
96 //
97 // TODO(sfiera): move to a world where the NTP URL is always chrome://newtab/.
Marc Treib 2016/07/12 08:17:46 hahahahaha... wait, you're serious. Let me laugh e
sfiera 2016/07/14 14:11:08 Restricted the TODO somewhat--I expect it's a non-
Marc Treib 2016/07/14 14:40:52 External as in remote? No. We might conceivably mo
92 const content::NavigationEntry* entry = 98 const content::NavigationEntry* entry =
93 content->GetController().GetVisibleEntry(); 99 content->GetController().GetVisibleEntry();
94 if (entry) 100 if (entry && (logger->ntp_url_ != entry->GetURL())) {
101 VLOG(1) << "NTP URL changed from \"" << logger->ntp_url_ << "\" to \""
102 << entry->GetURL() << "\"";
95 logger->ntp_url_ = entry->GetURL(); 103 logger->ntp_url_ = entry->GetURL();
104 }
96 105
97 return logger; 106 return logger;
98 } 107 }
99 108
100 void NTPUserDataLogger::LogEvent(NTPLoggingEventType event, 109 void NTPUserDataLogger::LogEvent(NTPLoggingEventType event,
101 base::TimeDelta time) { 110 base::TimeDelta time) {
102 switch (event) { 111 switch (event) {
103 // It is possible that our page gets update with a different set of 112 // It is possible that our page gets update with a different set of
104 // suggestions if the NTP is left open enough time. 113 // suggestions if the NTP is left open enough time.
105 // In either case, we want to flush our stats before recounting again. 114 // In either case, we want to flush our stats before recounting again.
(...skipping 16 matching lines...) Expand all
122 // the max as the load time. 131 // the max as the load time.
123 load_time_ = std::max(load_time_, time); 132 load_time_ = std::max(load_time_, time);
124 break; 133 break;
125 default: 134 default:
126 NOTREACHED(); 135 NOTREACHED();
127 } 136 }
128 } 137 }
129 138
130 void NTPUserDataLogger::LogMostVisitedImpression( 139 void NTPUserDataLogger::LogMostVisitedImpression(
131 int position, NTPLoggingTileSource tile_source) { 140 int position, NTPLoggingTileSource tile_source) {
141 if (position >= static_cast<int>(impression_was_logged_.size())) {
Marc Treib 2016/07/12 08:17:46 Hm, might as well just resize this to kNumMostVisi
sfiera 2016/07/14 14:11:07 Do we have a guarantee that we can't be called wit
Marc Treib 2016/07/14 14:40:52 No guarantee, but the histograms support only 8 bi
sfiera 2016/07/15 09:55:10 Fixed to be 8 always.
142 impression_was_logged_.resize(position + 1);
143 } else if (impression_was_logged_[position]) {
144 return;
145 }
146 impression_was_logged_[position] = true;
147
132 UMA_HISTOGRAM_ENUMERATION(kMostVisitedImpressionHistogramName, position, 148 UMA_HISTOGRAM_ENUMERATION(kMostVisitedImpressionHistogramName, position,
133 kNumMostVisited); 149 kNumMostVisited);
134 150
135 // Cannot rely on UMA histograms macro because the name of the histogram is 151 // Cannot rely on UMA histograms macro because the name of the histogram is
136 // generated dynamically. 152 // generated dynamically.
137 base::HistogramBase* counter = base::LinearHistogram::FactoryGet( 153 base::HistogramBase* counter = base::LinearHistogram::FactoryGet(
138 base::StringPrintf(kMostVisitedImpressionHistogramWithProvider, 154 base::StringPrintf(kMostVisitedImpressionHistogramWithProvider,
139 GetSourceName(tile_source).c_str()), 155 GetSourceName(tile_source).c_str()),
140 1, 156 1,
141 kNumMostVisited, 157 kNumMostVisited,
(...skipping 16 matching lines...) Expand all
158 kNumMostVisited, 174 kNumMostVisited,
159 kNumMostVisited + 1, 175 kNumMostVisited + 1,
160 base::Histogram::kUmaTargetedHistogramFlag); 176 base::Histogram::kUmaTargetedHistogramFlag);
161 counter->Add(position); 177 counter->Add(position);
162 178
163 // Records the action. This will be available as a time-stamped stream 179 // Records the action. This will be available as a time-stamped stream
164 // server-side and can be used to compute time-to-long-dwell. 180 // server-side and can be used to compute time-to-long-dwell.
165 content::RecordAction(base::UserMetricsAction("MostVisited_Clicked")); 181 content::RecordAction(base::UserMetricsAction("MostVisited_Clicked"));
166 } 182 }
167 183
184 // content::WebContentsObserver override
Marc Treib 2016/07/12 08:17:46 Any reason for moving this up here? (Bad rebase? I
sfiera 2016/07/14 14:11:07 Yep, that. Down.
185 void NTPUserDataLogger::NavigationEntryCommitted(
186 const content::LoadCommittedDetails& load_details) {
187 // User is navigating away from NTP; log stats.
188 if (load_details.previous_url.is_valid()
Marc Treib 2016/07/12 08:17:46 We could keep the early-out if the previous URL is
sfiera 2016/07/14 14:11:07 This conditional is now gone, because we don't emi
189 && search::MatchesOriginAndPath(ntp_url_, load_details.previous_url)) {
190 VLOG(1) << "Leaving New Tab Page";
191 EmitNtpStatistics(EmitReason::NAVIGATED_AWAY);
Marc Treib 2016/07/12 08:17:46 Is there no "return" here on purpose? (So that a r
sfiera 2016/07/14 14:11:07 Conditional is gone. (this did handle reload)
192 }
193
194 // User is returning to NTP, probably via the back button; reset stats for
195 // impressions.
196 if (load_details.previous_url.is_valid() &&
197 load_details.entry->GetURL().is_valid() &&
198 search::MatchesOriginAndPath(load_details.entry->GetURL(), ntp_url_)) {
Marc Treib 2016/07/12 08:17:46 Fun fact: search::MatchesOriginAndPath isn't symme
sfiera 2016/07/14 14:11:07 Changed to ==.
199 VLOG(1) << "Returning to New Tab Page";
200 impression_was_logged_.clear();
Marc Treib 2016/07/12 08:17:46 So LoadTime and NumberOfTiles won't be logged agai
sfiera 2016/07/14 14:11:07 Reset has_emitted_.
201 }
202 }
203
168 void NTPUserDataLogger::TabDeactivated() { 204 void NTPUserDataLogger::TabDeactivated() {
169 EmitNtpStatistics(EmitReason::CLOSED); 205 EmitNtpStatistics(EmitReason::CLOSED);
170 } 206 }
171 207
172 void NTPUserDataLogger::MostVisitedItemsChanged() {
173 EmitNtpStatistics(EmitReason::MV_CHANGED);
174 }
175
176 NTPUserDataLogger::NTPUserDataLogger(content::WebContents* contents) 208 NTPUserDataLogger::NTPUserDataLogger(content::WebContents* contents)
177 : content::WebContentsObserver(contents), 209 : content::WebContentsObserver(contents),
178 has_server_side_suggestions_(false), 210 has_server_side_suggestions_(false),
179 has_client_side_suggestions_(false), 211 has_client_side_suggestions_(false),
180 number_of_tiles_(0), 212 number_of_tiles_(0),
181 has_emitted_(false), 213 has_emitted_(false),
182 during_startup_(false) { 214 during_startup_(false) {
183 during_startup_ = !AfterStartupTaskUtils::IsBrowserStartupComplete(); 215 during_startup_ = !AfterStartupTaskUtils::IsBrowserStartupComplete();
184 216
185 // We record metrics about session data here because when this class typically 217 // We record metrics about session data here because when this class typically
186 // emits metrics it is too late. This session data would theoretically have 218 // emits metrics it is too late. This session data would theoretically have
187 // been used to populate the page, and we want to learn about its state when 219 // been used to populate the page, and we want to learn about its state when
188 // the NTP is being generated. 220 // the NTP is being generated.
189 if (contents) { 221 if (contents) {
190 ProfileSyncService* sync = ProfileSyncServiceFactory::GetForProfile( 222 ProfileSyncService* sync = ProfileSyncServiceFactory::GetForProfile(
191 Profile::FromBrowserContext(contents->GetBrowserContext())); 223 Profile::FromBrowserContext(contents->GetBrowserContext()));
192 if (sync) { 224 if (sync) {
193 browser_sync::SessionsSyncManager* sessions = 225 browser_sync::SessionsSyncManager* sessions =
194 static_cast<browser_sync::SessionsSyncManager*>( 226 static_cast<browser_sync::SessionsSyncManager*>(
195 sync->GetSessionsSyncableService()); 227 sync->GetSessionsSyncableService());
196 if (sessions) { 228 if (sessions) {
197 sync_sessions::SyncSessionsMetrics::RecordYoungestForeignTabAgeOnNTP( 229 sync_sessions::SyncSessionsMetrics::RecordYoungestForeignTabAgeOnNTP(
198 sessions); 230 sessions);
199 } 231 }
200 } 232 }
201 } 233 }
202 } 234 }
203 235
204 // content::WebContentsObserver override
205 void NTPUserDataLogger::NavigationEntryCommitted(
206 const content::LoadCommittedDetails& load_details) {
207 if (!load_details.previous_url.is_valid())
208 return;
209
210 if (search::MatchesOriginAndPath(ntp_url_, load_details.previous_url))
211 EmitNtpStatistics(EmitReason::NAVIGATED_AWAY);
212 }
213
214 void NTPUserDataLogger::EmitNtpStatistics(EmitReason reason) { 236 void NTPUserDataLogger::EmitNtpStatistics(EmitReason reason) {
215 // We only send statistics once per page. 237 // We only send statistics once per page.
216 // And we don't send if there are no tiles recorded. 238 // And we don't send if there are no tiles recorded.
217 if (has_emitted_ || !number_of_tiles_) 239 if (has_emitted_ || !number_of_tiles_)
218 return; 240 return;
219 241
220 // LoadTime only gets update once per page, so we don't have it on reloads. 242 // LoadTime only gets update once per page, so we don't have it on reloads.
221 if (load_time_ > base::TimeDelta::FromMilliseconds(0)) { 243 if (load_time_ > base::TimeDelta::FromMilliseconds(0)) {
222 logLoadTimeHistogram("NewTabPage.LoadTime", load_time_); 244 logLoadTimeHistogram("NewTabPage.LoadTime", load_time_);
223 245
(...skipping 13 matching lines...) Expand all
237 } 259 }
238 has_server_side_suggestions_ = false; 260 has_server_side_suggestions_ = false;
239 has_client_side_suggestions_ = false; 261 has_client_side_suggestions_ = false;
240 UMA_HISTOGRAM_CUSTOM_COUNTS( 262 UMA_HISTOGRAM_CUSTOM_COUNTS(
241 "NewTabPage.NumberOfTiles", number_of_tiles_, 0, kNumMostVisited, 263 "NewTabPage.NumberOfTiles", number_of_tiles_, 0, kNumMostVisited,
242 kNumMostVisited + 1); 264 kNumMostVisited + 1);
243 number_of_tiles_ = 0; 265 number_of_tiles_ = 0;
244 has_emitted_ = true; 266 has_emitted_ = true;
245 during_startup_ = false; 267 during_startup_ = false;
246 } 268 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698