| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/autofill/core/browser/autofill_metrics.h" | 5 #include "components/autofill/core/browser/autofill_metrics.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" |
| 13 #include "base/metrics/sparse_histogram.h" | 13 #include "base/metrics/sparse_histogram.h" |
| 14 #include "base/metrics/user_metrics.h" | 14 #include "base/metrics/user_metrics.h" |
| 15 #include "base/strings/string_piece.h" |
| 16 #include "base/strings/string_util.h" |
| 15 #include "base/time/time.h" | 17 #include "base/time/time.h" |
| 16 #include "components/autofill/core/browser/autofill_experiments.h" | 18 #include "components/autofill/core/browser/autofill_experiments.h" |
| 17 #include "components/autofill/core/browser/autofill_field.h" | 19 #include "components/autofill/core/browser/autofill_field.h" |
| 18 #include "components/autofill/core/browser/autofill_type.h" | 20 #include "components/autofill/core/browser/autofill_type.h" |
| 19 #include "components/autofill/core/browser/form_structure.h" | 21 #include "components/autofill/core/browser/form_structure.h" |
| 20 #include "components/autofill/core/common/form_data.h" | 22 #include "components/autofill/core/common/form_data.h" |
| 21 #include "components/ukm/public/ukm_entry_builder.h" | 23 #include "components/ukm/public/ukm_entry_builder.h" |
| 22 | 24 |
| 23 namespace internal { | 25 namespace internal { |
| 24 const char kUKMCardUploadDecisionEntryName[] = "Autofill.CardUploadDecision"; | 26 const char kUKMCardUploadDecisionEntryName[] = "Autofill.CardUploadDecision"; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 GROUP_CREDIT_CARD_DATE, | 75 GROUP_CREDIT_CARD_DATE, |
| 74 GROUP_CREDIT_CARD_TYPE, | 76 GROUP_CREDIT_CARD_TYPE, |
| 75 GROUP_PASSWORD, | 77 GROUP_PASSWORD, |
| 76 GROUP_ADDRESS_LINE_3, | 78 GROUP_ADDRESS_LINE_3, |
| 77 GROUP_USERNAME, | 79 GROUP_USERNAME, |
| 78 GROUP_STREET_ADDRESS, | 80 GROUP_STREET_ADDRESS, |
| 79 GROUP_CREDIT_CARD_VERIFICATION, | 81 GROUP_CREDIT_CARD_VERIFICATION, |
| 80 NUM_FIELD_TYPE_GROUPS_FOR_METRICS | 82 NUM_FIELD_TYPE_GROUPS_FOR_METRICS |
| 81 }; | 83 }; |
| 82 | 84 |
| 85 const int KMaxFieldTypeGroupMetric = |
| 86 (NUM_FIELD_TYPE_GROUPS_FOR_METRICS << 8) | |
| 87 AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS; |
| 88 |
| 83 std::string PreviousSaveCreditCardPromptUserDecisionToString( | 89 std::string PreviousSaveCreditCardPromptUserDecisionToString( |
| 84 int previous_save_credit_card_prompt_user_decision) { | 90 int previous_save_credit_card_prompt_user_decision) { |
| 85 DCHECK_LT(previous_save_credit_card_prompt_user_decision, | 91 DCHECK_LT(previous_save_credit_card_prompt_user_decision, |
| 86 prefs::NUM_PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISIONS); | 92 prefs::NUM_PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISIONS); |
| 87 std::string previous_response; | 93 std::string previous_response; |
| 88 if (previous_save_credit_card_prompt_user_decision == | 94 if (previous_save_credit_card_prompt_user_decision == |
| 89 prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_ACCEPTED) | 95 prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_ACCEPTED) |
| 90 previous_response = ".PreviouslyAccepted"; | 96 previous_response = ".PreviouslyAccepted"; |
| 91 else if (previous_save_credit_card_prompt_user_decision == | 97 else if (previous_save_credit_card_prompt_user_decision == |
| 92 prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_DENIED) | 98 prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_DENIED) |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 | 227 |
| 222 case USERNAME_FIELD: | 228 case USERNAME_FIELD: |
| 223 group = GROUP_USERNAME; | 229 group = GROUP_USERNAME; |
| 224 break; | 230 break; |
| 225 | 231 |
| 226 case TRANSACTION: | 232 case TRANSACTION: |
| 227 NOTREACHED(); | 233 NOTREACHED(); |
| 228 break; | 234 break; |
| 229 } | 235 } |
| 230 | 236 |
| 231 // Interpolate the |metric| with the |group|, so that all metrics for a given | 237 // Use bits 8-15 for the group and bits 0-7 for the metric. |
| 232 // |group| are adjacent. | 238 static_assert(AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS <= UINT8_MAX, |
| 233 return (group * AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS) + metric; | 239 "maximum field type quality metric must fit into 8 bits"); |
| 240 static_assert(NUM_FIELD_TYPE_GROUPS_FOR_METRICS <= UINT8_MAX, |
| 241 "number of field type groups must fit into 8 bits"); |
| 242 return (group << 8) | metric; |
| 234 } | 243 } |
| 235 | 244 |
| 236 namespace { | 245 namespace { |
| 237 | 246 |
| 238 // A version of the UMA_HISTOGRAM_ENUMERATION macro that allows the |name| | 247 // A version of the UMA_HISTOGRAM_ENUMERATION macro that allows the |name| |
| 239 // to vary over the program's runtime. | 248 // to vary over the program's runtime. |
| 240 void LogUMAHistogramEnumeration(const std::string& name, | 249 void LogUMAHistogramEnumeration(const std::string& name, |
| 241 int sample, | 250 int sample, |
| 242 int boundary_value) { | 251 int boundary_value) { |
| 243 DCHECK_LT(sample, boundary_value); | 252 DCHECK_LT(sample, boundary_value); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 261 base::HistogramBase* histogram = | 270 base::HistogramBase* histogram = |
| 262 base::Histogram::FactoryTimeGet( | 271 base::Histogram::FactoryTimeGet( |
| 263 name, | 272 name, |
| 264 base::TimeDelta::FromMilliseconds(1), | 273 base::TimeDelta::FromMilliseconds(1), |
| 265 base::TimeDelta::FromHours(1), | 274 base::TimeDelta::FromHours(1), |
| 266 50, | 275 50, |
| 267 base::HistogramBase::kUmaTargetedHistogramFlag); | 276 base::HistogramBase::kUmaTargetedHistogramFlag); |
| 268 histogram->AddTime(duration); | 277 histogram->AddTime(duration); |
| 269 } | 278 } |
| 270 | 279 |
| 271 // Logs a type quality metric. The primary histogram name is constructed based | 280 const char* GetQualityMetricTypeSuffix( |
| 272 // on |base_name|. The field-specific histogram name also factors in the | 281 AutofillMetrics::QualityMetricType metric_type) { |
| 273 // |field_type|. Logs a sample of |metric|, which should be in the range | |
| 274 // [0, |num_possible_metrics|). May log a suffixed version of the metric | |
| 275 // depending on |metric_type|. | |
| 276 void LogTypeQualityMetric(const std::string& base_name, | |
| 277 AutofillMetrics::FieldTypeQualityMetric metric, | |
| 278 ServerFieldType field_type, | |
| 279 AutofillMetrics::QualityMetricType metric_type) { | |
| 280 DCHECK_LT(metric, AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS); | |
| 281 | |
| 282 std::string suffix; | |
| 283 switch (metric_type) { | 282 switch (metric_type) { |
| 284 case AutofillMetrics::TYPE_SUBMISSION: | |
| 285 break; | |
| 286 case AutofillMetrics::TYPE_NO_SUBMISSION: | |
| 287 suffix = ".NoSubmission"; | |
| 288 break; | |
| 289 case AutofillMetrics::TYPE_AUTOCOMPLETE_BASED: | |
| 290 suffix = ".BasedOnAutocomplete"; | |
| 291 break; | |
| 292 default: | 283 default: |
| 293 NOTREACHED(); | 284 NOTREACHED(); |
| 285 // Fall through... |
| 286 |
| 287 case AutofillMetrics::TYPE_SUBMISSION: |
| 288 return ""; |
| 289 case AutofillMetrics::TYPE_NO_SUBMISSION: |
| 290 return ".NoSubmission"; |
| 291 case AutofillMetrics::TYPE_AUTOCOMPLETE_BASED: |
| 292 return ".BasedOnAutocomplete"; |
| 294 } | 293 } |
| 295 LogUMAHistogramEnumeration(base_name + suffix, metric, | 294 } |
| 295 |
| 296 // Given a set of |possible_types| for a field, select the best type to use as |
| 297 // the "actual" field type when calculating metrics. If the |predicted_type| is |
| 298 // among the |possible_types] then use that as the best type (i.e., the |
| 299 // prediction is deemed to have been correct). |
| 300 ServerFieldType GetActualFieldType(const ServerFieldTypeSet& possible_types, |
| 301 ServerFieldType predicted_type) { |
| 302 DCHECK_NE(possible_types.size(), 0u); |
| 303 |
| 304 if (possible_types.count(EMPTY_TYPE)) { |
| 305 DCHECK_EQ(possible_types.size(), 1u); |
| 306 return EMPTY_TYPE; |
| 307 } |
| 308 |
| 309 if (possible_types.count(UNKNOWN_TYPE)) { |
| 310 DCHECK_EQ(possible_types.size(), 1u); |
| 311 return UNKNOWN_TYPE; |
| 312 } |
| 313 |
| 314 if (possible_types.count(predicted_type)) |
| 315 return predicted_type; |
| 316 |
| 317 // Collapse field types that Chrome treats as identical, e.g. home and |
| 318 // billing address fields. |
| 319 ServerFieldTypeSet collapsed_field_types; |
| 320 for (const auto& type : possible_types) { |
| 321 DCHECK_NE(type, EMPTY_TYPE); |
| 322 DCHECK_NE(type, UNKNOWN_TYPE); |
| 323 |
| 324 // A phone number that's only missing its country code is (for metrics |
| 325 // purposes) the same as the whole phone number. |
| 326 if (type == PHONE_HOME_CITY_AND_NUMBER) |
| 327 collapsed_field_types.insert(PHONE_HOME_WHOLE_NUMBER); |
| 328 else |
| 329 collapsed_field_types.insert(AutofillType(type).GetStorableType()); |
| 330 } |
| 331 |
| 332 // Capture the field's type, if it is unambiguous. |
| 333 ServerFieldType actual_type = AMBIGUOUS_TYPE; |
| 334 if (collapsed_field_types.size() == 1) |
| 335 actual_type = *collapsed_field_types.begin(); |
| 336 |
| 337 DVLOG(2) << "Inferred Type: " << AutofillType(actual_type).ToString(); |
| 338 return actual_type; |
| 339 } |
| 340 |
| 341 // Logs field type prediction quality metrics. The primary histogram name is |
| 342 // constructed based on |source| The field-specific histogram name also factors |
| 343 // possible and predicted field types (|possible_types| and |predicted_type|, |
| 344 // respectively). May log a suffixed version of the metric depending on |
| 345 // |metric_type|. |
| 346 void LogPredictionQualityMetrics( |
| 347 const base::StringPiece& source, |
| 348 const ServerFieldTypeSet& possible_types, |
| 349 ServerFieldType predicted_type, |
| 350 AutofillMetrics::QualityMetricType metric_type) { |
| 351 // Generate histogram names. |
| 352 const char* const suffix = GetQualityMetricTypeSuffix(metric_type); |
| 353 std::string raw_data_histogram = |
| 354 base::JoinString({"Autofill.FieldPrediction.", source, suffix}, ""); |
| 355 std::string aggregate_histogram = base::JoinString( |
| 356 {"Autofill.FieldPredictionQuality.Aggregate.", source, suffix}, ""); |
| 357 std::string type_specific_histogram = base::JoinString( |
| 358 {"Autofill.FieldPredictionQuality.ByFieldType.", source, suffix}, ""); |
| 359 |
| 360 // Get the best type classification we can for the field. |
| 361 ServerFieldType actual_type = |
| 362 GetActualFieldType(possible_types, predicted_type); |
| 363 |
| 364 DVLOG(2) << "Predicted: " << AutofillType(predicted_type).ToString() << "; " |
| 365 << "Actual: " << AutofillType(actual_type).ToString(); |
| 366 |
| 367 DCHECK_LE(predicted_type, UINT16_MAX); |
| 368 DCHECK_LE(actual_type, UINT16_MAX); |
| 369 UMA_HISTOGRAM_SPARSE_SLOWLY(raw_data_histogram, |
| 370 (predicted_type << 16) | actual_type); |
| 371 |
| 372 // NO_SERVER_DATA is the equivalent of predicting UNKNOWN. |
| 373 if (predicted_type == NO_SERVER_DATA) |
| 374 predicted_type = UNKNOWN_TYPE; |
| 375 |
| 376 // The actual type being EMPTY_TYPE is the same as UNKNOWN_TYPE for comparison |
| 377 // purposes, but remember whether or not it was empty for more precise logging |
| 378 // later. |
| 379 bool is_empty = (actual_type == EMPTY_TYPE); |
| 380 bool is_ambiguous = (actual_type == AMBIGUOUS_TYPE); |
| 381 if (is_empty || is_ambiguous) |
| 382 actual_type = UNKNOWN_TYPE; |
| 383 |
| 384 // If the predicted and actual types match then it's either a true positive |
| 385 // or a true negative (if they are both unknown). Do not log type specific |
| 386 // true negatives (instead log a true positive for the "Ambiguous" type). |
| 387 if (predicted_type == actual_type) { |
| 388 if (actual_type == UNKNOWN_TYPE) { |
| 389 // Only log aggregate true negative; do not log type specific metrics |
| 390 // for UNKNOWN/EMPTY. |
| 391 DVLOG(2) << "TRUE NEGATIVE"; |
| 392 LogUMAHistogramEnumeration( |
| 393 aggregate_histogram, |
| 394 (is_empty ? AutofillMetrics::TRUE_NEGATIVE_EMPTY |
| 395 : (is_ambiguous ? AutofillMetrics::TRUE_NEGATIVE_AMBIGUOUS |
| 396 : AutofillMetrics::TRUE_NEGATIVE_UNKNOWN)), |
| 397 AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS); |
| 398 return; |
| 399 } |
| 400 |
| 401 DVLOG(2) << "TRUE POSITIVE"; |
| 402 // Log both aggregate and type specific true positive if we correctly |
| 403 // predict that type with which the field was filled. |
| 404 LogUMAHistogramEnumeration(aggregate_histogram, |
| 405 AutofillMetrics::TRUE_POSITIVE, |
| 406 AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS); |
| 407 LogUMAHistogramEnumeration( |
| 408 type_specific_histogram, |
| 409 GetFieldTypeGroupMetric(actual_type, AutofillMetrics::TRUE_POSITIVE), |
| 410 KMaxFieldTypeGroupMetric); |
| 411 return; |
| 412 } |
| 413 |
| 414 // Note: At this point predicted_type != actual type |
| 415 // If actual type is UNKNOWN_TYPE then the prediction is a false positive. |
| 416 // Further specialize the type of false positive by whether the field was |
| 417 // empty or contained an unknown value. |
| 418 if (actual_type == UNKNOWN_TYPE) { |
| 419 DVLOG(2) << "FALSE POSITIVE"; |
| 420 auto metric = |
| 421 (is_empty ? AutofillMetrics::FALSE_POSITIVE_EMPTY |
| 422 : (is_ambiguous ? AutofillMetrics::FALSE_POSITIVE_AMBIGUOUS |
| 423 : AutofillMetrics::FALSE_POSITIVE_UNKNOWN)); |
| 424 LogUMAHistogramEnumeration(aggregate_histogram, metric, |
| 425 AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS); |
| 426 LogUMAHistogramEnumeration(type_specific_histogram, |
| 427 GetFieldTypeGroupMetric(predicted_type, metric), |
| 428 KMaxFieldTypeGroupMetric); |
| 429 return; |
| 430 } |
| 431 |
| 432 // Note: At this point predicted_type != actual type, actual_type != UNKNOWN. |
| 433 // If predicted type is UNKNOWN_TYPE then the prediction is a false negative |
| 434 // unknown. |
| 435 if (predicted_type == UNKNOWN_TYPE) { |
| 436 DVLOG(2) << "FALSE NEGATIVE"; |
| 437 LogUMAHistogramEnumeration(aggregate_histogram, |
| 438 AutofillMetrics::FALSE_NEGATIVE_UNKNOWN, |
| 439 AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS); |
| 440 LogUMAHistogramEnumeration( |
| 441 type_specific_histogram, |
| 442 GetFieldTypeGroupMetric(actual_type, |
| 443 AutofillMetrics::FALSE_NEGATIVE_UNKNOWN), |
| 444 KMaxFieldTypeGroupMetric); |
| 445 return; |
| 446 } |
| 447 |
| 448 DVLOG(2) << "MISMATCH"; |
| 449 |
| 450 // Note: At this point predicted_type != actual type, actual_type != UNKNOWN, |
| 451 // predicted_type != UNKNOWN. |
| 452 // This is a mismatch. From the reference of the actual type, this is a false |
| 453 // negative (it was T, but predicted U). From the reference of the prediction, |
| 454 // this is a false positive (predicted it was T, but it was U). |
| 455 LogUMAHistogramEnumeration(aggregate_histogram, |
| 456 AutofillMetrics::FALSE_NEGATIVE_MISMATCH, |
| 296 AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS); | 457 AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS); |
| 297 | 458 LogUMAHistogramEnumeration( |
| 298 int field_type_group_metric = GetFieldTypeGroupMetric(field_type, metric); | 459 type_specific_histogram, |
| 299 int num_field_type_group_metrics = | 460 GetFieldTypeGroupMetric(actual_type, |
| 300 AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS * | 461 AutofillMetrics::FALSE_NEGATIVE_MISMATCH), |
| 301 NUM_FIELD_TYPE_GROUPS_FOR_METRICS; | 462 KMaxFieldTypeGroupMetric); |
| 302 LogUMAHistogramEnumeration(base_name + ".ByFieldType" + suffix, | 463 LogUMAHistogramEnumeration( |
| 303 field_type_group_metric, | 464 type_specific_histogram, |
| 304 num_field_type_group_metrics); | 465 GetFieldTypeGroupMetric(predicted_type, |
| 466 AutofillMetrics::FALSE_POSITIVE_MISMATCH), |
| 467 KMaxFieldTypeGroupMetric); |
| 305 } | 468 } |
| 306 | 469 |
| 307 } // namespace | 470 } // namespace |
| 308 | 471 |
| 309 // static | 472 // static |
| 310 void AutofillMetrics::LogCardUploadDecisionMetrics( | 473 void AutofillMetrics::LogCardUploadDecisionMetrics( |
| 311 int upload_decision_metrics) { | 474 int upload_decision_metrics) { |
| 312 DCHECK(upload_decision_metrics); | 475 DCHECK(upload_decision_metrics); |
| 313 DCHECK_LT(upload_decision_metrics, 1 << kNumCardUploadDecisionMetrics); | 476 DCHECK_LT(upload_decision_metrics, 1 << kNumCardUploadDecisionMetrics); |
| 314 | 477 |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 } | 656 } |
| 494 | 657 |
| 495 // static | 658 // static |
| 496 void AutofillMetrics::LogDeveloperEngagementMetric( | 659 void AutofillMetrics::LogDeveloperEngagementMetric( |
| 497 DeveloperEngagementMetric metric) { | 660 DeveloperEngagementMetric metric) { |
| 498 DCHECK_LT(metric, NUM_DEVELOPER_ENGAGEMENT_METRICS); | 661 DCHECK_LT(metric, NUM_DEVELOPER_ENGAGEMENT_METRICS); |
| 499 UMA_HISTOGRAM_ENUMERATION("Autofill.DeveloperEngagement", metric, | 662 UMA_HISTOGRAM_ENUMERATION("Autofill.DeveloperEngagement", metric, |
| 500 NUM_DEVELOPER_ENGAGEMENT_METRICS); | 663 NUM_DEVELOPER_ENGAGEMENT_METRICS); |
| 501 } | 664 } |
| 502 | 665 |
| 503 // static | 666 void AutofillMetrics::LogHeuristicPredictionQualityMetrics( |
| 504 void AutofillMetrics::LogHeuristicTypePrediction( | 667 const ServerFieldTypeSet& possible_types, |
| 505 FieldTypeQualityMetric metric, | 668 ServerFieldType predicted_type, |
| 506 ServerFieldType field_type, | 669 AutofillMetrics::QualityMetricType metric_type) { |
| 507 QualityMetricType metric_type) { | 670 LogPredictionQualityMetrics("Heuristic", possible_types, predicted_type, |
| 508 LogTypeQualityMetric("Autofill.Quality.HeuristicType", metric, field_type, | 671 metric_type); |
| 509 metric_type); | 672 } |
| 673 |
| 674 void AutofillMetrics::LogServerPredictionQualityMetrics( |
| 675 const ServerFieldTypeSet& possible_types, |
| 676 ServerFieldType predicted_type, |
| 677 AutofillMetrics::QualityMetricType metric_type) { |
| 678 LogPredictionQualityMetrics("Server", possible_types, predicted_type, |
| 679 metric_type); |
| 680 } |
| 681 |
| 682 void AutofillMetrics::LogOverallPredictionQualityMetrics( |
| 683 const ServerFieldTypeSet& possible_types, |
| 684 ServerFieldType predicted_type, |
| 685 AutofillMetrics::QualityMetricType metric_type) { |
| 686 LogPredictionQualityMetrics("Overall", possible_types, predicted_type, |
| 687 metric_type); |
| 510 } | 688 } |
| 511 | 689 |
| 512 // static | 690 // static |
| 513 void AutofillMetrics::LogOverallTypePrediction(FieldTypeQualityMetric metric, | |
| 514 ServerFieldType field_type, | |
| 515 QualityMetricType metric_type) { | |
| 516 LogTypeQualityMetric("Autofill.Quality.PredictedType", metric, field_type, | |
| 517 metric_type); | |
| 518 } | |
| 519 | |
| 520 // static | |
| 521 void AutofillMetrics::LogServerTypePrediction(FieldTypeQualityMetric metric, | |
| 522 ServerFieldType field_type, | |
| 523 QualityMetricType metric_type) { | |
| 524 LogTypeQualityMetric("Autofill.Quality.ServerType", metric, field_type, | |
| 525 metric_type); | |
| 526 } | |
| 527 | |
| 528 // static | |
| 529 void AutofillMetrics::LogServerQueryMetric(ServerQueryMetric metric) { | 691 void AutofillMetrics::LogServerQueryMetric(ServerQueryMetric metric) { |
| 530 DCHECK_LT(metric, NUM_SERVER_QUERY_METRICS); | 692 DCHECK_LT(metric, NUM_SERVER_QUERY_METRICS); |
| 531 UMA_HISTOGRAM_ENUMERATION("Autofill.ServerQueryResponse", metric, | 693 UMA_HISTOGRAM_ENUMERATION("Autofill.ServerQueryResponse", metric, |
| 532 NUM_SERVER_QUERY_METRICS); | 694 NUM_SERVER_QUERY_METRICS); |
| 533 } | 695 } |
| 534 | 696 |
| 535 // static | 697 // static |
| 536 void AutofillMetrics::LogUserHappinessMetric(UserHappinessMetric metric) { | 698 void AutofillMetrics::LogUserHappinessMetric(UserHappinessMetric metric) { |
| 537 DCHECK_LT(metric, NUM_USER_HAPPINESS_METRICS); | 699 DCHECK_LT(metric, NUM_USER_HAPPINESS_METRICS); |
| 538 UMA_HISTOGRAM_ENUMERATION("Autofill.UserHappiness", metric, | 700 UMA_HISTOGRAM_ENUMERATION("Autofill.UserHappiness", metric, |
| (...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1181 DCHECK(!form_parsed_timestamp_.is_null()); | 1343 DCHECK(!form_parsed_timestamp_.is_null()); |
| 1182 return (base::TimeTicks::Now() - form_parsed_timestamp_).InMilliseconds(); | 1344 return (base::TimeTicks::Now() - form_parsed_timestamp_).InMilliseconds(); |
| 1183 } | 1345 } |
| 1184 | 1346 |
| 1185 void AutofillMetrics::FormInteractionsUkmLogger::GetNewSourceID() { | 1347 void AutofillMetrics::FormInteractionsUkmLogger::GetNewSourceID() { |
| 1186 source_id_ = ukm_recorder_->GetNewSourceID(); | 1348 source_id_ = ukm_recorder_->GetNewSourceID(); |
| 1187 ukm_recorder_->UpdateSourceURL(source_id_, url_); | 1349 ukm_recorder_->UpdateSourceURL(source_id_, url_); |
| 1188 } | 1350 } |
| 1189 | 1351 |
| 1190 } // namespace autofill | 1352 } // namespace autofill |
| OLD | NEW |