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" |
| 11 #include "base/strings/stringprintf.h" | 11 #include "base/strings/stringprintf.h" |
| 12 #include "chrome/browser/after_startup_task_utils.h" | 12 #include "chrome/browser/after_startup_task_utils.h" |
| 13 #include "chrome/browser/profiles/profile.h" | 13 #include "chrome/browser/profiles/profile.h" |
| 14 #include "chrome/browser/search/search.h" | 14 #include "chrome/browser/search/search.h" |
| 15 #include "chrome/browser/sync/profile_sync_service_factory.h" | 15 #include "chrome/browser/sync/profile_sync_service_factory.h" |
| 16 #include "chrome/common/search/search_urls.h" | 16 #include "chrome/common/search/search_urls.h" |
| 17 #include "chrome/common/url_constants.h" | 17 #include "chrome/common/url_constants.h" |
| 18 #include "components/browser_sync/browser/profile_sync_service.h" | 18 #include "components/browser_sync/browser/profile_sync_service.h" |
| 19 #include "components/sync_sessions/sessions_sync_manager.h" | 19 #include "components/sync_sessions/sessions_sync_manager.h" |
| 20 #include "components/sync_sessions/sync_sessions_metrics.h" | 20 #include "components/sync_sessions/sync_sessions_metrics.h" |
| 21 #include "content/public/browser/navigation_details.h" | 21 #include "content/public/browser/navigation_details.h" |
| 22 #include "content/public/browser/navigation_entry.h" | 22 #include "content/public/browser/navigation_entry.h" |
| 23 #include "content/public/browser/user_metrics.h" | 23 #include "content/public/browser/user_metrics.h" |
| 24 #include "content/public/browser/web_contents.h" | 24 #include "content/public/browser/web_contents.h" |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 // Number of Most Visited elements on the NTP for logging purposes. | |
| 29 const int kNumMostVisited = 8; | |
| 30 | |
| 31 // Name of the histogram keeping track of suggestion impressions. | 28 // Name of the histogram keeping track of suggestion impressions. |
| 32 const char kMostVisitedImpressionHistogramName[] = | 29 const char kMostVisitedImpressionHistogramName[] = |
| 33 "NewTabPage.SuggestionsImpression"; | 30 "NewTabPage.SuggestionsImpression"; |
| 34 | 31 |
| 35 // Format string to generate the name for the histogram keeping track of | 32 // Format string to generate the name for the histogram keeping track of |
| 36 // suggestion impressions. | 33 // suggestion impressions. |
| 37 const char kMostVisitedImpressionHistogramWithProvider[] = | 34 const char kMostVisitedImpressionHistogramWithProvider[] = |
| 38 "NewTabPage.SuggestionsImpression.%s"; | 35 "NewTabPage.SuggestionsImpression.%s"; |
| 39 | 36 |
| 40 // Name of the histogram keeping track of suggestion navigations. | 37 // Name of the histogram keeping track of suggestion navigations. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 74 if (counter) | 71 if (counter) |
| 75 counter->AddTime(value); | 72 counter->AddTime(value); |
| 76 } | 73 } |
| 77 | 74 |
| 78 | 75 |
| 79 NTPUserDataLogger::~NTPUserDataLogger() {} | 76 NTPUserDataLogger::~NTPUserDataLogger() {} |
| 80 | 77 |
| 81 // static | 78 // static |
| 82 NTPUserDataLogger* NTPUserDataLogger::GetOrCreateFromWebContents( | 79 NTPUserDataLogger* NTPUserDataLogger::GetOrCreateFromWebContents( |
| 83 content::WebContents* content) { | 80 content::WebContents* content) { |
| 81 DCHECK(search::IsInstantNTP(content)); | |
| 82 | |
| 84 // Calling CreateForWebContents when an instance is already attached has no | 83 // Calling CreateForWebContents when an instance is already attached has no |
| 85 // effect, so we can do this. | 84 // effect, so we can do this. |
| 86 NTPUserDataLogger::CreateForWebContents(content); | 85 NTPUserDataLogger::CreateForWebContents(content); |
| 87 NTPUserDataLogger* logger = NTPUserDataLogger::FromWebContents(content); | 86 NTPUserDataLogger* logger = NTPUserDataLogger::FromWebContents(content); |
| 88 | 87 |
| 89 // We record the URL of this NTP in order to identify navigations that | 88 // 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 | 89 // originate from it. We use the NavigationController's URL since it might |
| 91 // differ from the WebContents URL which is usually chrome://newtab/. | 90 // differ from the WebContents URL which is usually chrome://newtab/. |
| 91 // | |
| 92 // We update the NTP URL every time this function is called, because the NTP | |
| 93 // URL sometimes changes while it is open, and we care about the final one for | |
| 94 // detecting when the user leaves or returns to the NTP. In particular, if the | |
| 95 // Google URL changes (e.g. google.com -> google.de), then we fall back to the | |
| 96 // local NTP. | |
| 92 const content::NavigationEntry* entry = | 97 const content::NavigationEntry* entry = |
| 93 content->GetController().GetVisibleEntry(); | 98 content->GetController().GetVisibleEntry(); |
| 94 if (entry) | 99 if (entry && (logger->ntp_url_ != entry->GetURL())) { |
| 100 DVLOG(1) << "NTP URL changed from \"" << logger->ntp_url_ << "\" to \"" | |
| 101 << entry->GetURL() << "\""; | |
| 95 logger->ntp_url_ = entry->GetURL(); | 102 logger->ntp_url_ = entry->GetURL(); |
| 103 } | |
| 96 | 104 |
| 97 return logger; | 105 return logger; |
| 98 } | 106 } |
| 99 | 107 |
| 100 void NTPUserDataLogger::LogEvent(NTPLoggingEventType event, | 108 void NTPUserDataLogger::LogEvent(NTPLoggingEventType event, |
| 101 base::TimeDelta time) { | 109 base::TimeDelta time) { |
| 102 switch (event) { | 110 switch (event) { |
| 103 case NTP_SERVER_SIDE_SUGGESTION: | 111 case NTP_SERVER_SIDE_SUGGESTION: |
| 104 has_server_side_suggestions_ = true; | 112 has_server_side_suggestions_ = true; |
| 105 break; | 113 break; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 116 case NTP_ALL_TILES_LOADED: | 124 case NTP_ALL_TILES_LOADED: |
| 117 EmitNtpStatistics(time); | 125 EmitNtpStatistics(time); |
| 118 break; | 126 break; |
| 119 default: | 127 default: |
| 120 NOTREACHED(); | 128 NOTREACHED(); |
| 121 } | 129 } |
| 122 } | 130 } |
| 123 | 131 |
| 124 void NTPUserDataLogger::LogMostVisitedImpression( | 132 void NTPUserDataLogger::LogMostVisitedImpression( |
| 125 int position, NTPLoggingTileSource tile_source) { | 133 int position, NTPLoggingTileSource tile_source) { |
| 134 if ((position >= kNumMostVisited) || (impression_was_logged_[position])) { | |
|
Marc Treib
2016/07/15 11:47:37
optional nit: no parens required around impression
| |
| 135 return; | |
| 136 } | |
| 137 impression_was_logged_[position] = true; | |
| 138 | |
| 126 UMA_HISTOGRAM_ENUMERATION(kMostVisitedImpressionHistogramName, position, | 139 UMA_HISTOGRAM_ENUMERATION(kMostVisitedImpressionHistogramName, position, |
| 127 kNumMostVisited); | 140 kNumMostVisited); |
| 128 | 141 |
| 129 // Cannot rely on UMA histograms macro because the name of the histogram is | 142 // Cannot rely on UMA histograms macro because the name of the histogram is |
| 130 // generated dynamically. | 143 // generated dynamically. |
| 131 base::HistogramBase* counter = base::LinearHistogram::FactoryGet( | 144 base::HistogramBase* counter = base::LinearHistogram::FactoryGet( |
| 132 base::StringPrintf(kMostVisitedImpressionHistogramWithProvider, | 145 base::StringPrintf(kMostVisitedImpressionHistogramWithProvider, |
| 133 GetSourceName(tile_source).c_str()), | 146 GetSourceName(tile_source).c_str()), |
| 134 1, | 147 1, |
| 135 kNumMostVisited, | 148 kNumMostVisited, |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 153 kNumMostVisited + 1, | 166 kNumMostVisited + 1, |
| 154 base::Histogram::kUmaTargetedHistogramFlag); | 167 base::Histogram::kUmaTargetedHistogramFlag); |
| 155 counter->Add(position); | 168 counter->Add(position); |
| 156 | 169 |
| 157 // Records the action. This will be available as a time-stamped stream | 170 // 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. | 171 // server-side and can be used to compute time-to-long-dwell. |
| 159 content::RecordAction(base::UserMetricsAction("MostVisited_Clicked")); | 172 content::RecordAction(base::UserMetricsAction("MostVisited_Clicked")); |
| 160 } | 173 } |
| 161 | 174 |
| 162 NTPUserDataLogger::NTPUserDataLogger(content::WebContents* contents) | 175 NTPUserDataLogger::NTPUserDataLogger(content::WebContents* contents) |
| 163 : has_server_side_suggestions_(false), | 176 : content::WebContentsObserver(contents), |
| 177 has_server_side_suggestions_(false), | |
| 164 has_client_side_suggestions_(false), | 178 has_client_side_suggestions_(false), |
| 165 number_of_tiles_(0), | 179 number_of_tiles_(0), |
| 166 has_emitted_(false), | 180 has_emitted_(false), |
| 167 during_startup_(false) { | 181 during_startup_(false) { |
| 168 during_startup_ = !AfterStartupTaskUtils::IsBrowserStartupComplete(); | 182 during_startup_ = !AfterStartupTaskUtils::IsBrowserStartupComplete(); |
| 169 | 183 |
| 170 // We record metrics about session data here because when this class typically | 184 // 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 | 185 // 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 | 186 // been used to populate the page, and we want to learn about its state when |
| 173 // the NTP is being generated. | 187 // the NTP is being generated. |
| 174 if (contents) { | 188 if (contents) { |
| 175 ProfileSyncService* sync = ProfileSyncServiceFactory::GetForProfile( | 189 ProfileSyncService* sync = ProfileSyncServiceFactory::GetForProfile( |
| 176 Profile::FromBrowserContext(contents->GetBrowserContext())); | 190 Profile::FromBrowserContext(contents->GetBrowserContext())); |
| 177 if (sync) { | 191 if (sync) { |
| 178 browser_sync::SessionsSyncManager* sessions = | 192 browser_sync::SessionsSyncManager* sessions = |
| 179 static_cast<browser_sync::SessionsSyncManager*>( | 193 static_cast<browser_sync::SessionsSyncManager*>( |
| 180 sync->GetSessionsSyncableService()); | 194 sync->GetSessionsSyncableService()); |
| 181 if (sessions) { | 195 if (sessions) { |
| 182 sync_sessions::SyncSessionsMetrics::RecordYoungestForeignTabAgeOnNTP( | 196 sync_sessions::SyncSessionsMetrics::RecordYoungestForeignTabAgeOnNTP( |
| 183 sessions); | 197 sessions); |
| 184 } | 198 } |
| 185 } | 199 } |
| 186 } | 200 } |
| 187 } | 201 } |
| 188 | 202 |
| 203 // content::WebContentsObserver override | |
| 204 void NTPUserDataLogger::NavigationEntryCommitted( | |
| 205 const content::LoadCommittedDetails& load_details) { | |
| 206 NavigatedFromURLToURL(load_details.previous_url, | |
| 207 load_details.entry->GetURL()); | |
| 208 } | |
| 209 | |
| 210 void NTPUserDataLogger::NavigatedFromURLToURL(const GURL& from, | |
| 211 const GURL& to) { | |
| 212 // User is returning to NTP, probably via the back button; reset stats. | |
| 213 if (from.is_valid() && to.is_valid() && (to == ntp_url_)) { | |
| 214 DVLOG(1) << "Returning to New Tab Page"; | |
| 215 impression_was_logged_.reset(); | |
| 216 has_emitted_ = false; | |
| 217 number_of_tiles_ = 0; | |
| 218 has_server_side_suggestions_ = false; | |
| 219 has_client_side_suggestions_ = false; | |
| 220 } | |
| 221 } | |
| 222 | |
| 189 void NTPUserDataLogger::EmitNtpStatistics(base::TimeDelta load_time) { | 223 void NTPUserDataLogger::EmitNtpStatistics(base::TimeDelta load_time) { |
| 190 // We only send statistics once per page. | 224 // We only send statistics once per page. |
| 191 if (has_emitted_) | 225 if (has_emitted_) |
| 192 return; | 226 return; |
| 227 DVLOG(1) << "Emitting NTP load time: " << load_time << ", " | |
| 228 << "number of tiles: " << number_of_tiles_; | |
| 193 | 229 |
| 194 logLoadTimeHistogram("NewTabPage.LoadTime", load_time); | 230 logLoadTimeHistogram("NewTabPage.LoadTime", load_time); |
| 195 | 231 |
| 196 // Split between ML and MV. | 232 // Split between ML and MV. |
| 197 std::string type = has_server_side_suggestions_ ? | 233 std::string type = has_server_side_suggestions_ ? |
| 198 "MostLikely" : "MostVisited"; | 234 "MostLikely" : "MostVisited"; |
| 199 logLoadTimeHistogram("NewTabPage.LoadTime." + type, load_time); | 235 logLoadTimeHistogram("NewTabPage.LoadTime." + type, load_time); |
| 200 // Split between Web and Local. | 236 // Split between Web and Local. |
| 201 std::string source = ntp_url_.SchemeIsHTTPOrHTTPS() ? "Web" : "LocalNTP"; | 237 std::string source = ntp_url_.SchemeIsHTTPOrHTTPS() ? "Web" : "LocalNTP"; |
| 202 logLoadTimeHistogram("NewTabPage.LoadTime." + source, load_time); | 238 logLoadTimeHistogram("NewTabPage.LoadTime." + source, load_time); |
| 203 | 239 |
| 204 // Split between Startup and non-startup. | 240 // Split between Startup and non-startup. |
| 205 std::string status = during_startup_ ? "Startup" : "NewTab"; | 241 std::string status = during_startup_ ? "Startup" : "NewTab"; |
| 206 logLoadTimeHistogram("NewTabPage.LoadTime." + status, load_time); | 242 logLoadTimeHistogram("NewTabPage.LoadTime." + status, load_time); |
| 207 | 243 |
| 208 has_server_side_suggestions_ = false; | 244 has_server_side_suggestions_ = false; |
| 209 has_client_side_suggestions_ = false; | 245 has_client_side_suggestions_ = false; |
| 210 UMA_HISTOGRAM_CUSTOM_COUNTS( | 246 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 211 "NewTabPage.NumberOfTiles", number_of_tiles_, 0, kNumMostVisited, | 247 "NewTabPage.NumberOfTiles", number_of_tiles_, 0, kNumMostVisited, |
| 212 kNumMostVisited + 1); | 248 kNumMostVisited + 1); |
| 213 number_of_tiles_ = 0; | 249 number_of_tiles_ = 0; |
| 214 has_emitted_ = true; | 250 has_emitted_ = true; |
| 215 during_startup_ = false; | 251 during_startup_ = false; |
| 216 } | 252 } |
| OLD | NEW |