Home | History | Annotate | Download | only in browser
      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 "components/autofill/core/browser/autofill_metrics.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/metrics/histogram.h"
      9 #include "base/time/time.h"
     10 #include "components/autofill/core/browser/autofill_type.h"
     11 #include "components/autofill/core/browser/form_structure.h"
     12 #include "components/autofill/core/common/form_data.h"
     13 
     14 namespace autofill {
     15 
     16 namespace {
     17 
     18 // Server experiments we support.
     19 enum ServerExperiment {
     20   NO_EXPERIMENT = 0,
     21   UNKNOWN_EXPERIMENT,
     22   ACCEPTANCE_RATIO_06,
     23   ACCEPTANCE_RATIO_1,
     24   ACCEPTANCE_RATIO_2,
     25   ACCEPTANCE_RATIO_4,
     26   ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_15,
     27   ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_25,
     28   ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_15_MIN_FORM_SCORE_5,
     29   TOOLBAR_DATA_ONLY,
     30   ACCEPTANCE_RATIO_04_WINNER_LEAD_RATIO_3_MIN_FORM_SCORE_4,
     31   NO_SERVER_RESPONSE,
     32   PROBABILITY_PICKER_05,
     33   PROBABILITY_PICKER_025,
     34   PROBABILITY_PICKER_025_CC_THRESHOLD_03,
     35   PROBABILITY_PICKER_025_CONTEXTUAL_CC_THRESHOLD_03,
     36   PROBABILITY_PICKER_025_CONTEXTUAL_CC_THRESHOLD_03_WITH_FALLBACK,
     37   PROBABILITY_PICKER_05_CC_NAME_THRESHOLD_03_EXPERIMENT_1,
     38   NUM_SERVER_EXPERIMENTS
     39 };
     40 
     41 enum FieldTypeGroupForMetrics {
     42   AMBIGUOUS = 0,
     43   NAME,
     44   COMPANY,
     45   ADDRESS_LINE_1,
     46   ADDRESS_LINE_2,
     47   ADDRESS_CITY,
     48   ADDRESS_STATE,
     49   ADDRESS_ZIP,
     50   ADDRESS_COUNTRY,
     51   PHONE,
     52   FAX,  // Deprecated.
     53   EMAIL,
     54   CREDIT_CARD_NAME,
     55   CREDIT_CARD_NUMBER,
     56   CREDIT_CARD_DATE,
     57   CREDIT_CARD_TYPE,
     58   NUM_FIELD_TYPE_GROUPS_FOR_METRICS
     59 };
     60 
     61 // First, translates |field_type| to the corresponding logical |group| from
     62 // |FieldTypeGroupForMetrics|.  Then, interpolates this with the given |metric|,
     63 // which should be in the range [0, |num_possible_metrics|).
     64 // Returns the interpolated index.
     65 //
     66 // The interpolation maps the pair (|group|, |metric|) to a single index, so
     67 // that all the indicies for a given group are adjacent.  In particular, with
     68 // the groups {AMBIGUOUS, NAME, ...} combining with the metrics {UNKNOWN, MATCH,
     69 // MISMATCH}, we create this set of mapped indices:
     70 // {
     71 //   AMBIGUOUS+UNKNOWN,
     72 //   AMBIGUOUS+MATCH,
     73 //   AMBIGUOUS+MISMATCH,
     74 //   NAME+UNKNOWN,
     75 //   NAME+MATCH,
     76 //   NAME+MISMATCH,
     77 //   ...
     78 // }.
     79 //
     80 // Clients must ensure that |field_type| is one of the types Chrome supports
     81 // natively, e.g. |field_type| must not be a billng address.
     82 int GetFieldTypeGroupMetric(const ServerFieldType field_type,
     83                             const int metric,
     84                             const int num_possible_metrics) {
     85   DCHECK_LT(metric, num_possible_metrics);
     86 
     87   FieldTypeGroupForMetrics group;
     88   switch (AutofillType(field_type).group()) {
     89     case ::autofill::NO_GROUP:
     90       group = AMBIGUOUS;
     91       break;
     92 
     93     case ::autofill::NAME:
     94       group = NAME;
     95       break;
     96 
     97     case ::autofill::COMPANY:
     98       group = COMPANY;
     99       break;
    100 
    101     case ::autofill::ADDRESS_HOME:
    102       switch (field_type) {
    103         case ADDRESS_HOME_LINE1:
    104           group = ADDRESS_LINE_1;
    105           break;
    106         case ADDRESS_HOME_LINE2:
    107           group = ADDRESS_LINE_2;
    108           break;
    109         case ADDRESS_HOME_CITY:
    110           group = ADDRESS_CITY;
    111           break;
    112         case ADDRESS_HOME_STATE:
    113           group = ADDRESS_STATE;
    114           break;
    115         case ADDRESS_HOME_ZIP:
    116           group = ADDRESS_ZIP;
    117           break;
    118         case ADDRESS_HOME_COUNTRY:
    119           group = ADDRESS_COUNTRY;
    120           break;
    121         default:
    122           NOTREACHED();
    123           group = AMBIGUOUS;
    124       }
    125       break;
    126 
    127     case ::autofill::EMAIL:
    128       group = EMAIL;
    129       break;
    130 
    131     case ::autofill::PHONE_HOME:
    132       group = PHONE;
    133       break;
    134 
    135     case ::autofill::CREDIT_CARD:
    136       switch (field_type) {
    137         case ::autofill::CREDIT_CARD_NAME:
    138           group = CREDIT_CARD_NAME;
    139           break;
    140         case ::autofill::CREDIT_CARD_NUMBER:
    141           group = CREDIT_CARD_NUMBER;
    142           break;
    143         case ::autofill::CREDIT_CARD_TYPE:
    144           group = CREDIT_CARD_TYPE;
    145         default:
    146           group = CREDIT_CARD_DATE;
    147       }
    148       break;
    149 
    150     default:
    151       NOTREACHED();
    152       group = AMBIGUOUS;
    153   }
    154 
    155   // Interpolate the |metric| with the |group|, so that all metrics for a given
    156   // |group| are adjacent.
    157   return (group * num_possible_metrics) + metric;
    158 }
    159 
    160 // Returns the histogram prefix to use for reporting metrics for |dialog_type|.
    161 std::string GetPrefixForDialogType(autofill::DialogType dialog_type) {
    162   switch (dialog_type) {
    163     case autofill::DIALOG_TYPE_AUTOCHECKOUT:
    164       return "Autocheckout";
    165 
    166     case autofill::DIALOG_TYPE_REQUEST_AUTOCOMPLETE:
    167       return "RequestAutocomplete";
    168   }
    169 
    170   NOTREACHED();
    171   return "UnknownDialogType";
    172 }
    173 
    174 std::string WalletApiMetricToString(
    175     AutofillMetrics::WalletApiCallMetric metric) {
    176   switch (metric) {
    177     case AutofillMetrics::ACCEPT_LEGAL_DOCUMENTS:
    178       return "AcceptLegalDocuments";
    179     case AutofillMetrics::AUTHENTICATE_INSTRUMENT:
    180       return "AuthenticateInstrument";
    181     case AutofillMetrics::GET_FULL_WALLET:
    182       return "GetFullWallet";
    183     case AutofillMetrics::GET_WALLET_ITEMS:
    184       return "GetWalletItems";
    185     case AutofillMetrics::SAVE_TO_WALLET:
    186       return "SaveToWallet";
    187     case AutofillMetrics::SEND_STATUS:
    188       return "SendStatus";
    189     case AutofillMetrics::UNKNOWN_API_CALL:
    190       NOTREACHED();
    191       return "UnknownApiCall";
    192   }
    193 
    194   NOTREACHED();
    195   return "UnknownApiCall";
    196 }
    197 
    198 // A version of the UMA_HISTOGRAM_ENUMERATION macro that allows the |name|
    199 // to vary over the program's runtime.
    200 void LogUMAHistogramEnumeration(const std::string& name,
    201                                 int sample,
    202                                 int boundary_value) {
    203   DCHECK_LT(sample, boundary_value);
    204 
    205   // Note: This leaks memory, which is expected behavior.
    206   base::HistogramBase* histogram =
    207       base::LinearHistogram::FactoryGet(
    208           name,
    209           1,
    210           boundary_value,
    211           boundary_value + 1,
    212           base::HistogramBase::kUmaTargetedHistogramFlag);
    213   histogram->Add(sample);
    214 }
    215 
    216 // A version of the UMA_HISTOGRAM_TIMES macro that allows the |name|
    217 // to vary over the program's runtime.
    218 void LogUMAHistogramTimes(const std::string& name,
    219                           const base::TimeDelta& duration) {
    220   // Note: This leaks memory, which is expected behavior.
    221   base::HistogramBase* histogram =
    222       base::Histogram::FactoryTimeGet(
    223           name,
    224           base::TimeDelta::FromMilliseconds(1),
    225           base::TimeDelta::FromSeconds(10),
    226           50,
    227           base::HistogramBase::kUmaTargetedHistogramFlag);
    228   histogram->AddTime(duration);
    229 }
    230 
    231 // A version of the UMA_HISTOGRAM_LONG_TIMES macro that allows the |name|
    232 // to vary over the program's runtime.
    233 void LogUMAHistogramLongTimes(const std::string& name,
    234                               const base::TimeDelta& duration) {
    235   // Note: This leaks memory, which is expected behavior.
    236   base::HistogramBase* histogram =
    237       base::Histogram::FactoryTimeGet(
    238           name,
    239           base::TimeDelta::FromMilliseconds(1),
    240           base::TimeDelta::FromHours(1),
    241           50,
    242           base::HistogramBase::kUmaTargetedHistogramFlag);
    243   histogram->AddTime(duration);
    244 }
    245 
    246 // Logs a type quality metric.  The primary histogram name is constructed based
    247 // on |base_name| and |experiment_id|.  The field-specific histogram name also
    248 // factors in the |field_type|.  Logs a sample of |metric|, which should be in
    249 // the range [0, |num_possible_metrics|).
    250 void LogTypeQualityMetric(const std::string& base_name,
    251                           const int metric,
    252                           const int num_possible_metrics,
    253                           const ServerFieldType field_type,
    254                           const std::string& experiment_id) {
    255   DCHECK_LT(metric, num_possible_metrics);
    256 
    257   std::string histogram_name = base_name;
    258   if (!experiment_id.empty())
    259     histogram_name += "_" + experiment_id;
    260   LogUMAHistogramEnumeration(histogram_name, metric, num_possible_metrics);
    261 
    262   std::string sub_histogram_name = base_name + ".ByFieldType";
    263   if (!experiment_id.empty())
    264     sub_histogram_name += "_" + experiment_id;
    265   const int field_type_group_metric =
    266       GetFieldTypeGroupMetric(field_type, metric, num_possible_metrics);
    267   const int num_field_type_group_metrics =
    268       num_possible_metrics * NUM_FIELD_TYPE_GROUPS_FOR_METRICS;
    269   LogUMAHistogramEnumeration(sub_histogram_name,
    270                              field_type_group_metric,
    271                              num_field_type_group_metrics);
    272 }
    273 
    274 void LogServerExperimentId(const std::string& histogram_name,
    275                            const std::string& experiment_id) {
    276   ServerExperiment metric = UNKNOWN_EXPERIMENT;
    277 
    278   const std::string default_experiment_name =
    279       FormStructure(FormData(), std::string()).server_experiment_id();
    280   if (experiment_id.empty())
    281     metric = NO_EXPERIMENT;
    282   else if (experiment_id == "ar06")
    283     metric = ACCEPTANCE_RATIO_06;
    284   else if (experiment_id == "ar1")
    285     metric = ACCEPTANCE_RATIO_1;
    286   else if (experiment_id == "ar2")
    287     metric = ACCEPTANCE_RATIO_2;
    288   else if (experiment_id == "ar4")
    289     metric = ACCEPTANCE_RATIO_4;
    290   else if (experiment_id == "ar05wlr15")
    291     metric = ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_15;
    292   else if (experiment_id == "ar05wlr25")
    293     metric = ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_25;
    294   else if (experiment_id == "ar05wr15fs5")
    295     metric = ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_15_MIN_FORM_SCORE_5;
    296   else if (experiment_id == "tbar1")
    297     metric = TOOLBAR_DATA_ONLY;
    298   else if (experiment_id == "ar04wr3fs4")
    299     metric = ACCEPTANCE_RATIO_04_WINNER_LEAD_RATIO_3_MIN_FORM_SCORE_4;
    300   else if (experiment_id == default_experiment_name)
    301     metric = NO_SERVER_RESPONSE;
    302   else if (experiment_id == "fp05")
    303     metric = PROBABILITY_PICKER_05;
    304   else if (experiment_id == "fp025")
    305     metric = PROBABILITY_PICKER_025;
    306   else if (experiment_id == "fp05cc03")
    307     metric = PROBABILITY_PICKER_025_CC_THRESHOLD_03;
    308   else if (experiment_id == "fp05cco03")
    309     metric = PROBABILITY_PICKER_025_CONTEXTUAL_CC_THRESHOLD_03;
    310   else if (experiment_id == "fp05cco03cstd")
    311     metric = PROBABILITY_PICKER_025_CONTEXTUAL_CC_THRESHOLD_03_WITH_FALLBACK;
    312   else if (experiment_id == "fp05cc03e1")
    313     metric = PROBABILITY_PICKER_05_CC_NAME_THRESHOLD_03_EXPERIMENT_1;
    314 
    315   DCHECK_LT(metric, NUM_SERVER_EXPERIMENTS);
    316   LogUMAHistogramEnumeration(histogram_name, metric, NUM_SERVER_EXPERIMENTS);
    317 }
    318 
    319 }  // namespace
    320 
    321 AutofillMetrics::AutofillMetrics() {
    322 }
    323 
    324 AutofillMetrics::~AutofillMetrics() {
    325 }
    326 
    327 void AutofillMetrics::LogAutocheckoutBubbleMetric(BubbleMetric metric) const {
    328   DCHECK_LT(metric, NUM_BUBBLE_METRICS);
    329 
    330   UMA_HISTOGRAM_ENUMERATION("Autocheckout.Bubble", metric, NUM_BUBBLE_METRICS);
    331 }
    332 
    333 void AutofillMetrics::LogAutocheckoutBuyFlowMetric(
    334     AutocheckoutBuyFlowMetric metric) const {
    335   DCHECK_LT(metric, NUM_AUTOCHECKOUT_BUY_FLOW_METRICS);
    336 
    337   UMA_HISTOGRAM_ENUMERATION("Autocheckout.BuyFlow", metric,
    338                             NUM_AUTOCHECKOUT_BUY_FLOW_METRICS);
    339 }
    340 
    341 void AutofillMetrics::LogCreditCardInfoBarMetric(InfoBarMetric metric) const {
    342   DCHECK_LT(metric, NUM_INFO_BAR_METRICS);
    343 
    344   UMA_HISTOGRAM_ENUMERATION("Autofill.CreditCardInfoBar", metric,
    345                             NUM_INFO_BAR_METRICS);
    346 }
    347 
    348 void AutofillMetrics::LogDialogDismissalState(
    349     autofill::DialogType dialog_type,
    350     DialogDismissalState state) const {
    351   std::string name = GetPrefixForDialogType(dialog_type) + ".DismissalState";
    352   LogUMAHistogramEnumeration(name, state, NUM_DIALOG_DISMISSAL_STATES);
    353 }
    354 
    355 void AutofillMetrics::LogDialogInitialUserState(
    356     autofill::DialogType dialog_type,
    357     DialogInitialUserStateMetric user_type) const {
    358   std::string name = GetPrefixForDialogType(dialog_type) + ".InitialUserState";
    359   LogUMAHistogramEnumeration(
    360       name, user_type, NUM_DIALOG_INITIAL_USER_STATE_METRICS);
    361 }
    362 
    363 void AutofillMetrics::LogDialogLatencyToShow(
    364     autofill::DialogType dialog_type,
    365     const base::TimeDelta& duration) const {
    366   std::string name =
    367       GetPrefixForDialogType(dialog_type) + ".UiLatencyToShow";
    368   LogUMAHistogramTimes(name, duration);
    369 }
    370 
    371 void AutofillMetrics::LogDialogPopupEvent(autofill::DialogType dialog_type,
    372                                           DialogPopupEvent event) const {
    373   std::string name = GetPrefixForDialogType(dialog_type) + ".PopupInDialog";
    374   LogUMAHistogramEnumeration(name, event, NUM_DIALOG_POPUP_EVENTS);
    375 }
    376 
    377 void AutofillMetrics::LogDialogSecurityMetric(
    378     autofill::DialogType dialog_type,
    379     DialogSecurityMetric metric) const {
    380   std::string name = GetPrefixForDialogType(dialog_type) + ".Security";
    381   LogUMAHistogramEnumeration(name, metric, NUM_DIALOG_SECURITY_METRICS);
    382 }
    383 
    384 void AutofillMetrics::LogDialogUiDuration(
    385     const base::TimeDelta& duration,
    386     autofill::DialogType dialog_type,
    387     DialogDismissalAction dismissal_action) const {
    388   std::string prefix = GetPrefixForDialogType(dialog_type);
    389 
    390   std::string suffix;
    391   switch (dismissal_action) {
    392     case DIALOG_ACCEPTED:
    393       suffix = "Submit";
    394       break;
    395 
    396     case DIALOG_CANCELED:
    397       suffix = "Cancel";
    398       break;
    399   }
    400 
    401   LogUMAHistogramLongTimes(prefix + ".UiDuration", duration);
    402   LogUMAHistogramLongTimes(prefix + ".UiDuration." + suffix, duration);
    403 }
    404 
    405 void AutofillMetrics::LogDialogUiEvent(autofill::DialogType dialog_type,
    406                                        DialogUiEvent event) const {
    407   std::string name = GetPrefixForDialogType(dialog_type) + ".UiEvents";
    408   LogUMAHistogramEnumeration(name, event, NUM_DIALOG_UI_EVENTS);
    409 }
    410 
    411 void AutofillMetrics::LogWalletErrorMetric(autofill::DialogType dialog_type,
    412                                            WalletErrorMetric metric) const {
    413   std::string name = GetPrefixForDialogType(dialog_type) + ".WalletErrors";
    414   LogUMAHistogramEnumeration(name, metric, NUM_WALLET_ERROR_METRICS);
    415 }
    416 
    417 void AutofillMetrics::LogWalletApiCallDuration(
    418     WalletApiCallMetric metric,
    419     const base::TimeDelta& duration) const {
    420   LogUMAHistogramTimes("Wallet.ApiCallDuration." +
    421                        WalletApiMetricToString(metric), duration);
    422 }
    423 
    424 void AutofillMetrics::LogWalletRequiredActionMetric(
    425       autofill::DialogType dialog_type,
    426       WalletRequiredActionMetric required_action) const {
    427   std::string name =
    428       GetPrefixForDialogType(dialog_type) + ".WalletRequiredActions";
    429   LogUMAHistogramEnumeration(
    430       name, required_action, NUM_WALLET_REQUIRED_ACTIONS);
    431 }
    432 
    433 void AutofillMetrics::LogAutocheckoutDuration(
    434     const base::TimeDelta& duration,
    435     AutocheckoutCompletionStatus status) const {
    436   std::string suffix;
    437   switch (status) {
    438     case AUTOCHECKOUT_CANCELLED:
    439       suffix = "Cancelled";
    440       break;
    441 
    442     case AUTOCHECKOUT_FAILED:
    443       suffix = "Failed";
    444       break;
    445 
    446     case AUTOCHECKOUT_SUCCEEDED:
    447       suffix = "Succeeded";
    448       break;
    449   }
    450 
    451   LogUMAHistogramLongTimes("Autocheckout.FlowDuration", duration);
    452   LogUMAHistogramLongTimes("Autocheckout.FlowDuration." + suffix, duration);
    453 }
    454 
    455 void AutofillMetrics::LogAutocheckoutWhitelistDownloadDuration(
    456     const base::TimeDelta& duration,
    457     AutocheckoutWhitelistDownloadStatus status) const {
    458   std::string suffix;
    459   switch (status) {
    460     case AUTOCHECKOUT_WHITELIST_DOWNLOAD_FAILED:
    461       suffix = "Failed";
    462       break;
    463 
    464     case AUTOCHECKOUT_WHITELIST_DOWNLOAD_SUCCEEDED:
    465       suffix = "Succeeded";
    466       break;
    467   }
    468 
    469   LogUMAHistogramTimes("Autocheckout.WhitelistDownloadDuration", duration);
    470   LogUMAHistogramTimes(
    471       "Autocheckout.WhitelistDownloadDuration." + suffix, duration);
    472 }
    473 
    474 void AutofillMetrics::LogDeveloperEngagementMetric(
    475     DeveloperEngagementMetric metric) const {
    476   DCHECK_LT(metric, NUM_DEVELOPER_ENGAGEMENT_METRICS);
    477 
    478   UMA_HISTOGRAM_ENUMERATION("Autofill.DeveloperEngagement", metric,
    479                             NUM_DEVELOPER_ENGAGEMENT_METRICS);
    480 }
    481 
    482 void AutofillMetrics::LogHeuristicTypePrediction(
    483     FieldTypeQualityMetric metric,
    484     ServerFieldType field_type,
    485     const std::string& experiment_id) const {
    486   LogTypeQualityMetric("Autofill.Quality.HeuristicType",
    487                        metric, NUM_FIELD_TYPE_QUALITY_METRICS,
    488                        field_type, experiment_id);
    489 }
    490 
    491 void AutofillMetrics::LogOverallTypePrediction(
    492     FieldTypeQualityMetric metric,
    493     ServerFieldType field_type,
    494     const std::string& experiment_id) const {
    495   LogTypeQualityMetric("Autofill.Quality.PredictedType",
    496                        metric, NUM_FIELD_TYPE_QUALITY_METRICS,
    497                        field_type, experiment_id);
    498 }
    499 
    500 void AutofillMetrics::LogServerTypePrediction(
    501     FieldTypeQualityMetric metric,
    502     ServerFieldType field_type,
    503     const std::string& experiment_id) const {
    504   LogTypeQualityMetric("Autofill.Quality.ServerType",
    505                        metric, NUM_FIELD_TYPE_QUALITY_METRICS,
    506                        field_type, experiment_id);
    507 }
    508 
    509 void AutofillMetrics::LogQualityMetric(QualityMetric metric,
    510                                        const std::string& experiment_id) const {
    511   DCHECK_LT(metric, NUM_QUALITY_METRICS);
    512 
    513   std::string histogram_name = "Autofill.Quality";
    514   if (!experiment_id.empty())
    515     histogram_name += "_" + experiment_id;
    516 
    517   LogUMAHistogramEnumeration(histogram_name, metric, NUM_QUALITY_METRICS);
    518 }
    519 
    520 void AutofillMetrics::LogServerQueryMetric(ServerQueryMetric metric) const {
    521   DCHECK_LT(metric, NUM_SERVER_QUERY_METRICS);
    522 
    523   UMA_HISTOGRAM_ENUMERATION("Autofill.ServerQueryResponse", metric,
    524                             NUM_SERVER_QUERY_METRICS);
    525 }
    526 
    527 void AutofillMetrics::LogUserHappinessMetric(UserHappinessMetric metric) const {
    528   DCHECK_LT(metric, NUM_USER_HAPPINESS_METRICS);
    529 
    530   UMA_HISTOGRAM_ENUMERATION("Autofill.UserHappiness", metric,
    531                             NUM_USER_HAPPINESS_METRICS);
    532 }
    533 
    534 void AutofillMetrics::LogFormFillDurationFromLoadWithAutofill(
    535     const base::TimeDelta& duration) const {
    536   UMA_HISTOGRAM_CUSTOM_TIMES("Autofill.FillDuration.FromLoad.WithAutofill",
    537                              duration,
    538                              base::TimeDelta::FromMilliseconds(100),
    539                              base::TimeDelta::FromMinutes(10),
    540                              50);
    541 }
    542 
    543 void AutofillMetrics::LogFormFillDurationFromLoadWithoutAutofill(
    544     const base::TimeDelta& duration) const {
    545   UMA_HISTOGRAM_CUSTOM_TIMES("Autofill.FillDuration.FromLoad.WithoutAutofill",
    546                              duration,
    547                              base::TimeDelta::FromMilliseconds(100),
    548                              base::TimeDelta::FromMinutes(10),
    549                              50);
    550 }
    551 
    552 void AutofillMetrics::LogFormFillDurationFromInteractionWithAutofill(
    553     const base::TimeDelta& duration) const {
    554   UMA_HISTOGRAM_CUSTOM_TIMES(
    555       "Autofill.FillDuration.FromInteraction.WithAutofill",
    556       duration,
    557       base::TimeDelta::FromMilliseconds(100),
    558       base::TimeDelta::FromMinutes(10),
    559       50);
    560 }
    561 
    562 void AutofillMetrics::LogFormFillDurationFromInteractionWithoutAutofill(
    563     const base::TimeDelta& duration) const {
    564   UMA_HISTOGRAM_CUSTOM_TIMES(
    565        "Autofill.FillDuration.FromInteraction.WithoutAutofill",
    566        duration,
    567        base::TimeDelta::FromMilliseconds(100),
    568        base::TimeDelta::FromMinutes(10),
    569        50);
    570 }
    571 
    572 void AutofillMetrics::LogIsAutofillEnabledAtStartup(bool enabled) const {
    573   UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.Startup", enabled);
    574 }
    575 
    576 void AutofillMetrics::LogIsAutofillEnabledAtPageLoad(bool enabled) const {
    577   UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.PageLoad", enabled);
    578 }
    579 
    580 void AutofillMetrics::LogStoredProfileCount(size_t num_profiles) const {
    581   UMA_HISTOGRAM_COUNTS("Autofill.StoredProfileCount", num_profiles);
    582 }
    583 
    584 void AutofillMetrics::LogAddressSuggestionsCount(size_t num_suggestions) const {
    585   UMA_HISTOGRAM_COUNTS("Autofill.AddressSuggestionsCount", num_suggestions);
    586 }
    587 
    588 void AutofillMetrics::LogServerExperimentIdForQuery(
    589     const std::string& experiment_id) const {
    590   LogServerExperimentId("Autofill.ServerExperimentId.Query", experiment_id);
    591 }
    592 
    593 void AutofillMetrics::LogServerExperimentIdForUpload(
    594     const std::string& experiment_id) const {
    595   LogServerExperimentId("Autofill.ServerExperimentId.Upload", experiment_id);
    596 }
    597 
    598 }  // namespace autofill
    599