| Index: components/autofill/core/browser/autofill_xml_parser.cc
|
| diff --git a/components/autofill/core/browser/autofill_xml_parser.cc b/components/autofill/core/browser/autofill_xml_parser.cc
|
| index acfa4c07f3daa5d7b1f2eb77aa34d65d540c10b7..7dec347787f293126d92621e39309b8484ffd72c 100644
|
| --- a/components/autofill/core/browser/autofill_xml_parser.cc
|
| +++ b/components/autofill/core/browser/autofill_xml_parser.cc
|
| @@ -4,149 +4,112 @@
|
|
|
| #include "components/autofill/core/browser/autofill_xml_parser.h"
|
|
|
| -#include <string.h>
|
| +#include <utility>
|
|
|
| #include "base/logging.h"
|
| #include "base/strings/string_number_conversions.h"
|
| #include "components/autofill/core/browser/autofill_server_field_info.h"
|
| -#include "third_party/webrtc/libjingle/xmllite/qname.h"
|
| +#include "components/autofill/core/browser/field_types.h"
|
| +#include "third_party/libxml/chromium/libxml_utils.h"
|
|
|
| namespace autofill {
|
|
|
| -AutofillXmlParser::AutofillXmlParser()
|
| - : succeeded_(true) {
|
| -}
|
| -
|
| -AutofillXmlParser::~AutofillXmlParser() {}
|
| -
|
| -void AutofillXmlParser::CharacterData(
|
| - buzz::XmlParseContext* context, const char* text, int len) {
|
| -}
|
| -
|
| -void AutofillXmlParser::EndElement(buzz::XmlParseContext* context,
|
| - const char* name) {
|
| -}
|
| -
|
| -void AutofillXmlParser::Error(buzz::XmlParseContext* context,
|
| - XML_Error error_code) {
|
| - succeeded_ = false;
|
| -}
|
| -
|
| -AutofillQueryXmlParser::AutofillQueryXmlParser(
|
| - std::vector<AutofillServerFieldInfo>* field_infos,
|
| - UploadRequired* upload_required)
|
| - : field_infos_(field_infos),
|
| - upload_required_(upload_required) {
|
| - DCHECK(upload_required_);
|
| -}
|
| +bool ParseAutofillQueryXml(std::string xml,
|
| + std::vector<AutofillServerFieldInfo>* field_infos,
|
| + UploadRequired* upload_required) {
|
| + DCHECK(field_infos);
|
| + DCHECK(upload_required);
|
| +
|
| + XmlReader reader;
|
| + if (!reader.Load(xml))
|
| + return false;
|
| +
|
| + // Seek to the first opening tag.
|
| + if (!reader.Read())
|
| + return false; // Malformed input.
|
| +
|
| + if (reader.NodeName() != "autofillqueryresponse")
|
| + return false; // Malformed input.
|
| +
|
| + *upload_required = USE_UPLOAD_RATES;
|
| + std::string upload_required_value;
|
| + if (reader.NodeAttribute("uploadrequired", &upload_required_value)) {
|
| + if (upload_required_value == "true")
|
| + *upload_required = UPLOAD_REQUIRED;
|
| + else if (upload_required_value == "false")
|
| + *upload_required = UPLOAD_NOT_REQUIRED;
|
| + }
|
|
|
| -AutofillQueryXmlParser::~AutofillQueryXmlParser() {}
|
| -
|
| -void AutofillQueryXmlParser::StartElement(buzz::XmlParseContext* context,
|
| - const char* name,
|
| - const char** attrs) {
|
| - buzz::QName qname = context->ResolveQName(name, false);
|
| - const std::string& element = qname.LocalPart();
|
| - if (element.compare("autofillqueryresponse") == 0) {
|
| - // We check for the upload required attribute below, but if it's not
|
| - // present, we use the default upload rates.
|
| - *upload_required_ = USE_UPLOAD_RATES;
|
| -
|
| - // |attrs| is a NULL-terminated list of (attribute, value) pairs.
|
| - while (*attrs) {
|
| - buzz::QName attribute_qname = context->ResolveQName(*attrs, true);
|
| - ++attrs;
|
| - const std::string& attribute_name = attribute_qname.LocalPart();
|
| - if (attribute_name.compare("uploadrequired") == 0) {
|
| - if (strcmp(*attrs, "true") == 0)
|
| - *upload_required_ = UPLOAD_REQUIRED;
|
| - else if (strcmp(*attrs, "false") == 0)
|
| - *upload_required_ = UPLOAD_NOT_REQUIRED;
|
| - }
|
| - ++attrs;
|
| - }
|
| - } else if (element.compare("field") == 0) {
|
| - if (!*attrs) {
|
| - // Missing the "autofilltype" attribute, abort.
|
| - context->RaiseError(XML_ERROR_ABORTED);
|
| - return;
|
| - }
|
| + field_infos->clear();
|
| + if (reader.IsClosingElement())
|
| + return true;
|
|
|
| - // Determine the field type from the attribute value. There should be one
|
| - // attribute (autofilltype) with an integer value.
|
| + if (!reader.Read())
|
| + return false; // Malformed input.
|
| + while (reader.NodeName() == "field") {
|
| AutofillServerFieldInfo field_info;
|
| field_info.field_type = UNKNOWN_TYPE;
|
|
|
| - // |attrs| is a NULL-terminated list of (attribute, value) pairs.
|
| - while (*attrs) {
|
| - buzz::QName attribute_qname = context->ResolveQName(*attrs, true);
|
| - ++attrs;
|
| - const std::string& attribute_name = attribute_qname.LocalPart();
|
| - if (attribute_name.compare("autofilltype") == 0) {
|
| - int value = GetIntValue(context, *attrs);
|
| - if (value >= 0 && value < MAX_VALID_FIELD_TYPE)
|
| - field_info.field_type = static_cast<ServerFieldType>(value);
|
| - else
|
| - field_info.field_type = NO_SERVER_DATA;
|
| - } else if (field_info.field_type == FIELD_WITH_DEFAULT_VALUE &&
|
| - attribute_name.compare("defaultvalue") == 0) {
|
| - field_info.default_value = *attrs;
|
| - }
|
| - ++attrs;
|
| + std::string autofill_type_value;
|
| + if (!reader.NodeAttribute("autofilltype", &autofill_type_value))
|
| + return false; // Missing required attribute.
|
| + int parsed_type = 0;
|
| + if (!base::StringToInt(autofill_type_value, &parsed_type) ||
|
| + parsed_type < 0 || parsed_type >= MAX_VALID_FIELD_TYPE) {
|
| + // Invalid attribute value should not make the whole parse fail.
|
| + field_info.field_type = NO_SERVER_DATA;
|
| + } else {
|
| + field_info.field_type = static_cast<ServerFieldType>(parsed_type);
|
| }
|
|
|
| - // Record this field type, default value pair.
|
| - field_infos_->push_back(field_info);
|
| - }
|
| -}
|
| + std::string default_value;
|
| + if (field_info.field_type == FIELD_WITH_DEFAULT_VALUE &&
|
| + reader.NodeAttribute("defaultvalue", &default_value)) {
|
| + field_info.default_value = std::move(default_value);
|
| + }
|
|
|
| -int AutofillQueryXmlParser::GetIntValue(buzz::XmlParseContext* context,
|
| - const char* attribute) {
|
| - int value = 0;
|
| - if (!base::StringToInt(attribute, &value)) {
|
| - context->RaiseError(XML_ERROR_SYNTAX);
|
| - return 0;
|
| - }
|
| - return value;
|
| -}
|
| + field_infos->push_back(field_info);
|
|
|
| -AutofillUploadXmlParser::AutofillUploadXmlParser(double* positive_upload_rate,
|
| - double* negative_upload_rate)
|
| - : succeeded_(false),
|
| - positive_upload_rate_(positive_upload_rate),
|
| - negative_upload_rate_(negative_upload_rate) {
|
| - DCHECK(positive_upload_rate_);
|
| - DCHECK(negative_upload_rate_);
|
| -}
|
| + if (!reader.Read())
|
| + return false; // Malformed input.
|
| + }
|
|
|
| -void AutofillUploadXmlParser::StartElement(buzz::XmlParseContext* context,
|
| - const char* name,
|
| - const char** attrs) {
|
| - buzz::QName qname = context->ResolveQName(name, false);
|
| - const std::string &element = qname.LocalPart();
|
| - if (element.compare("autofilluploadresponse") == 0) {
|
| - // Loop over all attributes to get the upload rates.
|
| - while (*attrs) {
|
| - buzz::QName attribute_qname = context->ResolveQName(attrs[0], true);
|
| - const std::string &attribute_name = attribute_qname.LocalPart();
|
| - if (attribute_name.compare("positiveuploadrate") == 0) {
|
| - *positive_upload_rate_ = GetDoubleValue(context, attrs[1]);
|
| - } else if (attribute_name.compare("negativeuploadrate") == 0) {
|
| - *negative_upload_rate_ = GetDoubleValue(context, attrs[1]);
|
| - }
|
| - attrs += 2; // We peeked at attrs[0] and attrs[1], skip past both.
|
| - }
|
| + if (reader.NodeName() != "autofillqueryresponse" ||
|
| + !reader.IsClosingElement()) {
|
| + return false; // Malformed input.
|
| }
|
| + return true;
|
| }
|
|
|
| -double AutofillUploadXmlParser::GetDoubleValue(buzz::XmlParseContext* context,
|
| - const char* attribute) {
|
| - double value = 0;
|
| - if (!base::StringToDouble(attribute, &value)) {
|
| - context->RaiseError(XML_ERROR_SYNTAX);
|
| - return 0.0;
|
| - }
|
| - return value;
|
| +bool ParseAutofillUploadXml(std::string xml,
|
| + double* positive_upload_rate,
|
| + double* negative_upload_rate) {
|
| + DCHECK(positive_upload_rate);
|
| + DCHECK(negative_upload_rate);
|
| +
|
| + XmlReader reader;
|
| + if (!reader.Load(xml))
|
| + return false;
|
| +
|
| + // Seek to the first opening tag.
|
| + if (!reader.Read())
|
| + return false; // Malformed input.
|
| +
|
| + if (reader.NodeName() != "autofilluploadresponse")
|
| + return false; // Malformed input.
|
| +
|
| + std::string attribute_value;
|
| + // TODO(crbug.com/561619) Make the two attributes non-required and use 1 as
|
| + // the default value.
|
| + if (!reader.NodeAttribute("positiveuploadrate", &attribute_value))
|
| + return false; // Missing required attribute.
|
| + if (!base::StringToDouble(attribute_value, positive_upload_rate))
|
| + return false; // Invalid attribute value.
|
| + if (!reader.NodeAttribute("negativeuploadrate", &attribute_value))
|
| + return false; // Missing required attribute.
|
| + if (!base::StringToDouble(attribute_value, negative_upload_rate))
|
| + return false; // Invalid attribute value.
|
| + return true;
|
| }
|
|
|
| } // namespace autofill
|
|
|