• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/ui/webui/ntp/ntp_user_data_logger.h"
6 
7 #include "base/metrics/histogram.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/search/most_visited_iframe_source.h"
11 #include "chrome/browser/search/search.h"
12 #include "chrome/common/search_urls.h"
13 #include "chrome/common/url_constants.h"
14 #include "content/public/browser/navigation_details.h"
15 #include "content/public/browser/navigation_entry.h"
16 #include "content/public/browser/user_metrics.h"
17 #include "content/public/browser/web_contents.h"
18 
19 // Macro to log UMA statistics related to the 8 tiles shown on the NTP.
20 #define UMA_HISTOGRAM_NTP_TILES(name, sample) \
21     UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, 0, 8, 9)
22 
23 namespace {
24 
25 // Used to track if suggestions were issued by the client or the server.
26 enum SuggestionsType {
27   CLIENT_SIDE = 0,
28   SERVER_SIDE = 1,
29   SUGGESTIONS_TYPE_COUNT = 2
30 };
31 
32 // Number of Most Visited elements on the NTP for logging purposes.
33 const int kNumMostVisited = 8;
34 
35 // Name of the histogram keeping track of Most Visited impressions.
36 const char kMostVisitedImpressionHistogramName[] =
37     "NewTabPage.SuggestionsImpression";
38 
39 // Format string to generate the name for the histogram keeping track of
40 // suggestion impressions.
41 const char kMostVisitedImpressionHistogramWithProvider[] =
42     "NewTabPage.SuggestionsImpression.%s";
43 
44 // Name of the histogram keeping track of Most Visited navigations.
45 const char kMostVisitedNavigationHistogramName[] =
46     "NewTabPage.MostVisited";
47 
48 // Format string to generate the name for the histogram keeping track of
49 // suggestion navigations.
50 const char kMostVisitedNavigationHistogramWithProvider[] =
51     "NewTabPage.MostVisited.%s";
52 
53 }  // namespace
54 
55 DEFINE_WEB_CONTENTS_USER_DATA_KEY(NTPUserDataLogger);
56 
~NTPUserDataLogger()57 NTPUserDataLogger::~NTPUserDataLogger() {}
58 
59 // static
GetOrCreateFromWebContents(content::WebContents * content)60 NTPUserDataLogger* NTPUserDataLogger::GetOrCreateFromWebContents(
61       content::WebContents* content) {
62   // Calling CreateForWebContents when an instance is already attached has no
63   // effect, so we can do this.
64   NTPUserDataLogger::CreateForWebContents(content);
65   NTPUserDataLogger* logger = NTPUserDataLogger::FromWebContents(content);
66 
67   // We record the URL of this NTP in order to identify navigations that
68   // originate from it. We use the NavigationController's URL since it might
69   // differ from the WebContents URL which is usually chrome://newtab/.
70   const content::NavigationEntry* entry =
71       content->GetController().GetVisibleEntry();
72   if (entry)
73     logger->ntp_url_ = entry->GetURL();
74 
75   return logger;
76 }
77 
78 // static
GetMostVisitedImpressionHistogramNameForProvider(const std::string & provider)79 std::string NTPUserDataLogger::GetMostVisitedImpressionHistogramNameForProvider(
80     const std::string& provider) {
81   return base::StringPrintf(kMostVisitedImpressionHistogramWithProvider,
82                             provider.c_str());
83 }
84 
85 // static
GetMostVisitedNavigationHistogramNameForProvider(const std::string & provider)86 std::string NTPUserDataLogger::GetMostVisitedNavigationHistogramNameForProvider(
87     const std::string& provider) {
88   return base::StringPrintf(kMostVisitedNavigationHistogramWithProvider,
89                             provider.c_str());
90 }
91 
EmitNtpStatistics()92 void NTPUserDataLogger::EmitNtpStatistics() {
93   UMA_HISTOGRAM_COUNTS("NewTabPage.NumberOfMouseOvers", number_of_mouseovers_);
94   number_of_mouseovers_ = 0;
95 
96   // Only log the following statistics if at least one tile is recorded. This
97   // check is required because the statistics are emitted whenever the user
98   // changes tab away from the NTP. However, if the user comes back to that NTP
99   // later the statistics are not regenerated (i.e. they are all 0). If we log
100   // them again we get a strong bias.
101   if (number_of_tiles_ > 0) {
102     UMA_HISTOGRAM_ENUMERATION(
103         "NewTabPage.SuggestionsType",
104         has_server_side_suggestions_ ? SERVER_SIDE : CLIENT_SIDE,
105         SUGGESTIONS_TYPE_COUNT);
106     has_server_side_suggestions_ = false;
107     UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfTiles", number_of_tiles_);
108     number_of_tiles_ = 0;
109     UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfThumbnailTiles",
110                             number_of_thumbnail_tiles_);
111     number_of_thumbnail_tiles_ = 0;
112     UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfGrayTiles",
113                             number_of_gray_tiles_);
114     number_of_gray_tiles_ = 0;
115     UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfExternalTiles",
116                             number_of_external_tiles_);
117     number_of_external_tiles_ = 0;
118     UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfThumbnailErrors",
119                             number_of_thumbnail_errors_);
120     number_of_thumbnail_errors_ = 0;
121     UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfGrayTileFallbacks",
122                             number_of_gray_tile_fallbacks_);
123     number_of_gray_tile_fallbacks_ = 0;
124     UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfExternalTileFallbacks",
125                             number_of_external_tile_fallbacks_);
126     number_of_external_tile_fallbacks_ = 0;
127   }
128 }
129 
LogEvent(NTPLoggingEventType event)130 void NTPUserDataLogger::LogEvent(NTPLoggingEventType event) {
131   switch (event) {
132     case NTP_SERVER_SIDE_SUGGESTION:
133       has_server_side_suggestions_ = true;
134       break;
135     case NTP_CLIENT_SIDE_SUGGESTION:
136       // We should never get a mix of server and client side suggestions,
137       // otherwise there could be a race condition depending on the order in
138       // which the iframes call this method.
139       DCHECK(!has_server_side_suggestions_);
140       break;
141     case NTP_TILE:
142       number_of_tiles_++;
143       break;
144     case NTP_THUMBNAIL_TILE:
145       number_of_thumbnail_tiles_++;
146       break;
147     case NTP_GRAY_TILE:
148       number_of_gray_tiles_++;
149       break;
150     case NTP_EXTERNAL_TILE:
151       number_of_external_tiles_++;
152       break;
153     case NTP_THUMBNAIL_ERROR:
154       number_of_thumbnail_errors_++;
155       break;
156     case NTP_GRAY_TILE_FALLBACK:
157       number_of_gray_tile_fallbacks_++;
158       break;
159     case NTP_EXTERNAL_TILE_FALLBACK:
160       number_of_external_tile_fallbacks_++;
161       break;
162     case NTP_MOUSEOVER:
163       number_of_mouseovers_++;
164       break;
165     default:
166       NOTREACHED();
167   }
168 }
169 
LogMostVisitedImpression(int position,const base::string16 & provider)170 void NTPUserDataLogger::LogMostVisitedImpression(
171     int position, const base::string16& provider) {
172   // Log the Most Visited navigation for navigations that have providers and
173   // those that dont.
174   UMA_HISTOGRAM_ENUMERATION(kMostVisitedImpressionHistogramName, position,
175                             kNumMostVisited);
176 
177   // If a provider is specified, log the metric specific to it.
178   if (!provider.empty()) {
179     // Cannot rely on UMA histograms macro because the name of the histogram is
180     // generated dynamically.
181     base::HistogramBase* counter = base::LinearHistogram::FactoryGet(
182         GetMostVisitedImpressionHistogramNameForProvider(
183             base::UTF16ToUTF8(provider)),
184         1,
185         kNumMostVisited,
186         kNumMostVisited + 1,
187         base::Histogram::kUmaTargetedHistogramFlag);
188     counter->Add(position);
189   }
190 }
191 
LogMostVisitedNavigation(int position,const base::string16 & provider)192 void NTPUserDataLogger::LogMostVisitedNavigation(
193     int position, const base::string16& provider) {
194   // Log the Most Visited navigation for navigations that have providers and
195   // those that dont.
196   UMA_HISTOGRAM_ENUMERATION(kMostVisitedNavigationHistogramName, position,
197                             kNumMostVisited);
198 
199   // If a provider is specified, log the metric specific to it.
200   if (!provider.empty()) {
201     // Cannot rely on UMA histograms macro because the name of the histogram is
202     // generated dynamically.
203     base::HistogramBase* counter = base::LinearHistogram::FactoryGet(
204         GetMostVisitedNavigationHistogramNameForProvider(
205             base::UTF16ToUTF8(provider)),
206         1,
207         kNumMostVisited,
208         kNumMostVisited + 1,
209         base::Histogram::kUmaTargetedHistogramFlag);
210     counter->Add(position);
211   }
212 
213   // Records the action. This will be available as a time-stamped stream
214   // server-side and can be used to compute time-to-long-dwell.
215   content::RecordAction(base::UserMetricsAction("MostVisited_Clicked"));
216 }
217 
218 // content::WebContentsObserver override
NavigationEntryCommitted(const content::LoadCommittedDetails & load_details)219 void NTPUserDataLogger::NavigationEntryCommitted(
220     const content::LoadCommittedDetails& load_details) {
221   if (!load_details.previous_url.is_valid())
222     return;
223 
224   if (search::MatchesOriginAndPath(ntp_url_, load_details.previous_url)) {
225     EmitNtpStatistics();
226   }
227 }
228 
NTPUserDataLogger(content::WebContents * contents)229 NTPUserDataLogger::NTPUserDataLogger(content::WebContents* contents)
230     : content::WebContentsObserver(contents),
231       has_server_side_suggestions_(false),
232       number_of_tiles_(0),
233       number_of_thumbnail_tiles_(0),
234       number_of_gray_tiles_(0),
235       number_of_external_tiles_(0),
236       number_of_thumbnail_errors_(0),
237       number_of_gray_tile_fallbacks_(0),
238       number_of_external_tile_fallbacks_(0),
239       number_of_mouseovers_(0) {
240 }
241