blob: ea1a605e67bcfdbfdd0b3439d17c1d8691bbdf96 [file] [log] [blame]
[email protected]663bd9e2011-03-21 01:07:011// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]ec64212b2010-03-18 01:02:432// 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
[email protected]8f608c52011-03-30 16:16:317#include <stdlib.h>
8#include <string.h>
9
10#include "base/logging.h"
[email protected]732acb02013-01-22 17:04:4511#include "chrome/browser/autofill/autofill_server_field_info.h"
[email protected]0116cf52011-11-01 02:44:3212#include "third_party/libjingle/source/talk/xmllite/qname.h"
[email protected]ec64212b2010-03-18 01:02:4313
[email protected]663bd9e2011-03-21 01:07:0114AutofillXmlParser::AutofillXmlParser()
[email protected]ec64212b2010-03-18 01:02:4315 : succeeded_(true) {
16}
17
[email protected]7c5935d2013-01-24 19:11:4318AutofillXmlParser::~AutofillXmlParser() {}
19
[email protected]663bd9e2011-03-21 01:07:0120void AutofillXmlParser::CharacterData(
[email protected]ec64212b2010-03-18 01:02:4321 buzz::XmlParseContext* context, const char* text, int len) {
22}
23
[email protected]663bd9e2011-03-21 01:07:0124void AutofillXmlParser::EndElement(buzz::XmlParseContext* context,
[email protected]ec64212b2010-03-18 01:02:4325 const char* name) {
26}
27
[email protected]663bd9e2011-03-21 01:07:0128void AutofillXmlParser::Error(buzz::XmlParseContext* context,
[email protected]ec64212b2010-03-18 01:02:4329 XML_Error error_code) {
30 succeeded_ = false;
31}
32
[email protected]663bd9e2011-03-21 01:07:0133AutofillQueryXmlParser::AutofillQueryXmlParser(
[email protected]732acb02013-01-22 17:04:4534 std::vector<AutofillServerFieldInfo>* field_infos,
[email protected]5f372f82011-01-31 23:20:5035 UploadRequired* upload_required,
36 std::string* experiment_id)
[email protected]732acb02013-01-22 17:04:4537 : field_infos_(field_infos),
[email protected]5f372f82011-01-31 23:20:5038 upload_required_(upload_required),
[email protected]e899b962013-01-18 20:52:0839 current_page_number_(-1),
40 total_pages_(-1),
[email protected]5f372f82011-01-31 23:20:5041 experiment_id_(experiment_id) {
[email protected]ec64212b2010-03-18 01:02:4342 DCHECK(upload_required_);
[email protected]5f372f82011-01-31 23:20:5043 DCHECK(experiment_id_);
[email protected]ec64212b2010-03-18 01:02:4344}
45
[email protected]7c5935d2013-01-24 19:11:4346AutofillQueryXmlParser::~AutofillQueryXmlParser() {}
47
[email protected]663bd9e2011-03-21 01:07:0148void AutofillQueryXmlParser::StartElement(buzz::XmlParseContext* context,
[email protected]ec64212b2010-03-18 01:02:4349 const char* name,
50 const char** attrs) {
51 buzz::QName qname = context->ResolveQName(name, false);
[email protected]5f372f82011-01-31 23:20:5052 const std::string& element = qname.LocalPart();
[email protected]ec64212b2010-03-18 01:02:4353 if (element.compare("autofillqueryresponse") == 0) {
[email protected]5f372f82011-01-31 23:20:5054 // 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.
[email protected]ec64212b2010-03-18 01:02:4357 *upload_required_ = USE_UPLOAD_RATES;
[email protected]5f372f82011-01-31 23:20:5058 *experiment_id_ = std::string();
59
60 // |attrs| is a NULL-terminated list of (attribute, value) pairs.
61 while (*attrs) {
[email protected]732acb02013-01-22 17:04:4562 buzz::QName attribute_qname = context->ResolveQName(*attrs, true);
63 ++attrs;
[email protected]5f372f82011-01-31 23:20:5064 const std::string& attribute_name = attribute_qname.LocalPart();
[email protected]ec64212b2010-03-18 01:02:4365 if (attribute_name.compare("uploadrequired") == 0) {
[email protected]732acb02013-01-22 17:04:4566 if (strcmp(*attrs, "true") == 0)
[email protected]ec64212b2010-03-18 01:02:4367 *upload_required_ = UPLOAD_REQUIRED;
[email protected]732acb02013-01-22 17:04:4568 else if (strcmp(*attrs, "false") == 0)
[email protected]ec64212b2010-03-18 01:02:4369 *upload_required_ = UPLOAD_NOT_REQUIRED;
[email protected]5f372f82011-01-31 23:20:5070 } else if (attribute_name.compare("experimentid") == 0) {
[email protected]732acb02013-01-22 17:04:4571 *experiment_id_ = *attrs;
[email protected]ec64212b2010-03-18 01:02:4372 }
[email protected]732acb02013-01-22 17:04:4573 ++attrs;
[email protected]ec64212b2010-03-18 01:02:4374 }
75 } else if (element.compare("field") == 0) {
[email protected]732acb02013-01-22 17:04:4576 if (!*attrs) {
[email protected]ec64212b2010-03-18 01:02:4377 // 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.
[email protected]732acb02013-01-22 17:04:4584 AutofillServerFieldInfo field_info;
85 field_info.field_type = UNKNOWN_TYPE;
[email protected]ec64212b2010-03-18 01:02:4386
[email protected]732acb02013-01-22 17:04:4587 // |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;
[email protected]ec64212b2010-03-18 01:02:43101 }
[email protected]732acb02013-01-22 17:04:45102 ++attrs;
[email protected]ec64212b2010-03-18 01:02:43103 }
104
[email protected]732acb02013-01-22 17:04:45105 // Record this field type, default value pair.
106 field_infos_->push_back(field_info);
[email protected]e899b962013-01-18 20:52:08107 } 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 }
[email protected]7c5935d2013-01-24 19:11:43119 } 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 }
[email protected]ec64212b2010-03-18 01:02:43145 }
146}
147
[email protected]663bd9e2011-03-21 01:07:01148int AutofillQueryXmlParser::GetIntValue(buzz::XmlParseContext* context,
[email protected]ec64212b2010-03-18 01:02:43149 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
[email protected]663bd9e2011-03-21 01:07:01159AutofillUploadXmlParser::AutofillUploadXmlParser(double* positive_upload_rate,
[email protected]ec64212b2010-03-18 01:02:43160 double* negative_upload_rate)
[email protected]8cd7fd02010-07-22 18:21:02161 : succeeded_(false),
162 positive_upload_rate_(positive_upload_rate),
[email protected]ec64212b2010-03-18 01:02:43163 negative_upload_rate_(negative_upload_rate) {
164 DCHECK(positive_upload_rate_);
165 DCHECK(negative_upload_rate_);
166}
167
[email protected]663bd9e2011-03-21 01:07:01168void AutofillUploadXmlParser::StartElement(buzz::XmlParseContext* context,
[email protected]ec64212b2010-03-18 01:02:43169 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
[email protected]663bd9e2011-03-21 01:07:01188double AutofillUploadXmlParser::GetDoubleValue(buzz::XmlParseContext* context,
[email protected]ec64212b2010-03-18 01:02:43189 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}