Home | History | Annotate | Download | only in autofill
      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 "third_party/libjingle/overrides/talk/xmllite/qname.h"
     12 
     13 AutofillXmlParser::AutofillXmlParser()
     14     : succeeded_(true) {
     15 }
     16 
     17 void AutofillXmlParser::CharacterData(
     18     buzz::XmlParseContext* context, const char* text, int len) {
     19 }
     20 
     21 void AutofillXmlParser::EndElement(buzz::XmlParseContext* context,
     22                                    const char* name) {
     23 }
     24 
     25 void AutofillXmlParser::Error(buzz::XmlParseContext* context,
     26                               XML_Error error_code) {
     27   succeeded_ = false;
     28 }
     29 
     30 AutofillQueryXmlParser::AutofillQueryXmlParser(
     31     std::vector<AutofillFieldType>* field_types,
     32     UploadRequired* upload_required,
     33     std::string* experiment_id)
     34     : field_types_(field_types),
     35       upload_required_(upload_required),
     36       experiment_id_(experiment_id) {
     37   DCHECK(upload_required_);
     38   DCHECK(experiment_id_);
     39 }
     40 
     41 void AutofillQueryXmlParser::StartElement(buzz::XmlParseContext* context,
     42                                           const char* name,
     43                                           const char** attrs) {
     44   buzz::QName qname = context->ResolveQName(name, false);
     45   const std::string& element = qname.LocalPart();
     46   if (element.compare("autofillqueryresponse") == 0) {
     47     // We check for the upload required attribute below, but if it's not
     48     // present, we use the default upload rates. Likewise, by default we assume
     49     // an empty experiment id.
     50     *upload_required_ = USE_UPLOAD_RATES;
     51     *experiment_id_ = std::string();
     52 
     53     // |attrs| is a NULL-terminated list of (attribute, value) pairs.
     54     while (*attrs) {
     55       buzz::QName attribute_qname = context->ResolveQName(attrs[0], true);
     56       const std::string& attribute_name = attribute_qname.LocalPart();
     57       if (attribute_name.compare("uploadrequired") == 0) {
     58         if (strcmp(attrs[1], "true") == 0)
     59           *upload_required_ = UPLOAD_REQUIRED;
     60         else if (strcmp(attrs[1], "false") == 0)
     61           *upload_required_ = UPLOAD_NOT_REQUIRED;
     62       } else if (attribute_name.compare("experimentid") == 0) {
     63         *experiment_id_ = attrs[1];
     64       }
     65 
     66       // Advance to the next (attribute, value) pair.
     67       attrs += 2;
     68     }
     69   } else if (element.compare("field") == 0) {
     70     if (!attrs[0]) {
     71       // Missing the "autofilltype" attribute, abort.
     72       context->RaiseError(XML_ERROR_ABORTED);
     73       return;
     74     }
     75 
     76     // Determine the field type from the attribute value.  There should be one
     77     // attribute (autofilltype) with an integer value.
     78     AutofillFieldType field_type = UNKNOWN_TYPE;
     79     buzz::QName attribute_qname = context->ResolveQName(attrs[0], true);
     80     const std::string& attribute_name = attribute_qname.LocalPart();
     81 
     82     if (attribute_name.compare("autofilltype") == 0) {
     83       int value = GetIntValue(context, attrs[1]);
     84       field_type = static_cast<AutofillFieldType>(value);
     85       if (field_type < 0 || field_type > MAX_VALID_FIELD_TYPE) {
     86         field_type = NO_SERVER_DATA;
     87       }
     88     }
     89 
     90     // Record this field type.
     91     field_types_->push_back(field_type);
     92   }
     93 }
     94 
     95 int AutofillQueryXmlParser::GetIntValue(buzz::XmlParseContext* context,
     96                                         const char* attribute) {
     97   char* attr_end = NULL;
     98   int value = strtol(attribute, &attr_end, 10);
     99   if (attr_end != NULL && attr_end == attribute) {
    100     context->RaiseError(XML_ERROR_SYNTAX);
    101     return 0;
    102   }
    103   return value;
    104 }
    105 
    106 AutofillUploadXmlParser::AutofillUploadXmlParser(double* positive_upload_rate,
    107                                                  double* negative_upload_rate)
    108     : succeeded_(false),
    109       positive_upload_rate_(positive_upload_rate),
    110       negative_upload_rate_(negative_upload_rate) {
    111   DCHECK(positive_upload_rate_);
    112   DCHECK(negative_upload_rate_);
    113 }
    114 
    115 void AutofillUploadXmlParser::StartElement(buzz::XmlParseContext* context,
    116                                            const char* name,
    117                                            const char** attrs) {
    118   buzz::QName qname = context->ResolveQName(name, false);
    119   const std::string &element = qname.LocalPart();
    120   if (element.compare("autofilluploadresponse") == 0) {
    121     // Loop over all attributes to get the upload rates.
    122     while (*attrs) {
    123       buzz::QName attribute_qname = context->ResolveQName(attrs[0], true);
    124       const std::string &attribute_name = attribute_qname.LocalPart();
    125       if (attribute_name.compare("positiveuploadrate") == 0) {
    126         *positive_upload_rate_ = GetDoubleValue(context, attrs[1]);
    127       } else if (attribute_name.compare("negativeuploadrate") == 0) {
    128         *negative_upload_rate_ = GetDoubleValue(context, attrs[1]);
    129       }
    130       attrs += 2;  // We peeked at attrs[0] and attrs[1], skip past both.
    131     }
    132   }
    133 }
    134 
    135 double AutofillUploadXmlParser::GetDoubleValue(buzz::XmlParseContext* context,
    136                                                const char* attribute) {
    137   char* attr_end = NULL;
    138   double value = strtod(attribute, &attr_end);
    139   if (attr_end != NULL && attr_end == attribute) {
    140     context->RaiseError(XML_ERROR_SYNTAX);
    141     return 0.0;
    142   }
    143   return value;
    144 }
    145