| 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 |