OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/autofill/form_structure.h" | 5 #include "chrome/browser/autofill/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 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 return UNKNOWN_TYPE; | 220 return UNKNOWN_TYPE; |
221 } | 221 } |
222 | 222 |
223 } // namespace | 223 } // namespace |
224 | 224 |
225 FormStructure::FormStructure(const FormData& form) | 225 FormStructure::FormStructure(const FormData& form) |
226 : form_name_(form.name), | 226 : form_name_(form.name), |
227 source_url_(form.origin), | 227 source_url_(form.origin), |
228 target_url_(form.action), | 228 target_url_(form.action), |
229 autofill_count_(0), | 229 autofill_count_(0), |
| 230 checkable_field_count_(0), |
230 upload_required_(USE_UPLOAD_RATES), | 231 upload_required_(USE_UPLOAD_RATES), |
231 server_experiment_id_("no server response"), | 232 server_experiment_id_("no server response"), |
232 has_author_specified_types_(false) { | 233 has_author_specified_types_(false) { |
233 // Copy the form fields. | 234 // Copy the form fields. |
234 std::map<string16, size_t> unique_names; | 235 std::map<string16, size_t> unique_names; |
235 for (std::vector<FormFieldData>::const_iterator field = | 236 for (std::vector<FormFieldData>::const_iterator field = |
236 form.fields.begin(); | 237 form.fields.begin(); |
237 field != form.fields.end(); field++) { | 238 field != form.fields.end(); field++) { |
238 // Add all supported form fields (including with empty names) to the | 239 // Skipping checkable elements when flag is not set, else these fields will |
239 // signature. This is a requirement for Autofill servers. | 240 // interfere with existing field signatures with Autofill servers. |
240 form_signature_field_names_.append("&"); | 241 // TODO(ramankk): Add checkable elements only on whitelisted pages |
241 form_signature_field_names_.append(UTF16ToUTF8(field->name)); | 242 if (!field->is_checkable || |
| 243 CommandLine::ForCurrentProcess()->HasSwitch( |
| 244 switches::kEnableExperimentalFormFilling)) { |
| 245 // Add all supported form fields (including with empty names) to the |
| 246 // signature. This is a requirement for Autofill servers. |
| 247 form_signature_field_names_.append("&"); |
| 248 form_signature_field_names_.append(UTF16ToUTF8(field->name)); |
| 249 } |
242 | 250 |
243 // Generate a unique name for this field by appending a counter to the name. | 251 // Generate a unique name for this field by appending a counter to the name. |
244 // Make sure to prepend the counter with a non-numeric digit so that we are | 252 // Make sure to prepend the counter with a non-numeric digit so that we are |
245 // guaranteed to avoid collisions. | 253 // guaranteed to avoid collisions. |
246 if (!unique_names.count(field->name)) | 254 if (!unique_names.count(field->name)) |
247 unique_names[field->name] = 1; | 255 unique_names[field->name] = 1; |
248 else | 256 else |
249 ++unique_names[field->name]; | 257 ++unique_names[field->name]; |
250 string16 unique_name = field->name + ASCIIToUTF16("_") + | 258 string16 unique_name = field->name + ASCIIToUTF16("_") + |
251 base::IntToString16(unique_names[field->name]); | 259 base::IntToString16(unique_names[field->name]); |
252 fields_.push_back(new AutofillField(*field, unique_name)); | 260 fields_.push_back(new AutofillField(*field, unique_name)); |
| 261 |
| 262 if (field->is_checkable) |
| 263 ++checkable_field_count_; |
253 } | 264 } |
254 | 265 |
255 std::string method = UTF16ToUTF8(form.method); | 266 std::string method = UTF16ToUTF8(form.method); |
256 if (StringToLowerASCII(method) == kFormMethodPost) { | 267 if (StringToLowerASCII(method) == kFormMethodPost) { |
257 method_ = POST; | 268 method_ = POST; |
258 } else { | 269 } else { |
259 // Either the method is 'get', or we don't know. In this case we default | 270 // Either the method is 'get', or we don't know. In this case we default |
260 // to GET. | 271 // to GET. |
261 method_ = GET; | 272 method_ = GET; |
262 } | 273 } |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 return true; | 410 return true; |
400 } | 411 } |
401 | 412 |
402 // static | 413 // static |
403 void FormStructure::ParseQueryResponse(const std::string& response_xml, | 414 void FormStructure::ParseQueryResponse(const std::string& response_xml, |
404 const std::vector<FormStructure*>& forms, | 415 const std::vector<FormStructure*>& forms, |
405 const AutofillMetrics& metric_logger) { | 416 const AutofillMetrics& metric_logger) { |
406 metric_logger.LogServerQueryMetric(AutofillMetrics::QUERY_RESPONSE_RECEIVED); | 417 metric_logger.LogServerQueryMetric(AutofillMetrics::QUERY_RESPONSE_RECEIVED); |
407 | 418 |
408 // Parse the field types from the server response to the query. | 419 // Parse the field types from the server response to the query. |
409 std::vector<AutofillFieldType> field_types; | 420 std::vector<AutofillServerFieldInfo> field_infos; |
410 UploadRequired upload_required; | 421 UploadRequired upload_required; |
411 std::string experiment_id; | 422 std::string experiment_id; |
412 AutofillQueryXmlParser parse_handler(&field_types, &upload_required, | 423 AutofillQueryXmlParser parse_handler(&field_infos, &upload_required, |
413 &experiment_id); | 424 &experiment_id); |
414 buzz::XmlParser parser(&parse_handler); | 425 buzz::XmlParser parser(&parse_handler); |
415 parser.Parse(response_xml.c_str(), response_xml.length(), true); | 426 parser.Parse(response_xml.c_str(), response_xml.length(), true); |
416 if (!parse_handler.succeeded()) | 427 if (!parse_handler.succeeded()) |
417 return; | 428 return; |
418 | 429 |
419 metric_logger.LogServerQueryMetric(AutofillMetrics::QUERY_RESPONSE_PARSED); | 430 metric_logger.LogServerQueryMetric(AutofillMetrics::QUERY_RESPONSE_PARSED); |
420 metric_logger.LogServerExperimentIdForQuery(experiment_id); | 431 metric_logger.LogServerExperimentIdForQuery(experiment_id); |
421 | 432 |
422 bool heuristics_detected_fillable_field = false; | 433 bool heuristics_detected_fillable_field = false; |
423 bool query_response_overrode_heuristics = false; | 434 bool query_response_overrode_heuristics = false; |
424 | 435 |
425 // Copy the field types into the actual form. | 436 // Copy the field types into the actual form. |
426 std::vector<AutofillFieldType>::iterator current_type = field_types.begin(); | 437 std::vector<AutofillServerFieldInfo>::iterator current_info = |
| 438 field_infos.begin(); |
427 for (std::vector<FormStructure*>::const_iterator iter = forms.begin(); | 439 for (std::vector<FormStructure*>::const_iterator iter = forms.begin(); |
428 iter != forms.end(); ++iter) { | 440 iter != forms.end(); ++iter) { |
429 FormStructure* form = *iter; | 441 FormStructure* form = *iter; |
430 form->upload_required_ = upload_required; | 442 form->upload_required_ = upload_required; |
431 form->server_experiment_id_ = experiment_id; | 443 form->server_experiment_id_ = experiment_id; |
432 | 444 |
433 for (std::vector<AutofillField*>::iterator field = form->fields_.begin(); | 445 for (std::vector<AutofillField*>::iterator field = form->fields_.begin(); |
434 field != form->fields_.end(); ++field, ++current_type) { | 446 field != form->fields_.end(); ++field, ++current_info) { |
435 // In some cases *successful* response does not return all the fields. | 447 // In some cases *successful* response does not return all the fields. |
436 // Quit the update of the types then. | 448 // Quit the update of the types then. |
437 if (current_type == field_types.end()) | 449 if (current_info == field_infos.end()) |
438 break; | 450 break; |
439 | 451 |
440 // UNKNOWN_TYPE is reserved for use by the client. | 452 // UNKNOWN_TYPE is reserved for use by the client. |
441 DCHECK_NE(*current_type, UNKNOWN_TYPE); | 453 DCHECK_NE(current_info->field_type, UNKNOWN_TYPE); |
442 | 454 |
443 AutofillFieldType heuristic_type = (*field)->type(); | 455 AutofillFieldType heuristic_type = (*field)->type(); |
444 if (heuristic_type != UNKNOWN_TYPE) | 456 if (heuristic_type != UNKNOWN_TYPE) |
445 heuristics_detected_fillable_field = true; | 457 heuristics_detected_fillable_field = true; |
446 | 458 |
447 (*field)->set_server_type(*current_type); | 459 (*field)->set_server_type(current_info->field_type); |
448 if (heuristic_type != (*field)->type()) | 460 if (heuristic_type != (*field)->type()) |
449 query_response_overrode_heuristics = true; | 461 query_response_overrode_heuristics = true; |
| 462 |
| 463 // Copy default value into the field if available. |
| 464 if (!current_info->default_value.empty()) |
| 465 (*field)->set_default_value(current_info->default_value); |
450 } | 466 } |
451 | 467 |
452 form->UpdateAutofillCount(); | 468 form->UpdateAutofillCount(); |
453 form->IdentifySections(false); | 469 form->IdentifySections(false); |
454 } | 470 } |
455 | 471 |
456 AutofillMetrics::ServerQueryMetric metric; | 472 AutofillMetrics::ServerQueryMetric metric; |
457 if (query_response_overrode_heuristics) { | 473 if (query_response_overrode_heuristics) { |
458 if (heuristics_detected_fillable_field) { | 474 if (heuristics_detected_fillable_field) { |
459 metric = AutofillMetrics::QUERY_RESPONSE_OVERRODE_LOCAL_HEURISTICS; | 475 metric = AutofillMetrics::QUERY_RESPONSE_OVERRODE_LOCAL_HEURISTICS; |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
544 } | 560 } |
545 } | 561 } |
546 | 562 |
547 bool FormStructure::ShouldBeParsed(bool require_method_post) const { | 563 bool FormStructure::ShouldBeParsed(bool require_method_post) const { |
548 // TODO(ramankk): Remove this check once we have better way of identifying the | 564 // TODO(ramankk): Remove this check once we have better way of identifying the |
549 // cases to trigger experimental form filling. | 565 // cases to trigger experimental form filling. |
550 if (CommandLine::ForCurrentProcess()->HasSwitch( | 566 if (CommandLine::ForCurrentProcess()->HasSwitch( |
551 switches::kEnableExperimentalFormFilling)) | 567 switches::kEnableExperimentalFormFilling)) |
552 return true; | 568 return true; |
553 | 569 |
554 if (field_count() < kRequiredFillableFields) | 570 // Ignore counting checkable elements towards minimum number of elements |
| 571 // required to parse. This avoids trying to crowdsource forms with few text |
| 572 // or select elements. |
| 573 if ((field_count() - checkable_field_count()) < kRequiredFillableFields) |
555 return false; | 574 return false; |
556 | 575 |
557 // Rule out http(s)://*/search?... | 576 // Rule out http(s)://*/search?... |
558 // e.g. http://www.google.com/search?q=... | 577 // e.g. http://www.google.com/search?q=... |
559 // http://search.yahoo.com/search?p=... | 578 // http://search.yahoo.com/search?p=... |
560 if (target_url_.path() == "/search") | 579 if (target_url_.path() == "/search") |
561 return false; | 580 return false; |
562 | 581 |
563 // Make sure there as at least one text field. | 582 // Make sure there as at least one text field. |
564 bool has_text_field = false; | 583 bool has_text_field = false; |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
806 | 825 |
807 AutofillField* FormStructure::field(size_t index) { | 826 AutofillField* FormStructure::field(size_t index) { |
808 return const_cast<AutofillField*>( | 827 return const_cast<AutofillField*>( |
809 static_cast<const FormStructure*>(this)->field(index)); | 828 static_cast<const FormStructure*>(this)->field(index)); |
810 } | 829 } |
811 | 830 |
812 size_t FormStructure::field_count() const { | 831 size_t FormStructure::field_count() const { |
813 return fields_.size(); | 832 return fields_.size(); |
814 } | 833 } |
815 | 834 |
| 835 size_t FormStructure::checkable_field_count() const { |
| 836 return checkable_field_count_; |
| 837 } |
| 838 |
816 std::string FormStructure::server_experiment_id() const { | 839 std::string FormStructure::server_experiment_id() const { |
817 return server_experiment_id_; | 840 return server_experiment_id_; |
818 } | 841 } |
819 | 842 |
820 FormData FormStructure::ToFormData() const { | 843 FormData FormStructure::ToFormData() const { |
821 // |data.user_submitted| will always be false. | 844 // |data.user_submitted| will always be false. |
822 FormData data; | 845 FormData data; |
823 data.name = form_name_; | 846 data.name = form_name_; |
824 data.origin = source_url_; | 847 data.origin = source_url_; |
825 data.action = target_url_; | 848 data.action = target_url_; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
877 // Do not send requests for forms with more than this many fields, as they are | 900 // Do not send requests for forms with more than this many fields, as they are |
878 // near certainly not valid/auto-fillable. | 901 // near certainly not valid/auto-fillable. |
879 const size_t kMaxFieldsOnTheForm = 48; | 902 const size_t kMaxFieldsOnTheForm = 48; |
880 if (field_count() > kMaxFieldsOnTheForm) | 903 if (field_count() > kMaxFieldsOnTheForm) |
881 return false; | 904 return false; |
882 | 905 |
883 // Add the child nodes for the form fields. | 906 // Add the child nodes for the form fields. |
884 for (size_t index = 0; index < field_count(); ++index) { | 907 for (size_t index = 0; index < field_count(); ++index) { |
885 const AutofillField* field = fields_[index]; | 908 const AutofillField* field = fields_[index]; |
886 if (request_type == FormStructure::UPLOAD) { | 909 if (request_type == FormStructure::UPLOAD) { |
| 910 // Don't upload checkable fields. |
| 911 if (field->is_checkable) |
| 912 continue; |
| 913 |
887 FieldTypeSet types = field->possible_types(); | 914 FieldTypeSet types = field->possible_types(); |
888 // |types| could be empty in unit-tests only. | 915 // |types| could be empty in unit-tests only. |
889 for (FieldTypeSet::iterator field_type = types.begin(); | 916 for (FieldTypeSet::iterator field_type = types.begin(); |
890 field_type != types.end(); ++field_type) { | 917 field_type != types.end(); ++field_type) { |
891 buzz::XmlElement *field_element = new buzz::XmlElement( | 918 buzz::XmlElement *field_element = new buzz::XmlElement( |
892 buzz::QName(kXMLElementField)); | 919 buzz::QName(kXMLElementField)); |
893 | 920 |
894 field_element->SetAttr(buzz::QName(kAttributeSignature), | 921 field_element->SetAttr(buzz::QName(kAttributeSignature), |
895 field->FieldSignature()); | 922 field->FieldSignature()); |
896 field_element->SetAttr(buzz::QName(kAttributeAutofillType), | 923 field_element->SetAttr(buzz::QName(kAttributeAutofillType), |
897 base::IntToString(*field_type)); | 924 base::IntToString(*field_type)); |
898 encompassing_xml_element->AddElement(field_element); | 925 encompassing_xml_element->AddElement(field_element); |
899 } | 926 } |
900 } else { | 927 } else { |
| 928 // Skip putting checkable fields in the request if the flag is not set. |
| 929 if (field->is_checkable && |
| 930 !CommandLine::ForCurrentProcess()->HasSwitch( |
| 931 switches::kEnableExperimentalFormFilling)) |
| 932 continue; |
| 933 |
901 buzz::XmlElement *field_element = new buzz::XmlElement( | 934 buzz::XmlElement *field_element = new buzz::XmlElement( |
902 buzz::QName(kXMLElementField)); | 935 buzz::QName(kXMLElementField)); |
903 field_element->SetAttr(buzz::QName(kAttributeSignature), | 936 field_element->SetAttr(buzz::QName(kAttributeSignature), |
904 field->FieldSignature()); | 937 field->FieldSignature()); |
905 encompassing_xml_element->AddElement(field_element); | 938 encompassing_xml_element->AddElement(field_element); |
906 } | 939 } |
907 } | 940 } |
908 return true; | 941 return true; |
909 } | 942 } |
910 | 943 |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1071 for (std::vector<AutofillField*>::iterator field = fields_.begin(); | 1104 for (std::vector<AutofillField*>::iterator field = fields_.begin(); |
1072 field != fields_.end(); ++field) { | 1105 field != fields_.end(); ++field) { |
1073 AutofillType::FieldTypeGroup field_type_group = | 1106 AutofillType::FieldTypeGroup field_type_group = |
1074 AutofillType((*field)->type()).group(); | 1107 AutofillType((*field)->type()).group(); |
1075 if (field_type_group == AutofillType::CREDIT_CARD) | 1108 if (field_type_group == AutofillType::CREDIT_CARD) |
1076 (*field)->set_section((*field)->section() + "-cc"); | 1109 (*field)->set_section((*field)->section() + "-cc"); |
1077 else | 1110 else |
1078 (*field)->set_section((*field)->section() + "-default"); | 1111 (*field)->set_section((*field)->section() + "-default"); |
1079 } | 1112 } |
1080 } | 1113 } |
OLD | NEW |