| 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 <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 #include "components/autofill/core/common/form_data.h" | 26 #include "components/autofill/core/common/form_data.h" |
| 27 #include "components/autofill/core/common/form_data_predictions.h" | 27 #include "components/autofill/core/common/form_data_predictions.h" |
| 28 #include "components/autofill/core/common/form_field_data.h" | 28 #include "components/autofill/core/common/form_field_data.h" |
| 29 #include "components/autofill/core/common/form_field_data_predictions.h" | 29 #include "components/autofill/core/common/form_field_data_predictions.h" |
| 30 #include "third_party/icu/source/i18n/unicode/regex.h" | 30 #include "third_party/icu/source/i18n/unicode/regex.h" |
| 31 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" | 31 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" |
| 32 | 32 |
| 33 namespace autofill { | 33 namespace autofill { |
| 34 namespace { | 34 namespace { |
| 35 | 35 |
| 36 const char kFormMethodPost[] = "post"; | |
| 37 | |
| 38 // XML elements and attributes. | 36 // XML elements and attributes. |
| 39 const char kAttributeAutofillUsed[] = "autofillused"; | 37 const char kAttributeAutofillUsed[] = "autofillused"; |
| 40 const char kAttributeAutofillType[] = "autofilltype"; | 38 const char kAttributeAutofillType[] = "autofilltype"; |
| 41 const char kAttributeClientVersion[] = "clientversion"; | 39 const char kAttributeClientVersion[] = "clientversion"; |
| 42 const char kAttributeDataPresent[] = "datapresent"; | 40 const char kAttributeDataPresent[] = "datapresent"; |
| 43 const char kAttributeFieldID[] = "fieldid"; | 41 const char kAttributeFieldID[] = "fieldid"; |
| 44 const char kAttributeFieldType[] = "fieldtype"; | 42 const char kAttributeFieldType[] = "fieldtype"; |
| 45 const char kAttributeFormSignature[] = "formsignature"; | 43 const char kAttributeFormSignature[] = "formsignature"; |
| 46 const char kAttributeName[] = "name"; | 44 const char kAttributeName[] = "name"; |
| 47 const char kAttributeSignature[] = "signature"; | 45 const char kAttributeSignature[] = "signature"; |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 373 // Make sure to prepend the counter with a non-numeric digit so that we are | 371 // Make sure to prepend the counter with a non-numeric digit so that we are |
| 374 // guaranteed to avoid collisions. | 372 // guaranteed to avoid collisions. |
| 375 if (!unique_names.count(field->name)) | 373 if (!unique_names.count(field->name)) |
| 376 unique_names[field->name] = 1; | 374 unique_names[field->name] = 1; |
| 377 else | 375 else |
| 378 ++unique_names[field->name]; | 376 ++unique_names[field->name]; |
| 379 base::string16 unique_name = field->name + base::ASCIIToUTF16("_") + | 377 base::string16 unique_name = field->name + base::ASCIIToUTF16("_") + |
| 380 base::IntToString16(unique_names[field->name]); | 378 base::IntToString16(unique_names[field->name]); |
| 381 fields_.push_back(new AutofillField(*field, unique_name)); | 379 fields_.push_back(new AutofillField(*field, unique_name)); |
| 382 } | 380 } |
| 383 | |
| 384 std::string method = base::UTF16ToUTF8(form.method); | |
| 385 if (StringToLowerASCII(method) == kFormMethodPost) { | |
| 386 method_ = POST; | |
| 387 } else { | |
| 388 // Either the method is 'get', or we don't know. In this case we default | |
| 389 // to GET. | |
| 390 method_ = GET; | |
| 391 } | |
| 392 } | 381 } |
| 393 | 382 |
| 394 FormStructure::~FormStructure() {} | 383 FormStructure::~FormStructure() {} |
| 395 | 384 |
| 396 void FormStructure::DetermineHeuristicTypes( | 385 void FormStructure::DetermineHeuristicTypes( |
| 397 const AutofillMetrics& metric_logger) { | 386 const AutofillMetrics& metric_logger) { |
| 398 // First, try to detect field types based on each field's |autocomplete| | 387 // First, try to detect field types based on each field's |autocomplete| |
| 399 // attribute value. If there is at least one form field that specifies an | 388 // attribute value. If there is at least one form field that specifies an |
| 400 // autocomplete type hint, don't try to apply other heuristics to match fields | 389 // autocomplete type hint, don't try to apply other heuristics to match fields |
| 401 // in this form. | 390 // in this form. |
| 402 bool has_author_specified_sections; | 391 bool has_author_specified_sections; |
| 403 ParseFieldTypesFromAutocompleteAttributes(&has_author_specified_types_, | 392 ParseFieldTypesFromAutocompleteAttributes(&has_author_specified_types_, |
| 404 &has_author_specified_sections); | 393 &has_author_specified_sections); |
| 405 | 394 |
| 406 if (!has_author_specified_types_) { | 395 if (!has_author_specified_types_) { |
| 407 ServerFieldTypeMap field_type_map; | 396 ServerFieldTypeMap field_type_map; |
| 408 FormField::ParseFormFields(fields_.get(), &field_type_map); | 397 FormField::ParseFormFields(fields_.get(), &field_type_map); |
| 409 for (size_t i = 0; i < field_count(); ++i) { | 398 for (size_t i = 0; i < field_count(); ++i) { |
| 410 AutofillField* field = fields_[i]; | 399 AutofillField* field = fields_[i]; |
| 411 ServerFieldTypeMap::iterator iter = | 400 ServerFieldTypeMap::iterator iter = |
| 412 field_type_map.find(field->unique_name()); | 401 field_type_map.find(field->unique_name()); |
| 413 if (iter != field_type_map.end()) | 402 if (iter != field_type_map.end()) |
| 414 field->set_heuristic_type(iter->second); | 403 field->set_heuristic_type(iter->second); |
| 415 } | 404 } |
| 416 } | 405 } |
| 417 | 406 |
| 418 UpdateAutofillCount(); | 407 UpdateAutofillCount(); |
| 419 IdentifySections(has_author_specified_sections); | 408 IdentifySections(has_author_specified_sections); |
| 420 | 409 |
| 421 if (IsAutofillable(true)) { | 410 if (IsAutofillable()) { |
| 422 metric_logger.LogDeveloperEngagementMetric( | 411 metric_logger.LogDeveloperEngagementMetric( |
| 423 AutofillMetrics::FILLABLE_FORM_PARSED); | 412 AutofillMetrics::FILLABLE_FORM_PARSED); |
| 424 if (has_author_specified_types_) { | 413 if (has_author_specified_types_) { |
| 425 metric_logger.LogDeveloperEngagementMetric( | 414 metric_logger.LogDeveloperEngagementMetric( |
| 426 AutofillMetrics::FILLABLE_FORM_CONTAINS_TYPE_HINTS); | 415 AutofillMetrics::FILLABLE_FORM_CONTAINS_TYPE_HINTS); |
| 427 } | 416 } |
| 428 } | 417 } |
| 429 } | 418 } |
| 430 | 419 |
| 431 bool FormStructure::EncodeUploadRequest( | 420 bool FormStructure::EncodeUploadRequest( |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 628 // static | 617 // static |
| 629 void FormStructure::GetFieldTypePredictions( | 618 void FormStructure::GetFieldTypePredictions( |
| 630 const std::vector<FormStructure*>& form_structures, | 619 const std::vector<FormStructure*>& form_structures, |
| 631 std::vector<FormDataPredictions>* forms) { | 620 std::vector<FormDataPredictions>* forms) { |
| 632 forms->clear(); | 621 forms->clear(); |
| 633 forms->reserve(form_structures.size()); | 622 forms->reserve(form_structures.size()); |
| 634 for (size_t i = 0; i < form_structures.size(); ++i) { | 623 for (size_t i = 0; i < form_structures.size(); ++i) { |
| 635 FormStructure* form_structure = form_structures[i]; | 624 FormStructure* form_structure = form_structures[i]; |
| 636 FormDataPredictions form; | 625 FormDataPredictions form; |
| 637 form.data.name = form_structure->form_name_; | 626 form.data.name = form_structure->form_name_; |
| 638 form.data.method = | |
| 639 base::ASCIIToUTF16((form_structure->method_ == POST) ? "POST" : "GET"); | |
| 640 form.data.origin = form_structure->source_url_; | 627 form.data.origin = form_structure->source_url_; |
| 641 form.data.action = form_structure->target_url_; | 628 form.data.action = form_structure->target_url_; |
| 642 form.signature = form_structure->FormSignature(); | 629 form.signature = form_structure->FormSignature(); |
| 643 | 630 |
| 644 for (std::vector<AutofillField*>::const_iterator field = | 631 for (std::vector<AutofillField*>::const_iterator field = |
| 645 form_structure->fields_.begin(); | 632 form_structure->fields_.begin(); |
| 646 field != form_structure->fields_.end(); ++field) { | 633 field != form_structure->fields_.end(); ++field) { |
| 647 form.data.fields.push_back(FormFieldData(**field)); | 634 form.data.fields.push_back(FormFieldData(**field)); |
| 648 | 635 |
| 649 FormFieldDataPredictions annotated_field; | 636 FormFieldDataPredictions annotated_field; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 675 base::UTF16ToUTF8(form_name_) + | 662 base::UTF16ToUTF8(form_name_) + |
| 676 form_signature_field_names_; | 663 form_signature_field_names_; |
| 677 | 664 |
| 678 return Hash64Bit(form_string); | 665 return Hash64Bit(form_string); |
| 679 } | 666 } |
| 680 | 667 |
| 681 bool FormStructure::ShouldSkipField(const FormFieldData& field) const { | 668 bool FormStructure::ShouldSkipField(const FormFieldData& field) const { |
| 682 return field.is_checkable; | 669 return field.is_checkable; |
| 683 } | 670 } |
| 684 | 671 |
| 685 bool FormStructure::IsAutofillable(bool require_method_post) const { | 672 bool FormStructure::IsAutofillable() const { |
| 686 if (autofill_count() < kRequiredAutofillFields) | 673 if (autofill_count() < kRequiredAutofillFields) |
| 687 return false; | 674 return false; |
| 688 | 675 |
| 689 return ShouldBeParsed(require_method_post); | 676 return ShouldBeParsed(); |
| 690 } | 677 } |
| 691 | 678 |
| 692 void FormStructure::UpdateAutofillCount() { | 679 void FormStructure::UpdateAutofillCount() { |
| 693 autofill_count_ = 0; | 680 autofill_count_ = 0; |
| 694 for (std::vector<AutofillField*>::const_iterator iter = begin(); | 681 for (std::vector<AutofillField*>::const_iterator iter = begin(); |
| 695 iter != end(); ++iter) { | 682 iter != end(); ++iter) { |
| 696 AutofillField* field = *iter; | 683 AutofillField* field = *iter; |
| 697 if (field && field->IsFieldFillable()) | 684 if (field && field->IsFieldFillable()) |
| 698 ++autofill_count_; | 685 ++autofill_count_; |
| 699 } | 686 } |
| 700 } | 687 } |
| 701 | 688 |
| 702 bool FormStructure::ShouldBeParsed(bool require_method_post) const { | 689 bool FormStructure::ShouldBeParsed() const { |
| 703 if (active_field_count() < kRequiredAutofillFields) | 690 if (active_field_count() < kRequiredAutofillFields) |
| 704 return false; | 691 return false; |
| 705 | 692 |
| 706 // Rule out http(s)://*/search?... | 693 // Rule out http(s)://*/search?... |
| 707 // e.g. http://www.google.com/search?q=... | 694 // e.g. http://www.google.com/search?q=... |
| 708 // http://search.yahoo.com/search?p=... | 695 // http://search.yahoo.com/search?p=... |
| 709 if (target_url_.path() == "/search") | 696 if (target_url_.path() == "/search") |
| 710 return false; | 697 return false; |
| 711 | 698 |
| 712 bool has_text_field = false; | 699 bool has_text_field = false; |
| 713 for (std::vector<AutofillField*>::const_iterator it = begin(); | 700 for (std::vector<AutofillField*>::const_iterator it = begin(); |
| 714 it != end() && !has_text_field; ++it) { | 701 it != end() && !has_text_field; ++it) { |
| 715 has_text_field |= (*it)->form_control_type != "select-one"; | 702 has_text_field |= (*it)->form_control_type != "select-one"; |
| 716 } | 703 } |
| 717 if (!has_text_field) | |
| 718 return false; | |
| 719 | 704 |
| 720 return !require_method_post || (method_ == POST); | 705 return has_text_field; |
| 721 } | 706 } |
| 722 | 707 |
| 723 bool FormStructure::ShouldBeCrowdsourced() const { | 708 bool FormStructure::ShouldBeCrowdsourced() const { |
| 724 return !has_author_specified_types_ && ShouldBeParsed(true); | 709 return !has_author_specified_types_ && ShouldBeParsed(); |
| 725 } | 710 } |
| 726 | 711 |
| 727 void FormStructure::UpdateFromCache(const FormStructure& cached_form) { | 712 void FormStructure::UpdateFromCache(const FormStructure& cached_form) { |
| 728 // Map from field signatures to cached fields. | 713 // Map from field signatures to cached fields. |
| 729 std::map<std::string, const AutofillField*> cached_fields; | 714 std::map<std::string, const AutofillField*> cached_fields; |
| 730 for (size_t i = 0; i < cached_form.field_count(); ++i) { | 715 for (size_t i = 0; i < cached_form.field_count(); ++i) { |
| 731 const AutofillField* field = cached_form.field(i); | 716 const AutofillField* field = cached_form.field(i); |
| 732 cached_fields[field->FieldSignature()] = field; | 717 cached_fields[field->FieldSignature()] = field; |
| 733 } | 718 } |
| 734 | 719 |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 924 size_t FormStructure::active_field_count() const { | 909 size_t FormStructure::active_field_count() const { |
| 925 return active_field_count_; | 910 return active_field_count_; |
| 926 } | 911 } |
| 927 | 912 |
| 928 FormData FormStructure::ToFormData() const { | 913 FormData FormStructure::ToFormData() const { |
| 929 // |data.user_submitted| will always be false. | 914 // |data.user_submitted| will always be false. |
| 930 FormData data; | 915 FormData data; |
| 931 data.name = form_name_; | 916 data.name = form_name_; |
| 932 data.origin = source_url_; | 917 data.origin = source_url_; |
| 933 data.action = target_url_; | 918 data.action = target_url_; |
| 934 data.method = base::ASCIIToUTF16(method_ == POST ? "POST" : "GET"); | |
| 935 | 919 |
| 936 for (size_t i = 0; i < fields_.size(); ++i) { | 920 for (size_t i = 0; i < fields_.size(); ++i) { |
| 937 data.fields.push_back(FormFieldData(*fields_[i])); | 921 data.fields.push_back(FormFieldData(*fields_[i])); |
| 938 } | 922 } |
| 939 | 923 |
| 940 return data; | 924 return data; |
| 941 } | 925 } |
| 942 | 926 |
| 943 bool FormStructure::operator==(const FormData& form) const { | 927 bool FormStructure::operator==(const FormData& form) const { |
| 944 // TODO(jhawkins): Is this enough to differentiate a form? | 928 // TODO(jhawkins): Is this enough to differentiate a form? |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1242 field != fields_.end(); ++field) { | 1226 field != fields_.end(); ++field) { |
| 1243 FieldTypeGroup field_type_group = (*field)->Type().group(); | 1227 FieldTypeGroup field_type_group = (*field)->Type().group(); |
| 1244 if (field_type_group == CREDIT_CARD) | 1228 if (field_type_group == CREDIT_CARD) |
| 1245 (*field)->set_section((*field)->section() + "-cc"); | 1229 (*field)->set_section((*field)->section() + "-cc"); |
| 1246 else | 1230 else |
| 1247 (*field)->set_section((*field)->section() + "-default"); | 1231 (*field)->set_section((*field)->section() + "-default"); |
| 1248 } | 1232 } |
| 1249 } | 1233 } |
| 1250 | 1234 |
| 1251 } // namespace autofill | 1235 } // namespace autofill |
| OLD | NEW |