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