• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 enum FieldTypeGroupForMetrics {
20   AMBIGUOUS = 0,
21   NAME,
22   COMPANY,
23   ADDRESS_LINE_1,
24   ADDRESS_LINE_2,
25   ADDRESS_CITY,
26   ADDRESS_STATE,
27   ADDRESS_ZIP,
28   ADDRESS_COUNTRY,
29   PHONE,
30   FAX,  // Deprecated.
31   EMAIL,
32   CREDIT_CARD_NAME,
33   CREDIT_CARD_NUMBER,
34   CREDIT_CARD_DATE,
35   CREDIT_CARD_TYPE,
36   PASSWORD,
37   ADDRESS_LINE_3,
38   NUM_FIELD_TYPE_GROUPS_FOR_METRICS
39 };
40 
41 // First, translates |field_type| to the corresponding logical |group| from
42 // |FieldTypeGroupForMetrics|.  Then, interpolates this with the given |metric|,
43 // which should be in the range [0, |num_possible_metrics|).
44 // Returns the interpolated index.
45 //
46 // The interpolation maps the pair (|group|, |metric|) to a single index, so
47 // that all the indicies for a given group are adjacent.  In particular, with
48 // the groups {AMBIGUOUS, NAME, ...} combining with the metrics {UNKNOWN, MATCH,
49 // MISMATCH}, we create this set of mapped indices:
50 // {
51 //   AMBIGUOUS+UNKNOWN,
52 //   AMBIGUOUS+MATCH,
53 //   AMBIGUOUS+MISMATCH,
54 //   NAME+UNKNOWN,
55 //   NAME+MATCH,
56 //   NAME+MISMATCH,
57 //   ...
58 // }.
59 //
60 // Clients must ensure that |field_type| is one of the types Chrome supports
61 // natively, e.g. |field_type| must not be a billng address.
GetFieldTypeGroupMetric(const ServerFieldType field_type,const int metric,const int num_possible_metrics)62 int GetFieldTypeGroupMetric(const ServerFieldType field_type,
63                             const int metric,
64                             const int num_possible_metrics) {
65   DCHECK_LT(metric, num_possible_metrics);
66 
67   FieldTypeGroupForMetrics group = AMBIGUOUS;
68   switch (AutofillType(field_type).group()) {
69     case ::autofill::NO_GROUP:
70       group = AMBIGUOUS;
71       break;
72 
73     case ::autofill::NAME:
74     case ::autofill::NAME_BILLING:
75       group = NAME;
76       break;
77 
78     case ::autofill::COMPANY:
79       group = COMPANY;
80       break;
81 
82     case ::autofill::ADDRESS_HOME:
83     case ::autofill::ADDRESS_BILLING:
84       switch (AutofillType(field_type).GetStorableType()) {
85         case ADDRESS_HOME_LINE1:
86           group = ADDRESS_LINE_1;
87           break;
88         case ADDRESS_HOME_LINE2:
89           group = ADDRESS_LINE_2;
90           break;
91         case ADDRESS_HOME_LINE3:
92           group = ADDRESS_LINE_3;
93           break;
94         case ADDRESS_HOME_CITY:
95           group = ADDRESS_CITY;
96           break;
97         case ADDRESS_HOME_STATE:
98           group = ADDRESS_STATE;
99           break;
100         case ADDRESS_HOME_ZIP:
101           group = ADDRESS_ZIP;
102           break;
103         case ADDRESS_HOME_COUNTRY:
104           group = ADDRESS_COUNTRY;
105           break;
106         default:
107           NOTREACHED();
108           group = AMBIGUOUS;
109           break;
110       }
111       break;
112 
113     case ::autofill::EMAIL:
114       group = EMAIL;
115       break;
116 
117     case ::autofill::PHONE_HOME:
118     case ::autofill::PHONE_BILLING:
119       group = PHONE;
120       break;
121 
122     case ::autofill::CREDIT_CARD:
123       switch (field_type) {
124         case ::autofill::CREDIT_CARD_NAME:
125           group = CREDIT_CARD_NAME;
126           break;
127         case ::autofill::CREDIT_CARD_NUMBER:
128           group = CREDIT_CARD_NUMBER;
129           break;
130         case ::autofill::CREDIT_CARD_TYPE:
131           group = CREDIT_CARD_TYPE;
132           break;
133         case ::autofill::CREDIT_CARD_EXP_MONTH:
134         case ::autofill::CREDIT_CARD_EXP_2_DIGIT_YEAR:
135         case ::autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR:
136         case ::autofill::CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR:
137         case ::autofill::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR:
138           group = CREDIT_CARD_DATE;
139           break;
140         default:
141           NOTREACHED();
142           group = AMBIGUOUS;
143           break;
144       }
145       break;
146 
147     case ::autofill::PASSWORD_FIELD:
148       group = PASSWORD;
149       break;
150   }
151 
152   // Interpolate the |metric| with the |group|, so that all metrics for a given
153   // |group| are adjacent.
154   return (group * num_possible_metrics) + metric;
155 }
156 
WalletApiMetricToString(AutofillMetrics::WalletApiCallMetric metric)157 std::string WalletApiMetricToString(
158     AutofillMetrics::WalletApiCallMetric metric) {
159   switch (metric) {
160     case AutofillMetrics::ACCEPT_LEGAL_DOCUMENTS:
161       return "AcceptLegalDocuments";
162     case AutofillMetrics::AUTHENTICATE_INSTRUMENT:
163       return "AuthenticateInstrument";
164     case AutofillMetrics::GET_FULL_WALLET:
165       return "GetFullWallet";
166     case AutofillMetrics::GET_WALLET_ITEMS:
167       return "GetWalletItems";
168     case AutofillMetrics::SAVE_TO_WALLET:
169       return "SaveToWallet";
170     case AutofillMetrics::UNKNOWN_API_CALL:
171     case AutofillMetrics::NUM_WALLET_API_CALLS:
172       NOTREACHED();
173       return "UnknownApiCall";
174   }
175 
176   NOTREACHED();
177   return "UnknownApiCall";
178 }
179 
180 // A version of the UMA_HISTOGRAM_ENUMERATION macro that allows the |name|
181 // to vary over the program's runtime.
LogUMAHistogramEnumeration(const std::string & name,int sample,int boundary_value)182 void LogUMAHistogramEnumeration(const std::string& name,
183                                 int sample,
184                                 int boundary_value) {
185   DCHECK_LT(sample, boundary_value);
186 
187   // Note: This leaks memory, which is expected behavior.
188   base::HistogramBase* histogram =
189       base::LinearHistogram::FactoryGet(
190           name,
191           1,
192           boundary_value,
193           boundary_value + 1,
194           base::HistogramBase::kUmaTargetedHistogramFlag);
195   histogram->Add(sample);
196 }
197 
198 // A version of the UMA_HISTOGRAM_TIMES macro that allows the |name|
199 // to vary over the program's runtime.
LogUMAHistogramTimes(const std::string & name,const base::TimeDelta & duration)200 void LogUMAHistogramTimes(const std::string& name,
201                           const base::TimeDelta& duration) {
202   // Note: This leaks memory, which is expected behavior.
203   base::HistogramBase* histogram =
204       base::Histogram::FactoryTimeGet(
205           name,
206           base::TimeDelta::FromMilliseconds(1),
207           base::TimeDelta::FromSeconds(10),
208           50,
209           base::HistogramBase::kUmaTargetedHistogramFlag);
210   histogram->AddTime(duration);
211 }
212 
213 // A version of the UMA_HISTOGRAM_LONG_TIMES macro that allows the |name|
214 // to vary over the program's runtime.
LogUMAHistogramLongTimes(const std::string & name,const base::TimeDelta & duration)215 void LogUMAHistogramLongTimes(const std::string& name,
216                               const base::TimeDelta& duration) {
217   // Note: This leaks memory, which is expected behavior.
218   base::HistogramBase* histogram =
219       base::Histogram::FactoryTimeGet(
220           name,
221           base::TimeDelta::FromMilliseconds(1),
222           base::TimeDelta::FromHours(1),
223           50,
224           base::HistogramBase::kUmaTargetedHistogramFlag);
225   histogram->AddTime(duration);
226 }
227 
228 // Logs a type quality metric.  The primary histogram name is constructed based
229 // on |base_name|.  The field-specific histogram name also factors in the
230 // |field_type|.  Logs a sample of |metric|, which should be in the range
231 // [0, |num_possible_metrics|).
LogTypeQualityMetric(const std::string & base_name,const int metric,const int num_possible_metrics,const ServerFieldType field_type)232 void LogTypeQualityMetric(const std::string& base_name,
233                           const int metric,
234                           const int num_possible_metrics,
235                           const ServerFieldType field_type) {
236   DCHECK_LT(metric, num_possible_metrics);
237 
238   std::string histogram_name = base_name;
239   LogUMAHistogramEnumeration(histogram_name, metric, num_possible_metrics);
240 
241   std::string sub_histogram_name = base_name + ".ByFieldType";
242   const int field_type_group_metric =
243       GetFieldTypeGroupMetric(field_type, metric, num_possible_metrics);
244   const int num_field_type_group_metrics =
245       num_possible_metrics * NUM_FIELD_TYPE_GROUPS_FOR_METRICS;
246   LogUMAHistogramEnumeration(sub_histogram_name,
247                              field_type_group_metric,
248                              num_field_type_group_metrics);
249 }
250 
251 }  // namespace
252 
AutofillMetrics()253 AutofillMetrics::AutofillMetrics() {
254 }
255 
~AutofillMetrics()256 AutofillMetrics::~AutofillMetrics() {
257 }
258 
LogCreditCardInfoBarMetric(InfoBarMetric metric) const259 void AutofillMetrics::LogCreditCardInfoBarMetric(InfoBarMetric metric) const {
260   DCHECK_LT(metric, NUM_INFO_BAR_METRICS);
261 
262   UMA_HISTOGRAM_ENUMERATION("Autofill.CreditCardInfoBar", metric,
263                             NUM_INFO_BAR_METRICS);
264 }
265 
LogDialogDismissalState(DialogDismissalState state) const266 void AutofillMetrics::LogDialogDismissalState(
267     DialogDismissalState state) const {
268   UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.DismissalState",
269                             state, NUM_DIALOG_DISMISSAL_STATES);
270 }
271 
LogDialogInitialUserState(DialogInitialUserStateMetric user_type) const272 void AutofillMetrics::LogDialogInitialUserState(
273     DialogInitialUserStateMetric user_type) const {
274   UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.InitialUserState",
275                             user_type, NUM_DIALOG_INITIAL_USER_STATE_METRICS);
276 }
277 
LogDialogLatencyToShow(const base::TimeDelta & duration) const278 void AutofillMetrics::LogDialogLatencyToShow(
279     const base::TimeDelta& duration) const {
280   LogUMAHistogramTimes("RequestAutocomplete.UiLatencyToShow", duration);
281 }
282 
LogDialogPopupEvent(DialogPopupEvent event) const283 void AutofillMetrics::LogDialogPopupEvent(DialogPopupEvent event) const {
284   UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.PopupInDialog",
285                             event, NUM_DIALOG_POPUP_EVENTS);
286 }
287 
LogDialogSecurityMetric(DialogSecurityMetric metric) const288 void AutofillMetrics::LogDialogSecurityMetric(
289     DialogSecurityMetric metric) const {
290   UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.Security",
291                             metric, NUM_DIALOG_SECURITY_METRICS);
292 }
293 
LogDialogUiDuration(const base::TimeDelta & duration,DialogDismissalAction dismissal_action) const294 void AutofillMetrics::LogDialogUiDuration(
295     const base::TimeDelta& duration,
296     DialogDismissalAction dismissal_action) const {
297   std::string suffix;
298   switch (dismissal_action) {
299     case DIALOG_ACCEPTED:
300       suffix = "Submit";
301       break;
302 
303     case DIALOG_CANCELED:
304       suffix = "Cancel";
305       break;
306   }
307 
308   LogUMAHistogramLongTimes("RequestAutocomplete.UiDuration", duration);
309   LogUMAHistogramLongTimes("RequestAutocomplete.UiDuration." + suffix,
310                            duration);
311 }
312 
LogDialogUiEvent(DialogUiEvent event) const313 void AutofillMetrics::LogDialogUiEvent(DialogUiEvent event) const {
314   UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.UiEvents", event,
315                             NUM_DIALOG_UI_EVENTS);
316 }
317 
LogWalletErrorMetric(WalletErrorMetric metric) const318 void AutofillMetrics::LogWalletErrorMetric(WalletErrorMetric metric) const {
319   UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.WalletErrors", metric,
320                             NUM_WALLET_ERROR_METRICS);
321 }
322 
LogWalletApiCallDuration(WalletApiCallMetric metric,const base::TimeDelta & duration) const323 void AutofillMetrics::LogWalletApiCallDuration(
324     WalletApiCallMetric metric,
325     const base::TimeDelta& duration) const {
326   LogUMAHistogramTimes("Wallet.ApiCallDuration." +
327                        WalletApiMetricToString(metric), duration);
328 }
329 
LogWalletMalformedResponseMetric(WalletApiCallMetric metric) const330 void AutofillMetrics::LogWalletMalformedResponseMetric(
331     WalletApiCallMetric metric) const {
332   UMA_HISTOGRAM_ENUMERATION("Wallet.MalformedResponse", metric,
333                             NUM_WALLET_API_CALLS);
334 }
335 
LogWalletRequiredActionMetric(WalletRequiredActionMetric required_action) const336 void AutofillMetrics::LogWalletRequiredActionMetric(
337       WalletRequiredActionMetric required_action) const {
338   UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.WalletRequiredActions",
339                             required_action, NUM_WALLET_REQUIRED_ACTIONS);
340 }
341 
LogWalletResponseCode(int response_code) const342 void AutofillMetrics::LogWalletResponseCode(int response_code) const {
343   UMA_HISTOGRAM_SPARSE_SLOWLY("Wallet.ResponseCode", response_code);
344 }
345 
LogDeveloperEngagementMetric(DeveloperEngagementMetric metric) const346 void AutofillMetrics::LogDeveloperEngagementMetric(
347     DeveloperEngagementMetric metric) const {
348   DCHECK_LT(metric, NUM_DEVELOPER_ENGAGEMENT_METRICS);
349 
350   UMA_HISTOGRAM_ENUMERATION("Autofill.DeveloperEngagement", metric,
351                             NUM_DEVELOPER_ENGAGEMENT_METRICS);
352 }
353 
LogHeuristicTypePrediction(FieldTypeQualityMetric metric,ServerFieldType field_type) const354 void AutofillMetrics::LogHeuristicTypePrediction(
355     FieldTypeQualityMetric metric,
356     ServerFieldType field_type) const {
357   LogTypeQualityMetric("Autofill.Quality.HeuristicType",
358                        metric, NUM_FIELD_TYPE_QUALITY_METRICS, field_type);
359 }
360 
LogOverallTypePrediction(FieldTypeQualityMetric metric,ServerFieldType field_type) const361 void AutofillMetrics::LogOverallTypePrediction(
362     FieldTypeQualityMetric metric,
363     ServerFieldType field_type) const {
364   LogTypeQualityMetric("Autofill.Quality.PredictedType",
365                        metric, NUM_FIELD_TYPE_QUALITY_METRICS, field_type);
366 }
367 
LogServerTypePrediction(FieldTypeQualityMetric metric,ServerFieldType field_type) const368 void AutofillMetrics::LogServerTypePrediction(
369     FieldTypeQualityMetric metric,
370     ServerFieldType field_type) const {
371   LogTypeQualityMetric("Autofill.Quality.ServerType",
372                        metric, NUM_FIELD_TYPE_QUALITY_METRICS, field_type);
373 }
374 
LogServerQueryMetric(ServerQueryMetric metric) const375 void AutofillMetrics::LogServerQueryMetric(ServerQueryMetric metric) const {
376   DCHECK_LT(metric, NUM_SERVER_QUERY_METRICS);
377 
378   UMA_HISTOGRAM_ENUMERATION("Autofill.ServerQueryResponse", metric,
379                             NUM_SERVER_QUERY_METRICS);
380 }
381 
LogUserHappinessMetric(UserHappinessMetric metric) const382 void AutofillMetrics::LogUserHappinessMetric(UserHappinessMetric metric) const {
383   DCHECK_LT(metric, NUM_USER_HAPPINESS_METRICS);
384 
385   UMA_HISTOGRAM_ENUMERATION("Autofill.UserHappiness", metric,
386                             NUM_USER_HAPPINESS_METRICS);
387 }
388 
LogFormFillDurationFromLoadWithAutofill(const base::TimeDelta & duration) const389 void AutofillMetrics::LogFormFillDurationFromLoadWithAutofill(
390     const base::TimeDelta& duration) const {
391   UMA_HISTOGRAM_CUSTOM_TIMES("Autofill.FillDuration.FromLoad.WithAutofill",
392                              duration,
393                              base::TimeDelta::FromMilliseconds(100),
394                              base::TimeDelta::FromMinutes(10),
395                              50);
396 }
397 
LogFormFillDurationFromLoadWithoutAutofill(const base::TimeDelta & duration) const398 void AutofillMetrics::LogFormFillDurationFromLoadWithoutAutofill(
399     const base::TimeDelta& duration) const {
400   UMA_HISTOGRAM_CUSTOM_TIMES("Autofill.FillDuration.FromLoad.WithoutAutofill",
401                              duration,
402                              base::TimeDelta::FromMilliseconds(100),
403                              base::TimeDelta::FromMinutes(10),
404                              50);
405 }
406 
LogFormFillDurationFromInteractionWithAutofill(const base::TimeDelta & duration) const407 void AutofillMetrics::LogFormFillDurationFromInteractionWithAutofill(
408     const base::TimeDelta& duration) const {
409   UMA_HISTOGRAM_CUSTOM_TIMES(
410       "Autofill.FillDuration.FromInteraction.WithAutofill",
411       duration,
412       base::TimeDelta::FromMilliseconds(100),
413       base::TimeDelta::FromMinutes(10),
414       50);
415 }
416 
LogFormFillDurationFromInteractionWithoutAutofill(const base::TimeDelta & duration) const417 void AutofillMetrics::LogFormFillDurationFromInteractionWithoutAutofill(
418     const base::TimeDelta& duration) const {
419   UMA_HISTOGRAM_CUSTOM_TIMES(
420        "Autofill.FillDuration.FromInteraction.WithoutAutofill",
421        duration,
422        base::TimeDelta::FromMilliseconds(100),
423        base::TimeDelta::FromMinutes(10),
424        50);
425 }
426 
LogIsAutofillEnabledAtStartup(bool enabled) const427 void AutofillMetrics::LogIsAutofillEnabledAtStartup(bool enabled) const {
428   UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.Startup", enabled);
429 }
430 
LogIsAutofillEnabledAtPageLoad(bool enabled) const431 void AutofillMetrics::LogIsAutofillEnabledAtPageLoad(bool enabled) const {
432   UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.PageLoad", enabled);
433 }
434 
LogStoredProfileCount(size_t num_profiles) const435 void AutofillMetrics::LogStoredProfileCount(size_t num_profiles) const {
436   UMA_HISTOGRAM_COUNTS("Autofill.StoredProfileCount", num_profiles);
437 }
438 
LogAddressSuggestionsCount(size_t num_suggestions) const439 void AutofillMetrics::LogAddressSuggestionsCount(size_t num_suggestions) const {
440   UMA_HISTOGRAM_COUNTS("Autofill.AddressSuggestionsCount", num_suggestions);
441 }
442 
443 }  // namespace autofill
444