OLD | NEW |
| (Empty) |
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 "chrome/browser/autofill/autofill_server_field_info.h" | |
12 #include "third_party/libjingle/source/talk/xmllite/qname.h" | |
13 | |
14 AutofillXmlParser::AutofillXmlParser() | |
15 : succeeded_(true) { | |
16 } | |
17 | |
18 AutofillXmlParser::~AutofillXmlParser() {} | |
19 | |
20 void AutofillXmlParser::CharacterData( | |
21 buzz::XmlParseContext* context, const char* text, int len) { | |
22 } | |
23 | |
24 void AutofillXmlParser::EndElement(buzz::XmlParseContext* context, | |
25 const char* name) { | |
26 } | |
27 | |
28 void AutofillXmlParser::Error(buzz::XmlParseContext* context, | |
29 XML_Error error_code) { | |
30 succeeded_ = false; | |
31 } | |
32 | |
33 AutofillQueryXmlParser::AutofillQueryXmlParser( | |
34 std::vector<AutofillServerFieldInfo>* field_infos, | |
35 UploadRequired* upload_required, | |
36 std::string* experiment_id) | |
37 : field_infos_(field_infos), | |
38 upload_required_(upload_required), | |
39 current_page_number_(-1), | |
40 total_pages_(-1), | |
41 experiment_id_(experiment_id) { | |
42 DCHECK(upload_required_); | |
43 DCHECK(experiment_id_); | |
44 } | |
45 | |
46 AutofillQueryXmlParser::~AutofillQueryXmlParser() {} | |
47 | |
48 void AutofillQueryXmlParser::StartElement(buzz::XmlParseContext* context, | |
49 const char* name, | |
50 const char** attrs) { | |
51 buzz::QName qname = context->ResolveQName(name, false); | |
52 const std::string& element = qname.LocalPart(); | |
53 if (element.compare("autofillqueryresponse") == 0) { | |
54 // We check for the upload required attribute below, but if it's not | |
55 // present, we use the default upload rates. Likewise, by default we assume | |
56 // an empty experiment id. | |
57 *upload_required_ = USE_UPLOAD_RATES; | |
58 *experiment_id_ = std::string(); | |
59 | |
60 // |attrs| is a NULL-terminated list of (attribute, value) pairs. | |
61 while (*attrs) { | |
62 buzz::QName attribute_qname = context->ResolveQName(*attrs, true); | |
63 ++attrs; | |
64 const std::string& attribute_name = attribute_qname.LocalPart(); | |
65 if (attribute_name.compare("uploadrequired") == 0) { | |
66 if (strcmp(*attrs, "true") == 0) | |
67 *upload_required_ = UPLOAD_REQUIRED; | |
68 else if (strcmp(*attrs, "false") == 0) | |
69 *upload_required_ = UPLOAD_NOT_REQUIRED; | |
70 } else if (attribute_name.compare("experimentid") == 0) { | |
71 *experiment_id_ = *attrs; | |
72 } | |
73 ++attrs; | |
74 } | |
75 } else if (element.compare("field") == 0) { | |
76 if (!*attrs) { | |
77 // Missing the "autofilltype" attribute, abort. | |
78 context->RaiseError(XML_ERROR_ABORTED); | |
79 return; | |
80 } | |
81 | |
82 // Determine the field type from the attribute value. There should be one | |
83 // attribute (autofilltype) with an integer value. | |
84 AutofillServerFieldInfo field_info; | |
85 field_info.field_type = UNKNOWN_TYPE; | |
86 | |
87 // |attrs| is a NULL-terminated list of (attribute, value) pairs. | |
88 while (*attrs) { | |
89 buzz::QName attribute_qname = context->ResolveQName(*attrs, true); | |
90 ++attrs; | |
91 const std::string& attribute_name = attribute_qname.LocalPart(); | |
92 if (attribute_name.compare("autofilltype") == 0) { | |
93 int value = GetIntValue(context, *attrs); | |
94 if (value >= 0 && value < MAX_VALID_FIELD_TYPE) | |
95 field_info.field_type = static_cast<AutofillFieldType>(value); | |
96 else | |
97 field_info.field_type = NO_SERVER_DATA; | |
98 } else if (field_info.field_type == FIELD_WITH_DEFAULT_VALUE && | |
99 attribute_name.compare("defaultvalue") == 0) { | |
100 field_info.default_value = *attrs; | |
101 } | |
102 ++attrs; | |
103 } | |
104 | |
105 // Record this field type, default value pair. | |
106 field_infos_->push_back(field_info); | |
107 } else if (element.compare("autofill_flow") == 0) { | |
108 // |attrs| is a NULL-terminated list of (attribute, value) pairs. | |
109 while (*attrs) { | |
110 buzz::QName attribute_qname = context->ResolveQName(*attrs, true); | |
111 ++attrs; | |
112 const std::string& attribute_name = attribute_qname.LocalPart(); | |
113 if (attribute_name.compare("page_no") == 0) | |
114 current_page_number_ = GetIntValue(context, *attrs); | |
115 else if (attribute_name.compare("total_pages") == 0) | |
116 total_pages_ = GetIntValue(context, *attrs); | |
117 ++attrs; | |
118 } | |
119 } else if (element.compare("page_advance_button") == 0) { | |
120 // |attrs| is a NULL-terminated list of (attribute, value) pairs. | |
121 // If both id and css_selector are set, the first one to appear will take | |
122 // precedence. | |
123 while (*attrs) { | |
124 buzz::QName attribute_qname = context->ResolveQName(*attrs, true); | |
125 ++attrs; | |
126 const std::string& attribute_name = attribute_qname.LocalPart(); | |
127 buzz::QName value_qname = context->ResolveQName(*attrs, true); | |
128 ++attrs; | |
129 const std::string& attribute_value = value_qname.LocalPart(); | |
130 if (attribute_name.compare("id") == 0 && !attribute_value.empty()) { | |
131 proceed_element_descriptor_.reset(new autofill::WebElementDescriptor()); | |
132 proceed_element_descriptor_->retrieval_method = | |
133 autofill::WebElementDescriptor::ID; | |
134 proceed_element_descriptor_->descriptor = attribute_value; | |
135 break; | |
136 } else if (attribute_name.compare("css_selector") == 0 && | |
137 !attribute_value.empty()) { | |
138 proceed_element_descriptor_.reset(new autofill::WebElementDescriptor()); | |
139 proceed_element_descriptor_->retrieval_method = | |
140 autofill::WebElementDescriptor::CSS_SELECTOR; | |
141 proceed_element_descriptor_->descriptor = attribute_value; | |
142 break; | |
143 } | |
144 } | |
145 } | |
146 } | |
147 | |
148 int AutofillQueryXmlParser::GetIntValue(buzz::XmlParseContext* context, | |
149 const char* attribute) { | |
150 char* attr_end = NULL; | |
151 int value = strtol(attribute, &attr_end, 10); | |
152 if (attr_end != NULL && attr_end == attribute) { | |
153 context->RaiseError(XML_ERROR_SYNTAX); | |
154 return 0; | |
155 } | |
156 return value; | |
157 } | |
158 | |
159 AutofillUploadXmlParser::AutofillUploadXmlParser(double* positive_upload_rate, | |
160 double* negative_upload_rate) | |
161 : succeeded_(false), | |
162 positive_upload_rate_(positive_upload_rate), | |
163 negative_upload_rate_(negative_upload_rate) { | |
164 DCHECK(positive_upload_rate_); | |
165 DCHECK(negative_upload_rate_); | |
166 } | |
167 | |
168 void AutofillUploadXmlParser::StartElement(buzz::XmlParseContext* context, | |
169 const char* name, | |
170 const char** attrs) { | |
171 buzz::QName qname = context->ResolveQName(name, false); | |
172 const std::string &element = qname.LocalPart(); | |
173 if (element.compare("autofilluploadresponse") == 0) { | |
174 // Loop over all attributes to get the upload rates. | |
175 while (*attrs) { | |
176 buzz::QName attribute_qname = context->ResolveQName(attrs[0], true); | |
177 const std::string &attribute_name = attribute_qname.LocalPart(); | |
178 if (attribute_name.compare("positiveuploadrate") == 0) { | |
179 *positive_upload_rate_ = GetDoubleValue(context, attrs[1]); | |
180 } else if (attribute_name.compare("negativeuploadrate") == 0) { | |
181 *negative_upload_rate_ = GetDoubleValue(context, attrs[1]); | |
182 } | |
183 attrs += 2; // We peeked at attrs[0] and attrs[1], skip past both. | |
184 } | |
185 } | |
186 } | |
187 | |
188 double AutofillUploadXmlParser::GetDoubleValue(buzz::XmlParseContext* context, | |
189 const char* attribute) { | |
190 char* attr_end = NULL; | |
191 double value = strtod(attribute, &attr_end); | |
192 if (attr_end != NULL && attr_end == attribute) { | |
193 context->RaiseError(XML_ERROR_SYNTAX); | |
194 return 0.0; | |
195 } | |
196 return value; | |
197 } | |
OLD | NEW |