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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 74 if (counter) | 74 if (counter) |
| 75 counter->AddTime(value); | 75 counter->AddTime(value); |
| 76 } | 76 } |
| 77 | 77 |
| 78 | 78 |
| 79 NTPUserDataLogger::~NTPUserDataLogger() {} | 79 NTPUserDataLogger::~NTPUserDataLogger() {} |
| 80 | 80 |
| 81 // static | 81 // static |
| 82 NTPUserDataLogger* NTPUserDataLogger::GetOrCreateFromWebContents( | 82 NTPUserDataLogger* NTPUserDataLogger::GetOrCreateFromWebContents( |
| 83 content::WebContents* content) { | 83 content::WebContents* content) { |
| 84 DCHECK(search::IsInstantNTP(content)); | |
| 85 | |
| 84 // Calling CreateForWebContents when an instance is already attached has no | 86 // Calling CreateForWebContents when an instance is already attached has no |
| 85 // effect, so we can do this. | 87 // effect, so we can do this. |
| 86 NTPUserDataLogger::CreateForWebContents(content); | 88 NTPUserDataLogger::CreateForWebContents(content); |
| 87 NTPUserDataLogger* logger = NTPUserDataLogger::FromWebContents(content); | 89 NTPUserDataLogger* logger = NTPUserDataLogger::FromWebContents(content); |
| 88 | 90 |
| 89 // We record the URL of this NTP in order to identify navigations that | 91 // 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 | 92 // originate from it. We use the NavigationController's URL since it might |
| 91 // differ from the WebContents URL which is usually chrome://newtab/. | 93 // differ from the WebContents URL which is usually chrome://newtab/. |
| 94 // | |
| 95 // We update the NTP URL every time this function is called, because the NTP | |
| 96 // URL sometimes changes while it is open, and we care about the final one for | |
| 97 // detecting when the user leaves or returns to the NTP. In particular, if the | |
| 98 // Google URL changes (e.g. google.com -> google.de), then we fall back to the | |
| 99 // local NTP. | |
| 100 // | |
| 101 // TODO(sfiera): move to a world where the Google NTP is at chrome://newtab/ | |
| 102 // to begin with and we don't need any such fallback behavior. | |
| 92 const content::NavigationEntry* entry = | 103 const content::NavigationEntry* entry = |
| 93 content->GetController().GetVisibleEntry(); | 104 content->GetController().GetVisibleEntry(); |
| 94 if (entry) | 105 if (entry && (logger->ntp_url_ != entry->GetURL())) { |
| 106 DVLOG(1) << "NTP URL changed from \"" << logger->ntp_url_ << "\" to \"" | |
| 107 << entry->GetURL() << "\""; | |
| 95 logger->ntp_url_ = entry->GetURL(); | 108 logger->ntp_url_ = entry->GetURL(); |
| 109 } | |
| 96 | 110 |
| 97 return logger; | 111 return logger; |
| 98 } | 112 } |
| 99 | 113 |
| 100 void NTPUserDataLogger::LogEvent(NTPLoggingEventType event, | 114 void NTPUserDataLogger::LogEvent(NTPLoggingEventType event, |
| 101 base::TimeDelta time) { | 115 base::TimeDelta time) { |
| 102 switch (event) { | 116 switch (event) { |
| 103 case NTP_SERVER_SIDE_SUGGESTION: | 117 case NTP_SERVER_SIDE_SUGGESTION: |
| 104 has_server_side_suggestions_ = true; | 118 has_server_side_suggestions_ = true; |
| 105 break; | 119 break; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 116 case NTP_ALL_TILES_LOADED: | 130 case NTP_ALL_TILES_LOADED: |
| 117 EmitNtpStatistics(time); | 131 EmitNtpStatistics(time); |
| 118 break; | 132 break; |
| 119 default: | 133 default: |
| 120 NOTREACHED(); | 134 NOTREACHED(); |
| 121 } | 135 } |
| 122 } | 136 } |
| 123 | 137 |
| 124 void NTPUserDataLogger::LogMostVisitedImpression( | 138 void NTPUserDataLogger::LogMostVisitedImpression( |
| 125 int position, NTPLoggingTileSource tile_source) { | 139 int position, NTPLoggingTileSource tile_source) { |
| 140 if (position >= static_cast<int>(impression_was_logged_.size())) { | |
| 141 impression_was_logged_.resize(position + 1); | |
| 142 } else if (impression_was_logged_[position]) { | |
| 143 return; | |
| 144 } | |
| 145 impression_was_logged_[position] = true; | |
| 146 | |
| 126 UMA_HISTOGRAM_ENUMERATION(kMostVisitedImpressionHistogramName, position, | 147 UMA_HISTOGRAM_ENUMERATION(kMostVisitedImpressionHistogramName, position, |
| 127 kNumMostVisited); | 148 kNumMostVisited); |
| 128 | 149 |
| 129 // Cannot rely on UMA histograms macro because the name of the histogram is | 150 // Cannot rely on UMA histograms macro because the name of the histogram is |
| 130 // generated dynamically. | 151 // generated dynamically. |
| 131 base::HistogramBase* counter = base::LinearHistogram::FactoryGet( | 152 base::HistogramBase* counter = base::LinearHistogram::FactoryGet( |
| 132 base::StringPrintf(kMostVisitedImpressionHistogramWithProvider, | 153 base::StringPrintf(kMostVisitedImpressionHistogramWithProvider, |
| 133 GetSourceName(tile_source).c_str()), | 154 GetSourceName(tile_source).c_str()), |
| 134 1, | 155 1, |
| 135 kNumMostVisited, | 156 kNumMostVisited, |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 153 kNumMostVisited + 1, | 174 kNumMostVisited + 1, |
| 154 base::Histogram::kUmaTargetedHistogramFlag); | 175 base::Histogram::kUmaTargetedHistogramFlag); |
| 155 counter->Add(position); | 176 counter->Add(position); |
| 156 | 177 |
| 157 // Records the action. This will be available as a time-stamped stream | 178 // Records the action. This will be available as a time-stamped stream |
| 158 // server-side and can be used to compute time-to-long-dwell. | 179 // server-side and can be used to compute time-to-long-dwell. |
| 159 content::RecordAction(base::UserMetricsAction("MostVisited_Clicked")); | 180 content::RecordAction(base::UserMetricsAction("MostVisited_Clicked")); |
| 160 } | 181 } |
| 161 | 182 |
| 162 NTPUserDataLogger::NTPUserDataLogger(content::WebContents* contents) | 183 NTPUserDataLogger::NTPUserDataLogger(content::WebContents* contents) |
| 163 : has_server_side_suggestions_(false), | 184 : content::WebContentsObserver(contents), |
| 185 has_server_side_suggestions_(false), | |
| 164 has_client_side_suggestions_(false), | 186 has_client_side_suggestions_(false), |
| 165 number_of_tiles_(0), | 187 number_of_tiles_(0), |
| 166 has_emitted_(false), | 188 has_emitted_(false), |
| 167 during_startup_(false) { | 189 during_startup_(false) { |
| 168 during_startup_ = !AfterStartupTaskUtils::IsBrowserStartupComplete(); | 190 during_startup_ = !AfterStartupTaskUtils::IsBrowserStartupComplete(); |
| 169 | 191 |
| 170 // We record metrics about session data here because when this class typically | 192 // We record metrics about session data here because when this class typically |
| 171 // emits metrics it is too late. This session data would theoretically have | 193 // emits metrics it is too late. This session data would theoretically have |
| 172 // been used to populate the page, and we want to learn about its state when | 194 // been used to populate the page, and we want to learn about its state when |
| 173 // the NTP is being generated. | 195 // the NTP is being generated. |
| 174 if (contents) { | 196 if (contents) { |
| 175 ProfileSyncService* sync = ProfileSyncServiceFactory::GetForProfile( | 197 ProfileSyncService* sync = ProfileSyncServiceFactory::GetForProfile( |
| 176 Profile::FromBrowserContext(contents->GetBrowserContext())); | 198 Profile::FromBrowserContext(contents->GetBrowserContext())); |
| 177 if (sync) { | 199 if (sync) { |
| 178 browser_sync::SessionsSyncManager* sessions = | 200 browser_sync::SessionsSyncManager* sessions = |
| 179 static_cast<browser_sync::SessionsSyncManager*>( | 201 static_cast<browser_sync::SessionsSyncManager*>( |
| 180 sync->GetSessionsSyncableService()); | 202 sync->GetSessionsSyncableService()); |
| 181 if (sessions) { | 203 if (sessions) { |
| 182 sync_sessions::SyncSessionsMetrics::RecordYoungestForeignTabAgeOnNTP( | 204 sync_sessions::SyncSessionsMetrics::RecordYoungestForeignTabAgeOnNTP( |
| 183 sessions); | 205 sessions); |
| 184 } | 206 } |
| 185 } | 207 } |
| 186 } | 208 } |
| 187 } | 209 } |
| 188 | 210 |
| 211 // content::WebContentsObserver override | |
| 212 void NTPUserDataLogger::NavigationEntryCommitted( | |
| 213 const content::LoadCommittedDetails& load_details) { | |
| 214 // User is returning to NTP, probably via the back button; reset stats. | |
| 215 if (load_details.previous_url.is_valid() && | |
| 216 load_details.entry->GetURL().is_valid() && | |
| 217 (load_details.entry->GetURL() == ntp_url_)) { | |
| 218 DVLOG(1) << "Returning to New Tab Page"; | |
| 219 impression_was_logged_.clear(); | |
| 220 has_emitted_ = false; | |
| 221 number_of_tiles_ = 0; | |
|
Marc Treib
2016/07/14 14:40:52
I was gonna say "Also reset has_[server|client]_si
sfiera
2016/07/15 09:55:10
Done.
Marc Treib
2016/07/15 10:04:46
Acknowledged.
| |
| 222 } | |
| 223 } | |
| 224 | |
| 189 void NTPUserDataLogger::EmitNtpStatistics(base::TimeDelta load_time) { | 225 void NTPUserDataLogger::EmitNtpStatistics(base::TimeDelta load_time) { |
| 190 // We only send statistics once per page. | 226 // We only send statistics once per page. |
| 191 if (has_emitted_) | 227 if (has_emitted_) |
| 192 return; | 228 return; |
| 229 DVLOG(1) << "Emitting NTP load time: " << load_time << ", " | |
| 230 << "number of tiles: " << number_of_tiles_; | |
| 193 | 231 |
| 194 logLoadTimeHistogram("NewTabPage.LoadTime", load_time); | 232 logLoadTimeHistogram("NewTabPage.LoadTime", load_time); |
| 195 | 233 |
| 196 // Split between ML and MV. | 234 // Split between ML and MV. |
| 197 std::string type = has_server_side_suggestions_ ? | 235 std::string type = has_server_side_suggestions_ ? |
| 198 "MostLikely" : "MostVisited"; | 236 "MostLikely" : "MostVisited"; |
| 199 logLoadTimeHistogram("NewTabPage.LoadTime." + type, load_time); | 237 logLoadTimeHistogram("NewTabPage.LoadTime." + type, load_time); |
| 200 // Split between Web and Local. | 238 // Split between Web and Local. |
| 201 std::string source = ntp_url_.SchemeIsHTTPOrHTTPS() ? "Web" : "LocalNTP"; | 239 std::string source = ntp_url_.SchemeIsHTTPOrHTTPS() ? "Web" : "LocalNTP"; |
| 202 logLoadTimeHistogram("NewTabPage.LoadTime." + source, load_time); | 240 logLoadTimeHistogram("NewTabPage.LoadTime." + source, load_time); |
| 203 | 241 |
| 204 // Split between Startup and non-startup. | 242 // Split between Startup and non-startup. |
| 205 std::string status = during_startup_ ? "Startup" : "NewTab"; | 243 std::string status = during_startup_ ? "Startup" : "NewTab"; |
| 206 logLoadTimeHistogram("NewTabPage.LoadTime." + status, load_time); | 244 logLoadTimeHistogram("NewTabPage.LoadTime." + status, load_time); |
| 207 | 245 |
| 208 has_server_side_suggestions_ = false; | 246 has_server_side_suggestions_ = false; |
| 209 has_client_side_suggestions_ = false; | 247 has_client_side_suggestions_ = false; |
| 210 UMA_HISTOGRAM_CUSTOM_COUNTS( | 248 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 211 "NewTabPage.NumberOfTiles", number_of_tiles_, 0, kNumMostVisited, | 249 "NewTabPage.NumberOfTiles", number_of_tiles_, 0, kNumMostVisited, |
| 212 kNumMostVisited + 1); | 250 kNumMostVisited + 1); |
| 213 number_of_tiles_ = 0; | 251 number_of_tiles_ = 0; |
| 214 has_emitted_ = true; | 252 has_emitted_ = true; |
| 215 during_startup_ = false; | 253 during_startup_ = false; |
| 216 } | 254 } |
| OLD | NEW |