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