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