• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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