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