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; |
| 585 |
553 encoded_signatures->push_back(signature); | 586 encoded_signatures->push_back(signature); |
554 } | 587 } |
| 588 if (!xml_writer.EndElement()) |
| 589 return false; |
555 | 590 |
556 if (!encoded_signatures->size()) | 591 if (!encoded_signatures->size()) |
557 return false; | 592 return false; |
558 | 593 |
559 // Note: Chrome used to also set 'accepts="e"' (where 'e' is for experiments), | 594 // 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 | 595 // 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. | 596 // it ever resurfaces, re-add code here to set the attribute accordingly. |
562 | 597 |
563 // Obtain the XML structure as a string. | 598 // Obtain the XML structure as a string. |
564 *encoded_xml = kXMLDeclaration; | 599 xml_writer.StopWriting(); |
565 *encoded_xml += autofill_request_xml.Str().c_str(); | 600 *encoded_xml = xml_writer.GetWrittenString(); |
566 | 601 |
567 return true; | 602 return true; |
568 } | 603 } |
569 | 604 |
570 // static | 605 // static |
571 void FormStructure::ParseQueryResponse(const std::string& response_xml, | 606 void FormStructure::ParseQueryResponse(std::string response_xml, |
572 const std::vector<FormStructure*>& forms, | 607 const std::vector<FormStructure*>& forms, |
573 rappor::RapporService* rappor_service) { | 608 rappor::RapporService* rappor_service) { |
574 AutofillMetrics::LogServerQueryMetric( | 609 AutofillMetrics::LogServerQueryMetric( |
575 AutofillMetrics::QUERY_RESPONSE_RECEIVED); | 610 AutofillMetrics::QUERY_RESPONSE_RECEIVED); |
576 | 611 |
577 // Parse the field types from the server response to the query. | 612 // Parse the field types from the server response to the query. |
578 std::vector<AutofillServerFieldInfo> field_infos; | 613 std::vector<AutofillServerFieldInfo> field_infos; |
579 UploadRequired upload_required; | 614 UploadRequired upload_required; |
580 AutofillQueryXmlParser parse_handler(&field_infos, | 615 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; | 616 return; |
586 | 617 |
587 AutofillMetrics::LogServerQueryMetric(AutofillMetrics::QUERY_RESPONSE_PARSED); | 618 AutofillMetrics::LogServerQueryMetric(AutofillMetrics::QUERY_RESPONSE_PARSED); |
588 | 619 |
589 bool heuristics_detected_fillable_field = false; | 620 bool heuristics_detected_fillable_field = false; |
590 bool query_response_overrode_heuristics = false; | 621 bool query_response_overrode_heuristics = false; |
591 | 622 |
592 // Copy the field types into the actual form. | 623 // Copy the field types into the actual form. |
593 std::vector<AutofillServerFieldInfo>::iterator current_info = | 624 std::vector<AutofillServerFieldInfo>::iterator current_info = |
594 field_infos.begin(); | 625 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) | | 1051 (((static_cast<uint64>(hash_bin[2])) & 0xFF) << 40) | |
1021 (((static_cast<uint64>(hash_bin[3])) & 0xFF) << 32) | | 1052 (((static_cast<uint64>(hash_bin[3])) & 0xFF) << 32) | |
1022 (((static_cast<uint64>(hash_bin[4])) & 0xFF) << 24) | | 1053 (((static_cast<uint64>(hash_bin[4])) & 0xFF) << 24) | |
1023 (((static_cast<uint64>(hash_bin[5])) & 0xFF) << 16) | | 1054 (((static_cast<uint64>(hash_bin[5])) & 0xFF) << 16) | |
1024 (((static_cast<uint64>(hash_bin[6])) & 0xFF) << 8) | | 1055 (((static_cast<uint64>(hash_bin[6])) & 0xFF) << 8) | |
1025 ((static_cast<uint64>(hash_bin[7])) & 0xFF); | 1056 ((static_cast<uint64>(hash_bin[7])) & 0xFF); |
1026 | 1057 |
1027 return base::Uint64ToString(hash64); | 1058 return base::Uint64ToString(hash64); |
1028 } | 1059 } |
1029 | 1060 |
1030 bool FormStructure::EncodeFormRequest( | 1061 bool FormStructure::IsMalformed() const { |
1031 FormStructure::EncodeRequestType request_type, | |
1032 buzz::XmlElement* encompassing_xml_element) const { | |
1033 if (!field_count()) // Nothing to add. | 1062 if (!field_count()) // Nothing to add. |
1034 return false; | 1063 return true; |
1035 | 1064 |
1036 // Some badly formatted web sites repeat fields - limit number of fields to | 1065 // 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. | 1066 // 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 | 1067 // Do not send requests for forms with more than this many fields, as they are |
1039 // near certainly not valid/auto-fillable. | 1068 // near certainly not valid/auto-fillable. |
1040 const size_t kMaxFieldsOnTheForm = 48; | 1069 const size_t kMaxFieldsOnTheForm = 48; |
1041 if (field_count() > kMaxFieldsOnTheForm) | 1070 if (field_count() > kMaxFieldsOnTheForm) |
1042 return false; | 1071 return true; |
| 1072 return false; |
| 1073 } |
1043 | 1074 |
| 1075 bool FormStructure::EncodeFormRequest(EncodeRequestType request_type, |
| 1076 XmlWriter* xml_writer) const { |
| 1077 DCHECK(!IsMalformed()); |
1044 // Add the child nodes for the form fields. | 1078 // Add the child nodes for the form fields. |
1045 for (size_t index = 0; index < field_count(); ++index) { | 1079 for (const AutofillField* field : fields_) { |
1046 const AutofillField* field = fields_[index]; | |
1047 switch (request_type) { | 1080 switch (request_type) { |
1048 case FormStructure::UPLOAD: | 1081 case FormStructure::UPLOAD: |
1049 EncodeFieldForUpload(*field, encompassing_xml_element); | 1082 if (!EncodeFieldForUpload(*field, xml_writer)) |
| 1083 return false; |
1050 break; | 1084 break; |
1051 case FormStructure::QUERY: | 1085 case FormStructure::QUERY: |
1052 if (ShouldSkipField(*field)) | 1086 if (ShouldSkipField(*field)) |
1053 continue; | 1087 continue; |
1054 EncodeFieldForQuery(*field, encompassing_xml_element); | 1088 if (!xml_writer->StartElement(kXMLElementField)) |
| 1089 return false; |
| 1090 if (!EncodeFieldForQuery(*field, xml_writer)) |
| 1091 return false; |
| 1092 if (!xml_writer->EndElement()) |
| 1093 return false; |
1055 break; | 1094 break; |
1056 case FormStructure::FIELD_ASSIGNMENTS: | 1095 case FormStructure::FIELD_ASSIGNMENTS: |
1057 EncodeFieldForFieldAssignments(*field, encompassing_xml_element); | 1096 if (!EncodeFieldForFieldAssignments(*field, xml_writer)) |
| 1097 return false; |
1058 break; | 1098 break; |
1059 } | 1099 } |
1060 } | 1100 } |
1061 return true; | 1101 return true; |
1062 } | 1102 } |
1063 | 1103 |
1064 void FormStructure::ParseFieldTypesFromAutocompleteAttributes() { | 1104 void FormStructure::ParseFieldTypesFromAutocompleteAttributes() { |
1065 const std::string kDefaultSection = "-default"; | 1105 const std::string kDefaultSection = "-default"; |
1066 | 1106 |
1067 has_author_specified_types_ = false; | 1107 has_author_specified_types_ = false; |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1310 for (AutofillField* field : fields_) { | 1350 for (AutofillField* field : fields_) { |
1311 FieldTypeGroup field_type_group = field->Type().group(); | 1351 FieldTypeGroup field_type_group = field->Type().group(); |
1312 if (field_type_group == CREDIT_CARD) | 1352 if (field_type_group == CREDIT_CARD) |
1313 field->set_section(field->section() + "-cc"); | 1353 field->set_section(field->section() + "-cc"); |
1314 else | 1354 else |
1315 field->set_section(field->section() + "-default"); | 1355 field->set_section(field->section() + "-default"); |
1316 } | 1356 } |
1317 } | 1357 } |
1318 | 1358 |
1319 } // namespace autofill | 1359 } // namespace autofill |
OLD | NEW |