| 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 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 for (const auto& field : fields_) { | 357 for (const auto& field : fields_) { |
| 357 const auto iter = field_type_map.find(field->unique_name()); | 358 const auto iter = field_type_map.find(field->unique_name()); |
| 358 if (iter != field_type_map.end()) | 359 if (iter != field_type_map.end()) |
| 359 field->set_heuristic_type(iter->second.BestHeuristicType()); | 360 field->set_heuristic_type(iter->second.BestHeuristicType()); |
| 360 } | 361 } |
| 361 } | 362 } |
| 362 | 363 |
| 363 UpdateAutofillCount(); | 364 UpdateAutofillCount(); |
| 364 IdentifySections(has_author_specified_sections_); | 365 IdentifySections(has_author_specified_sections_); |
| 365 | 366 |
| 367 std::vector<AutofillMetrics::DeveloperEngagementMetric> metrics; |
| 366 if (IsAutofillable()) { | 368 if (IsAutofillable()) { |
| 367 const auto metric = | 369 AutofillMetrics::DeveloperEngagementMetric metric = |
| 368 has_author_specified_types_ | 370 has_author_specified_types_ |
| 369 ? AutofillMetrics::FILLABLE_FORM_PARSED_WITH_TYPE_HINTS | 371 ? AutofillMetrics::FILLABLE_FORM_PARSED_WITH_TYPE_HINTS |
| 370 : AutofillMetrics::FILLABLE_FORM_PARSED_WITHOUT_TYPE_HINTS; | 372 : AutofillMetrics::FILLABLE_FORM_PARSED_WITHOUT_TYPE_HINTS; |
| 373 metrics.push_back(metric); |
| 371 AutofillMetrics::LogDeveloperEngagementMetric(metric); | 374 AutofillMetrics::LogDeveloperEngagementMetric(metric); |
| 372 AutofillMetrics::LogDeveloperEngagementUkm(ukm_service, source_url(), | |
| 373 metric); | |
| 374 } | 375 } |
| 375 | 376 |
| 376 if (has_author_specified_upi_vpa_hint_) { | 377 if (has_author_specified_upi_vpa_hint_) { |
| 377 AutofillMetrics::LogDeveloperEngagementMetric( | 378 AutofillMetrics::LogDeveloperEngagementMetric( |
| 378 AutofillMetrics::FORM_CONTAINS_UPI_VPA_HINT); | 379 AutofillMetrics::FORM_CONTAINS_UPI_VPA_HINT); |
| 379 AutofillMetrics::LogDeveloperEngagementUkm( | 380 metrics.push_back(AutofillMetrics::FORM_CONTAINS_UPI_VPA_HINT); |
| 380 ukm_service, source_url(), AutofillMetrics::FORM_CONTAINS_UPI_VPA_HINT); | |
| 381 } | 381 } |
| 382 | 382 |
| 383 AutofillMetrics::LogDeveloperEngagementUkm(ukm_service, source_url(), |
| 384 metrics); |
| 385 |
| 383 AutofillMetrics::LogDetermineHeuristicTypesTiming( | 386 AutofillMetrics::LogDetermineHeuristicTypesTiming( |
| 384 base::TimeTicks::Now() - determine_heuristic_types_start_time); | 387 base::TimeTicks::Now() - determine_heuristic_types_start_time); |
| 385 } | 388 } |
| 386 | 389 |
| 387 bool FormStructure::EncodeUploadRequest( | 390 bool FormStructure::EncodeUploadRequest( |
| 388 const ServerFieldTypeSet& available_field_types, | 391 const ServerFieldTypeSet& available_field_types, |
| 389 bool form_was_autofilled, | 392 bool form_was_autofilled, |
| 390 const std::string& login_form_signature, | 393 const std::string& login_form_signature, |
| 391 bool observed_submission, | 394 bool observed_submission, |
| 392 AutofillUploadContents* upload) const { | 395 AutofillUploadContents* upload) const { |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 674 UpdateAutofillCount(); | 677 UpdateAutofillCount(); |
| 675 | 678 |
| 676 // The form signature should match between query and upload requests to the | 679 // The form signature should match between query and upload requests to the |
| 677 // server. On many websites, form elements are dynamically added, removed, or | 680 // server. On many websites, form elements are dynamically added, removed, or |
| 678 // rearranged via JavaScript between page load and form submission, so we | 681 // rearranged via JavaScript between page load and form submission, so we |
| 679 // copy over the |form_signature_field_names_| corresponding to the query | 682 // copy over the |form_signature_field_names_| corresponding to the query |
| 680 // request. | 683 // request. |
| 681 form_signature_ = cached_form.form_signature_; | 684 form_signature_ = cached_form.form_signature_; |
| 682 } | 685 } |
| 683 | 686 |
| 684 void FormStructure::LogQualityMetrics(const base::TimeTicks& load_time, | 687 void FormStructure::LogQualityMetrics( |
| 685 const base::TimeTicks& interaction_time, | 688 const base::TimeTicks& load_time, |
| 686 const base::TimeTicks& submission_time, | 689 const base::TimeTicks& interaction_time, |
| 687 rappor::RapporServiceImpl* rappor_service, | 690 const base::TimeTicks& submission_time, |
| 688 bool did_show_suggestions, | 691 rappor::RapporServiceImpl* rappor_service, |
| 689 bool observed_submission) const { | 692 AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger, |
| 693 bool did_show_suggestions, |
| 694 bool observed_submission) const { |
| 690 size_t num_detected_field_types = 0; | 695 size_t num_detected_field_types = 0; |
| 691 size_t num_server_mismatches = 0; | 696 size_t num_server_mismatches = 0; |
| 692 size_t num_heuristic_mismatches = 0; | 697 size_t num_heuristic_mismatches = 0; |
| 693 size_t num_edited_autofilled_fields = 0; | 698 size_t num_edited_autofilled_fields = 0; |
| 694 bool did_autofill_all_possible_fields = true; | 699 bool did_autofill_all_possible_fields = true; |
| 695 bool did_autofill_some_possible_fields = false; | 700 bool did_autofill_some_possible_fields = false; |
| 696 for (size_t i = 0; i < field_count(); ++i) { | 701 for (size_t i = 0; i < field_count(); ++i) { |
| 697 auto* const field = this->field(i); | 702 auto* const field = this->field(i); |
| 698 | 703 |
| 699 // No further logging for password fields. Those are primarily related to a | 704 // No further logging for password fields. Those are primarily related to a |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 785 field_type, metric_type); | 790 field_type, metric_type); |
| 786 } | 791 } |
| 787 } | 792 } |
| 788 | 793 |
| 789 AutofillMetrics::LogNumberOfEditedAutofilledFields( | 794 AutofillMetrics::LogNumberOfEditedAutofilledFields( |
| 790 num_edited_autofilled_fields, observed_submission); | 795 num_edited_autofilled_fields, observed_submission); |
| 791 | 796 |
| 792 // We log "submission" and duration metrics if we are here after observing a | 797 // We log "submission" and duration metrics if we are here after observing a |
| 793 // submission event. | 798 // submission event. |
| 794 if (observed_submission) { | 799 if (observed_submission) { |
| 800 AutofillMetrics::AutofillFormSubmittedState state; |
| 795 if (num_detected_field_types < kRequiredFieldsForPredictionRoutines) { | 801 if (num_detected_field_types < kRequiredFieldsForPredictionRoutines) { |
| 796 AutofillMetrics::LogAutofillFormSubmittedState( | 802 state = AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA; |
| 797 AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA); | |
| 798 } else { | 803 } else { |
| 799 if (did_autofill_all_possible_fields) { | 804 if (did_autofill_all_possible_fields) { |
| 800 AutofillMetrics::LogAutofillFormSubmittedState( | 805 state = AutofillMetrics::FILLABLE_FORM_AUTOFILLED_ALL; |
| 801 AutofillMetrics::FILLABLE_FORM_AUTOFILLED_ALL); | |
| 802 } else if (did_autofill_some_possible_fields) { | 806 } else if (did_autofill_some_possible_fields) { |
| 803 AutofillMetrics::LogAutofillFormSubmittedState( | 807 state = AutofillMetrics::FILLABLE_FORM_AUTOFILLED_SOME; |
| 804 AutofillMetrics::FILLABLE_FORM_AUTOFILLED_SOME); | |
| 805 } else if (!did_show_suggestions) { | 808 } else if (!did_show_suggestions) { |
| 806 AutofillMetrics::LogAutofillFormSubmittedState( | 809 state = AutofillMetrics:: |
| 807 AutofillMetrics:: | 810 FILLABLE_FORM_AUTOFILLED_NONE_DID_NOT_SHOW_SUGGESTIONS; |
| 808 FILLABLE_FORM_AUTOFILLED_NONE_DID_NOT_SHOW_SUGGESTIONS); | |
| 809 } else { | 811 } else { |
| 810 AutofillMetrics::LogAutofillFormSubmittedState( | 812 state = |
| 811 AutofillMetrics:: | 813 AutofillMetrics::FILLABLE_FORM_AUTOFILLED_NONE_DID_SHOW_SUGGESTIONS; |
| 812 FILLABLE_FORM_AUTOFILLED_NONE_DID_SHOW_SUGGESTIONS); | |
| 813 } | 814 } |
| 814 | 815 |
| 815 // Log some RAPPOR metrics for problematic cases. | 816 // Log some RAPPOR metrics for problematic cases. |
| 816 if (num_server_mismatches >= kNumberOfMismatchesThreshold) { | 817 if (num_server_mismatches >= kNumberOfMismatchesThreshold) { |
| 817 rappor::SampleDomainAndRegistryFromGURL( | 818 rappor::SampleDomainAndRegistryFromGURL( |
| 818 rappor_service, "Autofill.HighNumberOfServerMismatches", | 819 rappor_service, "Autofill.HighNumberOfServerMismatches", |
| 819 source_url_); | 820 source_url_); |
| 820 } | 821 } |
| 821 if (num_heuristic_mismatches >= kNumberOfMismatchesThreshold) { | 822 if (num_heuristic_mismatches >= kNumberOfMismatchesThreshold) { |
| 822 rappor::SampleDomainAndRegistryFromGURL( | 823 rappor::SampleDomainAndRegistryFromGURL( |
| (...skipping 26 matching lines...) Expand all Loading... |
| 849 base::TimeDelta elapsed = submission_time - interaction_time; | 850 base::TimeDelta elapsed = submission_time - interaction_time; |
| 850 if (did_autofill_some_possible_fields) { | 851 if (did_autofill_some_possible_fields) { |
| 851 AutofillMetrics::LogFormFillDurationFromInteractionWithAutofill( | 852 AutofillMetrics::LogFormFillDurationFromInteractionWithAutofill( |
| 852 elapsed); | 853 elapsed); |
| 853 } else { | 854 } else { |
| 854 AutofillMetrics::LogFormFillDurationFromInteractionWithoutAutofill( | 855 AutofillMetrics::LogFormFillDurationFromInteractionWithoutAutofill( |
| 855 elapsed); | 856 elapsed); |
| 856 } | 857 } |
| 857 } | 858 } |
| 858 } | 859 } |
| 860 if (form_interactions_ukm_logger->url() != source_url()) |
| 861 form_interactions_ukm_logger->set_url(source_url()); |
| 862 AutofillMetrics::LogAutofillFormSubmittedState( |
| 863 state, form_interactions_ukm_logger); |
| 859 } | 864 } |
| 860 } | 865 } |
| 861 | 866 |
| 862 void FormStructure::LogQualityMetricsBasedOnAutocomplete() const { | 867 void FormStructure::LogQualityMetricsBasedOnAutocomplete() const { |
| 863 for (const auto& field : fields_) { | 868 for (const auto& field : fields_) { |
| 864 if (field->html_type() != HTML_TYPE_UNSPECIFIED && | 869 if (field->html_type() != HTML_TYPE_UNSPECIFIED && |
| 865 field->html_type() != HTML_TYPE_UNRECOGNIZED) { | 870 field->html_type() != HTML_TYPE_UNRECOGNIZED) { |
| 866 // The type inferred by the autocomplete attribute. | 871 // The type inferred by the autocomplete attribute. |
| 867 AutofillType type(field->html_type(), field->html_mode()); | 872 AutofillType type(field->html_type(), field->html_mode()); |
| 868 ServerFieldType actual_field_type = type.GetStorableType(); | 873 ServerFieldType actual_field_type = type.GetStorableType(); |
| (...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1339 filtered_strings[0].at(prefix_len)) { | 1344 filtered_strings[0].at(prefix_len)) { |
| 1340 // Mismatch found. | 1345 // Mismatch found. |
| 1341 return filtered_strings[i].substr(0, prefix_len); | 1346 return filtered_strings[i].substr(0, prefix_len); |
| 1342 } | 1347 } |
| 1343 } | 1348 } |
| 1344 } | 1349 } |
| 1345 return filtered_strings[0]; | 1350 return filtered_strings[0]; |
| 1346 } | 1351 } |
| 1347 | 1352 |
| 1348 } // namespace autofill | 1353 } // namespace autofill |
| OLD | NEW |