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