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.
5 #include "chrome/browser/ui/webui/ntp/ntp_user_data_logger.h"
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/web_contents.h"
18 // Macro to log UMA statistics related to the 8 tiles shown on the NTP.
19 #define UMA_HISTOGRAM_NTP_TILES(name, sample) \
20 UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, 0, 8, 9)
24 // Used to track if suggestions were issued by the client or the server.
25 enum SuggestionsType
{
28 SUGGESTIONS_TYPE_COUNT
= 2
31 // Format string to generate the name for the histogram keeping track of
32 // suggestion impressions.
33 const char kImpressionHistogramWithProvider
[] =
34 "NewTabPage.SuggestionsImpression.%s";
38 DEFINE_WEB_CONTENTS_USER_DATA_KEY(NTPUserDataLogger
);
40 NTPUserDataLogger::~NTPUserDataLogger() {}
43 NTPUserDataLogger
* NTPUserDataLogger::GetOrCreateFromWebContents(
44 content::WebContents
* content
) {
45 // Calling CreateForWebContents when an instance is already attached has no
46 // effect, so we can do this.
47 NTPUserDataLogger::CreateForWebContents(content
);
48 NTPUserDataLogger
* logger
= NTPUserDataLogger::FromWebContents(content
);
50 // We record the URL of this NTP in order to identify navigations that
51 // originate from it. We use the NavigationController's URL since it might
52 // differ from the WebContents URL which is usually chrome://newtab/.
53 const content::NavigationEntry
* entry
=
54 content
->GetController().GetVisibleEntry();
56 logger
->ntp_url_
= entry
->GetURL();
61 void NTPUserDataLogger::EmitNtpStatistics() {
62 UMA_HISTOGRAM_COUNTS("NewTabPage.NumberOfMouseOvers", number_of_mouseovers_
);
63 number_of_mouseovers_
= 0;
65 // Only log the following statistics if at least one tile is recorded. This
66 // check is required because the statistics are emitted whenever the user
67 // changes tab away from the NTP. However, if the user comes back to that NTP
68 // later the statistics are not regenerated (i.e. they are all 0). If we log
69 // them again we get a strong bias.
70 if (number_of_tiles_
> 0) {
71 UMA_HISTOGRAM_ENUMERATION(
72 "NewTabPage.SuggestionsType",
73 has_server_side_suggestions_
? SERVER_SIDE
: CLIENT_SIDE
,
74 SUGGESTIONS_TYPE_COUNT
);
75 has_server_side_suggestions_
= false;
76 UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfTiles", number_of_tiles_
);
78 UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfThumbnailTiles",
79 number_of_thumbnail_tiles_
);
80 number_of_thumbnail_tiles_
= 0;
81 UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfGrayTiles",
82 number_of_gray_tiles_
);
83 number_of_gray_tiles_
= 0;
84 UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfExternalTiles",
85 number_of_external_tiles_
);
86 number_of_external_tiles_
= 0;
87 UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfThumbnailErrors",
88 number_of_thumbnail_errors_
);
89 number_of_thumbnail_errors_
= 0;
90 UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfGrayTileFallbacks",
91 number_of_gray_tile_fallbacks_
);
92 number_of_gray_tile_fallbacks_
= 0;
93 UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfExternalTileFallbacks",
94 number_of_external_tile_fallbacks_
);
95 number_of_external_tile_fallbacks_
= 0;
99 void NTPUserDataLogger::LogEvent(NTPLoggingEventType event
) {
101 case NTP_SERVER_SIDE_SUGGESTION
:
102 has_server_side_suggestions_
= true;
104 case NTP_CLIENT_SIDE_SUGGESTION
:
105 // We should never get a mix of server and client side suggestions,
106 // otherwise there could be a race condition depending on the order in
107 // which the iframes call this method.
108 DCHECK(!has_server_side_suggestions_
);
113 case NTP_THUMBNAIL_TILE
:
114 number_of_thumbnail_tiles_
++;
117 number_of_gray_tiles_
++;
119 case NTP_EXTERNAL_TILE
:
120 number_of_external_tiles_
++;
122 case NTP_THUMBNAIL_ERROR
:
123 number_of_thumbnail_errors_
++;
125 case NTP_GRAY_TILE_FALLBACK
:
126 number_of_gray_tile_fallbacks_
++;
128 case NTP_EXTERNAL_TILE_FALLBACK
:
129 number_of_external_tile_fallbacks_
++;
132 number_of_mouseovers_
++;
139 void NTPUserDataLogger::LogImpression(int position
,
140 const base::string16
& provider
) {
141 // Cannot rely on UMA histograms macro because the name of the histogram is
142 // generated dynamically.
143 base::HistogramBase
* counter
= base::LinearHistogram::FactoryGet(
144 base::StringPrintf(kImpressionHistogramWithProvider
,
145 base::UTF16ToUTF8(provider
).c_str()),
146 1, MostVisitedIframeSource::kNumMostVisited
,
147 MostVisitedIframeSource::kNumMostVisited
+ 1,
148 base::Histogram::kUmaTargetedHistogramFlag
);
149 counter
->Add(position
);
152 // content::WebContentsObserver override
153 void NTPUserDataLogger::NavigationEntryCommitted(
154 const content::LoadCommittedDetails
& load_details
) {
155 if (!load_details
.previous_url
.is_valid())
158 if (search::MatchesOriginAndPath(ntp_url_
, load_details
.previous_url
)) {
163 NTPUserDataLogger::NTPUserDataLogger(content::WebContents
* contents
)
164 : content::WebContentsObserver(contents
),
165 has_server_side_suggestions_(false),
167 number_of_thumbnail_tiles_(0),
168 number_of_gray_tiles_(0),
169 number_of_external_tiles_(0),
170 number_of_thumbnail_errors_(0),
171 number_of_gray_tile_fallbacks_(0),
172 number_of_external_tile_fallbacks_(0),
173 number_of_mouseovers_(0) {