Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |