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 <map> | |
| 7 #include <utility> | 8 #include <utility> |
| 8 | 9 |
| 9 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| 10 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 11 #include "base/i18n/case_conversion.h" | 12 #include "base/i18n/case_conversion.h" |
| 12 #include "base/logging.h" | 13 #include "base/logging.h" |
| 13 #include "base/memory/scoped_ptr.h" | 14 #include "base/memory/scoped_ptr.h" |
| 14 #include "base/metrics/field_trial.h" | 15 #include "base/metrics/field_trial.h" |
| 15 #include "base/sha1.h" | 16 #include "base/sha1.h" |
| 16 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 17 #include "base/strings/string_split.h" | 18 #include "base/strings/string_split.h" |
| 18 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
| 19 #include "base/strings/stringprintf.h" | 20 #include "base/strings/stringprintf.h" |
| 20 #include "base/strings/utf_string_conversions.h" | 21 #include "base/strings/utf_string_conversions.h" |
| 21 #include "base/time/time.h" | 22 #include "base/time/time.h" |
| 22 #include "components/autofill/core/browser/autofill_metrics.h" | 23 #include "components/autofill/core/browser/autofill_metrics.h" |
| 24 #include "components/autofill/core/browser/autofill_server_field_info.h" | |
| 23 #include "components/autofill/core/browser/autofill_type.h" | 25 #include "components/autofill/core/browser/autofill_type.h" |
| 24 #include "components/autofill/core/browser/autofill_xml_parser.h" | 26 #include "components/autofill/core/browser/autofill_xml_parser.h" |
| 25 #include "components/autofill/core/browser/field_types.h" | 27 #include "components/autofill/core/browser/field_types.h" |
| 26 #include "components/autofill/core/browser/form_field.h" | 28 #include "components/autofill/core/browser/form_field.h" |
| 27 #include "components/autofill/core/common/autofill_constants.h" | 29 #include "components/autofill/core/common/autofill_constants.h" |
| 28 #include "components/autofill/core/common/form_data.h" | 30 #include "components/autofill/core/common/form_data.h" |
| 29 #include "components/autofill/core/common/form_data_predictions.h" | 31 #include "components/autofill/core/common/form_data_predictions.h" |
| 30 #include "components/autofill/core/common/form_field_data.h" | 32 #include "components/autofill/core/common/form_field_data.h" |
| 31 #include "components/autofill/core/common/form_field_data_predictions.h" | 33 #include "components/autofill/core/common/form_field_data_predictions.h" |
| 32 #include "components/rappor/rappor_service.h" | 34 #include "components/rappor/rappor_service.h" |
| 33 #include "components/rappor/rappor_utils.h" | 35 #include "components/rappor/rappor_utils.h" |
| 36 #include "third_party/libxml/chromium/libxml_utils.h" | |
| 34 #include "third_party/re2/re2/re2.h" | 37 #include "third_party/re2/re2/re2.h" |
| 35 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h" | |
| 36 | 38 |
| 37 namespace autofill { | 39 namespace autofill { |
| 38 namespace { | 40 namespace { |
| 39 | 41 |
| 40 // XML elements and attributes. | 42 // XML elements and attributes. |
| 41 const char kAttributeAutofillUsed[] = "autofillused"; | 43 const char kAttributeAutofillUsed[] = "autofillused"; |
| 42 const char kAttributeAutofillType[] = "autofilltype"; | 44 const char kAttributeAutofillType[] = "autofilltype"; |
| 43 const char kAttributeClientVersion[] = "clientversion"; | 45 const char kAttributeClientVersion[] = "clientversion"; |
| 44 const char kAttributeDataPresent[] = "datapresent"; | 46 const char kAttributeDataPresent[] = "datapresent"; |
| 45 const char kAttributeFieldID[] = "fieldid"; | 47 const char kAttributeFieldID[] = "fieldid"; |
| 46 const char kAttributeFieldType[] = "fieldtype"; | 48 const char kAttributeFieldType[] = "fieldtype"; |
| 47 const char kAttributeFieldLabel[] = "label"; | 49 const char kAttributeFieldLabel[] = "label"; |
| 48 const char kAttributeFormSignature[] = "formsignature"; | 50 const char kAttributeFormSignature[] = "formsignature"; |
| 49 const char kAttributeFormActionHostSignature[] = "actionsignature"; | 51 const char kAttributeFormActionHostSignature[] = "actionsignature"; |
| 50 const char kAttributeFormName[] = "formname"; | 52 const char kAttributeFormName[] = "formname"; |
| 51 const char kAttributeName[] = "name"; | 53 const char kAttributeName[] = "name"; |
| 52 const char kAttributeSignature[] = "signature"; | 54 const char kAttributeSignature[] = "signature"; |
| 53 const char kAttributeControlType[] = "type"; | 55 const char kAttributeControlType[] = "type"; |
| 54 const char kAttributeAutocomplete[] = "autocomplete"; | 56 const char kAttributeAutocomplete[] = "autocomplete"; |
| 55 const char kAttributeLoginFormSignature[] = "loginformsignature"; | 57 const char kAttributeLoginFormSignature[] = "loginformsignature"; |
| 56 const char kClientVersion[] = "6.1.1715.1442/en (GGLL)"; | 58 const char kClientVersion[] = "6.1.1715.1442/en (GGLL)"; |
| 57 const char kXMLDeclaration[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; | |
| 58 const char kXMLElementAutofillQuery[] = "autofillquery"; | 59 const char kXMLElementAutofillQuery[] = "autofillquery"; |
| 59 const char kXMLElementAutofillUpload[] = "autofillupload"; | 60 const char kXMLElementAutofillUpload[] = "autofillupload"; |
| 60 const char kXMLElementFieldAssignments[] = "fieldassignments"; | 61 const char kXMLElementFieldAssignments[] = "fieldassignments"; |
| 61 const char kXMLElementField[] = "field"; | 62 const char kXMLElementField[] = "field"; |
| 62 const char kXMLElementFields[] = "fields"; | 63 const char kXMLElementFields[] = "fields"; |
| 63 const char kXMLElementForm[] = "form"; | 64 const char kXMLElementForm[] = "form"; |
| 64 const char kBillingMode[] = "billing"; | 65 const char kBillingMode[] = "billing"; |
| 65 const char kShippingMode[] = "shipping"; | 66 const char kShippingMode[] = "shipping"; |
| 66 | 67 |
| 67 // Strip away >= 5 consecutive digits. | 68 // Strip away >= 5 consecutive digits. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 108 // Print all meaningfull bytes into a string. | 109 // Print all meaningfull bytes into a string. |
| 109 std::string data_presence; | 110 std::string data_presence; |
| 110 data_presence.reserve(data_end * 2 + 1); | 111 data_presence.reserve(data_end * 2 + 1); |
| 111 for (size_t i = 0; i < data_end; ++i) { | 112 for (size_t i = 0; i < data_end; ++i) { |
| 112 base::StringAppendF(&data_presence, "%02x", bit_field[i]); | 113 base::StringAppendF(&data_presence, "%02x", bit_field[i]); |
| 113 } | 114 } |
| 114 | 115 |
| 115 return data_presence; | 116 return data_presence; |
| 116 } | 117 } |
| 117 | 118 |
| 118 // Helper for |EncodeFormRequest()| and |EncodeFieldForUpload| that returns an | 119 // Assumes that |xml_writer| has just started an element with name |
| 119 // XmlElement for the given field in query xml, and also add it to the parent | 120 // |kXMLElementField|, and adds some field attributes based on |field|. Returns |
| 120 // XmlElement. | 121 // true on success, false on failure. |
| 121 buzz::XmlElement* EncodeFieldForQuery(const AutofillField& field, | 122 bool EncodeFieldForQuery(const AutofillField& field, XmlWriter* xml_writer) { |
| 122 buzz::XmlElement* parent) { | 123 if (!xml_writer->AddAttribute(kAttributeSignature, field.FieldSignature())) |
| 123 buzz::XmlElement* field_element = new buzz::XmlElement( | 124 return false; |
| 124 buzz::QName(kXMLElementField)); | |
| 125 field_element->SetAttr(buzz::QName(kAttributeSignature), | |
| 126 field.FieldSignature()); | |
| 127 if (IsAutofillFieldMetadataEnabled()) { | 125 if (IsAutofillFieldMetadataEnabled()) { |
| 128 if (!field.name.empty()) { | 126 if (!field.name.empty()) { |
| 129 field_element->SetAttr(buzz::QName(kAttributeName), | 127 if (!xml_writer->AddAttribute(kAttributeName, |
| 130 base::UTF16ToUTF8(field.name)); | 128 base::UTF16ToUTF8(field.name))) |
| 129 return false; | |
| 131 } | 130 } |
| 132 field_element->SetAttr(buzz::QName(kAttributeControlType), | 131 if (!xml_writer->AddAttribute(kAttributeControlType, |
| 133 field.form_control_type); | 132 field.form_control_type)) |
| 133 return false; | |
| 134 if (!field.label.empty()) { | 134 if (!field.label.empty()) { |
| 135 std::string truncated; | 135 std::string truncated; |
| 136 base::TruncateUTF8ToByteSize(base::UTF16ToUTF8(field.label), | 136 base::TruncateUTF8ToByteSize(base::UTF16ToUTF8(field.label), |
| 137 kMaxFieldLabelNumChars, &truncated); | 137 kMaxFieldLabelNumChars, &truncated); |
| 138 field_element->SetAttr(buzz::QName(kAttributeFieldLabel), truncated); | 138 if (!xml_writer->AddAttribute(kAttributeFieldLabel, truncated)) |
| 139 return false; | |
| 139 } | 140 } |
| 140 } | 141 } |
| 141 parent->AddElement(field_element); | 142 return true; |
| 142 return field_element; | |
| 143 } | 143 } |
| 144 | 144 |
| 145 // Helper for |EncodeFormRequest()| that creates XmlElements for the given field | 145 // Uses |xml_writer| to write one tag named |kXMLElementField| for each item in |
| 146 // in upload xml, and also add them to the parent XmlElement. | 146 // |field.possible_types()|, and adds some field attributes based on |field|. |
| 147 void EncodeFieldForUpload(const AutofillField& field, | 147 // Returns true on success, false on failure. |
| 148 buzz::XmlElement* parent) { | 148 bool EncodeFieldForUpload(const AutofillField& field, XmlWriter* xml_writer) { |
| 149 // Don't upload checkable fields. | 149 // Don't upload checkable fields. |
| 150 if (field.is_checkable) | 150 if (field.is_checkable) |
| 151 return; | 151 return true; |
| 152 | 152 |
| 153 ServerFieldTypeSet types = field.possible_types(); | 153 const ServerFieldTypeSet& types = field.possible_types(); |
| 154 // |types| could be empty in unit-tests only. | |
| 155 for (const auto& field_type : types) { | 154 for (const auto& field_type : types) { |
| 156 // We use the same field elements as the query and add a few more below. | 155 if (!xml_writer->StartElement(kXMLElementField)) |
| 157 buzz::XmlElement* field_element = EncodeFieldForQuery(field, parent); | 156 return false; |
| 157 // Add the same field elements as the query and a few more below. | |
| 158 if (!EncodeFieldForQuery(field, xml_writer)) | |
| 159 return false; | |
| 158 | 160 |
| 159 if (IsAutofillFieldMetadataEnabled() && | 161 if (IsAutofillFieldMetadataEnabled() && |
| 160 !field.autocomplete_attribute.empty()) { | 162 !field.autocomplete_attribute.empty()) { |
| 161 field_element->SetAttr(buzz::QName(kAttributeAutocomplete), | 163 if (!xml_writer->AddAttribute(kAttributeAutocomplete, |
| 162 field.autocomplete_attribute); | 164 field.autocomplete_attribute)) |
| 165 return false; | |
| 163 } | 166 } |
| 164 | 167 |
| 165 field_element->SetAttr(buzz::QName(kAttributeAutofillType), | 168 if (!xml_writer->AddAttribute(kAttributeAutofillType, |
| 166 base::IntToString(field_type)); | 169 base::IntToString(field_type))) |
| 170 return false; | |
| 171 if (!xml_writer->EndElement()) | |
| 172 return false; | |
| 167 } | 173 } |
| 174 return true; | |
| 168 } | 175 } |
| 169 | 176 |
| 170 // Helper for |EncodeFormRequest()| that creates XmlElements for the given field | 177 // Uses |xml_writer| to write one tag named |kXMLElementFields| for each item in |
| 171 // in field assignments xml, and also add them to the parent XmlElement. | 178 // |field.possible_types()|, and adds some field attributes based on |field|. |
| 172 void EncodeFieldForFieldAssignments(const AutofillField& field, | 179 // Returns true on success, false on failure. |
| 173 buzz::XmlElement* parent) { | 180 bool EncodeFieldForFieldAssignments(const AutofillField& field, |
| 174 ServerFieldTypeSet types = field.possible_types(); | 181 XmlWriter* xml_writer) { |
| 182 const ServerFieldTypeSet& types = field.possible_types(); | |
| 175 for (const auto& field_type : types) { | 183 for (const auto& field_type : types) { |
| 176 buzz::XmlElement *field_element = new buzz::XmlElement( | 184 if (!xml_writer->StartElement(kXMLElementFields)) |
| 177 buzz::QName(kXMLElementFields)); | 185 return false; |
| 178 | 186 |
| 179 field_element->SetAttr(buzz::QName(kAttributeFieldID), | 187 if (!xml_writer->AddAttribute(kAttributeFieldID, field.FieldSignature())) |
| 180 field.FieldSignature()); | 188 return false; |
| 181 field_element->SetAttr(buzz::QName(kAttributeFieldType), | 189 if (!xml_writer->AddAttribute(kAttributeFieldType, |
| 182 base::IntToString(field_type)); | 190 base::IntToString(field_type))) |
| 183 field_element->SetAttr(buzz::QName(kAttributeName), | 191 return false; |
| 184 base::UTF16ToUTF8(field.name)); | 192 if (!xml_writer->AddAttribute(kAttributeName, |
| 185 parent->AddElement(field_element); | 193 base::UTF16ToUTF8(field.name))) |
| 194 return false; | |
| 195 if (!xml_writer->EndElement()) | |
| 196 return false; | |
| 186 } | 197 } |
| 198 return true; | |
| 187 } | 199 } |
| 188 | 200 |
| 189 // Returns |true| iff the |token| is a type hint for a contact field, as | 201 // Returns |true| iff the |token| is a type hint for a contact field, as |
| 190 // specified in the implementation section of http://is.gd/whatwg_autocomplete | 202 // specified in the implementation section of http://is.gd/whatwg_autocomplete |
| 191 // Note that "fax" and "pager" are intentionally ignored, as Chrome does not | 203 // Note that "fax" and "pager" are intentionally ignored, as Chrome does not |
| 192 // support filling either type of information. | 204 // support filling either type of information. |
| 193 bool IsContactTypeHint(const std::string& token) { | 205 bool IsContactTypeHint(const std::string& token) { |
| 194 return token == "home" || token == "work" || token == "mobile"; | 206 return token == "home" || token == "work" || token == "mobile"; |
| 195 } | 207 } |
| 196 | 208 |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 435 AutofillMetrics::FILLABLE_FORM_CONTAINS_TYPE_HINTS); | 447 AutofillMetrics::FILLABLE_FORM_CONTAINS_TYPE_HINTS); |
| 436 } | 448 } |
| 437 } | 449 } |
| 438 } | 450 } |
| 439 | 451 |
| 440 bool FormStructure::EncodeUploadRequest( | 452 bool FormStructure::EncodeUploadRequest( |
| 441 const ServerFieldTypeSet& available_field_types, | 453 const ServerFieldTypeSet& available_field_types, |
| 442 bool form_was_autofilled, | 454 bool form_was_autofilled, |
| 443 const std::string& login_form_signature, | 455 const std::string& login_form_signature, |
| 444 std::string* encoded_xml) const { | 456 std::string* encoded_xml) const { |
| 457 DCHECK(encoded_xml); | |
| 445 DCHECK(ShouldBeCrowdsourced()); | 458 DCHECK(ShouldBeCrowdsourced()); |
| 446 | 459 |
| 447 // Verify that |available_field_types| agrees with the possible field types we | 460 // Verify that |available_field_types| agrees with the possible field types we |
| 448 // are uploading. | 461 // are uploading. |
| 449 for (const AutofillField* field : *this) { | 462 for (const AutofillField* field : *this) { |
| 450 for (const auto& type : field->possible_types()) { | 463 for (const auto& type : field->possible_types()) { |
| 451 DCHECK(type == UNKNOWN_TYPE || | 464 DCHECK(type == UNKNOWN_TYPE || type == EMPTY_TYPE || |
| 452 type == EMPTY_TYPE || | |
| 453 available_field_types.count(type)); | 465 available_field_types.count(type)); |
| 454 } | 466 } |
| 455 } | 467 } |
| 456 | 468 |
| 457 // Set up the <autofillupload> element and its attributes. | 469 // Set up the <autofillupload> element and its attributes. |
| 458 buzz::XmlElement autofill_request_xml( | 470 XmlWriter xml_writer; |
| 459 (buzz::QName(kXMLElementAutofillUpload))); | 471 xml_writer.StartWriting(); |
| 460 autofill_request_xml.SetAttr(buzz::QName(kAttributeClientVersion), | 472 xml_writer.StopIndenting(); |
| 461 kClientVersion); | 473 if (!xml_writer.StartElement(kXMLElementAutofillUpload)) |
| 462 autofill_request_xml.SetAttr(buzz::QName(kAttributeFormSignature), | 474 return false; |
| 463 FormSignature()); | 475 if (!xml_writer.AddAttribute(kAttributeClientVersion, kClientVersion)) |
| 464 autofill_request_xml.SetAttr(buzz::QName(kAttributeAutofillUsed), | 476 return false; |
| 465 form_was_autofilled ? "true" : "false"); | 477 if (!xml_writer.AddAttribute(kAttributeFormSignature, FormSignature())) |
| 466 autofill_request_xml.SetAttr(buzz::QName(kAttributeDataPresent), | 478 return false; |
| 467 EncodeFieldTypes(available_field_types).c_str()); | 479 if (!xml_writer.AddAttribute(kAttributeAutofillUsed, |
| 480 form_was_autofilled ? "true" : "false")) | |
| 481 return false; | |
| 482 if (!xml_writer.AddAttribute(kAttributeDataPresent, | |
| 483 EncodeFieldTypes(available_field_types))) | |
| 484 return false; | |
| 468 if (IsAutofillFieldMetadataEnabled()) { | 485 if (IsAutofillFieldMetadataEnabled()) { |
| 469 autofill_request_xml.SetAttr(buzz::QName(kAttributeFormActionHostSignature), | 486 if (!xml_writer.AddAttribute(kAttributeFormActionHostSignature, |
| 470 Hash64Bit(target_url_.host())); | 487 Hash64Bit(target_url_.host()))) |
| 471 if(!form_name().empty()) { | 488 return false; |
| 472 autofill_request_xml.SetAttr(buzz::QName(kAttributeFormName), | 489 if (!form_name().empty()) { |
| 473 base::UTF16ToUTF8(form_name())); | 490 if (!xml_writer.AddAttribute(kAttributeFormName, |
| 491 base::UTF16ToUTF8(form_name()))) | |
| 492 return false; | |
| 474 } | 493 } |
| 475 } | 494 } |
| 476 | 495 |
| 477 if (!login_form_signature.empty()) { | 496 if (!login_form_signature.empty()) { |
| 478 autofill_request_xml.SetAttr(buzz::QName(kAttributeLoginFormSignature), | 497 if (!xml_writer.AddAttribute(kAttributeLoginFormSignature, |
| 479 login_form_signature); | 498 login_form_signature)) |
| 499 return false; | |
| 480 } | 500 } |
| 481 | 501 |
| 482 if (!EncodeFormRequest(FormStructure::UPLOAD, &autofill_request_xml)) | 502 if (IsMalformed() || !EncodeFormRequest(FormStructure::UPLOAD, &xml_writer)) |
| 483 return false; // Malformed form, skip it. | 503 return false; // Malformed form, skip it. |
| 504 if (!xml_writer.EndElement()) | |
| 505 return false; | |
| 484 | 506 |
| 485 // Obtain the XML structure as a string. | 507 // Obtain the XML structure as a string. |
| 486 *encoded_xml = kXMLDeclaration; | 508 xml_writer.StopWriting(); |
| 487 *encoded_xml += autofill_request_xml.Str().c_str(); | 509 *encoded_xml = xml_writer.GetWrittenString(); |
| 488 | 510 |
| 489 // To enable this logging, run with the flag --vmodule="form_structure=2". | 511 // To enable this logging, run with the flag --vmodule="form_structure=2". |
| 490 VLOG(2) << "\n" << *encoded_xml; | 512 VLOG(2) << "\n" << *encoded_xml; |
| 491 | 513 |
| 492 return true; | 514 return true; |
| 493 } | 515 } |
| 494 | 516 |
| 495 bool FormStructure::EncodeFieldAssignments( | 517 bool FormStructure::EncodeFieldAssignments( |
| 496 const ServerFieldTypeSet& available_field_types, | 518 const ServerFieldTypeSet& available_field_types, |
| 497 std::string* encoded_xml) const { | 519 std::string* encoded_xml) const { |
| 520 DCHECK(encoded_xml); | |
| 498 DCHECK(ShouldBeCrowdsourced()); | 521 DCHECK(ShouldBeCrowdsourced()); |
| 499 | 522 |
| 500 // Set up the <fieldassignments> element and its attributes. | 523 // Set up the <fieldassignments> element and its attributes. |
| 501 buzz::XmlElement autofill_request_xml( | 524 XmlWriter xml_writer; |
| 502 (buzz::QName(kXMLElementFieldAssignments))); | 525 xml_writer.StartWriting(); |
| 503 autofill_request_xml.SetAttr(buzz::QName(kAttributeFormSignature), | 526 xml_writer.StopIndenting(); |
| 504 FormSignature()); | 527 if (!xml_writer.StartElement(kXMLElementFieldAssignments)) |
| 528 return false; | |
| 529 if (!xml_writer.AddAttribute(kAttributeFormSignature, FormSignature())) | |
| 530 return false; | |
| 505 | 531 |
| 506 if (!EncodeFormRequest(FormStructure::FIELD_ASSIGNMENTS, | 532 if (IsMalformed() || |
| 507 &autofill_request_xml)) | 533 !EncodeFormRequest(FormStructure::FIELD_ASSIGNMENTS, &xml_writer)) { |
| 508 return false; // Malformed form, skip it. | 534 return false; // Malformed form, skip it. |
| 535 } | |
| 536 if (!xml_writer.EndElement()) | |
| 537 return false; | |
| 509 | 538 |
| 510 // Obtain the XML structure as a string. | 539 // Obtain the XML structure as a string. |
| 511 *encoded_xml = kXMLDeclaration; | 540 xml_writer.StopWriting(); |
| 512 *encoded_xml += autofill_request_xml.Str().c_str(); | 541 *encoded_xml = xml_writer.GetWrittenString(); |
| 513 | 542 |
| 514 return true; | 543 return true; |
| 515 } | 544 } |
| 516 | 545 |
| 517 // static | 546 // static |
| 518 bool FormStructure::EncodeQueryRequest( | 547 bool FormStructure::EncodeQueryRequest( |
| 519 const std::vector<FormStructure*>& forms, | 548 const std::vector<FormStructure*>& forms, |
| 520 std::vector<std::string>* encoded_signatures, | 549 std::vector<std::string>* encoded_signatures, |
| 521 std::string* encoded_xml) { | 550 std::string* encoded_xml) { |
| 522 DCHECK(encoded_signatures); | 551 DCHECK(encoded_signatures); |
| 523 DCHECK(encoded_xml); | 552 DCHECK(encoded_xml); |
| 524 encoded_xml->clear(); | |
| 525 encoded_signatures->clear(); | 553 encoded_signatures->clear(); |
| 526 encoded_signatures->reserve(forms.size()); | 554 encoded_signatures->reserve(forms.size()); |
| 527 | 555 |
| 528 // Set up the <autofillquery> element and attributes. | 556 // Set up the <autofillquery> element and attributes. |
| 529 buzz::XmlElement autofill_request_xml( | 557 XmlWriter xml_writer; |
| 530 (buzz::QName(kXMLElementAutofillQuery))); | 558 xml_writer.StartWriting(); |
| 531 autofill_request_xml.SetAttr(buzz::QName(kAttributeClientVersion), | 559 xml_writer.StopIndenting(); |
| 532 kClientVersion); | 560 if (!xml_writer.StartElement(kXMLElementAutofillQuery)) |
| 561 return false; | |
| 562 if (!xml_writer.AddAttribute(kAttributeClientVersion, kClientVersion)) | |
| 563 return false; | |
| 533 | 564 |
| 534 // Some badly formatted web sites repeat forms - detect that and encode only | 565 // Some badly formatted web sites repeat forms - detect that and encode only |
| 535 // one form as returned data would be the same for all the repeated forms. | 566 // one form as returned data would be the same for all the repeated forms. |
| 536 std::set<std::string> processed_forms; | 567 std::set<std::string> processed_forms; |
| 537 for (const auto& it : forms) { | 568 for (const auto& form : forms) { |
| 538 std::string signature(it->FormSignature()); | 569 std::string signature(form->FormSignature()); |
| 539 if (processed_forms.find(signature) != processed_forms.end()) | 570 if (processed_forms.find(signature) != processed_forms.end()) |
| 540 continue; | 571 continue; |
| 541 processed_forms.insert(signature); | 572 processed_forms.insert(signature); |
| 542 scoped_ptr<buzz::XmlElement> encompassing_xml_element( | 573 if (form->IsMalformed()) |
| 543 new buzz::XmlElement(buzz::QName(kXMLElementForm))); | 574 continue; |
| 544 encompassing_xml_element->SetAttr(buzz::QName(kAttributeSignature), | 575 if (!xml_writer.StartElement(kXMLElementForm)) |
| 545 signature); | 576 return false; |
| 577 if (!xml_writer.AddAttribute(kAttributeSignature, signature)) | |
| 578 return false; | |
| 546 | 579 |
| 547 if (!it->EncodeFormRequest(FormStructure::QUERY, | 580 if (!form->EncodeFormRequest(FormStructure::QUERY, &xml_writer)) |
| 548 encompassing_xml_element.get())) { | 581 continue; |
| 549 continue; // Malformed form, skip it. | |
| 550 } | |
| 551 | 582 |
| 552 autofill_request_xml.AddElement(encompassing_xml_element.release()); | 583 if (!xml_writer.EndElement()) |
| 584 return false; | |
|
Mathieu
2015/11/25 17:59:10
nit: please add new line
vabr (Chromium)
2015/11/26 09:36:12
Done.
| |
| 553 encoded_signatures->push_back(signature); | 585 encoded_signatures->push_back(signature); |
| 554 } | 586 } |
| 587 if (!xml_writer.EndElement()) | |
| 588 return false; | |
| 555 | 589 |
| 556 if (!encoded_signatures->size()) | 590 if (!encoded_signatures->size()) |
| 557 return false; | 591 return false; |
| 558 | 592 |
| 559 // Note: Chrome used to also set 'accepts="e"' (where 'e' is for experiments), | 593 // Note: Chrome used to also set 'accepts="e"' (where 'e' is for experiments), |
| 560 // but no longer sets this because support for experiments is deprecated. If | 594 // but no longer sets this because support for experiments is deprecated. If |
| 561 // it ever resurfaces, re-add code here to set the attribute accordingly. | 595 // it ever resurfaces, re-add code here to set the attribute accordingly. |
| 562 | 596 |
| 563 // Obtain the XML structure as a string. | 597 // Obtain the XML structure as a string. |
| 564 *encoded_xml = kXMLDeclaration; | 598 xml_writer.StopWriting(); |
| 565 *encoded_xml += autofill_request_xml.Str().c_str(); | 599 *encoded_xml = xml_writer.GetWrittenString(); |
| 566 | 600 |
| 567 return true; | 601 return true; |
| 568 } | 602 } |
| 569 | 603 |
| 570 // static | 604 // static |
| 571 void FormStructure::ParseQueryResponse(const std::string& response_xml, | 605 void FormStructure::ParseQueryResponse(std::string response_xml, |
| 572 const std::vector<FormStructure*>& forms, | 606 const std::vector<FormStructure*>& forms, |
| 573 rappor::RapporService* rappor_service) { | 607 rappor::RapporService* rappor_service) { |
| 574 AutofillMetrics::LogServerQueryMetric( | 608 AutofillMetrics::LogServerQueryMetric( |
| 575 AutofillMetrics::QUERY_RESPONSE_RECEIVED); | 609 AutofillMetrics::QUERY_RESPONSE_RECEIVED); |
| 576 | 610 |
| 577 // Parse the field types from the server response to the query. | 611 // Parse the field types from the server response to the query. |
| 578 std::vector<AutofillServerFieldInfo> field_infos; | 612 std::vector<AutofillServerFieldInfo> field_infos; |
| 579 UploadRequired upload_required; | 613 UploadRequired upload_required; |
| 580 AutofillQueryXmlParser parse_handler(&field_infos, | 614 if (!ParseAutofillQueryXml(response_xml, &field_infos, &upload_required)) |
| 581 &upload_required); | |
| 582 buzz::XmlParser parser(&parse_handler); | |
| 583 parser.Parse(response_xml.c_str(), response_xml.length(), true); | |
| 584 if (!parse_handler.succeeded()) | |
| 585 return; | 615 return; |
| 586 | 616 |
| 587 AutofillMetrics::LogServerQueryMetric(AutofillMetrics::QUERY_RESPONSE_PARSED); | 617 AutofillMetrics::LogServerQueryMetric(AutofillMetrics::QUERY_RESPONSE_PARSED); |
| 588 | 618 |
| 589 bool heuristics_detected_fillable_field = false; | 619 bool heuristics_detected_fillable_field = false; |
| 590 bool query_response_overrode_heuristics = false; | 620 bool query_response_overrode_heuristics = false; |
| 591 | 621 |
| 592 // Copy the field types into the actual form. | 622 // Copy the field types into the actual form. |
| 593 std::vector<AutofillServerFieldInfo>::iterator current_info = | 623 std::vector<AutofillServerFieldInfo>::iterator current_info = |
| 594 field_infos.begin(); | 624 field_infos.begin(); |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1020 (((static_cast<uint64>(hash_bin[2])) & 0xFF) << 40) | | 1050 (((static_cast<uint64>(hash_bin[2])) & 0xFF) << 40) | |
| 1021 (((static_cast<uint64>(hash_bin[3])) & 0xFF) << 32) | | 1051 (((static_cast<uint64>(hash_bin[3])) & 0xFF) << 32) | |
| 1022 (((static_cast<uint64>(hash_bin[4])) & 0xFF) << 24) | | 1052 (((static_cast<uint64>(hash_bin[4])) & 0xFF) << 24) | |
| 1023 (((static_cast<uint64>(hash_bin[5])) & 0xFF) << 16) | | 1053 (((static_cast<uint64>(hash_bin[5])) & 0xFF) << 16) | |
| 1024 (((static_cast<uint64>(hash_bin[6])) & 0xFF) << 8) | | 1054 (((static_cast<uint64>(hash_bin[6])) & 0xFF) << 8) | |
| 1025 ((static_cast<uint64>(hash_bin[7])) & 0xFF); | 1055 ((static_cast<uint64>(hash_bin[7])) & 0xFF); |
| 1026 | 1056 |
| 1027 return base::Uint64ToString(hash64); | 1057 return base::Uint64ToString(hash64); |
| 1028 } | 1058 } |
| 1029 | 1059 |
| 1030 bool FormStructure::EncodeFormRequest( | 1060 bool FormStructure::IsMalformed() const { |
| 1031 FormStructure::EncodeRequestType request_type, | |
| 1032 buzz::XmlElement* encompassing_xml_element) const { | |
| 1033 if (!field_count()) // Nothing to add. | 1061 if (!field_count()) // Nothing to add. |
| 1034 return false; | 1062 return true; |
| 1035 | 1063 |
| 1036 // Some badly formatted web sites repeat fields - limit number of fields to | 1064 // Some badly formatted web sites repeat fields - limit number of fields to |
| 1037 // 48, which is far larger than any valid form and XML still fits into 2K. | 1065 // 48, which is far larger than any valid form and XML still fits into 2K. |
| 1038 // Do not send requests for forms with more than this many fields, as they are | 1066 // Do not send requests for forms with more than this many fields, as they are |
| 1039 // near certainly not valid/auto-fillable. | 1067 // near certainly not valid/auto-fillable. |
| 1040 const size_t kMaxFieldsOnTheForm = 48; | 1068 const size_t kMaxFieldsOnTheForm = 48; |
| 1041 if (field_count() > kMaxFieldsOnTheForm) | 1069 if (field_count() > kMaxFieldsOnTheForm) |
| 1042 return false; | 1070 return true; |
| 1071 return false; | |
| 1072 } | |
| 1043 | 1073 |
| 1074 bool FormStructure::EncodeFormRequest(EncodeRequestType request_type, | |
| 1075 XmlWriter* xml_writer) const { | |
| 1076 DCHECK(!IsMalformed()); | |
| 1044 // Add the child nodes for the form fields. | 1077 // Add the child nodes for the form fields. |
| 1045 for (size_t index = 0; index < field_count(); ++index) { | 1078 for (const AutofillField* field : fields_) { |
| 1046 const AutofillField* field = fields_[index]; | |
| 1047 switch (request_type) { | 1079 switch (request_type) { |
| 1048 case FormStructure::UPLOAD: | 1080 case FormStructure::UPLOAD: |
| 1049 EncodeFieldForUpload(*field, encompassing_xml_element); | 1081 if (!EncodeFieldForUpload(*field, xml_writer)) |
| 1082 return false; | |
| 1050 break; | 1083 break; |
| 1051 case FormStructure::QUERY: | 1084 case FormStructure::QUERY: |
| 1052 if (ShouldSkipField(*field)) | 1085 if (ShouldSkipField(*field)) |
| 1053 continue; | 1086 continue; |
| 1054 EncodeFieldForQuery(*field, encompassing_xml_element); | 1087 if (!xml_writer->StartElement(kXMLElementField)) |
| 1088 return false; | |
| 1089 if (!EncodeFieldForQuery(*field, xml_writer)) | |
| 1090 return false; | |
| 1091 if (!xml_writer->EndElement()) | |
| 1092 return false; | |
| 1055 break; | 1093 break; |
| 1056 case FormStructure::FIELD_ASSIGNMENTS: | 1094 case FormStructure::FIELD_ASSIGNMENTS: |
| 1057 EncodeFieldForFieldAssignments(*field, encompassing_xml_element); | 1095 if (!EncodeFieldForFieldAssignments(*field, xml_writer)) |
| 1096 return false; | |
| 1058 break; | 1097 break; |
| 1059 } | 1098 } |
| 1060 } | 1099 } |
| 1061 return true; | 1100 return true; |
| 1062 } | 1101 } |
| 1063 | 1102 |
| 1064 void FormStructure::ParseFieldTypesFromAutocompleteAttributes() { | 1103 void FormStructure::ParseFieldTypesFromAutocompleteAttributes() { |
| 1065 const std::string kDefaultSection = "-default"; | 1104 const std::string kDefaultSection = "-default"; |
| 1066 | 1105 |
| 1067 has_author_specified_types_ = false; | 1106 has_author_specified_types_ = false; |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1310 for (AutofillField* field : fields_) { | 1349 for (AutofillField* field : fields_) { |
| 1311 FieldTypeGroup field_type_group = field->Type().group(); | 1350 FieldTypeGroup field_type_group = field->Type().group(); |
| 1312 if (field_type_group == CREDIT_CARD) | 1351 if (field_type_group == CREDIT_CARD) |
| 1313 field->set_section(field->section() + "-cc"); | 1352 field->set_section(field->section() + "-cc"); |
| 1314 else | 1353 else |
| 1315 field->set_section(field->section() + "-default"); | 1354 field->set_section(field->section() + "-default"); |
| 1316 } | 1355 } |
| 1317 } | 1356 } |
| 1318 | 1357 |
| 1319 } // namespace autofill | 1358 } // namespace autofill |
| OLD | NEW |