1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autofill/autofill_xml_parser.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <stdlib.h>
8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <string.h>
9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/logging.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/libjingle/overrides/talk/xmllite/qname.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenAutofillXmlParser::AutofillXmlParser()
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : succeeded_(true) {
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutofillXmlParser::CharacterData(
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    buzz::XmlParseContext* context, const char* text, int len) {
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutofillXmlParser::EndElement(buzz::XmlParseContext* context,
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   const char* name) {
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutofillXmlParser::Error(buzz::XmlParseContext* context,
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              XML_Error error_code) {
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  succeeded_ = false;
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenAutofillQueryXmlParser::AutofillQueryXmlParser(
31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    std::vector<AutofillFieldType>* field_types,
3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    UploadRequired* upload_required,
3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::string* experiment_id)
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : field_types_(field_types),
3572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      upload_required_(upload_required),
3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      experiment_id_(experiment_id) {
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(upload_required_);
3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(experiment_id_);
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutofillQueryXmlParser::StartElement(buzz::XmlParseContext* context,
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          const char* name,
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          const char** attrs) {
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  buzz::QName qname = context->ResolveQName(name, false);
4572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const std::string& element = qname.LocalPart();
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (element.compare("autofillqueryresponse") == 0) {
4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // We check for the upload required attribute below, but if it's not
4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // present, we use the default upload rates. Likewise, by default we assume
4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // an empty experiment id.
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *upload_required_ = USE_UPLOAD_RATES;
5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    *experiment_id_ = std::string();
5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // |attrs| is a NULL-terminated list of (attribute, value) pairs.
5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    while (*attrs) {
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      buzz::QName attribute_qname = context->ResolveQName(attrs[0], true);
5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      const std::string& attribute_name = attribute_qname.LocalPart();
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (attribute_name.compare("uploadrequired") == 0) {
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (strcmp(attrs[1], "true") == 0)
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          *upload_required_ = UPLOAD_REQUIRED;
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        else if (strcmp(attrs[1], "false") == 0)
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          *upload_required_ = UPLOAD_NOT_REQUIRED;
6272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      } else if (attribute_name.compare("experimentid") == 0) {
6372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        *experiment_id_ = attrs[1];
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
6572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
6672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // Advance to the next (attribute, value) pair.
6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      attrs += 2;
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (element.compare("field") == 0) {
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!attrs[0]) {
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Missing the "autofilltype" attribute, abort.
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      context->RaiseError(XML_ERROR_ABORTED);
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Determine the field type from the attribute value.  There should be one
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // attribute (autofilltype) with an integer value.
78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    AutofillFieldType field_type = UNKNOWN_TYPE;
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    buzz::QName attribute_qname = context->ResolveQName(attrs[0], true);
8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const std::string& attribute_name = attribute_qname.LocalPart();
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (attribute_name.compare("autofilltype") == 0) {
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int value = GetIntValue(context, attrs[1]);
84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      field_type = static_cast<AutofillFieldType>(value);
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (field_type < 0 || field_type > MAX_VALID_FIELD_TYPE) {
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        field_type = NO_SERVER_DATA;
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Record this field type.
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    field_types_->push_back(field_type);
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint AutofillQueryXmlParser::GetIntValue(buzz::XmlParseContext* context,
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        const char* attribute) {
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char* attr_end = NULL;
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int value = strtol(attribute, &attr_end, 10);
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (attr_end != NULL && attr_end == attribute) {
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    context->RaiseError(XML_ERROR_SYNTAX);
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return value;
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenAutofillUploadXmlParser::AutofillUploadXmlParser(double* positive_upload_rate,
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                 double* negative_upload_rate)
1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : succeeded_(false),
1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      positive_upload_rate_(positive_upload_rate),
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      negative_upload_rate_(negative_upload_rate) {
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(positive_upload_rate_);
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(negative_upload_rate_);
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutofillUploadXmlParser::StartElement(buzz::XmlParseContext* context,
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           const char* name,
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           const char** attrs) {
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  buzz::QName qname = context->ResolveQName(name, false);
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const std::string &element = qname.LocalPart();
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (element.compare("autofilluploadresponse") == 0) {
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Loop over all attributes to get the upload rates.
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    while (*attrs) {
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      buzz::QName attribute_qname = context->ResolveQName(attrs[0], true);
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const std::string &attribute_name = attribute_qname.LocalPart();
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (attribute_name.compare("positiveuploadrate") == 0) {
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        *positive_upload_rate_ = GetDoubleValue(context, attrs[1]);
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else if (attribute_name.compare("negativeuploadrate") == 0) {
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        *negative_upload_rate_ = GetDoubleValue(context, attrs[1]);
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      attrs += 2;  // We peeked at attrs[0] and attrs[1], skip past both.
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsendouble AutofillUploadXmlParser::GetDoubleValue(buzz::XmlParseContext* context,
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                               const char* attribute) {
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char* attr_end = NULL;
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  double value = strtod(attribute, &attr_end);
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (attr_end != NULL && attr_end == attribute) {
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    context->RaiseError(XML_ERROR_SYNTAX);
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0.0;
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return value;
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
145