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