| 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" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
| 13 #include "base/sha1.h" | 13 #include "base/sha1.h" |
| 14 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 15 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
| 16 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
| 17 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
| 18 #include "base/time/time.h" | 18 #include "base/time/time.h" |
| 19 #include "components/autofill/content/browser/autocheckout_page_meta_data.h" | |
| 20 #include "components/autofill/core/browser/autofill_metrics.h" | 19 #include "components/autofill/core/browser/autofill_metrics.h" |
| 21 #include "components/autofill/core/browser/autofill_type.h" | 20 #include "components/autofill/core/browser/autofill_type.h" |
| 22 #include "components/autofill/core/browser/autofill_xml_parser.h" | 21 #include "components/autofill/core/browser/autofill_xml_parser.h" |
| 23 #include "components/autofill/core/browser/field_types.h" | 22 #include "components/autofill/core/browser/field_types.h" |
| 24 #include "components/autofill/core/browser/form_field.h" | 23 #include "components/autofill/core/browser/form_field.h" |
| 25 #include "components/autofill/core/common/autofill_constants.h" | 24 #include "components/autofill/core/common/autofill_constants.h" |
| 26 #include "components/autofill/core/common/form_data.h" | 25 #include "components/autofill/core/common/form_data.h" |
| 27 #include "components/autofill/core/common/form_data_predictions.h" | 26 #include "components/autofill/core/common/form_data_predictions.h" |
| 28 #include "components/autofill/core/common/form_field_data.h" | 27 #include "components/autofill/core/common/form_field_data.h" |
| 29 #include "components/autofill/core/common/form_field_data_predictions.h" | 28 #include "components/autofill/core/common/form_field_data_predictions.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 41 const char kAttributeAutofillType[] = "autofilltype"; | 40 const char kAttributeAutofillType[] = "autofilltype"; |
| 42 const char kAttributeClientVersion[] = "clientversion"; | 41 const char kAttributeClientVersion[] = "clientversion"; |
| 43 const char kAttributeDataPresent[] = "datapresent"; | 42 const char kAttributeDataPresent[] = "datapresent"; |
| 44 const char kAttributeFieldID[] = "fieldid"; | 43 const char kAttributeFieldID[] = "fieldid"; |
| 45 const char kAttributeFieldType[] = "fieldtype"; | 44 const char kAttributeFieldType[] = "fieldtype"; |
| 46 const char kAttributeFormSignature[] = "formsignature"; | 45 const char kAttributeFormSignature[] = "formsignature"; |
| 47 const char kAttributeName[] = "name"; | 46 const char kAttributeName[] = "name"; |
| 48 const char kAttributeSignature[] = "signature"; | 47 const char kAttributeSignature[] = "signature"; |
| 49 const char kAttributeUrlprefixSignature[] = "urlprefixsignature"; | 48 const char kAttributeUrlprefixSignature[] = "urlprefixsignature"; |
| 50 const char kAcceptedFeaturesExperiment[] = "e"; // e=experiments | 49 const char kAcceptedFeaturesExperiment[] = "e"; // e=experiments |
| 51 const char kAcceptedFeaturesAutocheckoutExperiment[] = "a,e"; // a=autocheckout | |
| 52 const char kClientVersion[] = "6.1.1715.1442/en (GGLL)"; | 50 const char kClientVersion[] = "6.1.1715.1442/en (GGLL)"; |
| 53 const char kXMLDeclaration[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; | 51 const char kXMLDeclaration[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; |
| 54 const char kXMLElementAutofillQuery[] = "autofillquery"; | 52 const char kXMLElementAutofillQuery[] = "autofillquery"; |
| 55 const char kXMLElementAutofillUpload[] = "autofillupload"; | 53 const char kXMLElementAutofillUpload[] = "autofillupload"; |
| 56 const char kXMLElementFieldAssignments[] = "fieldassignments"; | 54 const char kXMLElementFieldAssignments[] = "fieldassignments"; |
| 57 const char kXMLElementField[] = "field"; | 55 const char kXMLElementField[] = "field"; |
| 58 const char kXMLElementFields[] = "fields"; | 56 const char kXMLElementFields[] = "fields"; |
| 59 const char kXMLElementForm[] = "form"; | 57 const char kXMLElementForm[] = "form"; |
| 60 const char kBillingMode[] = "billing"; | 58 const char kBillingMode[] = "billing"; |
| 61 const char kShippingMode[] = "shipping"; | 59 const char kShippingMode[] = "shipping"; |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 if (status != U_ZERO_ERROR) { | 315 if (status != U_ZERO_ERROR) { |
| 318 DVLOG(1) << "Couldn't strip digits in " << UTF16ToUTF8(input); | 316 DVLOG(1) << "Couldn't strip digits in " << UTF16ToUTF8(input); |
| 319 return UTF16ToUTF8(input); | 317 return UTF16ToUTF8(input); |
| 320 } | 318 } |
| 321 | 319 |
| 322 return return_string; | 320 return return_string; |
| 323 } | 321 } |
| 324 | 322 |
| 325 } // namespace | 323 } // namespace |
| 326 | 324 |
| 327 FormStructure::FormStructure(const FormData& form, | 325 FormStructure::FormStructure(const FormData& form) |
| 328 const std::string& autocheckout_url_prefix) | |
| 329 : form_name_(form.name), | 326 : form_name_(form.name), |
| 330 source_url_(form.origin), | 327 source_url_(form.origin), |
| 331 target_url_(form.action), | 328 target_url_(form.action), |
| 332 autofill_count_(0), | 329 autofill_count_(0), |
| 333 active_field_count_(0), | 330 active_field_count_(0), |
| 334 upload_required_(USE_UPLOAD_RATES), | 331 upload_required_(USE_UPLOAD_RATES), |
| 335 server_experiment_id_("no server response"), | 332 server_experiment_id_("no server response"), |
| 336 has_author_specified_types_(false), | 333 has_author_specified_types_(false) { |
| 337 autocheckout_url_prefix_(autocheckout_url_prefix), | |
| 338 filled_by_autocheckout_(false) { | |
| 339 // Copy the form fields. | 334 // Copy the form fields. |
| 340 std::map<base::string16, size_t> unique_names; | 335 std::map<base::string16, size_t> unique_names; |
| 341 for (std::vector<FormFieldData>::const_iterator field = | 336 for (std::vector<FormFieldData>::const_iterator field = |
| 342 form.fields.begin(); | 337 form.fields.begin(); |
| 343 field != form.fields.end(); field++) { | 338 field != form.fields.end(); field++) { |
| 344 | 339 |
| 345 if (!ShouldSkipField(*field)) { | 340 if (!ShouldSkipField(*field)) { |
| 346 // Add all supported form fields (including with empty names) to the | 341 // Add all supported form fields (including with empty names) to the |
| 347 // signature. This is a requirement for Autofill servers. | 342 // signature. This is a requirement for Autofill servers. |
| 348 form_signature_field_names_.append("&"); | 343 form_signature_field_names_.append("&"); |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 encoded_xml->clear(); | 483 encoded_xml->clear(); |
| 489 encoded_signatures->clear(); | 484 encoded_signatures->clear(); |
| 490 encoded_signatures->reserve(forms.size()); | 485 encoded_signatures->reserve(forms.size()); |
| 491 | 486 |
| 492 // Set up the <autofillquery> element and attributes. | 487 // Set up the <autofillquery> element and attributes. |
| 493 buzz::XmlElement autofill_request_xml( | 488 buzz::XmlElement autofill_request_xml( |
| 494 (buzz::QName(kXMLElementAutofillQuery))); | 489 (buzz::QName(kXMLElementAutofillQuery))); |
| 495 autofill_request_xml.SetAttr(buzz::QName(kAttributeClientVersion), | 490 autofill_request_xml.SetAttr(buzz::QName(kAttributeClientVersion), |
| 496 kClientVersion); | 491 kClientVersion); |
| 497 | 492 |
| 498 // autocheckout_url_prefix tells the Autofill server where the forms in the | |
| 499 // request came from, and the the Autofill server checks internal status and | |
| 500 // decide to enable Autocheckout or not and may return Autocheckout related | |
| 501 // data in the response accordingly. | |
| 502 // There is no page/frame level object associated with FormStructure that | |
| 503 // we could extract URL prefix from. But, all the forms should come from the | |
| 504 // same frame, so they should have the same Autocheckout URL prefix. Thus we | |
| 505 // use URL prefix from the first form with Autocheckout enabled. | |
| 506 std::string autocheckout_url_prefix; | |
| 507 | |
| 508 // Some badly formatted web sites repeat forms - detect that and encode only | 493 // Some badly formatted web sites repeat forms - detect that and encode only |
| 509 // one form as returned data would be the same for all the repeated forms. | 494 // one form as returned data would be the same for all the repeated forms. |
| 510 std::set<std::string> processed_forms; | 495 std::set<std::string> processed_forms; |
| 511 for (ScopedVector<FormStructure>::const_iterator it = forms.begin(); | 496 for (ScopedVector<FormStructure>::const_iterator it = forms.begin(); |
| 512 it != forms.end(); | 497 it != forms.end(); |
| 513 ++it) { | 498 ++it) { |
| 514 std::string signature((*it)->FormSignature()); | 499 std::string signature((*it)->FormSignature()); |
| 515 if (processed_forms.find(signature) != processed_forms.end()) | 500 if (processed_forms.find(signature) != processed_forms.end()) |
| 516 continue; | 501 continue; |
| 517 processed_forms.insert(signature); | 502 processed_forms.insert(signature); |
| 518 scoped_ptr<buzz::XmlElement> encompassing_xml_element( | 503 scoped_ptr<buzz::XmlElement> encompassing_xml_element( |
| 519 new buzz::XmlElement(buzz::QName(kXMLElementForm))); | 504 new buzz::XmlElement(buzz::QName(kXMLElementForm))); |
| 520 encompassing_xml_element->SetAttr(buzz::QName(kAttributeSignature), | 505 encompassing_xml_element->SetAttr(buzz::QName(kAttributeSignature), |
| 521 signature); | 506 signature); |
| 522 | 507 |
| 523 if (!(*it)->EncodeFormRequest(FormStructure::QUERY, | 508 if (!(*it)->EncodeFormRequest(FormStructure::QUERY, |
| 524 encompassing_xml_element.get())) | 509 encompassing_xml_element.get())) |
| 525 continue; // Malformed form, skip it. | 510 continue; // Malformed form, skip it. |
| 526 | 511 |
| 527 if ((*it)->IsAutocheckoutEnabled()) { | |
| 528 if (autocheckout_url_prefix.empty()) { | |
| 529 autocheckout_url_prefix = (*it)->autocheckout_url_prefix_; | |
| 530 } else { | |
| 531 // Making sure all the forms in the request has the same url_prefix. | |
| 532 DCHECK_EQ(autocheckout_url_prefix, (*it)->autocheckout_url_prefix_); | |
| 533 } | |
| 534 } | |
| 535 | |
| 536 autofill_request_xml.AddElement(encompassing_xml_element.release()); | 512 autofill_request_xml.AddElement(encompassing_xml_element.release()); |
| 537 encoded_signatures->push_back(signature); | 513 encoded_signatures->push_back(signature); |
| 538 } | 514 } |
| 539 | 515 |
| 540 if (!encoded_signatures->size()) | 516 if (!encoded_signatures->size()) |
| 541 return false; | 517 return false; |
| 542 | 518 |
| 543 if (autocheckout_url_prefix.empty()) { | 519 autofill_request_xml.SetAttr(buzz::QName(kAttributeAcceptedFeatures), |
| 544 autofill_request_xml.SetAttr(buzz::QName(kAttributeAcceptedFeatures), | 520 kAcceptedFeaturesExperiment); |
| 545 kAcceptedFeaturesExperiment); | |
| 546 } else { | |
| 547 autofill_request_xml.SetAttr(buzz::QName(kAttributeAcceptedFeatures), | |
| 548 kAcceptedFeaturesAutocheckoutExperiment); | |
| 549 autofill_request_xml.SetAttr(buzz::QName(kAttributeUrlprefixSignature), | |
| 550 Hash64Bit(autocheckout_url_prefix)); | |
| 551 } | |
| 552 | 521 |
| 553 // Obtain the XML structure as a string. | 522 // Obtain the XML structure as a string. |
| 554 *encoded_xml = kXMLDeclaration; | 523 *encoded_xml = kXMLDeclaration; |
| 555 *encoded_xml += autofill_request_xml.Str().c_str(); | 524 *encoded_xml += autofill_request_xml.Str().c_str(); |
| 556 | 525 |
| 557 return true; | 526 return true; |
| 558 } | 527 } |
| 559 | 528 |
| 560 // static | 529 // static |
| 561 void FormStructure::ParseQueryResponse( | 530 void FormStructure::ParseQueryResponse( |
| 562 const std::string& response_xml, | 531 const std::string& response_xml, |
| 563 const std::vector<FormStructure*>& forms, | 532 const std::vector<FormStructure*>& forms, |
| 564 autofill::AutocheckoutPageMetaData* page_meta_data, | |
| 565 const AutofillMetrics& metric_logger) { | 533 const AutofillMetrics& metric_logger) { |
| 566 metric_logger.LogServerQueryMetric(AutofillMetrics::QUERY_RESPONSE_RECEIVED); | 534 metric_logger.LogServerQueryMetric(AutofillMetrics::QUERY_RESPONSE_RECEIVED); |
| 567 | 535 |
| 568 // Parse the field types from the server response to the query. | 536 // Parse the field types from the server response to the query. |
| 569 std::vector<AutofillServerFieldInfo> field_infos; | 537 std::vector<AutofillServerFieldInfo> field_infos; |
| 570 UploadRequired upload_required; | 538 UploadRequired upload_required; |
| 571 std::string experiment_id; | 539 std::string experiment_id; |
| 572 AutofillQueryXmlParser parse_handler(&field_infos, | 540 AutofillQueryXmlParser parse_handler(&field_infos, |
| 573 &upload_required, | 541 &upload_required, |
| 574 &experiment_id, | 542 &experiment_id); |
| 575 page_meta_data); | |
| 576 buzz::XmlParser parser(&parse_handler); | 543 buzz::XmlParser parser(&parse_handler); |
| 577 parser.Parse(response_xml.c_str(), response_xml.length(), true); | 544 parser.Parse(response_xml.c_str(), response_xml.length(), true); |
| 578 if (!parse_handler.succeeded()) | 545 if (!parse_handler.succeeded()) |
| 579 return; | 546 return; |
| 580 | 547 |
| 581 metric_logger.LogServerQueryMetric(AutofillMetrics::QUERY_RESPONSE_PARSED); | 548 metric_logger.LogServerQueryMetric(AutofillMetrics::QUERY_RESPONSE_PARSED); |
| 582 metric_logger.LogServerExperimentIdForQuery(experiment_id); | 549 metric_logger.LogServerExperimentIdForQuery(experiment_id); |
| 583 | 550 |
| 584 bool heuristics_detected_fillable_field = false; | 551 bool heuristics_detected_fillable_field = false; |
| 585 bool query_response_overrode_heuristics = false; | 552 bool query_response_overrode_heuristics = false; |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 host = source_url_.host(); | 652 host = source_url_.host(); |
| 686 } | 653 } |
| 687 | 654 |
| 688 std::string form_string = scheme + "://" + host + "&" + | 655 std::string form_string = scheme + "://" + host + "&" + |
| 689 UTF16ToUTF8(form_name_) + | 656 UTF16ToUTF8(form_name_) + |
| 690 form_signature_field_names_; | 657 form_signature_field_names_; |
| 691 | 658 |
| 692 return Hash64Bit(form_string); | 659 return Hash64Bit(form_string); |
| 693 } | 660 } |
| 694 | 661 |
| 695 bool FormStructure::IsAutocheckoutEnabled() const { | |
| 696 return !autocheckout_url_prefix_.empty(); | |
| 697 } | |
| 698 | |
| 699 bool FormStructure::ShouldSkipField(const FormFieldData& field) const { | 662 bool FormStructure::ShouldSkipField(const FormFieldData& field) const { |
| 700 return (field.is_checkable || field.form_control_type == "password") && | 663 return (field.is_checkable || field.form_control_type == "password"); |
| 701 !IsAutocheckoutEnabled(); | |
| 702 } | 664 } |
| 703 | 665 |
| 704 size_t FormStructure::RequiredFillableFields() const { | 666 size_t FormStructure::RequiredFillableFields() const { |
| 705 return IsAutocheckoutEnabled() ? 0 : kRequiredAutofillFields; | 667 return kRequiredAutofillFields; |
| 706 } | 668 } |
| 707 | 669 |
| 708 bool FormStructure::IsAutofillable(bool require_method_post) const { | 670 bool FormStructure::IsAutofillable(bool require_method_post) const { |
| 709 if (autofill_count() < RequiredFillableFields()) | 671 if (autofill_count() < RequiredFillableFields()) |
| 710 return false; | 672 return false; |
| 711 | 673 |
| 712 return ShouldBeParsed(require_method_post); | 674 return ShouldBeParsed(require_method_post); |
| 713 } | 675 } |
| 714 | 676 |
| 715 void FormStructure::UpdateAutofillCount() { | 677 void FormStructure::UpdateAutofillCount() { |
| 716 autofill_count_ = 0; | 678 autofill_count_ = 0; |
| 717 for (std::vector<AutofillField*>::const_iterator iter = begin(); | 679 for (std::vector<AutofillField*>::const_iterator iter = begin(); |
| 718 iter != end(); ++iter) { | 680 iter != end(); ++iter) { |
| 719 AutofillField* field = *iter; | 681 AutofillField* field = *iter; |
| 720 if (field && field->IsFieldFillable()) | 682 if (field && field->IsFieldFillable()) |
| 721 ++autofill_count_; | 683 ++autofill_count_; |
| 722 } | 684 } |
| 723 } | 685 } |
| 724 | 686 |
| 725 bool FormStructure::ShouldBeParsed(bool require_method_post) const { | 687 bool FormStructure::ShouldBeParsed(bool require_method_post) const { |
| 726 if (active_field_count() < RequiredFillableFields()) | 688 if (active_field_count() < RequiredFillableFields()) |
| 727 return false; | 689 return false; |
| 728 | 690 |
| 729 // Rule out http(s)://*/search?... | 691 // Rule out http(s)://*/search?... |
| 730 // e.g. http://www.google.com/search?q=... | 692 // e.g. http://www.google.com/search?q=... |
| 731 // http://search.yahoo.com/search?p=... | 693 // http://search.yahoo.com/search?p=... |
| 732 if (target_url_.path() == "/search") | 694 if (target_url_.path() == "/search") |
| 733 return false; | 695 return false; |
| 734 | 696 |
| 735 if (!IsAutocheckoutEnabled()) { | 697 bool has_text_field = false; |
| 736 // Make sure there is at least one text field when Autocheckout is | 698 for (std::vector<AutofillField*>::const_iterator it = begin(); |
| 737 // not enabled. | 699 it != end() && !has_text_field; ++it) { |
| 738 bool has_text_field = false; | 700 has_text_field |= (*it)->form_control_type != "select-one"; |
| 739 for (std::vector<AutofillField*>::const_iterator it = begin(); | |
| 740 it != end() && !has_text_field; ++it) { | |
| 741 has_text_field |= (*it)->form_control_type != "select-one"; | |
| 742 } | |
| 743 if (!has_text_field) | |
| 744 return false; | |
| 745 } | 701 } |
| 702 if (!has_text_field) |
| 703 return false; |
| 746 | 704 |
| 747 return !require_method_post || (method_ == POST); | 705 return !require_method_post || (method_ == POST); |
| 748 } | 706 } |
| 749 | 707 |
| 750 bool FormStructure::ShouldBeCrowdsourced() const { | 708 bool FormStructure::ShouldBeCrowdsourced() const { |
| 751 // Allow all forms in Autocheckout flow to be crowdsourced. | 709 return !has_author_specified_types_ && ShouldBeParsed(true); |
| 752 return (!has_author_specified_types_ && ShouldBeParsed(true)) || | |
| 753 IsAutocheckoutEnabled(); | |
| 754 } | 710 } |
| 755 | 711 |
| 756 void FormStructure::UpdateFromCache(const FormStructure& cached_form) { | 712 void FormStructure::UpdateFromCache(const FormStructure& cached_form) { |
| 757 // Map from field signatures to cached fields. | 713 // Map from field signatures to cached fields. |
| 758 std::map<std::string, const AutofillField*> cached_fields; | 714 std::map<std::string, const AutofillField*> cached_fields; |
| 759 for (size_t i = 0; i < cached_form.field_count(); ++i) { | 715 for (size_t i = 0; i < cached_form.field_count(); ++i) { |
| 760 const AutofillField* field = cached_form.field(i); | 716 const AutofillField* field = cached_form.field(i); |
| 761 cached_fields[field->FieldSignature()] = field; | 717 cached_fields[field->FieldSignature()] = field; |
| 762 } | 718 } |
| 763 | 719 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 775 field->value = base::string16(); | 731 field->value = base::string16(); |
| 776 } | 732 } |
| 777 | 733 |
| 778 field->set_heuristic_type(cached_field->second->heuristic_type()); | 734 field->set_heuristic_type(cached_field->second->heuristic_type()); |
| 779 field->set_server_type(cached_field->second->server_type()); | 735 field->set_server_type(cached_field->second->server_type()); |
| 780 } | 736 } |
| 781 } | 737 } |
| 782 | 738 |
| 783 UpdateAutofillCount(); | 739 UpdateAutofillCount(); |
| 784 | 740 |
| 785 filled_by_autocheckout_ = cached_form.filled_by_autocheckout(); | |
| 786 server_experiment_id_ = cached_form.server_experiment_id(); | 741 server_experiment_id_ = cached_form.server_experiment_id(); |
| 787 | 742 |
| 788 // The form signature should match between query and upload requests to the | 743 // The form signature should match between query and upload requests to the |
| 789 // server. On many websites, form elements are dynamically added, removed, or | 744 // server. On many websites, form elements are dynamically added, removed, or |
| 790 // rearranged via JavaScript between page load and form submission, so we | 745 // rearranged via JavaScript between page load and form submission, so we |
| 791 // copy over the |form_signature_field_names_| corresponding to the query | 746 // copy over the |form_signature_field_names_| corresponding to the query |
| 792 // request. | 747 // request. |
| 793 DCHECK_EQ(cached_form.form_name_, form_name_); | 748 DCHECK_EQ(cached_form.form_name_, form_name_); |
| 794 DCHECK_EQ(cached_form.source_url_, source_url_); | 749 DCHECK_EQ(cached_form.source_url_, source_url_); |
| 795 DCHECK_EQ(cached_form.target_url_, target_url_); | 750 DCHECK_EQ(cached_form.target_url_, target_url_); |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1250 field != fields_.end(); ++field) { | 1205 field != fields_.end(); ++field) { |
| 1251 FieldTypeGroup field_type_group = (*field)->Type().group(); | 1206 FieldTypeGroup field_type_group = (*field)->Type().group(); |
| 1252 if (field_type_group == CREDIT_CARD) | 1207 if (field_type_group == CREDIT_CARD) |
| 1253 (*field)->set_section((*field)->section() + "-cc"); | 1208 (*field)->set_section((*field)->section() + "-cc"); |
| 1254 else | 1209 else |
| 1255 (*field)->set_section((*field)->section() + "-default"); | 1210 (*field)->set_section((*field)->section() + "-default"); |
| 1256 } | 1211 } |
| 1257 } | 1212 } |
| 1258 | 1213 |
| 1259 } // namespace autofill | 1214 } // namespace autofill |
| OLD | NEW |