File: ntp_user_data_logger.cc

package info (click to toggle)
chromium-browser 41.0.2272.118-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 2,189,132 kB
  • sloc: cpp: 9,691,462; ansic: 3,341,451; python: 712,689; asm: 518,779; xml: 208,926; java: 169,820; sh: 119,353; perl: 68,907; makefile: 28,311; yacc: 13,305; objc: 11,385; tcl: 3,186; cs: 2,225; sql: 2,217; lex: 2,215; lisp: 1,349; pascal: 1,256; awk: 407; ruby: 155; sed: 53; php: 14; exp: 11
file content (240 lines) | stat: -rw-r--r-- 8,863 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/webui/ntp/ntp_user_data_logger.h"

#include "base/metrics/histogram.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/search/most_visited_iframe_source.h"
#include "chrome/browser/search/search.h"
#include "chrome/common/search_urls.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents.h"

// Macro to log UMA statistics related to the 8 tiles shown on the NTP.
#define UMA_HISTOGRAM_NTP_TILES(name, sample) \
    UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, 0, 8, 9)

namespace {

// Used to track if suggestions were issued by the client or the server.
enum SuggestionsType {
  CLIENT_SIDE = 0,
  SERVER_SIDE = 1,
  SUGGESTIONS_TYPE_COUNT = 2
};

// Number of Most Visited elements on the NTP for logging purposes.
const int kNumMostVisited = 8;

// Name of the histogram keeping track of Most Visited impressions.
const char kMostVisitedImpressionHistogramName[] =
    "NewTabPage.SuggestionsImpression";

// Format string to generate the name for the histogram keeping track of
// suggestion impressions.
const char kMostVisitedImpressionHistogramWithProvider[] =
    "NewTabPage.SuggestionsImpression.%s";

// Name of the histogram keeping track of Most Visited navigations.
const char kMostVisitedNavigationHistogramName[] =
    "NewTabPage.MostVisited";

// Format string to generate the name for the histogram keeping track of
// suggestion navigations.
const char kMostVisitedNavigationHistogramWithProvider[] =
    "NewTabPage.MostVisited.%s";

}  // namespace

DEFINE_WEB_CONTENTS_USER_DATA_KEY(NTPUserDataLogger);

NTPUserDataLogger::~NTPUserDataLogger() {}

// static
NTPUserDataLogger* NTPUserDataLogger::GetOrCreateFromWebContents(
      content::WebContents* content) {
  // Calling CreateForWebContents when an instance is already attached has no
  // effect, so we can do this.
  NTPUserDataLogger::CreateForWebContents(content);
  NTPUserDataLogger* logger = NTPUserDataLogger::FromWebContents(content);

  // We record the URL of this NTP in order to identify navigations that
  // originate from it. We use the NavigationController's URL since it might
  // differ from the WebContents URL which is usually chrome://newtab/.
  const content::NavigationEntry* entry =
      content->GetController().GetVisibleEntry();
  if (entry)
    logger->ntp_url_ = entry->GetURL();

  return logger;
}

// static
std::string NTPUserDataLogger::GetMostVisitedImpressionHistogramNameForProvider(
    const std::string& provider) {
  return base::StringPrintf(kMostVisitedImpressionHistogramWithProvider,
                            provider.c_str());
}

// static
std::string NTPUserDataLogger::GetMostVisitedNavigationHistogramNameForProvider(
    const std::string& provider) {
  return base::StringPrintf(kMostVisitedNavigationHistogramWithProvider,
                            provider.c_str());
}

void NTPUserDataLogger::EmitNtpStatistics() {
  UMA_HISTOGRAM_COUNTS("NewTabPage.NumberOfMouseOvers", number_of_mouseovers_);
  number_of_mouseovers_ = 0;

  // Only log the following statistics if at least one tile is recorded. This
  // check is required because the statistics are emitted whenever the user
  // changes tab away from the NTP. However, if the user comes back to that NTP
  // later the statistics are not regenerated (i.e. they are all 0). If we log
  // them again we get a strong bias.
  if (number_of_tiles_ > 0) {
    UMA_HISTOGRAM_ENUMERATION(
        "NewTabPage.SuggestionsType",
        has_server_side_suggestions_ ? SERVER_SIDE : CLIENT_SIDE,
        SUGGESTIONS_TYPE_COUNT);
    has_server_side_suggestions_ = false;
    UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfTiles", number_of_tiles_);
    number_of_tiles_ = 0;
    UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfThumbnailTiles",
                            number_of_thumbnail_tiles_);
    number_of_thumbnail_tiles_ = 0;
    UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfGrayTiles",
                            number_of_gray_tiles_);
    number_of_gray_tiles_ = 0;
    UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfExternalTiles",
                            number_of_external_tiles_);
    number_of_external_tiles_ = 0;
    UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfThumbnailErrors",
                            number_of_thumbnail_errors_);
    number_of_thumbnail_errors_ = 0;
    UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfGrayTileFallbacks",
                            number_of_gray_tile_fallbacks_);
    number_of_gray_tile_fallbacks_ = 0;
    UMA_HISTOGRAM_NTP_TILES("NewTabPage.NumberOfExternalTileFallbacks",
                            number_of_external_tile_fallbacks_);
    number_of_external_tile_fallbacks_ = 0;
  }
}

