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.
4
5 #include "components/autofill/core/browser/autofill_xml_parser.h"
6
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include "base/logging.h"
11 #include "components/autofill/core/browser/autofill_server_field_info.h"
12 #include "third_party/webrtc/libjingle/xmllite/qname.h"
13
14 namespace autofill {
15
AutofillXmlParser()16 AutofillXmlParser::AutofillXmlParser()
17 : succeeded_(true) {
18 }
19
~AutofillXmlParser()20 AutofillXmlParser::~AutofillXmlParser() {}
21
CharacterData(buzz::XmlParseContext * context,const char * text,int len)22 void AutofillXmlParser::CharacterData(
23 buzz::XmlParseContext* context, const char* text, int len) {
24 }
25
EndElement(buzz::XmlParseContext * context,const char * name)26 void AutofillXmlParser::EndElement(buzz::XmlParseContext* context,
27 const char* name) {
28 }
29
Error(buzz::XmlParseContext * context,XML_Error error_code)30 void AutofillXmlParser::Error(buzz::XmlParseContext* context,
31 XML_Error error_code) {
32 succeeded_ = false;
33 }
34
AutofillQueryXmlParser(std::vector<AutofillServerFieldInfo> * field_infos,UploadRequired * upload_required)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_);
41 }
42
~AutofillQueryXmlParser()43 AutofillQueryXmlParser::~AutofillQueryXmlParser() {}
44
StartElement(buzz::XmlParseContext * context,const char * name,const char ** attrs)45 void AutofillQueryXmlParser::StartElement(buzz::XmlParseContext* context,
46 const char* name,
47 const char** attrs) {
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;
54
55 // |attrs| is a NULL-terminated list of (attribute, value) pairs.
56 while (*attrs) {
57 buzz::QName attribute_qname = context->ResolveQName(*attrs, true);
58 ++attrs;
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;
65 }
66 ++attrs;
67 }
68 } else if (element.compare("field") == 0) {
69 if (!*attrs) {
70 // Missing the "autofilltype" attribute, abort.
71 context->RaiseError(XML_ERROR_ABORTED);
72 return;
73 }
74
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;
79
80 // |attrs| is a NULL-terminated list of (attribute, value) pairs.
81 while (*attrs) {
82 buzz::QName attribute_qname = context->ResolveQName(*attrs, true);
83 ++attrs;
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);
89 else
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;
94 }
95 ++attrs;
96 }
97
98 // Record this field type, default value pair.
99 field_infos_->push_back(field_info);
100 }
101 }
102
ParseElementDescriptor(buzz::XmlParseContext * context,const char * const * attrs,WebElementDescriptor * element_descriptor)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
108 // precedence.
109 // |attrs| is a NULL-terminated list of (attribute, value) pairs.
110 while (*attrs) {
111 buzz::QName attribute_qname = context->ResolveQName(*attrs, true);
112 ++attrs;
113 const std::string& attribute_name = attribute_qname.LocalPart();
114 buzz::QName value_qname = context->ResolveQName(*attrs, true);
115 ++attrs;
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;
120 break;
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;
126 break;
127 }
128 }
129 }
130
GetIntValue(buzz::XmlParseContext * context,const char * attribute)131 int AutofillQueryXmlParser::GetIntValue(buzz::XmlParseContext* context,
132 const char* attribute) {
133 char* attr_end = NULL;
134 int value = strtol(attribute, &attr_end, 10);
135 if (attr_end != NULL && attr_end == attribute) {
136 context->RaiseError(XML_ERROR_SYNTAX);
137 return 0;
138 }
139 return value;
140 }
141
AutofillUploadXmlParser(double * positive_upload_rate,double * negative_upload_rate)142 AutofillUploadXmlParser::AutofillUploadXmlParser(double* positive_upload_rate,
143 double* negative_upload_rate)
144 : succeeded_(false),
145 positive_upload_rate_(positive_upload_rate),
146 negative_upload_rate_(negative_upload_rate) {
147 DCHECK(positive_upload_rate_);
148 DCHECK(negative_upload_rate_);
149 }
150
StartElement(buzz::XmlParseContext * context,const char * name,const char ** attrs)151 void AutofillUploadXmlParser::StartElement(buzz::XmlParseContext* context,
152 const char* name,
153 const char** attrs) {
154 buzz::QName qname = context->ResolveQName(name, false);
155 const std::string &element = qname.LocalPart();
156 if (element.compare("autofilluploadresponse") == 0) {
157 // Loop over all attributes to get the upload rates.
158 while (*attrs) {
159 buzz::QName attribute_qname = context->ResolveQName(attrs[0], true);
160 const std::string &attribute_name = attribute_qname.LocalPart();
161 if (attribute_name.compare("positiveuploadrate") == 0) {
162 *positive_upload_rate_ = GetDoubleValue(context, attrs[1]);
163 } else if (attribute_name.compare("negativeuploadrate") == 0) {
164 *negative_upload_rate_ = GetDoubleValue(context, attrs[1]);
165 }
166 attrs += 2; // We peeked at attrs[0] and attrs[1], skip past both.
167 }
168 }
169 }
170
GetDoubleValue(buzz::XmlParseContext * context,const char * attribute)171 double AutofillUploadXmlParser::GetDoubleValue(buzz::XmlParseContext* context,
172 const char* attribute) {
173 char* attr_end = NULL;
174 double value = strtod(attribute, &attr_end);
175 if (attr_end != NULL && attr_end == attribute) {
176 context->RaiseError(XML_ERROR_SYNTAX);
177 return 0.0;
178 }
179 return value;
180 }
181
182 } // namespace autofill
183