// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include "base/string_util.h" #include "base/test/test_timeouts.h" #include "base/utf_string_conversions.h" #include "chrome/browser/autofill/autofill_download.h" #include "chrome/common/net/test_url_fetcher_factory.h" #include "chrome/test/testing_profile.h" #include "net/url_request/url_request_status.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h" #include "webkit/glue/form_data.h" using webkit_glue::FormData; using WebKit::WebInputElement; // This tests AutoFillDownloadManager. AutoFillDownloadTestHelper implements // AutoFillDownloadManager::Observer and creates an instance of // AutoFillDownloadManager. Then it records responses to different initiated // requests, which are verified later. To mock network requests // TestURLFetcherFactory is used, which creates URLFetchers that do not // go over the wire, but allow calling back HTTP responses directly. // The responses in test are out of order and verify: successful query request, // successful upload request, failed upload request. class AutoFillDownloadTestHelper : public AutoFillDownloadManager::Observer { public: AutoFillDownloadTestHelper() : download_manager(&profile) { download_manager.SetObserver(this); // For chromium builds forces Start*Request to actually execute. download_manager.is_testing_ = true; } ~AutoFillDownloadTestHelper() { download_manager.SetObserver(NULL); } // AutoFillDownloadManager::Observer overridables: virtual void OnLoadedAutoFillHeuristics( const std::string& heuristic_xml) { ResponseData response; response.response = heuristic_xml; response.type_of_response = QUERY_SUCCESSFULL; responses_.push_back(response); }; virtual void OnUploadedAutoFillHeuristics(const std::string& form_signature) { ResponseData response; response.type_of_response = UPLOAD_SUCCESSFULL; responses_.push_back(response); } virtual void OnHeuristicsRequestError( const std::string& form_signature, AutoFillDownloadManager::AutoFillRequestType request_type, int http_error) { ResponseData response; response.signature = form_signature; response.error = http_error; response.type_of_response = request_type == AutoFillDownloadManager::REQUEST_QUERY ? REQUEST_QUERY_FAILED : REQUEST_UPLOAD_FAILED; responses_.push_back(response); } enum TYPE_OF_RESPONSE { QUERY_SUCCESSFULL, UPLOAD_SUCCESSFULL, REQUEST_QUERY_FAILED, REQUEST_UPLOAD_FAILED, }; struct ResponseData { TYPE_OF_RESPONSE type_of_response; int error; std::string signature; std::string response; ResponseData() : type_of_response(REQUEST_QUERY_FAILED), error(0) { } }; std::list responses_; TestingProfile profile; AutoFillDownloadManager download_manager; }; namespace { TEST(AutoFillDownloadTest, QueryAndUploadTest) { MessageLoopForUI message_loop; // Create and register factory. AutoFillDownloadTestHelper helper; TestURLFetcherFactory factory; URLFetcher::set_factory(&factory); FormData form; form.method = ASCIIToUTF16("post"); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("username"), ASCIIToUTF16("username"), string16(), ASCIIToUTF16("text"), 0)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("First Name"), ASCIIToUTF16("firstname"), string16(), ASCIIToUTF16("text"), 0)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Last Name"), ASCIIToUTF16("lastname"), string16(), ASCIIToUTF16("text"), 0)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("email"), ASCIIToUTF16("email"), string16(), ASCIIToUTF16("text"), 0)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("email2"), ASCIIToUTF16("email2"), string16(), ASCIIToUTF16("text"), 0)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("password"), ASCIIToUTF16("password"), string16(), ASCIIToUTF16("password"), 0)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("Submit"), string16(), ASCIIToUTF16("submit"), 0)); FormStructure *form_structure = new FormStructure(form); ScopedVector form_structures; form_structures.push_back(form_structure); form.fields.clear(); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("address"), ASCIIToUTF16("address"), string16(), ASCIIToUTF16("text"), 0)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("address2"), ASCIIToUTF16("address2"), string16(), ASCIIToUTF16("text"), 0)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("city"), ASCIIToUTF16("city"), string16(), ASCIIToUTF16("text"), 0)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("Submit"), string16(), ASCIIToUTF16("submit"), 0)); form_structure = new FormStructure(form); form_structures.push_back(form_structure); // Request with id 0. EXPECT_TRUE(helper.download_manager.StartQueryRequest(form_structures)); // Set upload to 100% so requests happen. helper.download_manager.SetPositiveUploadRate(1.0); helper.download_manager.SetNegativeUploadRate(1.0); // Request with id 1. EXPECT_TRUE(helper.download_manager.StartUploadRequest(*(form_structures[0]), true)); // Request with id 2. EXPECT_TRUE(helper.download_manager.StartUploadRequest(*(form_structures[1]), false)); const char *responses[] = { "" "" "" "" "" "" "" "" "" "", "", "", }; // Return them out of sequence. TestURLFetcher* fetcher = factory.GetFetcherByID(1); ASSERT_TRUE(fetcher); fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(), URLRequestStatus(), 200, ResponseCookies(), std::string(responses[1])); // After that upload rates would be adjusted to 0.5/0.3 EXPECT_DOUBLE_EQ(0.5, helper.download_manager.GetPositiveUploadRate()); EXPECT_DOUBLE_EQ(0.3, helper.download_manager.GetNegativeUploadRate()); fetcher = factory.GetFetcherByID(2); ASSERT_TRUE(fetcher); fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(), URLRequestStatus(), 404, ResponseCookies(), std::string(responses[2])); fetcher = factory.GetFetcherByID(0); ASSERT_TRUE(fetcher); fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(), URLRequestStatus(), 200, ResponseCookies(), std::string(responses[0])); EXPECT_EQ(static_cast(3), helper.responses_.size()); EXPECT_EQ(AutoFillDownloadTestHelper::UPLOAD_SUCCESSFULL, helper.responses_.front().type_of_response); EXPECT_EQ(0, helper.responses_.front().error); EXPECT_EQ(std::string(), helper.responses_.front().signature); // Expected response on non-query request is an empty string. EXPECT_EQ(std::string(), helper.responses_.front().response); helper.responses_.pop_front(); EXPECT_EQ(AutoFillDownloadTestHelper::REQUEST_UPLOAD_FAILED, helper.responses_.front().type_of_response); EXPECT_EQ(404, helper.responses_.front().error); EXPECT_EQ(form_structures[1]->FormSignature(), helper.responses_.front().signature); // Expected response on non-query request is an empty string. EXPECT_EQ(std::string(), helper.responses_.front().response); helper.responses_.pop_front(); EXPECT_EQ(helper.responses_.front().type_of_response, AutoFillDownloadTestHelper::QUERY_SUCCESSFULL); EXPECT_EQ(0, helper.responses_.front().error); EXPECT_EQ(std::string(), helper.responses_.front().signature); EXPECT_EQ(responses[0], helper.responses_.front().response); helper.responses_.pop_front(); // Set upload to 0% so no new requests happen. helper.download_manager.SetPositiveUploadRate(0.0); helper.download_manager.SetNegativeUploadRate(0.0); // No actual requests for the next two calls, as we set upload rate to 0%. EXPECT_FALSE(helper.download_manager.StartUploadRequest(*(form_structures[0]), true)); EXPECT_FALSE(helper.download_manager.StartUploadRequest(*(form_structures[1]), false)); fetcher = factory.GetFetcherByID(3); EXPECT_EQ(NULL, fetcher); // Request with id 3. EXPECT_TRUE(helper.download_manager.StartQueryRequest(form_structures)); fetcher = factory.GetFetcherByID(3); ASSERT_TRUE(fetcher); fetcher->set_backoff_delay( base::TimeDelta::FromMilliseconds(TestTimeouts::action_max_timeout_ms())); fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(), URLRequestStatus(), 500, ResponseCookies(), std::string(responses[0])); EXPECT_EQ(AutoFillDownloadTestHelper::REQUEST_QUERY_FAILED, helper.responses_.front().type_of_response); EXPECT_EQ(500, helper.responses_.front().error); // Expected response on non-query request is an empty string. EXPECT_EQ(std::string(), helper.responses_.front().response); helper.responses_.pop_front(); // Query requests should be ignored for the next 10 seconds. EXPECT_FALSE(helper.download_manager.StartQueryRequest(form_structures)); fetcher = factory.GetFetcherByID(4); EXPECT_EQ(NULL, fetcher); // Set upload to 100% so requests happen. helper.download_manager.SetPositiveUploadRate(1.0); // Request with id 4. EXPECT_TRUE(helper.download_manager.StartUploadRequest(*(form_structures[0]), true)); fetcher = factory.GetFetcherByID(4); ASSERT_TRUE(fetcher); fetcher->set_backoff_delay( base::TimeDelta::FromMilliseconds(TestTimeouts::action_max_timeout_ms())); fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(), URLRequestStatus(), 503, ResponseCookies(), std::string(responses[2])); EXPECT_EQ(AutoFillDownloadTestHelper::REQUEST_UPLOAD_FAILED, helper.responses_.front().type_of_response); EXPECT_EQ(503, helper.responses_.front().error); helper.responses_.pop_front(); // Upload requests should be ignored for the next 10 seconds. EXPECT_FALSE(helper.download_manager.StartUploadRequest(*(form_structures[0]), true)); fetcher = factory.GetFetcherByID(5); EXPECT_EQ(NULL, fetcher); // Make sure consumer of URLFetcher does the right thing. URLFetcher::set_factory(NULL); } } // namespace