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 |