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 <string> 6 #include <vector> 7 8 #include "base/memory/scoped_ptr.h" 9 #include "base/strings/string_number_conversions.h" 10 #include "components/autofill/content/browser/autocheckout_page_meta_data.h" 11 #include "components/autofill/core/browser/autofill_xml_parser.h" 12 #include "components/autofill/core/browser/field_types.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 #include "third_party/libjingle/source/talk/xmllite/xmlparser.h" 15 16 namespace autofill { 17 namespace { 18 19 class AutofillQueryXmlParserTest : public testing::Test { 20 public: 21 AutofillQueryXmlParserTest(): upload_required_(USE_UPLOAD_RATES) {}; 22 virtual ~AutofillQueryXmlParserTest() {}; 23 24 protected: 25 void ParseQueryXML(const std::string& xml, bool should_succeed) { 26 // Create a parser. 27 AutofillQueryXmlParser parse_handler(&field_infos_, 28 &upload_required_, 29 &experiment_id_, 30 &page_meta_data_); 31 buzz::XmlParser parser(&parse_handler); 32 parser.Parse(xml.c_str(), xml.length(), true); 33 EXPECT_EQ(should_succeed, parse_handler.succeeded()); 34 } 35 36 std::vector<AutofillServerFieldInfo> field_infos_; 37 UploadRequired upload_required_; 38 std::string experiment_id_; 39 autofill::AutocheckoutPageMetaData page_meta_data_; 40 }; 41 42 class AutofillUploadXmlParserTest : public testing::Test { 43 public: 44 AutofillUploadXmlParserTest(): positive_(0), negative_(0) {}; 45 virtual ~AutofillUploadXmlParserTest() {}; 46 47 protected: 48 void ParseUploadXML(const std::string& xml, bool should_succeed) { 49 // Create a parser. 50 AutofillUploadXmlParser parse_handler(&positive_, &negative_); 51 buzz::XmlParser parser(&parse_handler); 52 parser.Parse(xml.c_str(), xml.length(), true); 53 54 EXPECT_EQ(should_succeed, parse_handler.succeeded()); 55 } 56 57 double positive_; 58 double negative_; 59 }; 60 61 TEST_F(AutofillQueryXmlParserTest, BasicQuery) { 62 // An XML string representing a basic query response. 63 std::string xml = "<autofillqueryresponse>" 64 "<field autofilltype=\"0\" />" 65 "<field autofilltype=\"1\" />" 66 "<field autofilltype=\"3\" />" 67 "<field autofilltype=\"2\" />" 68 "<field autofilltype=\"61\" defaultvalue=\"default\"/>" 69 "</autofillqueryresponse>"; 70 ParseQueryXML(xml, true); 71 72 EXPECT_EQ(USE_UPLOAD_RATES, upload_required_); 73 ASSERT_EQ(5U, field_infos_.size()); 74 EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type); 75 EXPECT_EQ(UNKNOWN_TYPE, field_infos_[1].field_type); 76 EXPECT_EQ(NAME_FIRST, field_infos_[2].field_type); 77 EXPECT_EQ(EMPTY_TYPE, field_infos_[3].field_type); 78 EXPECT_TRUE(field_infos_[3].default_value.empty()); 79 EXPECT_EQ(FIELD_WITH_DEFAULT_VALUE, field_infos_[4].field_type); 80 EXPECT_EQ("default", field_infos_[4].default_value); 81 EXPECT_TRUE(experiment_id_.empty()); 82 } 83 84 // Test parsing the upload required attribute. 85 TEST_F(AutofillQueryXmlParserTest, TestUploadRequired) { 86 std::string xml = "<autofillqueryresponse uploadrequired=\"true\">" 87 "<field autofilltype=\"0\" />" 88 "</autofillqueryresponse>"; 89 90 ParseQueryXML(xml, true); 91 92 EXPECT_EQ(upload_required_, upload_required_); 93 ASSERT_EQ(1U, field_infos_.size()); 94 EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type); 95 EXPECT_TRUE(experiment_id_.empty()); 96 97 field_infos_.clear(); 98 xml = "<autofillqueryresponse uploadrequired=\"false\">" 99 "<field autofilltype=\"0\" />" 100 "</autofillqueryresponse>"; 101 102 ParseQueryXML(xml, true); 103 104 EXPECT_EQ(UPLOAD_NOT_REQUIRED, upload_required_); 105 ASSERT_EQ(1U, field_infos_.size()); 106 EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type); 107 EXPECT_TRUE(experiment_id_.empty()); 108 109 field_infos_.clear(); 110 xml = "<autofillqueryresponse uploadrequired=\"bad_value\">" 111 "<field autofilltype=\"0\" />" 112 "</autofillqueryresponse>"; 113 114 ParseQueryXML(xml, true); 115 116 EXPECT_EQ(USE_UPLOAD_RATES, upload_required_); 117 ASSERT_EQ(1U, field_infos_.size()); 118 EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type); 119 EXPECT_TRUE(experiment_id_.empty()); 120 } 121 122 // Test parsing the experiment id attribute 123 TEST_F(AutofillQueryXmlParserTest, ParseExperimentId) { 124 // When the attribute is missing, we should get back the default value -- the 125 // empty string. 126 std::string xml = "<autofillqueryresponse>" 127 "<field autofilltype=\"0\" />" 128 "</autofillqueryresponse>"; 129 130 ParseQueryXML(xml, true); 131 132 EXPECT_EQ(USE_UPLOAD_RATES, upload_required_); 133 ASSERT_EQ(1U, field_infos_.size()); 134 EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type); 135 EXPECT_TRUE(experiment_id_.empty()); 136 137 field_infos_.clear(); 138 139 // When the attribute is present, make sure we parse it. 140 xml = "<autofillqueryresponse experimentid=\"FancyNewAlgorithm\">" 141 "<field autofilltype=\"0\" />" 142 "</autofillqueryresponse>"; 143 144 ParseQueryXML(xml, true); 145 146 EXPECT_EQ(USE_UPLOAD_RATES, upload_required_); 147 ASSERT_EQ(1U, field_infos_.size()); 148 EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type); 149 EXPECT_EQ(std::string("FancyNewAlgorithm"), experiment_id_); 150 151 field_infos_.clear(); 152 153 // Make sure that we can handle parsing both the upload required and the 154 // experiment id attribute together. 155 xml = "<autofillqueryresponse uploadrequired=\"false\"" 156 " experimentid=\"ServerSmartyPants\">" 157 "<field autofilltype=\"0\" />" 158 "</autofillqueryresponse>"; 159 160 ParseQueryXML(xml, true); 161 162 EXPECT_EQ(UPLOAD_NOT_REQUIRED, upload_required_); 163 ASSERT_EQ(1U, field_infos_.size()); 164 EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type); 165 EXPECT_EQ("ServerSmartyPants", experiment_id_); 166 } 167 168 // Fails on ASAN bot. http://crbug.com/253797 169 #if defined(ADDRESS_SANITIZER) 170 #define MAYBE_ParseAutofillFlow DISABLED_ParseAutofillFlow 171 #else 172 #define MAYBE_ParseAutofillFlow ParseAutofillFlow 173 #endif 174 175 // Test XML response with autofill_flow information. 176 TEST_F(AutofillQueryXmlParserTest, MAYBE_ParseAutofillFlow) { 177 std::string xml = "<autofillqueryresponse>" 178 "<field autofilltype=\"55\"/>" 179 "<autofill_flow page_no=\"1\" total_pages=\"10\">" 180 "<page_advance_button id=\"foo\"/>" 181 "<flow_page page_no=\"0\">" 182 "<type>1</type>" 183 "<type>2</type>" 184 "</flow_page>" 185 "<flow_page page_no=\"1\">" 186 "<type>3</type>" 187 "</flow_page>" 188 "</autofill_flow>" 189 "</autofillqueryresponse>"; 190 191 ParseQueryXML(xml, true); 192 193 EXPECT_EQ(1U, field_infos_.size()); 194 EXPECT_EQ(1, page_meta_data_.current_page_number); 195 EXPECT_EQ(10, page_meta_data_.total_pages); 196 EXPECT_TRUE(page_meta_data_.ignore_ajax); 197 EXPECT_EQ("foo", page_meta_data_.proceed_element_descriptor.descriptor); 198 EXPECT_EQ(autofill::WebElementDescriptor::ID, 199 page_meta_data_.proceed_element_descriptor.retrieval_method); 200 EXPECT_EQ(2U, page_meta_data_.page_types.size()); 201 EXPECT_EQ(2U, page_meta_data_.page_types[0].size()); 202 EXPECT_EQ(1U, page_meta_data_.page_types[1].size()); 203 EXPECT_EQ(AUTOCHECKOUT_STEP_SHIPPING, page_meta_data_.page_types[0][0]); 204 EXPECT_EQ(AUTOCHECKOUT_STEP_DELIVERY, page_meta_data_.page_types[0][1]); 205 EXPECT_EQ(AUTOCHECKOUT_STEP_BILLING, page_meta_data_.page_types[1][0]); 206 207 // Clear |field_infos_| for the next test; 208 field_infos_.clear(); 209 210 // Test css_selector as page_advance_button. 211 xml = "<autofillqueryresponse>" 212 "<field autofilltype=\"55\"/>" 213 "<autofill_flow page_no=\"1\" total_pages=\"10\">" 214 "<page_advance_button css_selector=\"[name="foo"]\"/>" 215 "</autofill_flow>" 216 "</autofillqueryresponse>"; 217 218 ParseQueryXML(xml, true); 219 220 EXPECT_EQ(1U, field_infos_.size()); 221 EXPECT_EQ(1, page_meta_data_.current_page_number); 222 EXPECT_EQ(10, page_meta_data_.total_pages); 223 EXPECT_EQ("[name=\"foo\"]", 224 page_meta_data_.proceed_element_descriptor.descriptor); 225 EXPECT_EQ(autofill::WebElementDescriptor::CSS_SELECTOR, 226 page_meta_data_.proceed_element_descriptor.retrieval_method); 227 228 // Clear |field_infos_| for the next test; 229 field_infos_.clear(); 230 231 // Test first attribute is always the one set. 232 xml = "<autofillqueryresponse>" 233 "<field autofilltype=\"55\"/>" 234 "<autofill_flow page_no=\"1\" total_pages=\"10\">" 235 "<page_advance_button css_selector=\"[name="foo"]\"" 236 " id=\"foo\"/>" 237 "</autofill_flow>" 238 "</autofillqueryresponse>"; 239 240 ParseQueryXML(xml, true); 241 242 EXPECT_EQ(1U, field_infos_.size()); 243 EXPECT_EQ(1, page_meta_data_.current_page_number); 244 EXPECT_EQ(10, page_meta_data_.total_pages); 245 EXPECT_EQ("[name=\"foo\"]", 246 page_meta_data_.proceed_element_descriptor.descriptor); 247 EXPECT_EQ(autofill::WebElementDescriptor::CSS_SELECTOR, 248 page_meta_data_.proceed_element_descriptor.retrieval_method); 249 250 // Clear |field_infos_| for the next test; 251 field_infos_.clear(); 252 253 // Test parsing click_elements_before_formfill correctly. 254 xml = "<autofillqueryresponse>" 255 "<field autofilltype=\"55\"/>" 256 "<autofill_flow page_no=\"1\" total_pages=\"10\">" 257 "<click_elements_before_formfill>" 258 "<web_element id=\"btn1\" /></click_elements_before_formfill>" 259 "<click_elements_before_formfill>" 260 "<web_element css_selector=\"[name="btn2"]\"/>" 261 "</click_elements_before_formfill>" 262 "</autofill_flow>" 263 "</autofillqueryresponse>"; 264 265 ParseQueryXML(xml, true); 266 267 EXPECT_EQ(1U, field_infos_.size()); 268 EXPECT_EQ(1, page_meta_data_.current_page_number); 269 EXPECT_EQ(10, page_meta_data_.total_pages); 270 ASSERT_EQ(2U, page_meta_data_.click_elements_before_form_fill.size()); 271 autofill::WebElementDescriptor& click_elment = 272 page_meta_data_.click_elements_before_form_fill[0]; 273 EXPECT_EQ("btn1", click_elment.descriptor); 274 EXPECT_EQ(autofill::WebElementDescriptor::ID, click_elment.retrieval_method); 275 click_elment = page_meta_data_.click_elements_before_form_fill[1]; 276 EXPECT_EQ("[name=\"btn2\"]", click_elment.descriptor); 277 EXPECT_EQ(autofill::WebElementDescriptor::CSS_SELECTOR, 278 click_elment.retrieval_method); 279 280 // Clear |field_infos_| for the next test; 281 field_infos_.clear(); 282 283 // Test parsing click_elements_after_formfill correctly. 284 xml = "<autofillqueryresponse>" 285 "<field autofilltype=\"55\"/>" 286 "<autofill_flow page_no=\"1\" total_pages=\"10\">" 287 "<click_elements_after_formfill>" 288 "<web_element id=\"btn1\" /></click_elements_after_formfill>" 289 "</autofill_flow>" 290 "</autofillqueryresponse>"; 291 292 ParseQueryXML(xml, true); 293 294 EXPECT_EQ(1U, field_infos_.size()); 295 EXPECT_EQ(1, page_meta_data_.current_page_number); 296 EXPECT_EQ(10, page_meta_data_.total_pages); 297 ASSERT_EQ(1U, page_meta_data_.click_elements_after_form_fill.size()); 298 click_elment = page_meta_data_.click_elements_after_form_fill[0]; 299 EXPECT_EQ("btn1", click_elment.descriptor); 300 EXPECT_EQ(autofill::WebElementDescriptor::ID, click_elment.retrieval_method); 301 302 // Clear |field_infos_| for the next test. 303 field_infos_.clear(); 304 305 // Test setting of ignore_ajax attribute. 306 xml = "<autofillqueryresponse>" 307 "<field autofilltype=\"55\"/>" 308 "<autofill_flow page_no=\"1\" total_pages=\"10\" ignore_ajax=\"true\">" 309 "<page_advance_button css_selector=\"[name="foo"]\"" 310 " id=\"foo\"/>" 311 "</autofill_flow>" 312 "</autofillqueryresponse>"; 313 314 ParseQueryXML(xml, true); 315 316 EXPECT_EQ(1U, field_infos_.size()); 317 EXPECT_EQ(1, page_meta_data_.current_page_number); 318 EXPECT_EQ(10, page_meta_data_.total_pages); 319 EXPECT_TRUE(page_meta_data_.ignore_ajax); 320 EXPECT_EQ("[name=\"foo\"]", 321 page_meta_data_.proceed_element_descriptor.descriptor); 322 EXPECT_EQ(autofill::WebElementDescriptor::CSS_SELECTOR, 323 page_meta_data_.proceed_element_descriptor.retrieval_method); 324 325 // Clear |field_infos_| for the next test. 326 field_infos_.clear(); 327 328 // Test redundant setting to false of ignore_ajax attribute. 329 xml = "<autofillqueryresponse>" 330 "<field autofilltype=\"55\"/>" 331 "<autofill_flow page_no=\"1\" total_pages=\"10\" ignore_ajax=\"false\">" 332 "<page_advance_button css_selector=\"[name="foo"]\"" 333 " id=\"foo\"/>" 334 "</autofill_flow>" 335 "</autofillqueryresponse>"; 336 337 ParseQueryXML(xml, true); 338 339 EXPECT_EQ(1U, field_infos_.size()); 340 EXPECT_EQ(1, page_meta_data_.current_page_number); 341 EXPECT_EQ(10, page_meta_data_.total_pages); 342 EXPECT_FALSE(page_meta_data_.ignore_ajax); 343 EXPECT_EQ("[name=\"foo\"]", 344 page_meta_data_.proceed_element_descriptor.descriptor); 345 EXPECT_EQ(autofill::WebElementDescriptor::CSS_SELECTOR, 346 page_meta_data_.proceed_element_descriptor.retrieval_method); 347 } 348 349 // Test badly formed XML queries. 350 TEST_F(AutofillQueryXmlParserTest, ParseErrors) { 351 // Test no Autofill type. 352 std::string xml = "<autofillqueryresponse>" 353 "<field/>" 354 "</autofillqueryresponse>"; 355 356 ParseQueryXML(xml, false); 357 358 EXPECT_EQ(USE_UPLOAD_RATES, upload_required_); 359 EXPECT_EQ(0U, field_infos_.size()); 360 EXPECT_TRUE(experiment_id_.empty()); 361 362 // Test an incorrect Autofill type. 363 xml = "<autofillqueryresponse>" 364 "<field autofilltype=\"-1\"/>" 365 "</autofillqueryresponse>"; 366 367 ParseQueryXML(xml, true); 368 369 EXPECT_EQ(USE_UPLOAD_RATES, upload_required_); 370 ASSERT_EQ(1U, field_infos_.size()); 371 // AutofillType was out of range and should be set to NO_SERVER_DATA. 372 EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type); 373 EXPECT_TRUE(experiment_id_.empty()); 374 375 // Test upper bound for the field type, MAX_VALID_FIELD_TYPE. 376 field_infos_.clear(); 377 xml = "<autofillqueryresponse><field autofilltype=\"" + 378 base::IntToString(MAX_VALID_FIELD_TYPE) + "\"/></autofillqueryresponse>"; 379 380 ParseQueryXML(xml, true); 381 382 EXPECT_EQ(USE_UPLOAD_RATES, upload_required_); 383 ASSERT_EQ(1U, field_infos_.size()); 384 // AutofillType was out of range and should be set to NO_SERVER_DATA. 385 EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type); 386 EXPECT_TRUE(experiment_id_.empty()); 387 388 // Test an incorrect Autofill type. 389 field_infos_.clear(); 390 xml = "<autofillqueryresponse>" 391 "<field autofilltype=\"No Type\"/>" 392 "</autofillqueryresponse>"; 393 394 // Parse fails but an entry is still added to field_infos_. 395 ParseQueryXML(xml, false); 396 397 EXPECT_EQ(USE_UPLOAD_RATES, upload_required_); 398 ASSERT_EQ(1U, field_infos_.size()); 399 EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type); 400 EXPECT_TRUE(experiment_id_.empty()); 401 } 402 403 // Test successfull upload response. 404 TEST_F(AutofillUploadXmlParserTest, TestSuccessfulResponse) { 405 ParseUploadXML("<autofilluploadresponse positiveuploadrate=\"0.5\" " 406 "negativeuploadrate=\"0.3\"/>", 407 true); 408 409 EXPECT_DOUBLE_EQ(0.5, positive_); 410 EXPECT_DOUBLE_EQ(0.3, negative_); 411 } 412 413 // Test failed upload response. 414 TEST_F(AutofillUploadXmlParserTest, TestFailedResponse) { 415 ParseUploadXML("<autofilluploadresponse positiveuploadrate=\"\" " 416 "negativeuploadrate=\"0.3\"/>", 417 false); 418 419 EXPECT_DOUBLE_EQ(0, positive_); 420 EXPECT_DOUBLE_EQ(0.3, negative_); // Partially parsed. 421 negative_ = 0; 422 423 ParseUploadXML("<autofilluploadresponse positiveuploadrate=\"0.5\" " 424 "negativeuploadrate=\"0.3\"", 425 false); 426 427 EXPECT_DOUBLE_EQ(0, positive_); 428 EXPECT_DOUBLE_EQ(0, negative_); 429 430 ParseUploadXML("bad data", false); 431 432 EXPECT_DOUBLE_EQ(0, positive_); 433 EXPECT_DOUBLE_EQ(0, negative_); 434 435 ParseUploadXML(std::string(), false); 436 437 EXPECT_DOUBLE_EQ(0, positive_); 438 EXPECT_DOUBLE_EQ(0, negative_); 439 } 440 441 } // namespace 442 } // namespace autofill 443