Home | History | Annotate | Download | only in browser
      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