Home | History | Annotate | Download | only in ntp
      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 
     57 NTPUserDataLogger::~NTPUserDataLogger() {}
     58 
     59 // static
     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
     79 std::string NTPUserDataLogger::GetMostVisitedImpressionHistogramNameForProvider(
     80     const std::string& provider) {
     81   return base::StringPrintf(kMostVisitedImpressionHistogramWithProvider,
     82                             provider.c_str());
     83 }
     84 
     85 // static
     86 std::string NTPUserDataLogger::GetMostVisitedNavigationHistogramNameForProvider(
     87     const std::string& provider) {
     88   return base::StringPrintf(kMostVisitedNavigationHistogramWithProvider,
     89                             provider.c_str());
     90 }
     91 
     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 
    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 
    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 
    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
    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 
    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