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/form_structure.h" | 5 #include "components/autofill/core/browser/form_structure.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <map> | 10 #include <map> |
11 #include <utility> | 11 #include <utility> |
| 12 #include <vector> |
12 | 13 |
13 #include "base/command_line.h" | 14 #include "base/command_line.h" |
14 #include "base/i18n/case_conversion.h" | 15 #include "base/i18n/case_conversion.h" |
15 #include "base/logging.h" | 16 #include "base/logging.h" |
16 #include "base/memory/ptr_util.h" | 17 #include "base/memory/ptr_util.h" |
17 #include "base/metrics/field_trial.h" | 18 #include "base/metrics/field_trial.h" |
18 #include "base/sha1.h" | 19 #include "base/sha1.h" |
19 #include "base/strings/string_number_conversions.h" | 20 #include "base/strings/string_number_conversions.h" |
20 #include "base/strings/string_split.h" | 21 #include "base/strings/string_split.h" |
21 #include "base/strings/string_util.h" | 22 #include "base/strings/string_util.h" |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 for (const auto& field : fields_) { | 358 for (const auto& field : fields_) { |
358 const auto iter = field_type_map.find(field->unique_name()); | 359 const auto iter = field_type_map.find(field->unique_name()); |
359 if (iter != field_type_map.end()) | 360 if (iter != field_type_map.end()) |
360 field->set_heuristic_type(iter->second.BestHeuristicType()); | 361 field->set_heuristic_type(iter->second.BestHeuristicType()); |
361 } | 362 } |
362 } | 363 } |
363 | 364 |
364 UpdateAutofillCount(); | 365 UpdateAutofillCount(); |
365 IdentifySections(has_author_specified_sections_); | 366 IdentifySections(has_author_specified_sections_); |
366 | 367 |
| 368 std::vector<AutofillMetrics::DeveloperEngagementMetric> metrics; |
367 if (IsAutofillable()) { | 369 if (IsAutofillable()) { |
368 const auto metric = | 370 AutofillMetrics::DeveloperEngagementMetric metric = |
369 has_author_specified_types_ | 371 has_author_specified_types_ |
370 ? AutofillMetrics::FILLABLE_FORM_PARSED_WITH_TYPE_HINTS | 372 ? AutofillMetrics::FILLABLE_FORM_PARSED_WITH_TYPE_HINTS |
371 : AutofillMetrics::FILLABLE_FORM_PARSED_WITHOUT_TYPE_HINTS; | 373 : AutofillMetrics::FILLABLE_FORM_PARSED_WITHOUT_TYPE_HINTS; |
| 374 metrics.push_back(metric); |
372 AutofillMetrics::LogDeveloperEngagementMetric(metric); | 375 AutofillMetrics::LogDeveloperEngagementMetric(metric); |
373 AutofillMetrics::LogDeveloperEngagementUkm(ukm_service, source_url(), | |
374 metric); | |
375 } | 376 } |
376 | 377 |
377 if (has_author_specified_upi_vpa_hint_) { | 378 if (has_author_specified_upi_vpa_hint_) { |
378 AutofillMetrics::LogDeveloperEngagementMetric( | 379 AutofillMetrics::LogDeveloperEngagementMetric( |
379 AutofillMetrics::FORM_CONTAINS_UPI_VPA_HINT); | 380 AutofillMetrics::FORM_CONTAINS_UPI_VPA_HINT); |
380 AutofillMetrics::LogDeveloperEngagementUkm( | 381 metrics.push_back(AutofillMetrics::FORM_CONTAINS_UPI_VPA_HINT); |
381 ukm_service, source_url(), AutofillMetrics::FORM_CONTAINS_UPI_VPA_HINT); | |
382 } | 382 } |
383 | 383 |
| 384 AutofillMetrics::LogDeveloperEngagementUkm(ukm_service, source_url(), |
| 385 metrics); |
| 386 |
384 AutofillMetrics::LogDetermineHeuristicTypesTiming( | 387 AutofillMetrics::LogDetermineHeuristicTypesTiming( |
385 base::TimeTicks::Now() - determine_heuristic_types_start_time); | 388 base::TimeTicks::Now() - determine_heuristic_types_start_time); |
386 } | 389 } |
387 | 390 |
388 bool FormStructure::EncodeUploadRequest( | 391 bool FormStructure::EncodeUploadRequest( |
389 const ServerFieldTypeSet& available_field_types, | 392 const ServerFieldTypeSet& available_field_types, |
390 bool form_was_autofilled, | 393 bool form_was_autofilled, |
391 const std::string& login_form_signature, | 394 const std::string& login_form_signature, |
392 bool observed_submission, | 395 bool observed_submission, |
393 AutofillUploadContents* upload) const { | 396 AutofillUploadContents* upload) const { |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 UpdateAutofillCount(); | 678 UpdateAutofillCount(); |
676 | 679 |
677 // The form signature should match between query and upload requests to the | 680 // The form signature should match between query and upload requests to the |
678 // server. On many websites, form elements are dynamically added, removed, or | 681 // server. On many websites, form elements are dynamically added, removed, or |
679 // rearranged via JavaScript between page load and form submission, so we | 682 // rearranged via JavaScript between page load and form submission, so we |
680 // copy over the |form_signature_field_names_| corresponding to the query | 683 // copy over the |form_signature_field_names_| corresponding to the query |
681 // request. | 684 // request. |
682 form_signature_ = cached_form.form_signature_; | 685 form_signature_ = cached_form.form_signature_; |
683 } | 686 } |
684 | 687 |
685 void FormStructure::LogQualityMetrics(const base::TimeTicks& load_time, | 688 void FormStructure::LogQualityMetrics( |
686 const base::TimeTicks& interaction_time, | 689 const base::TimeTicks& load_time, |
687 const base::TimeTicks& submission_time, | 690 const base::TimeTicks& interaction_time, |
688 rappor::RapporServiceImpl* rappor_service, | 691 const base::TimeTicks& submission_time, |
689 bool did_show_suggestions, | 692 rappor::RapporServiceImpl* rappor_service, |
690 bool observed_submission) const { | 693 AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger, |
| 694 bool did_show_suggestions, |
| 695 bool observed_submission) const { |
691 size_t num_detected_field_types = 0; | 696 size_t num_detected_field_types = 0; |
692 size_t num_server_mismatches = 0; | 697 size_t num_server_mismatches = 0; |
693 size_t num_heuristic_mismatches = 0; | 698 size_t num_heuristic_mismatches = 0; |
694 size_t num_edited_autofilled_fields = 0; | 699 size_t num_edited_autofilled_fields = 0; |
695 bool did_autofill_all_possible_fields = true; | 700 bool did_autofill_all_possible_fields = true; |
696 bool did_autofill_some_possible_fields = false; | 701 bool did_autofill_some_possible_fields = false; |
697 | 702 |
698 // Determine the correct suffix for the metric, depending on whether or | 703 // Determine the correct suffix for the metric, depending on whether or |
699 // not a submission was observed. | 704 // not a submission was observed. |
700 const AutofillMetrics::QualityMetricType metric_type = | 705 const AutofillMetrics::QualityMetricType metric_type = |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
817 field_type, metric_type); | 822 field_type, metric_type); |
818 } | 823 } |
819 } | 824 } |
820 | 825 |
821 AutofillMetrics::LogNumberOfEditedAutofilledFields( | 826 AutofillMetrics::LogNumberOfEditedAutofilledFields( |
822 num_edited_autofilled_fields, observed_submission); | 827 num_edited_autofilled_fields, observed_submission); |
823 | 828 |
824 // We log "submission" and duration metrics if we are here after observing a | 829 // We log "submission" and duration metrics if we are here after observing a |
825 // submission event. | 830 // submission event. |
826 if (observed_submission) { | 831 if (observed_submission) { |
| 832 AutofillMetrics::AutofillFormSubmittedState state; |
827 if (num_detected_field_types < kRequiredFieldsForPredictionRoutines) { | 833 if (num_detected_field_types < kRequiredFieldsForPredictionRoutines) { |
828 AutofillMetrics::LogAutofillFormSubmittedState( | 834 state = AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA; |
829 AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA); | |
830 } else { | 835 } else { |
831 if (did_autofill_all_possible_fields) { | 836 if (did_autofill_all_possible_fields) { |
832 AutofillMetrics::LogAutofillFormSubmittedState( | 837 state = AutofillMetrics::FILLABLE_FORM_AUTOFILLED_ALL; |
833 AutofillMetrics::FILLABLE_FORM_AUTOFILLED_ALL); | |
834 } else if (did_autofill_some_possible_fields) { | 838 } else if (did_autofill_some_possible_fields) { |
835 AutofillMetrics::LogAutofillFormSubmittedState( | 839 state = AutofillMetrics::FILLABLE_FORM_AUTOFILLED_SOME; |
836 AutofillMetrics::FILLABLE_FORM_AUTOFILLED_SOME); | |
837 } else if (!did_show_suggestions) { | 840 } else if (!did_show_suggestions) { |
838 AutofillMetrics::LogAutofillFormSubmittedState( | 841 state = AutofillMetrics:: |
839 AutofillMetrics:: | 842 FILLABLE_FORM_AUTOFILLED_NONE_DID_NOT_SHOW_SUGGESTIONS; |
840 FILLABLE_FORM_AUTOFILLED_NONE_DID_NOT_SHOW_SUGGESTIONS); | |
841 } else { | 843 } else { |
842 AutofillMetrics::LogAutofillFormSubmittedState( | 844 state = |
843 AutofillMetrics:: | 845 AutofillMetrics::FILLABLE_FORM_AUTOFILLED_NONE_DID_SHOW_SUGGESTIONS; |
844 FILLABLE_FORM_AUTOFILLED_NONE_DID_SHOW_SUGGESTIONS); | |
845 } | 846 } |
846 | 847 |
847 // Log some RAPPOR metrics for problematic cases. | 848 // Log some RAPPOR metrics for problematic cases. |
848 if (num_server_mismatches >= kNumberOfMismatchesThreshold) { | 849 if (num_server_mismatches >= kNumberOfMismatchesThreshold) { |
849 rappor::SampleDomainAndRegistryFromGURL( | 850 rappor::SampleDomainAndRegistryFromGURL( |
850 rappor_service, "Autofill.HighNumberOfServerMismatches", | 851 rappor_service, "Autofill.HighNumberOfServerMismatches", |
851 source_url_); | 852 source_url_); |
852 } | 853 } |
853 if (num_heuristic_mismatches >= kNumberOfMismatchesThreshold) { | 854 if (num_heuristic_mismatches >= kNumberOfMismatchesThreshold) { |
854 rappor::SampleDomainAndRegistryFromGURL( | 855 rappor::SampleDomainAndRegistryFromGURL( |
(...skipping 26 matching lines...) Expand all Loading... |
881 base::TimeDelta elapsed = submission_time - interaction_time; | 882 base::TimeDelta elapsed = submission_time - interaction_time; |
882 if (did_autofill_some_possible_fields) { | 883 if (did_autofill_some_possible_fields) { |
883 AutofillMetrics::LogFormFillDurationFromInteractionWithAutofill( | 884 AutofillMetrics::LogFormFillDurationFromInteractionWithAutofill( |
884 elapsed); | 885 elapsed); |
885 } else { | 886 } else { |
886 AutofillMetrics::LogFormFillDurationFromInteractionWithoutAutofill( | 887 AutofillMetrics::LogFormFillDurationFromInteractionWithoutAutofill( |
887 elapsed); | 888 elapsed); |
888 } | 889 } |
889 } | 890 } |
890 } | 891 } |
| 892 if (form_interactions_ukm_logger->url() != source_url()) |
| 893 form_interactions_ukm_logger->UpdateSourceURL(source_url()); |
| 894 AutofillMetrics::LogAutofillFormSubmittedState( |
| 895 state, form_interactions_ukm_logger); |
891 } | 896 } |
892 } | 897 } |
893 | 898 |
894 void FormStructure::LogQualityMetricsBasedOnAutocomplete() const { | 899 void FormStructure::LogQualityMetricsBasedOnAutocomplete() const { |
895 for (const auto& field : fields_) { | 900 for (const auto& field : fields_) { |
896 if (field->html_type() != HTML_TYPE_UNSPECIFIED && | 901 if (field->html_type() != HTML_TYPE_UNSPECIFIED && |
897 field->html_type() != HTML_TYPE_UNRECOGNIZED) { | 902 field->html_type() != HTML_TYPE_UNRECOGNIZED) { |
898 // The type inferred by the autocomplete attribute. | 903 // The type inferred by the autocomplete attribute. |
899 AutofillType type(field->html_type(), field->html_mode()); | 904 AutofillType type(field->html_type(), field->html_mode()); |
900 ServerFieldType actual_field_type = type.GetStorableType(); | 905 ServerFieldType actual_field_type = type.GetStorableType(); |
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1371 filtered_strings[0].at(prefix_len)) { | 1376 filtered_strings[0].at(prefix_len)) { |
1372 // Mismatch found. | 1377 // Mismatch found. |
1373 return filtered_strings[i].substr(0, prefix_len); | 1378 return filtered_strings[i].substr(0, prefix_len); |
1374 } | 1379 } |
1375 } | 1380 } |
1376 } | 1381 } |
1377 return filtered_strings[0]; | 1382 return filtered_strings[0]; |
1378 } | 1383 } |
1379 | 1384 |
1380 } // namespace autofill | 1385 } // namespace autofill |
OLD | NEW |