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