| 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 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 has_password_field_ = true; | 314 has_password_field_ = true; |
| 315 else | 315 else |
| 316 all_fields_are_passwords_ = false; | 316 all_fields_are_passwords_ = false; |
| 317 | 317 |
| 318 // Generate a unique name for this field by appending a counter to the name. | 318 // Generate a unique name for this field by appending a counter to the name. |
| 319 // Make sure to prepend the counter with a non-numeric digit so that we are | 319 // Make sure to prepend the counter with a non-numeric digit so that we are |
| 320 // guaranteed to avoid collisions. | 320 // guaranteed to avoid collisions. |
| 321 base::string16 unique_name = | 321 base::string16 unique_name = |
| 322 field.name + base::ASCIIToUTF16("_") + | 322 field.name + base::ASCIIToUTF16("_") + |
| 323 base::SizeTToString16(++unique_names[field.name]); | 323 base::SizeTToString16(++unique_names[field.name]); |
| 324 fields_.push_back(new AutofillField(field, unique_name)); | 324 fields_.push_back(base::MakeUnique<AutofillField>(field, unique_name)); |
| 325 } | 325 } |
| 326 | 326 |
| 327 form_signature_ = autofill::CalculateFormSignature(form); | 327 form_signature_ = autofill::CalculateFormSignature(form); |
| 328 // Do further processing on the fields, as needed. | 328 // Do further processing on the fields, as needed. |
| 329 ProcessExtractedFields(); | 329 ProcessExtractedFields(); |
| 330 } | 330 } |
| 331 | 331 |
| 332 FormStructure::~FormStructure() {} | 332 FormStructure::~FormStructure() {} |
| 333 | 333 |
| 334 void FormStructure::DetermineHeuristicTypes() { | 334 void FormStructure::DetermineHeuristicTypes() { |
| 335 const auto determine_heuristic_types_start_time = base::TimeTicks::Now(); | 335 const auto determine_heuristic_types_start_time = base::TimeTicks::Now(); |
| 336 | 336 |
| 337 // First, try to detect field types based on each field's |autocomplete| | 337 // First, try to detect field types based on each field's |autocomplete| |
| 338 // attribute value. | 338 // attribute value. |
| 339 if (!was_parsed_for_autocomplete_attributes_) | 339 if (!was_parsed_for_autocomplete_attributes_) |
| 340 ParseFieldTypesFromAutocompleteAttributes(); | 340 ParseFieldTypesFromAutocompleteAttributes(); |
| 341 | 341 |
| 342 // Then if there are enough active fields, and if we are dealing with either a | 342 // Then if there are enough active fields, and if we are dealing with either a |
| 343 // proper <form> or a <form>-less checkout, run the heuristics and server | 343 // proper <form> or a <form>-less checkout, run the heuristics and server |
| 344 // prediction routines. | 344 // prediction routines. |
| 345 if (active_field_count() >= kRequiredFieldsForPredictionRoutines && | 345 if (active_field_count() >= kRequiredFieldsForPredictionRoutines && |
| 346 (is_form_tag_ || is_formless_checkout_)) { | 346 (is_form_tag_ || is_formless_checkout_)) { |
| 347 const FieldCandidatesMap field_type_map = | 347 const FieldCandidatesMap field_type_map = |
| 348 FormField::ParseFormFields(fields_.get(), is_form_tag_); | 348 FormField::ParseFormFields(fields_, is_form_tag_); |
| 349 for (AutofillField* field : fields_) { | 349 for (const auto& field : fields_) { |
| 350 const auto iter = field_type_map.find(field->unique_name()); | 350 const auto iter = field_type_map.find(field->unique_name()); |
| 351 if (iter != field_type_map.end()) | 351 if (iter != field_type_map.end()) |
| 352 field->set_heuristic_type(iter->second.BestHeuristicType()); | 352 field->set_heuristic_type(iter->second.BestHeuristicType()); |
| 353 } | 353 } |
| 354 } | 354 } |
| 355 | 355 |
| 356 UpdateAutofillCount(); | 356 UpdateAutofillCount(); |
| 357 IdentifySections(has_author_specified_sections_); | 357 IdentifySections(has_author_specified_sections_); |
| 358 | 358 |
| 359 if (IsAutofillable()) { | 359 if (IsAutofillable()) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 372 bool FormStructure::EncodeUploadRequest( | 372 bool FormStructure::EncodeUploadRequest( |
| 373 const ServerFieldTypeSet& available_field_types, | 373 const ServerFieldTypeSet& available_field_types, |
| 374 bool form_was_autofilled, | 374 bool form_was_autofilled, |
| 375 const std::string& login_form_signature, | 375 const std::string& login_form_signature, |
| 376 bool observed_submission, | 376 bool observed_submission, |
| 377 AutofillUploadContents* upload) const { | 377 AutofillUploadContents* upload) const { |
| 378 DCHECK(ShouldBeCrowdsourced()); | 378 DCHECK(ShouldBeCrowdsourced()); |
| 379 | 379 |
| 380 // Verify that |available_field_types| agrees with the possible field types we | 380 // Verify that |available_field_types| agrees with the possible field types we |
| 381 // are uploading. | 381 // are uploading. |
| 382 for (const AutofillField* field : *this) { | 382 for (const auto& field : fields_) { |
| 383 for (const auto& type : field->possible_types()) { | 383 for (const auto& type : field->possible_types()) { |
| 384 DCHECK(type == UNKNOWN_TYPE || type == EMPTY_TYPE || | 384 DCHECK(type == UNKNOWN_TYPE || type == EMPTY_TYPE || |
| 385 available_field_types.count(type)); | 385 available_field_types.count(type)); |
| 386 } | 386 } |
| 387 } | 387 } |
| 388 | 388 |
| 389 upload->set_submission(observed_submission); | 389 upload->set_submission(observed_submission); |
| 390 upload->set_client_version(kClientVersion); | 390 upload->set_client_version(kClientVersion); |
| 391 upload->set_form_signature(form_signature()); | 391 upload->set_form_signature(form_signature()); |
| 392 upload->set_autofill_used(form_was_autofilled); | 392 upload->set_autofill_used(form_was_autofilled); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 461 bool heuristics_detected_fillable_field = false; | 461 bool heuristics_detected_fillable_field = false; |
| 462 bool query_response_overrode_heuristics = false; | 462 bool query_response_overrode_heuristics = false; |
| 463 | 463 |
| 464 // Copy the field types into the actual form. | 464 // Copy the field types into the actual form. |
| 465 auto current_field = response.field().begin(); | 465 auto current_field = response.field().begin(); |
| 466 for (FormStructure* form : forms) { | 466 for (FormStructure* form : forms) { |
| 467 form->upload_required_ = | 467 form->upload_required_ = |
| 468 response.upload_required() ? UPLOAD_REQUIRED : UPLOAD_NOT_REQUIRED; | 468 response.upload_required() ? UPLOAD_REQUIRED : UPLOAD_NOT_REQUIRED; |
| 469 | 469 |
| 470 bool query_response_has_no_server_data = true; | 470 bool query_response_has_no_server_data = true; |
| 471 for (AutofillField* field : form->fields_) { | 471 for (const auto& field : *form) { |
| 472 if (form->ShouldSkipField(*field)) | 472 if (form->ShouldSkipField(*field)) |
| 473 continue; | 473 continue; |
| 474 | 474 |
| 475 // In some cases *successful* response does not return all the fields. | 475 // In some cases *successful* response does not return all the fields. |
| 476 // Quit the update of the types then. | 476 // Quit the update of the types then. |
| 477 if (current_field == response.field().end()) | 477 if (current_field == response.field().end()) |
| 478 break; | 478 break; |
| 479 | 479 |
| 480 ServerFieldType field_type = | 480 ServerFieldType field_type = |
| 481 static_cast<ServerFieldType>(current_field->autofill_type()); | 481 static_cast<ServerFieldType>(current_field->autofill_type()); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 526 std::vector<FormDataPredictions> forms; | 526 std::vector<FormDataPredictions> forms; |
| 527 forms.reserve(form_structures.size()); | 527 forms.reserve(form_structures.size()); |
| 528 for (const FormStructure* form_structure : form_structures) { | 528 for (const FormStructure* form_structure : form_structures) { |
| 529 FormDataPredictions form; | 529 FormDataPredictions form; |
| 530 form.data.name = form_structure->form_name_; | 530 form.data.name = form_structure->form_name_; |
| 531 form.data.origin = form_structure->source_url_; | 531 form.data.origin = form_structure->source_url_; |
| 532 form.data.action = form_structure->target_url_; | 532 form.data.action = form_structure->target_url_; |
| 533 form.data.is_form_tag = form_structure->is_form_tag_; | 533 form.data.is_form_tag = form_structure->is_form_tag_; |
| 534 form.signature = form_structure->FormSignatureAsStr(); | 534 form.signature = form_structure->FormSignatureAsStr(); |
| 535 | 535 |
| 536 for (const AutofillField* field : form_structure->fields_) { | 536 for (const auto& field : *form_structure) { |
| 537 form.data.fields.push_back(FormFieldData(*field)); | 537 form.data.fields.push_back(FormFieldData(*field)); |
| 538 | 538 |
| 539 FormFieldDataPredictions annotated_field; | 539 FormFieldDataPredictions annotated_field; |
| 540 annotated_field.signature = field->FieldSignatureAsStr(); | 540 annotated_field.signature = field->FieldSignatureAsStr(); |
| 541 annotated_field.heuristic_type = | 541 annotated_field.heuristic_type = |
| 542 AutofillType(field->heuristic_type()).ToString(); | 542 AutofillType(field->heuristic_type()).ToString(); |
| 543 annotated_field.server_type = | 543 annotated_field.server_type = |
| 544 AutofillType(field->server_type()).ToString(); | 544 AutofillType(field->server_type()).ToString(); |
| 545 annotated_field.overall_type = field->Type().ToString(); | 545 annotated_field.overall_type = field->Type().ToString(); |
| 546 annotated_field.parseable_name = | 546 annotated_field.parseable_name = |
| (...skipping 20 matching lines...) Expand all Loading... |
| 567 bool FormStructure::IsAutofillable() const { | 567 bool FormStructure::IsAutofillable() const { |
| 568 if (autofill_count() < kRequiredFieldsForPredictionRoutines) | 568 if (autofill_count() < kRequiredFieldsForPredictionRoutines) |
| 569 return false; | 569 return false; |
| 570 | 570 |
| 571 return ShouldBeParsed(); | 571 return ShouldBeParsed(); |
| 572 } | 572 } |
| 573 | 573 |
| 574 bool FormStructure::IsCompleteCreditCardForm() const { | 574 bool FormStructure::IsCompleteCreditCardForm() const { |
| 575 bool found_cc_number = false; | 575 bool found_cc_number = false; |
| 576 bool found_cc_expiration = false; | 576 bool found_cc_expiration = false; |
| 577 for (const AutofillField* field : fields_) { | 577 for (const auto& field : fields_) { |
| 578 ServerFieldType type = field->Type().GetStorableType(); | 578 ServerFieldType type = field->Type().GetStorableType(); |
| 579 if (!found_cc_expiration && IsCreditCardExpirationType(type)) { | 579 if (!found_cc_expiration && IsCreditCardExpirationType(type)) { |
| 580 found_cc_expiration = true; | 580 found_cc_expiration = true; |
| 581 } else if (!found_cc_number && type == CREDIT_CARD_NUMBER) { | 581 } else if (!found_cc_number && type == CREDIT_CARD_NUMBER) { |
| 582 found_cc_number = true; | 582 found_cc_number = true; |
| 583 } | 583 } |
| 584 if (found_cc_expiration && found_cc_number) | 584 if (found_cc_expiration && found_cc_number) |
| 585 return true; | 585 return true; |
| 586 } | 586 } |
| 587 return false; | 587 return false; |
| 588 } | 588 } |
| 589 | 589 |
| 590 void FormStructure::UpdateAutofillCount() { | 590 void FormStructure::UpdateAutofillCount() { |
| 591 autofill_count_ = 0; | 591 autofill_count_ = 0; |
| 592 for (const AutofillField* field : *this) { | 592 for (const auto& field : fields_) { |
| 593 if (field && field->IsFieldFillable()) | 593 if (field && field->IsFieldFillable()) |
| 594 ++autofill_count_; | 594 ++autofill_count_; |
| 595 } | 595 } |
| 596 } | 596 } |
| 597 | 597 |
| 598 bool FormStructure::ShouldBeParsed() const { | 598 bool FormStructure::ShouldBeParsed() const { |
| 599 if (active_field_count() < kRequiredFieldsForPredictionRoutines && | 599 if (active_field_count() < kRequiredFieldsForPredictionRoutines && |
| 600 (!all_fields_are_passwords() || | 600 (!all_fields_are_passwords() || |
| 601 active_field_count() < kRequiredFieldsForFormsWithOnlyPasswordFields) && | 601 active_field_count() < kRequiredFieldsForFormsWithOnlyPasswordFields) && |
| 602 !has_author_specified_types_) { | 602 !has_author_specified_types_) { |
| 603 return false; | 603 return false; |
| 604 } | 604 } |
| 605 | 605 |
| 606 // Rule out http(s)://*/search?... | 606 // Rule out http(s)://*/search?... |
| 607 // e.g. http://www.google.com/search?q=... | 607 // e.g. http://www.google.com/search?q=... |
| 608 // http://search.yahoo.com/search?p=... | 608 // http://search.yahoo.com/search?p=... |
| 609 if (target_url_.path_piece() == "/search") | 609 if (target_url_.path_piece() == "/search") |
| 610 return false; | 610 return false; |
| 611 | 611 |
| 612 bool has_text_field = false; | 612 bool has_text_field = false; |
| 613 for (const AutofillField* it : *this) { | 613 for (const auto& it : fields_) { |
| 614 has_text_field |= it->form_control_type != "select-one"; | 614 has_text_field |= it->form_control_type != "select-one"; |
| 615 } | 615 } |
| 616 | 616 |
| 617 return has_text_field; | 617 return has_text_field; |
| 618 } | 618 } |
| 619 | 619 |
| 620 bool FormStructure::ShouldBeCrowdsourced() const { | 620 bool FormStructure::ShouldBeCrowdsourced() const { |
| 621 return (has_password_field_ || | 621 return (has_password_field_ || |
| 622 active_field_count() >= kRequiredFieldsForPredictionRoutines) && | 622 active_field_count() >= kRequiredFieldsForPredictionRoutines) && |
| 623 ShouldBeParsed(); | 623 ShouldBeParsed(); |
| 624 } | 624 } |
| 625 | 625 |
| 626 void FormStructure::UpdateFromCache(const FormStructure& cached_form) { | 626 void FormStructure::UpdateFromCache(const FormStructure& cached_form) { |
| 627 // Map from field signatures to cached fields. | 627 // Map from field signatures to cached fields. |
| 628 std::map<std::string, const AutofillField*> cached_fields; | 628 std::map<std::string, const AutofillField*> cached_fields; |
| 629 for (size_t i = 0; i < cached_form.field_count(); ++i) { | 629 for (size_t i = 0; i < cached_form.field_count(); ++i) { |
| 630 const AutofillField* field = cached_form.field(i); | 630 const AutofillField* field = cached_form.field(i); |
| 631 cached_fields[field->FieldSignatureAsStr()] = field; | 631 cached_fields[field->FieldSignatureAsStr()] = field; |
| 632 } | 632 } |
| 633 | 633 |
| 634 for (AutofillField* field : *this) { | 634 for (const auto& field : fields_) { |
| 635 std::map<std::string, const AutofillField*>::const_iterator cached_field = | 635 std::map<std::string, const AutofillField*>::const_iterator cached_field = |
| 636 cached_fields.find(field->FieldSignatureAsStr()); | 636 cached_fields.find(field->FieldSignatureAsStr()); |
| 637 if (cached_field != cached_fields.end()) { | 637 if (cached_field != cached_fields.end()) { |
| 638 if (field->form_control_type != "select-one" && | 638 if (field->form_control_type != "select-one" && |
| 639 field->value == cached_field->second->value) { | 639 field->value == cached_field->second->value) { |
| 640 // From the perspective of learning user data, text fields containing | 640 // From the perspective of learning user data, text fields containing |
| 641 // default values are equivalent to empty fields. | 641 // default values are equivalent to empty fields. |
| 642 field->value = base::string16(); | 642 field->value = base::string16(); |
| 643 } | 643 } |
| 644 | 644 |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 839 } else { | 839 } else { |
| 840 AutofillMetrics::LogFormFillDurationFromInteractionWithoutAutofill( | 840 AutofillMetrics::LogFormFillDurationFromInteractionWithoutAutofill( |
| 841 elapsed); | 841 elapsed); |
| 842 } | 842 } |
| 843 } | 843 } |
| 844 } | 844 } |
| 845 } | 845 } |
| 846 } | 846 } |
| 847 | 847 |
| 848 void FormStructure::LogQualityMetricsBasedOnAutocomplete() const { | 848 void FormStructure::LogQualityMetricsBasedOnAutocomplete() const { |
| 849 for (const AutofillField* field : fields_) { | 849 for (const auto& field : fields_) { |
| 850 if (field->html_type() != HTML_TYPE_UNSPECIFIED && | 850 if (field->html_type() != HTML_TYPE_UNSPECIFIED && |
| 851 field->html_type() != HTML_TYPE_UNRECOGNIZED) { | 851 field->html_type() != HTML_TYPE_UNRECOGNIZED) { |
| 852 // The type inferred by the autocomplete attribute. | 852 // The type inferred by the autocomplete attribute. |
| 853 AutofillType type(field->html_type(), field->html_mode()); | 853 AutofillType type(field->html_type(), field->html_mode()); |
| 854 ServerFieldType actual_field_type = type.GetStorableType(); | 854 ServerFieldType actual_field_type = type.GetStorableType(); |
| 855 | 855 |
| 856 const AutofillMetrics::QualityMetricType metric_type = | 856 const AutofillMetrics::QualityMetricType metric_type = |
| 857 AutofillMetrics::TYPE_AUTOCOMPLETE_BASED; | 857 AutofillMetrics::TYPE_AUTOCOMPLETE_BASED; |
| 858 // Log the quality of our heuristics predictions. | 858 // Log the quality of our heuristics predictions. |
| 859 if (field->heuristic_type() == UNKNOWN_TYPE) { | 859 if (field->heuristic_type() == UNKNOWN_TYPE) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 880 } | 880 } |
| 881 } | 881 } |
| 882 } | 882 } |
| 883 } | 883 } |
| 884 | 884 |
| 885 void FormStructure::ParseFieldTypesFromAutocompleteAttributes() { | 885 void FormStructure::ParseFieldTypesFromAutocompleteAttributes() { |
| 886 const std::string kDefaultSection = "-default"; | 886 const std::string kDefaultSection = "-default"; |
| 887 | 887 |
| 888 has_author_specified_types_ = false; | 888 has_author_specified_types_ = false; |
| 889 has_author_specified_sections_ = false; | 889 has_author_specified_sections_ = false; |
| 890 for (AutofillField* field : fields_) { | 890 for (const auto& field : fields_) { |
| 891 // To prevent potential section name collisions, add a default suffix for | 891 // To prevent potential section name collisions, add a default suffix for |
| 892 // other fields. Without this, 'autocomplete' attribute values | 892 // other fields. Without this, 'autocomplete' attribute values |
| 893 // "section--shipping street-address" and "shipping street-address" would be | 893 // "section--shipping street-address" and "shipping street-address" would be |
| 894 // parsed identically, given the section handling code below. We do this | 894 // parsed identically, given the section handling code below. We do this |
| 895 // before any validation so that fields with invalid attributes still end up | 895 // before any validation so that fields with invalid attributes still end up |
| 896 // in the default section. These default section names will be overridden | 896 // in the default section. These default section names will be overridden |
| 897 // by subsequent heuristic parsing steps if there are no author-specified | 897 // by subsequent heuristic parsing steps if there are no author-specified |
| 898 // section names. | 898 // section names. |
| 899 field->set_section(kDefaultSection); | 899 field->set_section(kDefaultSection); |
| 900 | 900 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1000 break; | 1000 break; |
| 1001 } | 1001 } |
| 1002 } | 1002 } |
| 1003 } | 1003 } |
| 1004 return filled_something; | 1004 return filled_something; |
| 1005 } | 1005 } |
| 1006 | 1006 |
| 1007 std::set<base::string16> FormStructure::PossibleValues(ServerFieldType type) { | 1007 std::set<base::string16> FormStructure::PossibleValues(ServerFieldType type) { |
| 1008 std::set<base::string16> values; | 1008 std::set<base::string16> values; |
| 1009 AutofillType target_type(type); | 1009 AutofillType target_type(type); |
| 1010 for (const AutofillField* field : fields_) { | 1010 for (const auto& field : fields_) { |
| 1011 if (field->Type().GetStorableType() != target_type.GetStorableType() || | 1011 if (field->Type().GetStorableType() != target_type.GetStorableType() || |
| 1012 field->Type().group() != target_type.group()) { | 1012 field->Type().group() != target_type.group()) { |
| 1013 continue; | 1013 continue; |
| 1014 } | 1014 } |
| 1015 | 1015 |
| 1016 // No option values; anything goes. | 1016 // No option values; anything goes. |
| 1017 if (field->option_values.empty()) { | 1017 if (field->option_values.empty()) { |
| 1018 values.clear(); | 1018 values.clear(); |
| 1019 break; | 1019 break; |
| 1020 } | 1020 } |
| 1021 | 1021 |
| 1022 for (const base::string16& val : field->option_values) { | 1022 for (const base::string16& val : field->option_values) { |
| 1023 if (!val.empty()) | 1023 if (!val.empty()) |
| 1024 values.insert(base::i18n::ToUpper(val)); | 1024 values.insert(base::i18n::ToUpper(val)); |
| 1025 } | 1025 } |
| 1026 | 1026 |
| 1027 for (const base::string16& content : field->option_contents) { | 1027 for (const base::string16& content : field->option_contents) { |
| 1028 if (!content.empty()) | 1028 if (!content.empty()) |
| 1029 values.insert(base::i18n::ToUpper(content)); | 1029 values.insert(base::i18n::ToUpper(content)); |
| 1030 } | 1030 } |
| 1031 } | 1031 } |
| 1032 | 1032 |
| 1033 return values; | 1033 return values; |
| 1034 } | 1034 } |
| 1035 | 1035 |
| 1036 base::string16 FormStructure::GetUniqueValue(HtmlFieldType type) const { | 1036 base::string16 FormStructure::GetUniqueValue(HtmlFieldType type) const { |
| 1037 base::string16 value; | 1037 base::string16 value; |
| 1038 for (const AutofillField* field : fields_) { | 1038 for (const auto& field : fields_) { |
| 1039 if (field->html_type() != type) | 1039 if (field->html_type() != type) |
| 1040 continue; | 1040 continue; |
| 1041 | 1041 |
| 1042 // More than one value found; abort rather than choosing one arbitrarily. | 1042 // More than one value found; abort rather than choosing one arbitrarily. |
| 1043 if (!value.empty() && !field->value.empty()) { | 1043 if (!value.empty() && !field->value.empty()) { |
| 1044 value.clear(); | 1044 value.clear(); |
| 1045 break; | 1045 break; |
| 1046 } | 1046 } |
| 1047 | 1047 |
| 1048 value = field->value; | 1048 value = field->value; |
| 1049 } | 1049 } |
| 1050 | 1050 |
| 1051 return value; | 1051 return value; |
| 1052 } | 1052 } |
| 1053 | 1053 |
| 1054 const AutofillField* FormStructure::field(size_t index) const { | 1054 const AutofillField* FormStructure::field(size_t index) const { |
| 1055 if (index >= fields_.size()) { | 1055 if (index >= fields_.size()) { |
| 1056 NOTREACHED(); | 1056 NOTREACHED(); |
| 1057 return NULL; | 1057 return NULL; |
| 1058 } | 1058 } |
| 1059 | 1059 |
| 1060 return fields_[index]; | 1060 return fields_[index].get(); |
| 1061 } | 1061 } |
| 1062 | 1062 |
| 1063 AutofillField* FormStructure::field(size_t index) { | 1063 AutofillField* FormStructure::field(size_t index) { |
| 1064 return const_cast<AutofillField*>( | 1064 return const_cast<AutofillField*>( |
| 1065 static_cast<const FormStructure*>(this)->field(index)); | 1065 static_cast<const FormStructure*>(this)->field(index)); |
| 1066 } | 1066 } |
| 1067 | 1067 |
| 1068 size_t FormStructure::field_count() const { | 1068 size_t FormStructure::field_count() const { |
| 1069 return fields_.size(); | 1069 return fields_.size(); |
| 1070 } | 1070 } |
| 1071 | 1071 |
| 1072 size_t FormStructure::active_field_count() const { | 1072 size_t FormStructure::active_field_count() const { |
| 1073 return active_field_count_; | 1073 return active_field_count_; |
| 1074 } | 1074 } |
| 1075 | 1075 |
| 1076 FormData FormStructure::ToFormData() const { | 1076 FormData FormStructure::ToFormData() const { |
| 1077 FormData data; | 1077 FormData data; |
| 1078 data.name = form_name_; | 1078 data.name = form_name_; |
| 1079 data.origin = source_url_; | 1079 data.origin = source_url_; |
| 1080 data.action = target_url_; | 1080 data.action = target_url_; |
| 1081 | 1081 |
| 1082 for (size_t i = 0; i < fields_.size(); ++i) { | 1082 data.fields.resize(fields_.size()); |
| 1083 data.fields.push_back(FormFieldData(*fields_[i])); | 1083 std::transform(fields_.cbegin(), fields_.cend(), data.fields.begin(), |
| 1084 } | 1084 [](const std::unique_ptr<AutofillField>& field) { |
| 1085 return FormFieldData(*field); |
| 1086 }); |
| 1085 | 1087 |
| 1086 return data; | 1088 return data; |
| 1087 } | 1089 } |
| 1088 | 1090 |
| 1089 bool FormStructure::operator==(const FormData& form) const { | 1091 bool FormStructure::operator==(const FormData& form) const { |
| 1090 // TODO(jhawkins): Is this enough to differentiate a form? | 1092 // TODO(jhawkins): Is this enough to differentiate a form? |
| 1091 if (form_name_ == form.name && source_url_ == form.origin && | 1093 if (form_name_ == form.name && source_url_ == form.origin && |
| 1092 target_url_ == form.action) { | 1094 target_url_ == form.action) { |
| 1093 return true; | 1095 return true; |
| 1094 } | 1096 } |
| 1095 | 1097 |
| 1096 // TODO(jhawkins): Compare field names, IDs and labels once we have labels | 1098 // TODO(jhawkins): Compare field names, IDs and labels once we have labels |
| 1097 // set up. | 1099 // set up. |
| 1098 | 1100 |
| 1099 return false; | 1101 return false; |
| 1100 } | 1102 } |
| 1101 | 1103 |
| 1102 bool FormStructure::operator!=(const FormData& form) const { | 1104 bool FormStructure::operator!=(const FormData& form) const { |
| 1103 return !operator==(form); | 1105 return !operator==(form); |
| 1104 } | 1106 } |
| 1105 | 1107 |
| 1106 void FormStructure::EncodeFormForQuery( | 1108 void FormStructure::EncodeFormForQuery( |
| 1107 AutofillQueryContents::Form* query_form) const { | 1109 AutofillQueryContents::Form* query_form) const { |
| 1108 DCHECK(!IsMalformed()); | 1110 DCHECK(!IsMalformed()); |
| 1109 | 1111 |
| 1110 query_form->set_signature(form_signature()); | 1112 query_form->set_signature(form_signature()); |
| 1111 for (const AutofillField* field : fields_) { | 1113 for (const auto& field : fields_) { |
| 1112 if (ShouldSkipField(*field)) | 1114 if (ShouldSkipField(*field)) |
| 1113 continue; | 1115 continue; |
| 1114 | 1116 |
| 1115 AutofillQueryContents::Form::Field* added_field = query_form->add_field(); | 1117 AutofillQueryContents::Form::Field* added_field = query_form->add_field(); |
| 1116 | 1118 |
| 1117 added_field->set_signature(field->GetFieldSignature()); | 1119 added_field->set_signature(field->GetFieldSignature()); |
| 1118 | 1120 |
| 1119 if (IsAutofillFieldMetadataEnabled()) { | 1121 if (IsAutofillFieldMetadataEnabled()) { |
| 1120 added_field->set_type(field->form_control_type); | 1122 added_field->set_type(field->form_control_type); |
| 1121 | 1123 |
| 1122 if (!field->name.empty()) | 1124 if (!field->name.empty()) |
| 1123 added_field->set_name(base::UTF16ToUTF8(field->name)); | 1125 added_field->set_name(base::UTF16ToUTF8(field->name)); |
| 1124 | 1126 |
| 1125 } | 1127 } |
| 1126 } | 1128 } |
| 1127 } | 1129 } |
| 1128 | 1130 |
| 1129 void FormStructure::EncodeFormForUpload(AutofillUploadContents* upload) const { | 1131 void FormStructure::EncodeFormForUpload(AutofillUploadContents* upload) const { |
| 1130 DCHECK(!IsMalformed()); | 1132 DCHECK(!IsMalformed()); |
| 1131 | 1133 |
| 1132 for (const AutofillField* field : fields_) { | 1134 for (const auto& field : fields_) { |
| 1133 // Don't upload checkable fields. | 1135 // Don't upload checkable fields. |
| 1134 if (IsCheckable(field->check_status)) | 1136 if (IsCheckable(field->check_status)) |
| 1135 continue; | 1137 continue; |
| 1136 | 1138 |
| 1137 const ServerFieldTypeSet& types = field->possible_types(); | 1139 const ServerFieldTypeSet& types = field->possible_types(); |
| 1138 for (const auto& field_type : types) { | 1140 for (const auto& field_type : types) { |
| 1139 // Add the same field elements as the query and a few more below. | 1141 // Add the same field elements as the query and a few more below. |
| 1140 if (ShouldSkipField(*field)) | 1142 if (ShouldSkipField(*field)) |
| 1141 continue; | 1143 continue; |
| 1142 | 1144 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1190 return; | 1192 return; |
| 1191 | 1193 |
| 1192 if (!has_author_specified_sections) { | 1194 if (!has_author_specified_sections) { |
| 1193 // Name sections after the first field in the section. | 1195 // Name sections after the first field in the section. |
| 1194 base::string16 current_section = fields_.front()->unique_name(); | 1196 base::string16 current_section = fields_.front()->unique_name(); |
| 1195 | 1197 |
| 1196 // Keep track of the types we've seen in this section. | 1198 // Keep track of the types we've seen in this section. |
| 1197 std::set<ServerFieldType> seen_types; | 1199 std::set<ServerFieldType> seen_types; |
| 1198 ServerFieldType previous_type = UNKNOWN_TYPE; | 1200 ServerFieldType previous_type = UNKNOWN_TYPE; |
| 1199 | 1201 |
| 1200 for (AutofillField* field : fields_) { | 1202 for (const auto& field : fields_) { |
| 1201 const ServerFieldType current_type = field->Type().GetStorableType(); | 1203 const ServerFieldType current_type = field->Type().GetStorableType(); |
| 1202 | 1204 |
| 1203 bool already_saw_current_type = seen_types.count(current_type) > 0; | 1205 bool already_saw_current_type = seen_types.count(current_type) > 0; |
| 1204 | 1206 |
| 1205 // Forms often ask for multiple phone numbers -- e.g. both a daytime and | 1207 // Forms often ask for multiple phone numbers -- e.g. both a daytime and |
| 1206 // evening phone number. Our phone number detection is also generally a | 1208 // evening phone number. Our phone number detection is also generally a |
| 1207 // little off. Hence, ignore this field type as a signal here. | 1209 // little off. Hence, ignore this field type as a signal here. |
| 1208 if (AutofillType(current_type).group() == PHONE_HOME) | 1210 if (AutofillType(current_type).group() == PHONE_HOME) |
| 1209 already_saw_current_type = false; | 1211 already_saw_current_type = false; |
| 1210 | 1212 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1244 seen_types.insert(current_type); | 1246 seen_types.insert(current_type); |
| 1245 previous_type = current_type; | 1247 previous_type = current_type; |
| 1246 } | 1248 } |
| 1247 | 1249 |
| 1248 field->set_section(base::UTF16ToUTF8(current_section)); | 1250 field->set_section(base::UTF16ToUTF8(current_section)); |
| 1249 } | 1251 } |
| 1250 } | 1252 } |
| 1251 | 1253 |
| 1252 // Ensure that credit card and address fields are in separate sections. | 1254 // Ensure that credit card and address fields are in separate sections. |
| 1253 // This simplifies the section-aware logic in autofill_manager.cc. | 1255 // This simplifies the section-aware logic in autofill_manager.cc. |
| 1254 for (AutofillField* field : fields_) { | 1256 for (const auto& field : fields_) { |
| 1255 FieldTypeGroup field_type_group = field->Type().group(); | 1257 FieldTypeGroup field_type_group = field->Type().group(); |
| 1256 if (field_type_group == CREDIT_CARD) | 1258 if (field_type_group == CREDIT_CARD) |
| 1257 field->set_section(field->section() + "-cc"); | 1259 field->set_section(field->section() + "-cc"); |
| 1258 else | 1260 else |
| 1259 field->set_section(field->section() + "-default"); | 1261 field->set_section(field->section() + "-default"); |
| 1260 } | 1262 } |
| 1261 } | 1263 } |
| 1262 | 1264 |
| 1263 bool FormStructure::ShouldSkipField(const FormFieldData& field) const { | 1265 bool FormStructure::ShouldSkipField(const FormFieldData& field) const { |
| 1264 return IsCheckable(field.check_status); | 1266 return IsCheckable(field.check_status); |
| 1265 } | 1267 } |
| 1266 | 1268 |
| 1267 void FormStructure::ProcessExtractedFields() { | 1269 void FormStructure::ProcessExtractedFields() { |
| 1268 // Update the field name parsed by heuristics if several criteria are met. | 1270 // Update the field name parsed by heuristics if several criteria are met. |
| 1269 // Several fields must be present in the form. | 1271 // Several fields must be present in the form. |
| 1270 if (field_count() < kCommonNamePrefixRemovalFieldThreshold) | 1272 if (field_count() < kCommonNamePrefixRemovalFieldThreshold) |
| 1271 return; | 1273 return; |
| 1272 | 1274 |
| 1273 // Find the longest common prefix within all the field names. | 1275 // Find the longest common prefix within all the field names. |
| 1274 std::vector<base::string16> names; | 1276 std::vector<base::string16> names; |
| 1275 names.reserve(field_count()); | 1277 names.reserve(field_count()); |
| 1276 for (const AutofillField* field : *this) | 1278 for (const auto& field : fields_) |
| 1277 names.push_back(field->name); | 1279 names.push_back(field->name); |
| 1278 | 1280 |
| 1279 const base::string16 longest_prefix = FindLongestCommonPrefix(names); | 1281 const base::string16 longest_prefix = FindLongestCommonPrefix(names); |
| 1280 if (longest_prefix.size() < kMinCommonNamePrefixLength) | 1282 if (longest_prefix.size() < kMinCommonNamePrefixLength) |
| 1281 return; | 1283 return; |
| 1282 | 1284 |
| 1283 // The name without the prefix will be used for heuristics parsing. | 1285 // The name without the prefix will be used for heuristics parsing. |
| 1284 for (AutofillField* field : *this) { | 1286 for (const auto& field : fields_) { |
| 1285 if (field->name.size() > longest_prefix.size()) { | 1287 if (field->name.size() > longest_prefix.size()) { |
| 1286 field->set_parseable_name( | 1288 field->set_parseable_name( |
| 1287 field->name.substr(longest_prefix.size(), field->name.size())); | 1289 field->name.substr(longest_prefix.size(), field->name.size())); |
| 1288 } | 1290 } |
| 1289 } | 1291 } |
| 1290 } | 1292 } |
| 1291 | 1293 |
| 1292 // static | 1294 // static |
| 1293 base::string16 FormStructure::FindLongestCommonPrefix( | 1295 base::string16 FormStructure::FindLongestCommonPrefix( |
| 1294 const std::vector<base::string16>& strings) { | 1296 const std::vector<base::string16>& strings) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1316 filtered_strings[0].at(prefix_len)) { | 1318 filtered_strings[0].at(prefix_len)) { |
| 1317 // Mismatch found. | 1319 // Mismatch found. |
| 1318 return filtered_strings[i].substr(0, prefix_len); | 1320 return filtered_strings[i].substr(0, prefix_len); |
| 1319 } | 1321 } |
| 1320 } | 1322 } |
| 1321 } | 1323 } |
| 1322 return filtered_strings[0]; | 1324 return filtered_strings[0]; |
| 1323 } | 1325 } |
| 1324 | 1326 |
| 1325 } // namespace autofill | 1327 } // namespace autofill |
| OLD | NEW |