1 // Copyright (c) 2011 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 "chrome/browser/autofill/autofill_xml_parser.h"
6
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include "base/logging.h"
11 #include "third_party/libjingle/overrides/talk/xmllite/qname.h"
12
AutofillXmlParser()13 AutofillXmlParser::AutofillXmlParser()
14 : succeeded_(true) {
15 }
16
CharacterData(buzz::XmlParseContext * context,const char * text,int len)17 void AutofillXmlParser::CharacterData(
18 buzz::XmlParseContext* context, const char* text, int len) {
19 }
20
EndElement(buzz::XmlParseContext * context,const char * name)21 void AutofillXmlParser::EndElement(buzz::XmlParseContext* context,
22 const char* name) {
23 }
24
Error(buzz::XmlParseContext * context,XML_Error error_code)25 void AutofillXmlParser::Error(buzz::XmlParseContext* context,
26 XML_Error error_code) {
27 succeeded_ = false;
28 }
29
AutofillQueryXmlParser(std::vector<AutofillFieldType> * field_types,UploadRequired * upload_required,std::string * experiment_id)30 AutofillQueryXmlParser::AutofillQueryXmlParser(
31 std::vector<AutofillFieldType>* field_types,
32 UploadRequired* upload_required,
33 std::string* experiment_id)
34 : field_types_(field_types),
35 upload_required_(upload_required),
36 experiment_id_(experiment_id) {
37 DCHECK(upload_required_);
38 DCHECK(experiment_id_);
39 }
40
StartElement(buzz::XmlParseContext * context,const char * name,const char ** attrs)41 void AutofillQueryXmlParser::StartElement(buzz::XmlParseContext* context,
42 const char* name,
43 const char** attrs) {
44 buzz::QName qname = context->ResolveQName(name, false);
45 const std::string& element = qname.LocalPart();
46 if (element.compare("autofillqueryresponse") == 0) {
47 // We check for the upload required attribute below, but if it's not
48 // present, we use the default upload rates. Likewise, by default we assume
49 // an empty experiment id.
50 *upload_required_ = USE_UPLOAD_RATES;
51 *experiment_id_ = std::string();
52
53 // |attrs| is a NULL-terminated list of (attribute, value) pairs.
54 while (*attrs) {
55 buzz::QName attribute_qname = context->ResolveQName(attrs[0], true);
56 const std::string& attribute_name = attribute_qname.LocalPart();
57 if (attribute_name.compare("uploadrequired") == 0) {
58 if (strcmp(attrs[1], "true") == 0)
59 *upload_required_ = UPLOAD_REQUIRED;
60 else if (strcmp(attrs[1], "false") == 0)
61 *upload_required_ = UPLOAD_NOT_REQUIRED;
62 } else if (attribute_name.compare("experimentid") == 0) {
63 *experiment_id_ = attrs[1];
64 }
65
66 // Advance to the next (attribute, value) pair.
67 attrs += 2;
68 }
69 } else if (element.compare("field") == 0) {
70 if (!attrs[0]) {
71 // Missing the "autofilltype" attribute, abort.
72 context->RaiseError(XML_ERROR_ABORTED);
73 return;
74 }
75
76 // Determine the field type from the attribute value. There should be one
77 // attribute (autofilltype) with an integer value.
78 AutofillFieldType field_type = UNKNOWN_TYPE;
79 buzz::QName attribute_qname = context->ResolveQName(attrs[0], true);
80 const std::string& attribute_name = attribute_qname.LocalPart();
81
82 if (attribute_name.compare("autofilltype") == 0) {
83 int value = GetIntValue(context, attrs[1]);
84 field_type = static_cast<AutofillFieldType>(value);
85 if (field_type < 0 || field_type > MAX_VALID_FIELD_TYPE) {
86 field_type = NO_SERVER_DATA;
87 }
88 }
89
90 // Record this field type.
91 field_types_->push_back(field_type);
92 }
93 }
94
GetIntValue(buzz::XmlParseContext * context,const char * attribute)95 int AutofillQueryXmlParser::GetIntValue(buzz::XmlParseContext* context,
96 const char* attribute) {
97 char* attr_end = NULL;
98 int value = strtol(attribute, &attr_end, 10);
99 if (attr_end != NULL && attr_end == attribute) {
100 context->RaiseError(XML_ERROR_SYNTAX);
101 return 0;
102 }
103 return value;
104 }
105
AutofillUploadXmlParser(double * positive_upload_rate,double * negative_upload_rate)106 AutofillUploadXmlParser::AutofillUploadXmlParser(double* positive_upload_rate,
107 double* negative_upload_rate)
108 : succeeded_(false),
109 positive_upload_rate_(positive_upload_rate),
110 negative_upload_rate_(negative_upload_rate) {
111 DCHECK(positive_upload_rate_);
112 DCHECK(negative_upload_rate_);
113 }
114
StartElement(buzz::XmlParseContext * context,const char * name,const char ** attrs)115 void AutofillUploadXmlParser::StartElement(buzz::XmlParseContext* context,
116 const char* name,
117 const char** attrs) {
118 buzz::QName qname = context->ResolveQName(name, false);
119 const std::string &element = qname.LocalPart();
120 if (element.compare("autofilluploadresponse") == 0) {
121 // Loop over all attributes to get the upload rates.
122 while (*attrs) {
123 buzz::QName attribute_qname = context->ResolveQName(attrs[0], true);
124 const std::string &attribute_name = attribute_qname.LocalPart();
125 if (attribute_name.compare("positiveuploadrate") == 0) {
126 *positive_upload_rate_ = GetDoubleValue(context, attrs[1]);
127 } else if (attribute_name.compare("negativeuploadrate") == 0) {
128 *negative_upload_rate_ = GetDoubleValue(context, attrs[1]);
129 }
130 attrs += 2; // We peeked at attrs[0] and attrs[1], skip past both.
131 }
132 }
133 }
134
GetDoubleValue(buzz::XmlParseContext * context,const char * attribute)135 double AutofillUploadXmlParser::GetDoubleValue(buzz::XmlParseContext* context,
136 const char* attribute) {
137 char* attr_end = NULL;
138 double value = strtod(attribute, &attr_end);
139 if (attr_end != NULL && attr_end == attribute) {
140 context->RaiseError(XML_ERROR_SYNTAX);
141 return 0.0;
142 }
143 return value;
144 }
145