Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(225)

Unified Diff: components/autofill/core/browser/form_structure.cc

Issue 1477733003: Replace xmllite with libxml in autofill (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@556433_remove_dead_code
Patch Set: Just rebased Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/autofill/core/browser/form_structure.cc
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc
index 1c7be1347e14e70e83d4b8a9e4dbb8ca93e548fc..351acbcc6ba6735a0352dbc776cb34aabcff5337 100644
--- a/components/autofill/core/browser/form_structure.cc
+++ b/components/autofill/core/browser/form_structure.cc
@@ -4,6 +4,7 @@
#include "components/autofill/core/browser/form_structure.h"
+#include <map>
#include <utility>
#include "base/basictypes.h"
@@ -20,6 +21,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/autofill_server_field_info.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/autofill_xml_parser.h"
#include "components/autofill/core/browser/field_types.h"
@@ -31,8 +33,8 @@
#include "components/autofill/core/common/form_field_data_predictions.h"
#include "components/rappor/rappor_service.h"
#include "components/rappor/rappor_utils.h"
+#include "third_party/libxml/chromium/libxml_utils.h"
#include "third_party/re2/re2/re2.h"
-#include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
namespace autofill {
namespace {
@@ -54,7 +56,6 @@ const char kAttributeControlType[] = "type";
const char kAttributeAutocomplete[] = "autocomplete";
const char kAttributeLoginFormSignature[] = "loginformsignature";
const char kClientVersion[] = "6.1.1715.1442/en (GGLL)";
-const char kXMLDeclaration[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
const char kXMLElementAutofillQuery[] = "autofillquery";
const char kXMLElementAutofillUpload[] = "autofillupload";
const char kXMLElementFieldAssignments[] = "fieldassignments";
@@ -115,75 +116,86 @@ std::string EncodeFieldTypes(const ServerFieldTypeSet& available_field_types) {
return data_presence;
}
-// Helper for |EncodeFormRequest()| and |EncodeFieldForUpload| that returns an
-// XmlElement for the given field in query xml, and also add it to the parent
-// XmlElement.
-buzz::XmlElement* EncodeFieldForQuery(const AutofillField& field,
- buzz::XmlElement* parent) {
- buzz::XmlElement* field_element = new buzz::XmlElement(
- buzz::QName(kXMLElementField));
- field_element->SetAttr(buzz::QName(kAttributeSignature),
- field.FieldSignature());
+// Assumes that |xml_writer| has just started an element with name
+// |kXMLElementField|, and adds some field attributes based on |field|. Returns
+// true on success, false on failure.
+bool EncodeFieldForQuery(const AutofillField& field, XmlWriter* xml_writer) {
+ if (!xml_writer->AddAttribute(kAttributeSignature, field.FieldSignature()))
+ return false;
if (IsAutofillFieldMetadataEnabled()) {
if (!field.name.empty()) {
- field_element->SetAttr(buzz::QName(kAttributeName),
- base::UTF16ToUTF8(field.name));
+ if (!xml_writer->AddAttribute(kAttributeName,
+ base::UTF16ToUTF8(field.name)))
+ return false;
}
- field_element->SetAttr(buzz::QName(kAttributeControlType),
- field.form_control_type);
+ if (!xml_writer->AddAttribute(kAttributeControlType,
+ field.form_control_type))
+ return false;
if (!field.label.empty()) {
std::string truncated;
base::TruncateUTF8ToByteSize(base::UTF16ToUTF8(field.label),
kMaxFieldLabelNumChars, &truncated);
- field_element->SetAttr(buzz::QName(kAttributeFieldLabel), truncated);
+ if (!xml_writer->AddAttribute(kAttributeFieldLabel, truncated))
+ return false;
}
}
- parent->AddElement(field_element);
- return field_element;
+ return true;
}
-// Helper for |EncodeFormRequest()| that creates XmlElements for the given field
-// in upload xml, and also add them to the parent XmlElement.
-void EncodeFieldForUpload(const AutofillField& field,
- buzz::XmlElement* parent) {
+// Uses |xml_writer| to write one tag named |kXMLElementField| for each item in
+// |field.possible_types()|, and adds some field attributes based on |field|.
+// Returns true on success, false on failure.
+bool EncodeFieldForUpload(const AutofillField& field, XmlWriter* xml_writer) {
// Don't upload checkable fields.
if (field.is_checkable)
- return;
+ return true;
- ServerFieldTypeSet types = field.possible_types();
- // |types| could be empty in unit-tests only.
+ const ServerFieldTypeSet& types = field.possible_types();
for (const auto& field_type : types) {
- // We use the same field elements as the query and add a few more below.
- buzz::XmlElement* field_element = EncodeFieldForQuery(field, parent);
+ if (!xml_writer->StartElement(kXMLElementField))
+ return false;
+ // Add the same field elements as the query and a few more below.
+ if (!EncodeFieldForQuery(field, xml_writer))
+ return false;
if (IsAutofillFieldMetadataEnabled() &&
!field.autocomplete_attribute.empty()) {
- field_element->SetAttr(buzz::QName(kAttributeAutocomplete),
- field.autocomplete_attribute);
+ if (!xml_writer->AddAttribute(kAttributeAutocomplete,
+ field.autocomplete_attribute))
+ return false;
}
- field_element->SetAttr(buzz::QName(kAttributeAutofillType),
- base::IntToString(field_type));
+ if (!xml_writer->AddAttribute(kAttributeAutofillType,
+ base::IntToString(field_type)))
+ return false;
+ if (!xml_writer->EndElement())
+ return false;
}
+ return true;
}
-// Helper for |EncodeFormRequest()| that creates XmlElements for the given field
-// in field assignments xml, and also add them to the parent XmlElement.
-void EncodeFieldForFieldAssignments(const AutofillField& field,
- buzz::XmlElement* parent) {
- ServerFieldTypeSet types = field.possible_types();
+// Uses |xml_writer| to write one tag named |kXMLElementFields| for each item in
+// |field.possible_types()|, and adds some field attributes based on |field|.
+// Returns true on success, false on failure.
+bool EncodeFieldForFieldAssignments(const AutofillField& field,
+ XmlWriter* xml_writer) {
+ const ServerFieldTypeSet& types = field.possible_types();
for (const auto& field_type : types) {
- buzz::XmlElement *field_element = new buzz::XmlElement(
- buzz::QName(kXMLElementFields));
-
- field_element->SetAttr(buzz::QName(kAttributeFieldID),
- field.FieldSignature());
- field_element->SetAttr(buzz::QName(kAttributeFieldType),
- base::IntToString(field_type));
- field_element->SetAttr(buzz::QName(kAttributeName),
- base::UTF16ToUTF8(field.name));
- parent->AddElement(field_element);
+ if (!xml_writer->StartElement(kXMLElementFields))
+ return false;
+
+ if (!xml_writer->AddAttribute(kAttributeFieldID, field.FieldSignature()))
+ return false;
+ if (!xml_writer->AddAttribute(kAttributeFieldType,
+ base::IntToString(field_type)))
+ return false;
+ if (!xml_writer->AddAttribute(kAttributeName,
+ base::UTF16ToUTF8(field.name)))
+ return false;
+ if (!xml_writer->EndElement())
+ return false;
}
+ return true;
}
// Returns |true| iff the |token| is a type hint for a contact field, as
@@ -442,49 +454,59 @@ bool FormStructure::EncodeUploadRequest(
bool form_was_autofilled,
const std::string& login_form_signature,
std::string* encoded_xml) const {
+ DCHECK(encoded_xml);
DCHECK(ShouldBeCrowdsourced());
// Verify that |available_field_types| agrees with the possible field types we
// are uploading.
for (const AutofillField* field : *this) {
for (const auto& type : field->possible_types()) {
- DCHECK(type == UNKNOWN_TYPE ||
- type == EMPTY_TYPE ||
+ DCHECK(type == UNKNOWN_TYPE || type == EMPTY_TYPE ||
available_field_types.count(type));
}
}
// Set up the <autofillupload> element and its attributes.
- buzz::XmlElement autofill_request_xml(
- (buzz::QName(kXMLElementAutofillUpload)));
- autofill_request_xml.SetAttr(buzz::QName(kAttributeClientVersion),
- kClientVersion);
- autofill_request_xml.SetAttr(buzz::QName(kAttributeFormSignature),
- FormSignature());
- autofill_request_xml.SetAttr(buzz::QName(kAttributeAutofillUsed),
- form_was_autofilled ? "true" : "false");
- autofill_request_xml.SetAttr(buzz::QName(kAttributeDataPresent),
- EncodeFieldTypes(available_field_types).c_str());
+ XmlWriter xml_writer;
+ xml_writer.StartWriting();
+ xml_writer.StopIndenting();
+ if (!xml_writer.StartElement(kXMLElementAutofillUpload))
+ return false;
+ if (!xml_writer.AddAttribute(kAttributeClientVersion, kClientVersion))
+ return false;
+ if (!xml_writer.AddAttribute(kAttributeFormSignature, FormSignature()))
+ return false;
+ if (!xml_writer.AddAttribute(kAttributeAutofillUsed,
+ form_was_autofilled ? "true" : "false"))
+ return false;
+ if (!xml_writer.AddAttribute(kAttributeDataPresent,
+ EncodeFieldTypes(available_field_types)))
+ return false;
if (IsAutofillFieldMetadataEnabled()) {
- autofill_request_xml.SetAttr(buzz::QName(kAttributeFormActionHostSignature),
- Hash64Bit(target_url_.host()));
- if(!form_name().empty()) {
- autofill_request_xml.SetAttr(buzz::QName(kAttributeFormName),
- base::UTF16ToUTF8(form_name()));
+ if (!xml_writer.AddAttribute(kAttributeFormActionHostSignature,
+ Hash64Bit(target_url_.host())))
+ return false;
+ if (!form_name().empty()) {
+ if (!xml_writer.AddAttribute(kAttributeFormName,
+ base::UTF16ToUTF8(form_name())))
+ return false;
}
}
if (!login_form_signature.empty()) {
- autofill_request_xml.SetAttr(buzz::QName(kAttributeLoginFormSignature),
- login_form_signature);
+ if (!xml_writer.AddAttribute(kAttributeLoginFormSignature,
+ login_form_signature))
+ return false;
}
- if (!EncodeFormRequest(FormStructure::UPLOAD, &autofill_request_xml))
+ if (IsMalformed() || !EncodeFormRequest(FormStructure::UPLOAD, &xml_writer))
return false; // Malformed form, skip it.
+ if (!xml_writer.EndElement())
+ return false;
// Obtain the XML structure as a string.
- *encoded_xml = kXMLDeclaration;
- *encoded_xml += autofill_request_xml.Str().c_str();
+ xml_writer.StopWriting();
+ *encoded_xml = xml_writer.GetWrittenString();
// To enable this logging, run with the flag --vmodule="form_structure=2".
VLOG(2) << "\n" << *encoded_xml;
@@ -495,21 +517,28 @@ bool FormStructure::EncodeUploadRequest(
bool FormStructure::EncodeFieldAssignments(
const ServerFieldTypeSet& available_field_types,
std::string* encoded_xml) const {
+ DCHECK(encoded_xml);
DCHECK(ShouldBeCrowdsourced());
// Set up the <fieldassignments> element and its attributes.
- buzz::XmlElement autofill_request_xml(
- (buzz::QName(kXMLElementFieldAssignments)));
- autofill_request_xml.SetAttr(buzz::QName(kAttributeFormSignature),
- FormSignature());
+ XmlWriter xml_writer;
+ xml_writer.StartWriting();
+ xml_writer.StopIndenting();
+ if (!xml_writer.StartElement(kXMLElementFieldAssignments))
+ return false;
+ if (!xml_writer.AddAttribute(kAttributeFormSignature, FormSignature()))
+ return false;
- if (!EncodeFormRequest(FormStructure::FIELD_ASSIGNMENTS,
- &autofill_request_xml))
+ if (IsMalformed() ||
+ !EncodeFormRequest(FormStructure::FIELD_ASSIGNMENTS, &xml_writer)) {
return false; // Malformed form, skip it.
+ }
+ if (!xml_writer.EndElement())
+ return false;
// Obtain the XML structure as a string.
- *encoded_xml = kXMLDeclaration;
- *encoded_xml += autofill_request_xml.Str().c_str();
+ xml_writer.StopWriting();
+ *encoded_xml = xml_writer.GetWrittenString();
return true;
}
@@ -521,37 +550,43 @@ bool FormStructure::EncodeQueryRequest(
std::string* encoded_xml) {
DCHECK(encoded_signatures);
DCHECK(encoded_xml);
- encoded_xml->clear();
encoded_signatures->clear();
encoded_signatures->reserve(forms.size());
// Set up the <autofillquery> element and attributes.
- buzz::XmlElement autofill_request_xml(
- (buzz::QName(kXMLElementAutofillQuery)));
- autofill_request_xml.SetAttr(buzz::QName(kAttributeClientVersion),
- kClientVersion);
+ XmlWriter xml_writer;
+ xml_writer.StartWriting();
+ xml_writer.StopIndenting();
+ if (!xml_writer.StartElement(kXMLElementAutofillQuery))
+ return false;
+ if (!xml_writer.AddAttribute(kAttributeClientVersion, kClientVersion))
+ return false;
// Some badly formatted web sites repeat forms - detect that and encode only
// one form as returned data would be the same for all the repeated forms.
std::set<std::string> processed_forms;
- for (const auto& it : forms) {
- std::string signature(it->FormSignature());
+ for (const auto& form : forms) {
+ std::string signature(form->FormSignature());
if (processed_forms.find(signature) != processed_forms.end())
continue;
processed_forms.insert(signature);
- scoped_ptr<buzz::XmlElement> encompassing_xml_element(
- new buzz::XmlElement(buzz::QName(kXMLElementForm)));
- encompassing_xml_element->SetAttr(buzz::QName(kAttributeSignature),
- signature);
-
- if (!it->EncodeFormRequest(FormStructure::QUERY,
- encompassing_xml_element.get())) {
- continue; // Malformed form, skip it.
- }
+ if (form->IsMalformed())
+ continue;
+ if (!xml_writer.StartElement(kXMLElementForm))
+ return false;
+ if (!xml_writer.AddAttribute(kAttributeSignature, signature))
+ return false;
+
+ if (!form->EncodeFormRequest(FormStructure::QUERY, &xml_writer))
+ continue;
+
+ if (!xml_writer.EndElement())
+ return false;
- autofill_request_xml.AddElement(encompassing_xml_element.release());
encoded_signatures->push_back(signature);
}
+ if (!xml_writer.EndElement())
+ return false;
if (!encoded_signatures->size())
return false;
@@ -561,14 +596,14 @@ bool FormStructure::EncodeQueryRequest(
// it ever resurfaces, re-add code here to set the attribute accordingly.
// Obtain the XML structure as a string.
- *encoded_xml = kXMLDeclaration;
- *encoded_xml += autofill_request_xml.Str().c_str();
+ xml_writer.StopWriting();
+ *encoded_xml = xml_writer.GetWrittenString();
return true;
}
// static
-void FormStructure::ParseQueryResponse(const std::string& response_xml,
+void FormStructure::ParseQueryResponse(std::string response_xml,
const std::vector<FormStructure*>& forms,
rappor::RapporService* rappor_service) {
AutofillMetrics::LogServerQueryMetric(
@@ -577,11 +612,7 @@ void FormStructure::ParseQueryResponse(const std::string& response_xml,
// Parse the field types from the server response to the query.
std::vector<AutofillServerFieldInfo> field_infos;
UploadRequired upload_required;
- AutofillQueryXmlParser parse_handler(&field_infos,
- &upload_required);
- buzz::XmlParser parser(&parse_handler);
- parser.Parse(response_xml.c_str(), response_xml.length(), true);
- if (!parse_handler.succeeded())
+ if (!ParseAutofillQueryXml(response_xml, &field_infos, &upload_required))
return;
AutofillMetrics::LogServerQueryMetric(AutofillMetrics::QUERY_RESPONSE_PARSED);
@@ -1027,11 +1058,9 @@ std::string FormStructure::Hash64Bit(const std::string& str) {
return base::Uint64ToString(hash64);
}
-bool FormStructure::EncodeFormRequest(
- FormStructure::EncodeRequestType request_type,
- buzz::XmlElement* encompassing_xml_element) const {
+bool FormStructure::IsMalformed() const {
if (!field_count()) // Nothing to add.
- return false;
+ return true;
// Some badly formatted web sites repeat fields - limit number of fields to
// 48, which is far larger than any valid form and XML still fits into 2K.
@@ -1039,22 +1068,33 @@ bool FormStructure::EncodeFormRequest(
// near certainly not valid/auto-fillable.
const size_t kMaxFieldsOnTheForm = 48;
if (field_count() > kMaxFieldsOnTheForm)
- return false;
+ return true;
+ return false;
+}
+bool FormStructure::EncodeFormRequest(EncodeRequestType request_type,
+ XmlWriter* xml_writer) const {
+ DCHECK(!IsMalformed());
// Add the child nodes for the form fields.
- for (size_t index = 0; index < field_count(); ++index) {
- const AutofillField* field = fields_[index];
+ for (const AutofillField* field : fields_) {
switch (request_type) {
case FormStructure::UPLOAD:
- EncodeFieldForUpload(*field, encompassing_xml_element);
+ if (!EncodeFieldForUpload(*field, xml_writer))
+ return false;
break;
case FormStructure::QUERY:
if (ShouldSkipField(*field))
continue;
- EncodeFieldForQuery(*field, encompassing_xml_element);
+ if (!xml_writer->StartElement(kXMLElementField))
+ return false;
+ if (!EncodeFieldForQuery(*field, xml_writer))
+ return false;
+ if (!xml_writer->EndElement())
+ return false;
break;
case FormStructure::FIELD_ASSIGNMENTS:
- EncodeFieldForFieldAssignments(*field, encompassing_xml_element);
+ if (!EncodeFieldForFieldAssignments(*field, xml_writer))
+ return false;
break;
}
}
« no previous file with comments | « components/autofill/core/browser/form_structure.h ('k') | components/autofill/core/browser/form_structure_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698