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
3 // found in the LICENSE file.
5 #include "components/autofill/core/browser/autofill_xml_parser.h"
9 #include "base/logging.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "components/autofill/core/browser/autofill_server_field_info.h"
12 #include "third_party/webrtc/libjingle/xmllite/qname.h"
16 AutofillXmlParser::AutofillXmlParser()
20 AutofillXmlParser::~AutofillXmlParser() {}
22 void AutofillXmlParser::CharacterData(
23 buzz::XmlParseContext
* context
, const char* text
, int len
) {
26 void AutofillXmlParser::EndElement(buzz::XmlParseContext
* context
,
30 void AutofillXmlParser::Error(buzz::XmlParseContext
* context
,
31 XML_Error error_code
) {
35 AutofillQueryXmlParser::AutofillQueryXmlParser(
36 std::vector
<AutofillServerFieldInfo
>* field_infos
,
37 UploadRequired
* upload_required
)
38 : field_infos_(field_infos
),
39 upload_required_(upload_required
) {
40 DCHECK(upload_required_
);
43 AutofillQueryXmlParser::~AutofillQueryXmlParser() {}
45 void AutofillQueryXmlParser::StartElement(buzz::XmlParseContext
* context
,
48 buzz::QName qname
= context
->ResolveQName(name
, false);
49 const std::string
& element
= qname
.LocalPart();
50 if (element
.compare("autofillqueryresponse") == 0) {
51 // We check for the upload required attribute below, but if it's not
52 // present, we use the default upload rates.
53 *upload_required_
= USE_UPLOAD_RATES
;
55 // |attrs| is a NULL-terminated list of (attribute, value) pairs.
57 buzz::QName attribute_qname
= context
->ResolveQName(*attrs
, true);
59 const std::string
& attribute_name
= attribute_qname
.LocalPart();
60 if (attribute_name
.compare("uploadrequired") == 0) {
61 if (strcmp(*attrs
, "true") == 0)
62 *upload_required_
= UPLOAD_REQUIRED
;
63 else if (strcmp(*attrs
, "false") == 0)
64 *upload_required_
= UPLOAD_NOT_REQUIRED
;
68 } else if (element
.compare("field") == 0) {
70 // Missing the "autofilltype" attribute, abort.
71 context
->RaiseError(XML_ERROR_ABORTED
);
75 // Determine the field type from the attribute value. There should be one
76 // attribute (autofilltype) with an integer value.
77 AutofillServerFieldInfo field_info
;
78 field_info
.field_type
= UNKNOWN_TYPE
;
80 // |attrs| is a NULL-terminated list of (attribute, value) pairs.
82 buzz::QName attribute_qname
= context
->ResolveQName(*attrs
, true);
84 const std::string
& attribute_name
= attribute_qname
.LocalPart();
85 if (attribute_name
.compare("autofilltype") == 0) {
86 int value
= GetIntValue(context
, *attrs
);
87 if (value
>= 0 && value
< MAX_VALID_FIELD_TYPE
)
88 field_info
.field_type
= static_cast<ServerFieldType
>(value
);
90 field_info
.field_type
= NO_SERVER_DATA
;
91 } else if (field_info
.field_type
== FIELD_WITH_DEFAULT_VALUE
&&
92 attribute_name
.compare("defaultvalue") == 0) {
93 field_info
.default_value
= *attrs
;
98 // Record this field type, default value pair.
99 field_infos_
->push_back(field_info
);
103 void AutofillQueryXmlParser::ParseElementDescriptor(
104 buzz::XmlParseContext
* context
,
105 const char* const* attrs
,
106 WebElementDescriptor
* element_descriptor
) {
107 // If both id and css_selector are set, the first one to appear will take
109 // |attrs| is a NULL-terminated list of (attribute, value) pairs.
111 buzz::QName attribute_qname
= context
->ResolveQName(*attrs
, true);
113 const std::string
& attribute_name
= attribute_qname
.LocalPart();
114 buzz::QName value_qname
= context
->ResolveQName(*attrs
, true);
116 const std::string
& attribute_value
= value_qname
.LocalPart();
117 if (attribute_name
.compare("id") == 0 && !attribute_value
.empty()) {
118 element_descriptor
->retrieval_method
= autofill::WebElementDescriptor::ID
;
119 element_descriptor
->descriptor
= attribute_value
;
121 } else if (attribute_name
.compare("css_selector") == 0 &&
122 !attribute_value
.empty()) {
123 element_descriptor
->retrieval_method
=
124 autofill::WebElementDescriptor::CSS_SELECTOR
;
125 element_descriptor
->descriptor
= attribute_value
;
131 int AutofillQueryXmlParser::GetIntValue(buzz::XmlParseContext
* context
,
132 const char* attribute
) {
134 if (!base::StringToInt(attribute
, &value
)) {
135 context
->RaiseError(XML_ERROR_SYNTAX
);
141 AutofillUploadXmlParser::AutofillUploadXmlParser(double* positive_upload_rate
,
142 double* negative_upload_rate
)
144 positive_upload_rate_(positive_upload_rate
),
145 negative_upload_rate_(negative_upload_rate
) {
146 DCHECK(positive_upload_rate_
);
147 DCHECK(negative_upload_rate_
);
150 void AutofillUploadXmlParser::StartElement(buzz::XmlParseContext
* context
,
152 const char** attrs
) {
153 buzz::QName qname
= context
->ResolveQName(name
, false);
154 const std::string
&element
= qname
.LocalPart();
155 if (element
.compare("autofilluploadresponse") == 0) {
156 // Loop over all attributes to get the upload rates.
158 buzz::QName attribute_qname
= context
->ResolveQName(attrs
[0], true);
159 const std::string
&attribute_name
= attribute_qname
.LocalPart();
160 if (attribute_name
.compare("positiveuploadrate") == 0) {
161 *positive_upload_rate_
= GetDoubleValue(context
, attrs
[1]);
162 } else if (attribute_name
.compare("negativeuploadrate") == 0) {
163 *negative_upload_rate_
= GetDoubleValue(context
, attrs
[1]);
165 attrs
+= 2; // We peeked at attrs[0] and attrs[1], skip past both.
170 double AutofillUploadXmlParser::GetDoubleValue(buzz::XmlParseContext
* context
,
171 const char* attribute
) {
173 if (!base::StringToDouble(attribute
, &value
)) {
174 context
->RaiseError(XML_ERROR_SYNTAX
);
180 } // namespace autofill