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