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 <list> 6 7 #include "base/message_loop/message_loop.h" 8 #include "base/prefs/pref_service.h" 9 #include "base/strings/string_util.h" 10 #include "base/strings/utf_string_conversions.h" 11 #include "base/test/test_timeouts.h" 12 #include "components/autofill/core/browser/autofill_download.h" 13 #include "components/autofill/core/browser/autofill_field.h" 14 #include "components/autofill/core/browser/autofill_metrics.h" 15 #include "components/autofill/core/browser/autofill_test_utils.h" 16 #include "components/autofill/core/browser/autofill_type.h" 17 #include "components/autofill/core/browser/form_structure.h" 18 #include "components/autofill/core/browser/test_autofill_driver.h" 19 #include "components/autofill/core/common/form_data.h" 20 #include "net/url_request/test_url_fetcher_factory.h" 21 #include "net/url_request/url_request_status.h" 22 #include "net/url_request/url_request_test_util.h" 23 #include "testing/gmock/include/gmock/gmock.h" 24 #include "testing/gtest/include/gtest/gtest.h" 25 26 using base::ASCIIToUTF16; 27 28 namespace autofill { 29 30 namespace { 31 32 class MockAutofillMetrics : public AutofillMetrics { 33 public: 34 MockAutofillMetrics() {} 35 MOCK_CONST_METHOD1(LogServerQueryMetric, void(ServerQueryMetric metric)); 36 37 private: 38 DISALLOW_COPY_AND_ASSIGN(MockAutofillMetrics); 39 }; 40 41 // Call |fetcher->OnURLFetchComplete()| as the URLFetcher would when 42 // a response is received. Params allow caller to set fake status. 43 void FakeOnURLFetchComplete(net::TestURLFetcher* fetcher, 44 int response_code, 45 const std::string& response_body) { 46 fetcher->set_url(GURL()); 47 fetcher->set_status(net::URLRequestStatus()); 48 fetcher->set_response_code(response_code); 49 fetcher->SetResponseString(response_body); 50 51 fetcher->delegate()->OnURLFetchComplete(fetcher); 52 } 53 54 } // namespace 55 56 // This tests AutofillDownloadManager. AutofillDownloadTest implements 57 // AutofillDownloadManager::Observer and creates an instance of 58 // AutofillDownloadManager. Then it records responses to different initiated 59 // requests, which are verified later. To mock network requests 60 // TestURLFetcherFactory is used, which creates URLFetchers that do not 61 // go over the wire, but allow calling back HTTP responses directly. 62 // The responses in test are out of order and verify: successful query request, 63 // successful upload request, failed upload request. 64 class AutofillDownloadTest : public AutofillDownloadManager::Observer, 65 public testing::Test { 66 public: 67 AutofillDownloadTest() 68 : prefs_(test::PrefServiceForTesting()), 69 request_context_(new net::TestURLRequestContextGetter( 70 base::MessageLoopProxy::current())), 71 download_manager_(&driver_, prefs_.get(), this) { 72 driver_.SetURLRequestContext(request_context_); 73 } 74 75 void LimitCache(size_t cache_size) { 76 download_manager_.set_max_form_cache_size(cache_size); 77 } 78 79 // AutofillDownloadManager::Observer implementation. 80 virtual void OnLoadedServerPredictions( 81 const std::string& response_xml) OVERRIDE { 82 ResponseData response; 83 response.response = response_xml; 84 response.type_of_response = QUERY_SUCCESSFULL; 85 responses_.push_back(response); 86 } 87 88 virtual void OnUploadedPossibleFieldTypes() OVERRIDE { 89 ResponseData response; 90 response.type_of_response = UPLOAD_SUCCESSFULL; 91 responses_.push_back(response); 92 } 93 94 virtual void OnServerRequestError( 95 const std::string& form_signature, 96 AutofillDownloadManager::RequestType request_type, 97 int http_error) OVERRIDE { 98 ResponseData response; 99 response.signature = form_signature; 100 response.error = http_error; 101 response.type_of_response = 102 request_type == AutofillDownloadManager::REQUEST_QUERY ? 103 REQUEST_QUERY_FAILED : REQUEST_UPLOAD_FAILED; 104 responses_.push_back(response); 105 } 106 107 enum ResponseType { 108 QUERY_SUCCESSFULL, 109 UPLOAD_SUCCESSFULL, 110 REQUEST_QUERY_FAILED, 111 REQUEST_UPLOAD_FAILED, 112 }; 113 114 struct ResponseData { 115 ResponseType type_of_response; 116 int error; 117 std::string signature; 118 std::string response; 119 120 ResponseData() : type_of_response(REQUEST_QUERY_FAILED), error(0) {} 121 }; 122 123 base::MessageLoop message_loop_; 124 std::list<ResponseData> responses_; 125 scoped_ptr<PrefService> prefs_; 126 scoped_refptr<net::TestURLRequestContextGetter> request_context_; 127 TestAutofillDriver driver_; 128 AutofillDownloadManager download_manager_; 129 }; 130 131 TEST_F(AutofillDownloadTest, QueryAndUploadTest) { 132 // Create and register factory. 133 net::TestURLFetcherFactory factory; 134 135 FormData form; 136 form.method = ASCIIToUTF16("post"); 137 138 FormFieldData field; 139 field.label = ASCIIToUTF16("username"); 140 field.name = ASCIIToUTF16("username"); 141 field.form_control_type = "text"; 142 form.fields.push_back(field); 143 144 field.label = ASCIIToUTF16("First Name"); 145 field.name = ASCIIToUTF16("firstname"); 146 field.form_control_type = "text"; 147 form.fields.push_back(field); 148 149 field.label = ASCIIToUTF16("Last Name"); 150 field.name = ASCIIToUTF16("lastname"); 151 field.form_control_type = "text"; 152 form.fields.push_back(field); 153 154 field.label = ASCIIToUTF16("email"); 155 field.name = ASCIIToUTF16("email"); 156 field.form_control_type = "text"; 157 form.fields.push_back(field); 158 159 field.label = ASCIIToUTF16("email2"); 160 field.name = ASCIIToUTF16("email2"); 161 field.form_control_type = "text"; 162 form.fields.push_back(field); 163 164 field.label = ASCIIToUTF16("password"); 165 field.name = ASCIIToUTF16("password"); 166 field.form_control_type = "password"; 167 form.fields.push_back(field); 168 169 field.label = base::string16(); 170 field.name = ASCIIToUTF16("Submit"); 171 field.form_control_type = "submit"; 172 form.fields.push_back(field); 173 174 FormStructure *form_structure = new FormStructure(form); 175 ScopedVector<FormStructure> form_structures; 176 form_structures.push_back(form_structure); 177 178 form.fields.clear(); 179 180 field.label = ASCIIToUTF16("address"); 181 field.name = ASCIIToUTF16("address"); 182 field.form_control_type = "text"; 183 form.fields.push_back(field); 184 185 field.label = ASCIIToUTF16("address2"); 186 field.name = ASCIIToUTF16("address2"); 187 field.form_control_type = "text"; 188 form.fields.push_back(field); 189 190 field.label = ASCIIToUTF16("city"); 191 field.name = ASCIIToUTF16("city"); 192 field.form_control_type = "text"; 193 form.fields.push_back(field); 194 195 field.label = base::string16(); 196 field.name = ASCIIToUTF16("Submit"); 197 field.form_control_type = "submit"; 198 form.fields.push_back(field); 199 200 form_structure = new FormStructure(form); 201 form_structures.push_back(form_structure); 202 203 // Request with id 0. 204 MockAutofillMetrics mock_metric_logger; 205 EXPECT_CALL(mock_metric_logger, 206 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1); 207 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures.get(), 208 mock_metric_logger)); 209 // Set upload to 100% so requests happen. 210 download_manager_.SetPositiveUploadRate(1.0); 211 download_manager_.SetNegativeUploadRate(1.0); 212 // Request with id 1. 213 EXPECT_TRUE(download_manager_.StartUploadRequest( 214 *(form_structures[0]), true, ServerFieldTypeSet())); 215 // Request with id 2. 216 EXPECT_TRUE(download_manager_.StartUploadRequest( 217 *(form_structures[1]), false, ServerFieldTypeSet())); 218 219 const char *responses[] = { 220 "<autofillqueryresponse>" 221 "<field autofilltype=\"0\" />" 222 "<field autofilltype=\"3\" />" 223 "<field autofilltype=\"5\" />" 224 "<field autofilltype=\"9\" />" 225 "<field autofilltype=\"0\" />" 226 "<field autofilltype=\"30\" />" 227 "<field autofilltype=\"31\" />" 228 "<field autofilltype=\"33\" />" 229 "</autofillqueryresponse>", 230 "<autofilluploadresponse positiveuploadrate=\"0.5\" " 231 "negativeuploadrate=\"0.3\"/>", 232 "<html></html>", 233 }; 234 235 // Return them out of sequence. 236 net::TestURLFetcher* fetcher = factory.GetFetcherByID(1); 237 ASSERT_TRUE(fetcher); 238 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[1])); 239 240 // After that upload rates would be adjusted to 0.5/0.3 241 EXPECT_DOUBLE_EQ(0.5, download_manager_.GetPositiveUploadRate()); 242 EXPECT_DOUBLE_EQ(0.3, download_manager_.GetNegativeUploadRate()); 243 244 fetcher = factory.GetFetcherByID(2); 245 ASSERT_TRUE(fetcher); 246 FakeOnURLFetchComplete(fetcher, 404, std::string(responses[2])); 247 248 fetcher = factory.GetFetcherByID(0); 249 ASSERT_TRUE(fetcher); 250 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[0])); 251 EXPECT_EQ(static_cast<size_t>(3), responses_.size()); 252 253 EXPECT_EQ(AutofillDownloadTest::UPLOAD_SUCCESSFULL, 254 responses_.front().type_of_response); 255 EXPECT_EQ(0, responses_.front().error); 256 EXPECT_EQ(std::string(), responses_.front().signature); 257 // Expected response on non-query request is an empty string. 258 EXPECT_EQ(std::string(), responses_.front().response); 259 responses_.pop_front(); 260 261 EXPECT_EQ(AutofillDownloadTest::REQUEST_UPLOAD_FAILED, 262 responses_.front().type_of_response); 263 EXPECT_EQ(404, responses_.front().error); 264 EXPECT_EQ(form_structures[1]->FormSignature(), 265 responses_.front().signature); 266 // Expected response on non-query request is an empty string. 267 EXPECT_EQ(std::string(), responses_.front().response); 268 responses_.pop_front(); 269 270 EXPECT_EQ(responses_.front().type_of_response, 271 AutofillDownloadTest::QUERY_SUCCESSFULL); 272 EXPECT_EQ(0, responses_.front().error); 273 EXPECT_EQ(std::string(), responses_.front().signature); 274 EXPECT_EQ(responses[0], responses_.front().response); 275 responses_.pop_front(); 276 277 // Set upload to 0% so no new requests happen. 278 download_manager_.SetPositiveUploadRate(0.0); 279 download_manager_.SetNegativeUploadRate(0.0); 280 // No actual requests for the next two calls, as we set upload rate to 0%. 281 EXPECT_FALSE(download_manager_.StartUploadRequest( 282 *(form_structures[0]), true, ServerFieldTypeSet())); 283 EXPECT_FALSE(download_manager_.StartUploadRequest( 284 *(form_structures[1]), false, ServerFieldTypeSet())); 285 fetcher = factory.GetFetcherByID(3); 286 EXPECT_EQ(NULL, fetcher); 287 288 // Modify form structures to miss the cache. 289 field.label = ASCIIToUTF16("Address line 2"); 290 field.name = ASCIIToUTF16("address2"); 291 field.form_control_type = "text"; 292 form.fields.push_back(field); 293 form_structure = new FormStructure(form); 294 form_structures.push_back(form_structure); 295 296 // Request with id 3. 297 EXPECT_CALL(mock_metric_logger, 298 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1); 299 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures.get(), 300 mock_metric_logger)); 301 fetcher = factory.GetFetcherByID(3); 302 ASSERT_TRUE(fetcher); 303 fetcher->set_backoff_delay(TestTimeouts::action_max_timeout()); 304 FakeOnURLFetchComplete(fetcher, 500, std::string(responses[0])); 305 306 EXPECT_EQ(AutofillDownloadTest::REQUEST_QUERY_FAILED, 307 responses_.front().type_of_response); 308 EXPECT_EQ(500, responses_.front().error); 309 // Expected response on non-query request is an empty string. 310 EXPECT_EQ(std::string(), responses_.front().response); 311 responses_.pop_front(); 312 313 // Query requests should be ignored for the next 10 seconds. 314 EXPECT_CALL(mock_metric_logger, 315 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(0); 316 EXPECT_FALSE(download_manager_.StartQueryRequest(form_structures.get(), 317 mock_metric_logger)); 318 fetcher = factory.GetFetcherByID(4); 319 EXPECT_EQ(NULL, fetcher); 320 321 // Set upload required to true so requests happen. 322 form_structures[0]->upload_required_ = UPLOAD_REQUIRED; 323 // Request with id 4. 324 EXPECT_TRUE(download_manager_.StartUploadRequest( 325 *(form_structures[0]), true, ServerFieldTypeSet())); 326 fetcher = factory.GetFetcherByID(4); 327 ASSERT_TRUE(fetcher); 328 fetcher->set_backoff_delay(TestTimeouts::action_max_timeout()); 329 FakeOnURLFetchComplete(fetcher, 503, std::string(responses[2])); 330 EXPECT_EQ(AutofillDownloadTest::REQUEST_UPLOAD_FAILED, 331 responses_.front().type_of_response); 332 EXPECT_EQ(503, responses_.front().error); 333 responses_.pop_front(); 334 335 // Upload requests should be ignored for the next 10 seconds. 336 EXPECT_FALSE(download_manager_.StartUploadRequest( 337 *(form_structures[0]), true, ServerFieldTypeSet())); 338 fetcher = factory.GetFetcherByID(5); 339 EXPECT_EQ(NULL, fetcher); 340 } 341 342 TEST_F(AutofillDownloadTest, CacheQueryTest) { 343 // Create and register factory. 344 net::TestURLFetcherFactory factory; 345 346 FormData form; 347 form.method = ASCIIToUTF16("post"); 348 349 FormFieldData field; 350 field.form_control_type = "text"; 351 352 field.label = ASCIIToUTF16("username"); 353 field.name = ASCIIToUTF16("username"); 354 form.fields.push_back(field); 355 356 field.label = ASCIIToUTF16("First Name"); 357 field.name = ASCIIToUTF16("firstname"); 358 form.fields.push_back(field); 359 360 field.label = ASCIIToUTF16("Last Name"); 361 field.name = ASCIIToUTF16("lastname"); 362 form.fields.push_back(field); 363 364 FormStructure *form_structure = new FormStructure(form); 365 ScopedVector<FormStructure> form_structures0; 366 form_structures0.push_back(form_structure); 367 368 // Add a slightly different form, which should result in a different request. 369 field.label = ASCIIToUTF16("email"); 370 field.name = ASCIIToUTF16("email"); 371 form.fields.push_back(field); 372 form_structure = new FormStructure(form); 373 ScopedVector<FormStructure> form_structures1; 374 form_structures1.push_back(form_structure); 375 376 // Add another slightly different form, which should also result in a 377 // different request. 378 field.label = ASCIIToUTF16("email2"); 379 field.name = ASCIIToUTF16("email2"); 380 form.fields.push_back(field); 381 form_structure = new FormStructure(form); 382 ScopedVector<FormStructure> form_structures2; 383 form_structures2.push_back(form_structure); 384 385 // Limit cache to two forms. 386 LimitCache(2); 387 388 const char *responses[] = { 389 "<autofillqueryresponse>" 390 "<field autofilltype=\"0\" />" 391 "<field autofilltype=\"3\" />" 392 "<field autofilltype=\"5\" />" 393 "</autofillqueryresponse>", 394 "<autofillqueryresponse>" 395 "<field autofilltype=\"0\" />" 396 "<field autofilltype=\"3\" />" 397 "<field autofilltype=\"5\" />" 398 "<field autofilltype=\"9\" />" 399 "</autofillqueryresponse>", 400 "<autofillqueryresponse>" 401 "<field autofilltype=\"0\" />" 402 "<field autofilltype=\"3\" />" 403 "<field autofilltype=\"5\" />" 404 "<field autofilltype=\"9\" />" 405 "<field autofilltype=\"0\" />" 406 "</autofillqueryresponse>", 407 }; 408 409 // Request with id 0. 410 MockAutofillMetrics mock_metric_logger; 411 EXPECT_CALL(mock_metric_logger, 412 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1); 413 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get(), 414 mock_metric_logger)); 415 // No responses yet 416 EXPECT_EQ(static_cast<size_t>(0), responses_.size()); 417 418 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); 419 ASSERT_TRUE(fetcher); 420 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[0])); 421 ASSERT_EQ(static_cast<size_t>(1), responses_.size()); 422 EXPECT_EQ(responses[0], responses_.front().response); 423 424 responses_.clear(); 425 426 // No actual request - should be a cache hit. 427 EXPECT_CALL(mock_metric_logger, 428 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1); 429 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get(), 430 mock_metric_logger)); 431 // Data is available immediately from cache - no over-the-wire trip. 432 ASSERT_EQ(static_cast<size_t>(1), responses_.size()); 433 EXPECT_EQ(responses[0], responses_.front().response); 434 responses_.clear(); 435 436 // Request with id 1. 437 EXPECT_CALL(mock_metric_logger, 438 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1); 439 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures1.get(), 440 mock_metric_logger)); 441 // No responses yet 442 EXPECT_EQ(static_cast<size_t>(0), responses_.size()); 443 444 fetcher = factory.GetFetcherByID(1); 445 ASSERT_TRUE(fetcher); 446 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[1])); 447 ASSERT_EQ(static_cast<size_t>(1), responses_.size()); 448 EXPECT_EQ(responses[1], responses_.front().response); 449 450 responses_.clear(); 451 452 // Request with id 2. 453 EXPECT_CALL(mock_metric_logger, 454 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1); 455 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures2.get(), 456 mock_metric_logger)); 457 458 fetcher = factory.GetFetcherByID(2); 459 ASSERT_TRUE(fetcher); 460 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[2])); 461 ASSERT_EQ(static_cast<size_t>(1), responses_.size()); 462 EXPECT_EQ(responses[2], responses_.front().response); 463 464 responses_.clear(); 465 466 // No actual requests - should be a cache hit. 467 EXPECT_CALL(mock_metric_logger, 468 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1); 469 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures1.get(), 470 mock_metric_logger)); 471 472 EXPECT_CALL(mock_metric_logger, 473 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1); 474 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures2.get(), 475 mock_metric_logger)); 476 477 ASSERT_EQ(static_cast<size_t>(2), responses_.size()); 478 EXPECT_EQ(responses[1], responses_.front().response); 479 EXPECT_EQ(responses[2], responses_.back().response); 480 responses_.clear(); 481 482 // The first structure should've expired. 483 // Request with id 3. 484 EXPECT_CALL(mock_metric_logger, 485 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1); 486 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get(), 487 mock_metric_logger)); 488 // No responses yet 489 EXPECT_EQ(static_cast<size_t>(0), responses_.size()); 490 491 fetcher = factory.GetFetcherByID(3); 492 ASSERT_TRUE(fetcher); 493 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[0])); 494 ASSERT_EQ(static_cast<size_t>(1), responses_.size()); 495 EXPECT_EQ(responses[0], responses_.front().response); 496 } 497 498 } // namespace autofill 499