void NTPUserDataLogger::LogEvent(NTPLoggingEventType event) {
  switch (event) {
    case NTP_SERVER_SIDE_SUGGESTION:
      has_server_side_suggestions_ = true;
      break;
    case NTP_CLIENT_SIDE_SUGGESTION:
      // We should never get a mix of server and client side suggestions,
      // otherwise there could be a race condition depending on the order in
      // which the iframes call this method.
      DCHECK(!has_server_side_suggestions_);
      break;
    case NTP_TILE:
      number_of_tiles_++;
      break;
    case NTP_THUMBNAIL_TILE:
      number_of_thumbnail_tiles_++;
      break;
    case NTP_GRAY_TILE:
      number_of_gray_tiles_++;
      break;
    case NTP_EXTERNAL_TILE:
      number_of_external_tiles_++;
      break;
    case NTP_THUMBNAIL_ERROR:
      number_of_thumbnail_errors_++;
      break;
    case NTP_GRAY_TILE_FALLBACK:
      number_of_gray_tile_fallbacks_++;
      break;
    case NTP_EXTERNAL_TILE_FALLBACK:
      number_of_external_tile_fallbacks_++;
      break;
    case NTP_MOUSEOVER:
      number_of_mouseovers_++;
      break;
    default:
      NOTREACHED();
  }
}

void NTPUserDataLogger::LogMostVisitedImpression(
    int position, const base::string16& provider) {
  // Log the Most Visited navigation for navigations that have providers and
  // those that dont.
  UMA_HISTOGRAM_ENUMERATION(kMostVisitedImpressionHistogramName, position,
                            kNumMostVisited);

  // If a provider is specified, log the metric specific to it.
  if (!provider.empty()) {
    // Cannot rely on UMA histograms macro because the name of the histogram is
    // generated dynamically.
    base::HistogramBase* counter = base::LinearHistogram::FactoryGet(
        GetMostVisitedImpressionHistogramNameForProvider(
            base::UTF16ToUTF8(provider)),
        1,
        kNumMostVisited,
        kNumMostVisited + 1,
        base::Histogram::kUmaTargetedHistogramFlag);
    counter->Add(position);
  }
}

void NTPUserDataLogger::LogMostVisitedNavigation(
    int position, const base::string16& provider) {
  // Log the Most Visited navigation for navigations that have providers and
  // those that dont.
  UMA_HISTOGRAM_ENUMERATION(kMostVisitedNavigationHistogramName, position,
                            kNumMostVisited);

  // If a provider is specified, log the metric specific to it.
  if (!provider.empty()) {
    // Cannot rely on UMA histograms macro because the name of the histogram is
    // generated dynamically.
    base::HistogramBase* counter = base::LinearHistogram::FactoryGet(
        GetMostVisitedNavigationHistogramNameForProvider(
            base::UTF16ToUTF8(provider)),
        1,
        kNumMostVisited,
        kNumMostVisited + 1,
        base::Histogram::kUmaTargetedHistogramFlag);
    counter->Add(position);
  }

  // Records the action. This will be available as a time-stamped stream
  // server-side and can be used to compute time-to-long-dwell.
  content::RecordAction(base::UserMetricsAction("MostVisited_Clicked"));
}

// content::WebContentsObserver override
void NTPUserDataLogger::NavigationEntryCommitted(
    const content::LoadCommittedDetails& load_details) {
  if (!load_details.previous_url.is_valid())
    return;

  if (search::MatchesOriginAndPath(ntp_url_, load_details.previous_url)) {
    EmitNtpStatistics();
  }
}

NTPUserDataLogger::NTPUserDataLogger(content::WebContents* contents)
    : content::WebContentsObserver(contents),
      has_server_side_suggestions_(false),
      number_of_tiles_(0),
      number_of_thumbnail_tiles_(0),
      number_of_gray_tiles_(0),
      number_of_external_tiles_(0),
      number_of_thumbnail_errors_(0),
      number_of_gray_tile_fallbacks_(0),
      number_of_external_tile_fallbacks_(0),
      number_of_mouseovers_(0) {
}