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