Home | History | Annotate | Download | only in autofill
      1 // Copyright (c) 2011 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/autofill/autofill_metrics.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/metrics/histogram.h"
      9 #include "chrome/browser/autofill/autofill_type.h"
     10 
     11 namespace {
     12 
     13 enum FieldTypeGroupForMetrics {
     14   AMBIGUOUS = 0,
     15   NAME,
     16   COMPANY,
     17   ADDRESS_LINE_1,
     18   ADDRESS_LINE_2,
     19   ADDRESS_CITY,
     20   ADDRESS_STATE,
     21   ADDRESS_ZIP,
     22   ADDRESS_COUNTRY,
     23   PHONE,
     24   FAX,
     25   EMAIL,
     26   CREDIT_CARD_NAME,
     27   CREDIT_CARD_NUMBER,
     28   CREDIT_CARD_DATE,
     29   NUM_FIELD_TYPE_GROUPS_FOR_METRICS
     30 };
     31 
     32 // Translates |field_type| to the corresponding logical grouping for metrics,
     33 // and then interpolates this with the given |metric|, which should be in the
     34 // range [0, |num_possible_metrics|).  Returns the interpolated metric.
     35 // Clients must ensure that |field_type| is one of the types Chrome supports
     36 // natively, e.g. |field_type| must not be a billng address.
     37 int GetFieldTypeGroupMetric(const AutofillFieldType field_type,
     38                             const int metric,
     39                             const int num_possible_metrics) {
     40   DCHECK(metric < num_possible_metrics);
     41 
     42   FieldTypeGroupForMetrics group;
     43   switch (AutofillType(field_type).group()) {
     44     case AutofillType::NO_GROUP:
     45       group = AMBIGUOUS;
     46       break;
     47 
     48     case AutofillType::NAME:
     49       group = NAME;
     50       break;
     51 
     52     case AutofillType::COMPANY:
     53       group = COMPANY;
     54       break;
     55 
     56     case AutofillType::ADDRESS_HOME:
     57       switch (field_type) {
     58         case ADDRESS_HOME_LINE1:
     59           group = ADDRESS_LINE_1;
     60           break;
     61         case ADDRESS_HOME_LINE2:
     62           group = ADDRESS_LINE_2;
     63           break;
     64         case ADDRESS_HOME_CITY:
     65           group = ADDRESS_CITY;
     66           break;
     67         case ADDRESS_HOME_STATE:
     68           group = ADDRESS_STATE;
     69           break;
     70         case ADDRESS_HOME_ZIP:
     71           group = ADDRESS_ZIP;
     72           break;
     73         case ADDRESS_HOME_COUNTRY:
     74           group = ADDRESS_COUNTRY;
     75           break;
     76         default:
     77           NOTREACHED();
     78           group = AMBIGUOUS;
     79       }
     80       break;
     81 
     82     case AutofillType::EMAIL:
     83       group = EMAIL;
     84       break;
     85 
     86     case AutofillType::PHONE_HOME:
     87       group = PHONE;
     88       break;
     89 
     90     case AutofillType::PHONE_FAX:
     91       group = FAX;
     92       break;
     93 
     94     case AutofillType::CREDIT_CARD:
     95       switch (field_type) {
     96         case ::CREDIT_CARD_NAME:
     97           group = CREDIT_CARD_NAME;
     98           break;
     99         case ::CREDIT_CARD_NUMBER:
    100           group = CREDIT_CARD_NUMBER;
    101           break;
    102         default:
    103           group = CREDIT_CARD_DATE;
    104       }
    105       break;
    106 
    107     default:
    108       NOTREACHED();
    109       group = AMBIGUOUS;
    110   }
    111 
    112   // Interpolate the |metric| with the |group|, so that all metrics for a given
    113   // |group| are adjacent.  The resulting metrics will be arranged as:
    114   // AMBIGUOUS_UNKNOWN
    115   // AMBIGUOUS_MATCH
    116   // AMBIGUOUS_MISMATCH
    117   // NAME_UNKNOWN
    118   // NAME_MATCH
    119   // NAME_MISMATCH
    120   // ...
    121   return (group * num_possible_metrics) + metric;
    122 }
    123 
    124 // A version of the UMA_HISTOGRAM_ENUMERATION macro that allows the |name|
    125 // to vary over the program's runtime.
    126 void LogUMAHistogramEnumeration(const std::string& name,
    127                                 int sample,
    128                                 int boundary_value) {
    129   // We can't use the UMA_HISTOGRAM_ENUMERATION macro here because the histogram
    130   // name can vary over the duration of the program.
    131   // Note that this leaks memory; that is expected behavior.
    132   base::Histogram* counter =
    133       base::LinearHistogram::FactoryGet(
    134           name,
    135           1,
    136           boundary_value,
    137           boundary_value + 1,
    138           base::Histogram::kUmaTargetedHistogramFlag);
    139   counter->Add(sample);
    140 }
    141 
    142 // Logs a type quality metric.  The primary histogram name is constructed based
    143 // on |base_name| and |experiment_id|.  The field-specific histogram name also
    144 // factors in the |field_type|.  Logs a sample of |metric|, which should be in
    145 // the range [0, |num_possible_metrics|).
    146 void LogTypeQualityMetric(const std::string& base_name,
    147                           const int metric,
    148                           const int num_possible_metrics,
    149                           const AutofillFieldType field_type,
    150                           const std::string& experiment_id) {
    151   DCHECK(metric < num_possible_metrics);
    152 
    153   std::string histogram_name = base_name;
    154   if (!experiment_id.empty())
    155     histogram_name += "_" + experiment_id;
    156   LogUMAHistogramEnumeration(histogram_name, metric, num_possible_metrics);
    157 
    158   std::string sub_histogram_name = base_name + ".ByFieldType";
    159   if (!experiment_id.empty())
    160     sub_histogram_name += "_" + experiment_id;
    161   const int field_type_group_metric =
    162       GetFieldTypeGroupMetric(field_type, metric, num_possible_metrics);
    163   const int num_field_type_group_metrics =
    164       num_possible_metrics * NUM_FIELD_TYPE_GROUPS_FOR_METRICS;
    165   LogUMAHistogramEnumeration(sub_histogram_name,
    166                              field_type_group_metric,
    167                              num_field_type_group_metrics);
    168 }
    169 
    170 }  // namespace
    171 
    172 AutofillMetrics::AutofillMetrics() {
    173 }
    174 
    175 AutofillMetrics::~AutofillMetrics() {
    176 }
    177 
    178 void AutofillMetrics::Log(CreditCardInfoBarMetric metric) const {
    179   DCHECK(metric < NUM_CREDIT_CARD_INFO_BAR_METRICS);
    180 
    181   UMA_HISTOGRAM_ENUMERATION("Autofill.CreditCardInfoBar", metric,
    182                             NUM_CREDIT_CARD_INFO_BAR_METRICS);
    183 }
    184 
    185 void AutofillMetrics::Log(HeuristicTypeQualityMetric metric,
    186                           AutofillFieldType field_type,
    187                           const std::string& experiment_id) const {
    188   LogTypeQualityMetric("Autofill.Quality.HeuristicType",
    189                        metric, NUM_HEURISTIC_TYPE_QUALITY_METRICS,
    190                        field_type, experiment_id);
    191 }
    192 
    193 void AutofillMetrics::Log(PredictedTypeQualityMetric metric,
    194                           AutofillFieldType field_type,
    195                           const std::string& experiment_id) const {
    196   LogTypeQualityMetric("Autofill.Quality.PredictedType",
    197                        metric, NUM_PREDICTED_TYPE_QUALITY_METRICS,
    198                        field_type, experiment_id);
    199 }
    200 
    201 void AutofillMetrics::Log(QualityMetric metric,
    202                           const std::string& experiment_id) const {
    203   DCHECK(metric < NUM_QUALITY_METRICS);
    204 
    205   std::string histogram_name = "Autofill.Quality";
    206   if (!experiment_id.empty())
    207     histogram_name += "_" + experiment_id;
    208 
    209   LogUMAHistogramEnumeration(histogram_name, metric, NUM_QUALITY_METRICS);
    210 }
    211 
    212 void AutofillMetrics::Log(ServerQueryMetric metric) const {
    213   DCHECK(metric < NUM_SERVER_QUERY_METRICS);
    214 
    215   UMA_HISTOGRAM_ENUMERATION("Autofill.ServerQueryResponse", metric,
    216                             NUM_SERVER_QUERY_METRICS);
    217 }
    218 
    219 void AutofillMetrics::Log(ServerTypeQualityMetric metric,
    220                           AutofillFieldType field_type,
    221                           const std::string& experiment_id) const {
    222   LogTypeQualityMetric("Autofill.Quality.ServerType",
    223                        metric, NUM_SERVER_TYPE_QUALITY_METRICS,
    224                        field_type, experiment_id);
    225 }
    226 
    227 void AutofillMetrics::LogIsAutofillEnabledAtStartup(bool enabled) const {
    228   UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.Startup", enabled);
    229 }
    230 
    231 void AutofillMetrics::LogIsAutofillEnabledAtPageLoad(bool enabled) const {
    232   UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.PageLoad", enabled);
    233 }
    234 
    235 void AutofillMetrics::LogStoredProfileCount(size_t num_profiles) const {
    236   UMA_HISTOGRAM_COUNTS("Autofill.StoredProfileCount", num_profiles);
    237 }
    238 
    239 void AutofillMetrics::LogAddressSuggestionsCount(size_t num_suggestions) const {
    240   UMA_HISTOGRAM_COUNTS("Autofill.AddressSuggestionsCount", num_suggestions);
    241 }
    242