| 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> |
| (...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 | 493 |
| 494 // In some cases *successful* response does not return all the fields. | 494 // In some cases *successful* response does not return all the fields. |
| 495 // Quit the update of the types then. | 495 // Quit the update of the types then. |
| 496 if (current_field == response.field().end()) | 496 if (current_field == response.field().end()) |
| 497 break; | 497 break; |
| 498 | 498 |
| 499 ServerFieldType field_type = | 499 ServerFieldType field_type = |
| 500 static_cast<ServerFieldType>(current_field->autofill_type()); | 500 static_cast<ServerFieldType>(current_field->autofill_type()); |
| 501 query_response_has_no_server_data &= field_type == NO_SERVER_DATA; | 501 query_response_has_no_server_data &= field_type == NO_SERVER_DATA; |
| 502 | 502 |
| 503 // If |form->has_author_specified_types| only password fields should be | 503 // UNKNOWN_TYPE is reserved for use by the client. |
| 504 // updated. | 504 DCHECK_NE(field_type, UNKNOWN_TYPE); |
| 505 if (!form->has_author_specified_types_ || | |
| 506 field->form_control_type == "password") { | |
| 507 // UNKNOWN_TYPE is reserved for use by the client. | |
| 508 DCHECK_NE(field_type, UNKNOWN_TYPE); | |
| 509 | 505 |
| 510 ServerFieldType heuristic_type = field->heuristic_type(); | 506 ServerFieldType heuristic_type = field->heuristic_type(); |
| 511 if (heuristic_type != UNKNOWN_TYPE) | 507 if (heuristic_type != UNKNOWN_TYPE) |
| 512 heuristics_detected_fillable_field = true; | 508 heuristics_detected_fillable_field = true; |
| 513 | 509 |
| 514 field->set_server_type(field_type); | 510 field->set_server_type(field_type); |
| 515 if (heuristic_type != field->Type().GetStorableType()) | 511 if (heuristic_type != field->Type().GetStorableType()) |
| 516 query_response_overrode_heuristics = true; | 512 query_response_overrode_heuristics = true; |
| 517 } | |
| 518 | 513 |
| 519 ++current_field; | 514 ++current_field; |
| 520 } | 515 } |
| 521 | 516 |
| 522 AutofillMetrics::LogServerResponseHasDataForForm( | 517 AutofillMetrics::LogServerResponseHasDataForForm( |
| 523 !query_response_has_no_server_data); | 518 !query_response_has_no_server_data); |
| 524 if (query_response_has_no_server_data && form->source_url().is_valid()) { | 519 if (query_response_has_no_server_data && form->source_url().is_valid()) { |
| 525 rappor::SampleDomainAndRegistryFromGURL( | 520 rappor::SampleDomainAndRegistryFromGURL( |
| 526 rappor_service, "Autofill.QueryResponseHasNoServerDataForForm", | 521 rappor_service, "Autofill.QueryResponseHasNoServerDataForForm", |
| 527 form->source_url()); | 522 form->source_url()); |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 727 field_type = *collapsed_field_types.begin(); | 722 field_type = *collapsed_field_types.begin(); |
| 728 | 723 |
| 729 ServerFieldType heuristic_type = | 724 ServerFieldType heuristic_type = |
| 730 AutofillType(field->heuristic_type()).GetStorableType(); | 725 AutofillType(field->heuristic_type()).GetStorableType(); |
| 731 ServerFieldType server_type = | 726 ServerFieldType server_type = |
| 732 AutofillType(field->server_type()).GetStorableType(); | 727 AutofillType(field->server_type()).GetStorableType(); |
| 733 ServerFieldType predicted_type = field->Type().GetStorableType(); | 728 ServerFieldType predicted_type = field->Type().GetStorableType(); |
| 734 | 729 |
| 735 // Log heuristic, server, and overall type quality metrics, independently of | 730 // Log heuristic, server, and overall type quality metrics, independently of |
| 736 // whether the field was autofilled. | 731 // whether the field was autofilled. |
| 732 const AutofillMetrics::QualityMetricType metric_type = |
| 733 observed_submission ? AutofillMetrics::TYPE_SUBMISSION |
| 734 : AutofillMetrics::TYPE_NO_SUBMISSION; |
| 737 if (heuristic_type == UNKNOWN_TYPE) { | 735 if (heuristic_type == UNKNOWN_TYPE) { |
| 738 AutofillMetrics::LogHeuristicTypePrediction( | 736 AutofillMetrics::LogHeuristicTypePrediction(AutofillMetrics::TYPE_UNKNOWN, |
| 739 AutofillMetrics::TYPE_UNKNOWN, field_type, observed_submission); | 737 field_type, metric_type); |
| 740 } else if (field_types.count(heuristic_type)) { | 738 } else if (field_types.count(heuristic_type)) { |
| 741 AutofillMetrics::LogHeuristicTypePrediction( | 739 AutofillMetrics::LogHeuristicTypePrediction(AutofillMetrics::TYPE_MATCH, |
| 742 AutofillMetrics::TYPE_MATCH, field_type, observed_submission); | 740 field_type, metric_type); |
| 743 } else { | 741 } else { |
| 744 ++num_heuristic_mismatches; | 742 ++num_heuristic_mismatches; |
| 745 AutofillMetrics::LogHeuristicTypePrediction( | 743 AutofillMetrics::LogHeuristicTypePrediction( |
| 746 AutofillMetrics::TYPE_MISMATCH, field_type, observed_submission); | 744 AutofillMetrics::TYPE_MISMATCH, field_type, metric_type); |
| 747 } | 745 } |
| 748 | 746 |
| 749 if (server_type == NO_SERVER_DATA) { | 747 if (server_type == NO_SERVER_DATA) { |
| 750 AutofillMetrics::LogServerTypePrediction(AutofillMetrics::TYPE_UNKNOWN, | 748 AutofillMetrics::LogServerTypePrediction(AutofillMetrics::TYPE_UNKNOWN, |
| 751 field_type, observed_submission); | 749 field_type, metric_type); |
| 752 } else if (field_types.count(server_type)) { | 750 } else if (field_types.count(server_type)) { |
| 753 AutofillMetrics::LogServerTypePrediction(AutofillMetrics::TYPE_MATCH, | 751 AutofillMetrics::LogServerTypePrediction(AutofillMetrics::TYPE_MATCH, |
| 754 field_type, observed_submission); | 752 field_type, metric_type); |
| 755 } else { | 753 } else { |
| 756 ++num_server_mismatches; | 754 ++num_server_mismatches; |
| 757 AutofillMetrics::LogServerTypePrediction(AutofillMetrics::TYPE_MISMATCH, | 755 AutofillMetrics::LogServerTypePrediction(AutofillMetrics::TYPE_MISMATCH, |
| 758 field_type, observed_submission); | 756 field_type, metric_type); |
| 759 } | 757 } |
| 760 | 758 |
| 761 if (predicted_type == UNKNOWN_TYPE) { | 759 if (predicted_type == UNKNOWN_TYPE) { |
| 762 AutofillMetrics::LogOverallTypePrediction( | 760 AutofillMetrics::LogOverallTypePrediction(AutofillMetrics::TYPE_UNKNOWN, |
| 763 AutofillMetrics::TYPE_UNKNOWN, field_type, observed_submission); | 761 field_type, metric_type); |
| 764 } else if (field_types.count(predicted_type)) { | 762 } else if (field_types.count(predicted_type)) { |
| 765 AutofillMetrics::LogOverallTypePrediction( | 763 AutofillMetrics::LogOverallTypePrediction(AutofillMetrics::TYPE_MATCH, |
| 766 AutofillMetrics::TYPE_MATCH, field_type, observed_submission); | 764 field_type, metric_type); |
| 767 } else { | 765 } else { |
| 768 AutofillMetrics::LogOverallTypePrediction( | 766 AutofillMetrics::LogOverallTypePrediction(AutofillMetrics::TYPE_MISMATCH, |
| 769 AutofillMetrics::TYPE_MISMATCH, field_type, observed_submission); | 767 field_type, metric_type); |
| 770 } | 768 } |
| 771 } | 769 } |
| 772 | 770 |
| 773 AutofillMetrics::LogNumberOfEditedAutofilledFields( | 771 AutofillMetrics::LogNumberOfEditedAutofilledFields( |
| 774 num_edited_autofilled_fields, observed_submission); | 772 num_edited_autofilled_fields, observed_submission); |
| 775 | 773 |
| 776 // We log "submission" and duration metrics if we are here after observing a | 774 // We log "submission" and duration metrics if we are here after observing a |
| 777 // submission event. | 775 // submission event. |
| 778 if (observed_submission) { | 776 if (observed_submission) { |
| 779 if (num_detected_field_types < kRequiredFieldsForPredictionRoutines) { | 777 if (num_detected_field_types < kRequiredFieldsForPredictionRoutines) { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 836 elapsed); | 834 elapsed); |
| 837 } else { | 835 } else { |
| 838 AutofillMetrics::LogFormFillDurationFromInteractionWithoutAutofill( | 836 AutofillMetrics::LogFormFillDurationFromInteractionWithoutAutofill( |
| 839 elapsed); | 837 elapsed); |
| 840 } | 838 } |
| 841 } | 839 } |
| 842 } | 840 } |
| 843 } | 841 } |
| 844 } | 842 } |
| 845 | 843 |
| 844 void FormStructure::LogQualityMetricsBasedOnAutocomplete() const { |
| 845 for (const AutofillField* field : fields_) { |
| 846 if (field->html_type() != HTML_TYPE_UNSPECIFIED && |
| 847 field->html_type() != HTML_TYPE_UNRECOGNIZED) { |
| 848 // The type inferred by the autocomplete attribute. |
| 849 AutofillType type(field->html_type(), field->html_mode()); |
| 850 ServerFieldType actual_field_type = type.GetStorableType(); |
| 851 |
| 852 const AutofillMetrics::QualityMetricType metric_type = |
| 853 AutofillMetrics::TYPE_AUTOCOMPLETE_BASED; |
| 854 // Log the quality of our heuristics predictions. |
| 855 if (field->heuristic_type() == UNKNOWN_TYPE) { |
| 856 AutofillMetrics::LogHeuristicTypePrediction( |
| 857 AutofillMetrics::TYPE_UNKNOWN, actual_field_type, metric_type); |
| 858 } else if (field->heuristic_type() == actual_field_type) { |
| 859 AutofillMetrics::LogHeuristicTypePrediction( |
| 860 AutofillMetrics::TYPE_MATCH, actual_field_type, metric_type); |
| 861 } else { |
| 862 AutofillMetrics::LogHeuristicTypePrediction( |
| 863 AutofillMetrics::TYPE_MISMATCH, actual_field_type, metric_type); |
| 864 } |
| 865 |
| 866 // Log the quality of our server predictions. |
| 867 if (field->server_type() == NO_SERVER_DATA) { |
| 868 AutofillMetrics::LogServerTypePrediction( |
| 869 AutofillMetrics::TYPE_UNKNOWN, actual_field_type, metric_type); |
| 870 } else if (field->server_type() == actual_field_type) { |
| 871 AutofillMetrics::LogServerTypePrediction( |
| 872 AutofillMetrics::TYPE_MATCH, actual_field_type, metric_type); |
| 873 } else { |
| 874 AutofillMetrics::LogServerTypePrediction( |
| 875 AutofillMetrics::TYPE_MISMATCH, actual_field_type, metric_type); |
| 876 } |
| 877 } |
| 878 } |
| 879 } |
| 880 |
| 846 void FormStructure::ParseFieldTypesFromAutocompleteAttributes() { | 881 void FormStructure::ParseFieldTypesFromAutocompleteAttributes() { |
| 847 const std::string kDefaultSection = "-default"; | 882 const std::string kDefaultSection = "-default"; |
| 848 | 883 |
| 849 has_author_specified_types_ = false; | 884 has_author_specified_types_ = false; |
| 850 has_author_specified_sections_ = false; | 885 has_author_specified_sections_ = false; |
| 851 for (AutofillField* field : fields_) { | 886 for (AutofillField* field : fields_) { |
| 852 // To prevent potential section name collisions, add a default suffix for | 887 // To prevent potential section name collisions, add a default suffix for |
| 853 // other fields. Without this, 'autocomplete' attribute values | 888 // other fields. Without this, 'autocomplete' attribute values |
| 854 // "section--shipping street-address" and "shipping street-address" would be | 889 // "section--shipping street-address" and "shipping street-address" would be |
| 855 // parsed identically, given the section handling code below. We do this | 890 // parsed identically, given the section handling code below. We do this |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1330 filtered_strings[0].at(prefix_len)) { | 1365 filtered_strings[0].at(prefix_len)) { |
| 1331 // Mismatch found. | 1366 // Mismatch found. |
| 1332 return filtered_strings[i].substr(0, prefix_len); | 1367 return filtered_strings[i].substr(0, prefix_len); |
| 1333 } | 1368 } |
| 1334 } | 1369 } |
| 1335 } | 1370 } |
| 1336 return filtered_strings[0]; | 1371 return filtered_strings[0]; |
| 1337 } | 1372 } |
| 1338 | 1373 |
| 1339 } // namespace autofill | 1374 } // namespace autofill |
| OLD | NEW |