Chromium Code Reviews| 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 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 345 | 345 |
| 346 } // namespace | 346 } // namespace |
| 347 | 347 |
| 348 FormStructure::FormStructure(const FormData& form) | 348 FormStructure::FormStructure(const FormData& form) |
| 349 : form_name_(form.name), | 349 : form_name_(form.name), |
| 350 source_url_(form.origin), | 350 source_url_(form.origin), |
| 351 target_url_(form.action), | 351 target_url_(form.action), |
| 352 autofill_count_(0), | 352 autofill_count_(0), |
| 353 active_field_count_(0), | 353 active_field_count_(0), |
| 354 upload_required_(USE_UPLOAD_RATES), | 354 upload_required_(USE_UPLOAD_RATES), |
| 355 has_author_specified_types_(false) { | 355 has_author_specified_types_(false), |
| 356 has_password_field_(false) { | |
| 356 // Copy the form fields. | 357 // Copy the form fields. |
| 357 std::map<base::string16, size_t> unique_names; | 358 std::map<base::string16, size_t> unique_names; |
| 358 for (std::vector<FormFieldData>::const_iterator field = | 359 for (std::vector<FormFieldData>::const_iterator field = |
| 359 form.fields.begin(); | 360 form.fields.begin(); |
| 360 field != form.fields.end(); ++field) { | 361 field != form.fields.end(); ++field) { |
| 361 if (!ShouldSkipField(*field)) { | 362 if (!ShouldSkipField(*field)) { |
| 362 // Add all supported form fields (including with empty names) to the | 363 // Add all supported form fields (including with empty names) to the |
| 363 // signature. This is a requirement for Autofill servers. | 364 // signature. This is a requirement for Autofill servers. |
| 364 form_signature_field_names_.append("&"); | 365 form_signature_field_names_.append("&"); |
| 365 form_signature_field_names_.append(StripDigitsIfRequired(field->name)); | 366 form_signature_field_names_.append(StripDigitsIfRequired(field->name)); |
| 366 | 367 |
| 367 ++active_field_count_; | 368 ++active_field_count_; |
| 368 } | 369 } |
| 369 | 370 |
| 371 if (field->form_control_type == "password") | |
| 372 has_password_field_ = true; | |
| 373 | |
| 370 // Generate a unique name for this field by appending a counter to the name. | 374 // Generate a unique name for this field by appending a counter to the name. |
| 371 // Make sure to prepend the counter with a non-numeric digit so that we are | 375 // Make sure to prepend the counter with a non-numeric digit so that we are |
| 372 // guaranteed to avoid collisions. | 376 // guaranteed to avoid collisions. |
| 373 if (!unique_names.count(field->name)) | 377 if (!unique_names.count(field->name)) |
| 374 unique_names[field->name] = 1; | 378 unique_names[field->name] = 1; |
| 375 else | 379 else |
| 376 ++unique_names[field->name]; | 380 ++unique_names[field->name]; |
| 377 base::string16 unique_name = field->name + base::ASCIIToUTF16("_") + | 381 base::string16 unique_name = field->name + base::ASCIIToUTF16("_") + |
| 378 base::IntToString16(unique_names[field->name]); | 382 base::IntToString16(unique_names[field->name]); |
| 379 fields_.push_back(new AutofillField(*field, unique_name)); | 383 fields_.push_back(new AutofillField(*field, unique_name)); |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 553 &upload_required); | 557 &upload_required); |
| 554 buzz::XmlParser parser(&parse_handler); | 558 buzz::XmlParser parser(&parse_handler); |
| 555 parser.Parse(response_xml.c_str(), response_xml.length(), true); | 559 parser.Parse(response_xml.c_str(), response_xml.length(), true); |
| 556 if (!parse_handler.succeeded()) | 560 if (!parse_handler.succeeded()) |
| 557 return; | 561 return; |
| 558 | 562 |
| 559 metric_logger.LogServerQueryMetric(AutofillMetrics::QUERY_RESPONSE_PARSED); | 563 metric_logger.LogServerQueryMetric(AutofillMetrics::QUERY_RESPONSE_PARSED); |
| 560 | 564 |
| 561 bool heuristics_detected_fillable_field = false; | 565 bool heuristics_detected_fillable_field = false; |
| 562 bool query_response_overrode_heuristics = false; | 566 bool query_response_overrode_heuristics = false; |
| 567 bool non_password_field_processed = false; | |
| 563 | 568 |
| 564 // Copy the field types into the actual form. | 569 // Copy the field types into the actual form. |
| 565 std::vector<AutofillServerFieldInfo>::iterator current_info = | 570 std::vector<AutofillServerFieldInfo>::iterator current_info = |
| 566 field_infos.begin(); | 571 field_infos.begin(); |
| 567 for (std::vector<FormStructure*>::const_iterator iter = forms.begin(); | 572 for (std::vector<FormStructure*>::const_iterator iter = forms.begin(); |
| 568 iter != forms.end(); ++iter) { | 573 iter != forms.end(); ++iter) { |
| 569 FormStructure* form = *iter; | 574 FormStructure* form = *iter; |
| 570 form->upload_required_ = upload_required; | 575 form->upload_required_ = upload_required; |
| 571 | 576 |
| 572 for (std::vector<AutofillField*>::iterator field = form->fields_.begin(); | 577 for (std::vector<AutofillField*>::iterator field = form->fields_.begin(); |
| 573 field != form->fields_.end(); ++field) { | 578 field != form->fields_.end(); ++field) { |
| 574 if (form->ShouldSkipField(**field)) | 579 if (form->ShouldSkipField(**field)) |
| 575 continue; | 580 continue; |
| 576 | 581 |
| 577 // In some cases *successful* response does not return all the fields. | 582 // In some cases *successful* response does not return all the fields. |
| 578 // Quit the update of the types then. | 583 // Quit the update of the types then. |
| 579 if (current_info == field_infos.end()) | 584 if (current_info == field_infos.end()) |
| 580 break; | 585 break; |
| 581 | 586 |
| 582 // UNKNOWN_TYPE is reserved for use by the client. | 587 if (form->ShouldSkipProcessingNonPasswordFields()) { |
| 583 DCHECK_NE(current_info->field_type, UNKNOWN_TYPE); | 588 // Heuristic values can be ignored for password fields as Autofill |
| 589 // doesn't handle them. UMA stats can also be skipped in that case. | |
| 590 if ((*field)->Type().group() == PASSWORD_FIELD) | |
| 591 (*field)->set_server_type(current_info->field_type); | |
| 592 } else { | |
| 593 non_password_field_processed = true; | |
|
Ilya Sherman
2014/10/24 01:24:45
Wait, where do you check that a non-password field
Garrett Casto
2014/10/24 21:13:09
I agree that the name doesn't do a great job of ex
| |
| 584 | 594 |
| 585 ServerFieldType heuristic_type = (*field)->heuristic_type(); | 595 // UNKNOWN_TYPE is reserved for use by the client. |
| 586 if (heuristic_type != UNKNOWN_TYPE) | 596 DCHECK_NE(current_info->field_type, UNKNOWN_TYPE); |
| 587 heuristics_detected_fillable_field = true; | |
| 588 | 597 |
| 589 (*field)->set_server_type(current_info->field_type); | 598 ServerFieldType heuristic_type = (*field)->heuristic_type(); |
| 590 if (heuristic_type != (*field)->Type().GetStorableType()) | 599 if (heuristic_type != UNKNOWN_TYPE) |
| 591 query_response_overrode_heuristics = true; | 600 heuristics_detected_fillable_field = true; |
| 592 | 601 |
| 593 // Copy default value into the field if available. | 602 (*field)->set_server_type(current_info->field_type); |
| 594 if (!current_info->default_value.empty()) | 603 if (heuristic_type != (*field)->Type().GetStorableType()) |
| 595 (*field)->set_default_value(current_info->default_value); | 604 query_response_overrode_heuristics = true; |
| 605 | |
| 606 // Copy default value into the field if available. | |
| 607 if (!current_info->default_value.empty()) | |
| 608 (*field)->set_default_value(current_info->default_value); | |
| 609 } | |
| 596 | 610 |
| 597 ++current_info; | 611 ++current_info; |
| 598 } | 612 } |
| 599 | 613 |
| 600 form->UpdateAutofillCount(); | 614 form->UpdateAutofillCount(); |
| 601 form->IdentifySections(false); | 615 form->IdentifySections(false); |
| 602 } | 616 } |
| 603 | 617 |
| 604 AutofillMetrics::ServerQueryMetric metric; | 618 // Only log metrics if response was for non-password fields, since password |
| 605 if (query_response_overrode_heuristics) { | 619 // fields don't have local heuristics to measure. |
| 606 if (heuristics_detected_fillable_field) { | 620 if (non_password_field_processed) { |
| 607 metric = AutofillMetrics::QUERY_RESPONSE_OVERRODE_LOCAL_HEURISTICS; | 621 AutofillMetrics::ServerQueryMetric metric; |
| 622 if (query_response_overrode_heuristics) { | |
| 623 if (heuristics_detected_fillable_field) { | |
| 624 metric = AutofillMetrics::QUERY_RESPONSE_OVERRODE_LOCAL_HEURISTICS; | |
| 625 } else { | |
| 626 metric = AutofillMetrics::QUERY_RESPONSE_WITH_NO_LOCAL_HEURISTICS; | |
| 627 } | |
| 608 } else { | 628 } else { |
| 609 metric = AutofillMetrics::QUERY_RESPONSE_WITH_NO_LOCAL_HEURISTICS; | 629 metric = AutofillMetrics::QUERY_RESPONSE_MATCHED_LOCAL_HEURISTICS; |
| 610 } | 630 } |
| 611 } else { | 631 metric_logger.LogServerQueryMetric(metric); |
| 612 metric = AutofillMetrics::QUERY_RESPONSE_MATCHED_LOCAL_HEURISTICS; | |
| 613 } | 632 } |
| 614 metric_logger.LogServerQueryMetric(metric); | |
| 615 } | 633 } |
| 616 | 634 |
| 617 // static | 635 // static |
| 618 void FormStructure::GetFieldTypePredictions( | 636 void FormStructure::GetFieldTypePredictions( |
| 619 const std::vector<FormStructure*>& form_structures, | 637 const std::vector<FormStructure*>& form_structures, |
| 620 std::vector<FormDataPredictions>* forms) { | 638 std::vector<FormDataPredictions>* forms) { |
| 621 forms->clear(); | 639 forms->clear(); |
| 622 forms->reserve(form_structures.size()); | 640 forms->reserve(form_structures.size()); |
| 623 for (size_t i = 0; i < form_structures.size(); ++i) { | 641 for (size_t i = 0; i < form_structures.size(); ++i) { |
| 624 FormStructure* form_structure = form_structures[i]; | 642 FormStructure* form_structure = form_structures[i]; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 699 bool has_text_field = false; | 717 bool has_text_field = false; |
| 700 for (std::vector<AutofillField*>::const_iterator it = begin(); | 718 for (std::vector<AutofillField*>::const_iterator it = begin(); |
| 701 it != end() && !has_text_field; ++it) { | 719 it != end() && !has_text_field; ++it) { |
| 702 has_text_field |= (*it)->form_control_type != "select-one"; | 720 has_text_field |= (*it)->form_control_type != "select-one"; |
| 703 } | 721 } |
| 704 | 722 |
| 705 return has_text_field; | 723 return has_text_field; |
| 706 } | 724 } |
| 707 | 725 |
| 708 bool FormStructure::ShouldBeCrowdsourced() const { | 726 bool FormStructure::ShouldBeCrowdsourced() const { |
| 709 return !has_author_specified_types_ && ShouldBeParsed(); | 727 return (has_password_field_ || !has_author_specified_types_) && |
| 728 ShouldBeParsed(); | |
| 729 } | |
| 730 | |
| 731 bool FormStructure::ShouldSkipProcessingNonPasswordFields() const { | |
|
Ilya Sherman
2014/10/24 01:24:45
This method name is pretty long and, IMO, still a
Garrett Casto
2014/10/24 21:13:09
Done.
| |
| 732 return has_password_field_ && has_author_specified_types_; | |
| 710 } | 733 } |
| 711 | 734 |
| 712 void FormStructure::UpdateFromCache(const FormStructure& cached_form) { | 735 void FormStructure::UpdateFromCache(const FormStructure& cached_form) { |
| 713 // Map from field signatures to cached fields. | 736 // Map from field signatures to cached fields. |
| 714 std::map<std::string, const AutofillField*> cached_fields; | 737 std::map<std::string, const AutofillField*> cached_fields; |
| 715 for (size_t i = 0; i < cached_form.field_count(); ++i) { | 738 for (size_t i = 0; i < cached_form.field_count(); ++i) { |
| 716 const AutofillField* field = cached_form.field(i); | 739 const AutofillField* field = cached_form.field(i); |
| 717 cached_fields[field->FieldSignature()] = field; | 740 cached_fields[field->FieldSignature()] = field; |
| 718 } | 741 } |
| 719 | 742 |
| (...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1228 field != fields_.end(); ++field) { | 1251 field != fields_.end(); ++field) { |
| 1229 FieldTypeGroup field_type_group = (*field)->Type().group(); | 1252 FieldTypeGroup field_type_group = (*field)->Type().group(); |
| 1230 if (field_type_group == CREDIT_CARD) | 1253 if (field_type_group == CREDIT_CARD) |
| 1231 (*field)->set_section((*field)->section() + "-cc"); | 1254 (*field)->set_section((*field)->section() + "-cc"); |
| 1232 else | 1255 else |
| 1233 (*field)->set_section((*field)->section() + "-default"); | 1256 (*field)->set_section((*field)->section() + "-default"); |
| 1234 } | 1257 } |
| 1235 } | 1258 } |
| 1236 | 1259 |
| 1237 } // namespace autofill | 1260 } // namespace autofill |
| OLD | NEW |