Home | History | Annotate | Download | only in url_request
      1 // Copyright (c) 2012 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 "net/url_request/url_request_ftp_job.h"
      6 
      7 #include "base/memory/ref_counted.h"
      8 #include "base/memory/scoped_vector.h"
      9 #include "base/run_loop.h"
     10 #include "net/base/request_priority.h"
     11 #include "net/ftp/ftp_auth_cache.h"
     12 #include "net/http/http_transaction_unittest.h"
     13 #include "net/proxy/mock_proxy_resolver.h"
     14 #include "net/proxy/proxy_config_service.h"
     15 #include "net/proxy/proxy_config_service_fixed.h"
     16 #include "net/socket/socket_test_util.h"
     17 #include "net/url_request/ftp_protocol_handler.h"
     18 #include "net/url_request/url_request.h"
     19 #include "net/url_request/url_request_context.h"
     20 #include "net/url_request/url_request_job_factory_impl.h"
     21 #include "net/url_request/url_request_status.h"
     22 #include "net/url_request/url_request_test_util.h"
     23 #include "testing/gtest/include/gtest/gtest.h"
     24 #include "url/gurl.h"
     25 
     26 namespace net {
     27 
     28 class FtpTestURLRequestContext : public TestURLRequestContext {
     29  public:
     30   FtpTestURLRequestContext(ClientSocketFactory* socket_factory,
     31                            ProxyService* proxy_service,
     32                            NetworkDelegate* network_delegate,
     33                            FtpTransactionFactory* ftp_transaction_factory)
     34       : TestURLRequestContext(true),
     35         ftp_protocol_handler_(new FtpProtocolHandler(ftp_transaction_factory)) {
     36     set_client_socket_factory(socket_factory);
     37     context_storage_.set_proxy_service(proxy_service);
     38     set_network_delegate(network_delegate);
     39     URLRequestJobFactoryImpl* job_factory = new URLRequestJobFactoryImpl;
     40     job_factory->SetProtocolHandler("ftp", ftp_protocol_handler_);
     41     context_storage_.set_job_factory(job_factory);
     42     Init();
     43   }
     44 
     45   FtpAuthCache* GetFtpAuthCache() {
     46     return ftp_protocol_handler_->ftp_auth_cache_.get();
     47   }
     48 
     49   void set_proxy_service(ProxyService* proxy_service) {
     50     context_storage_.set_proxy_service(proxy_service);
     51   }
     52 
     53  private:
     54   FtpProtocolHandler* ftp_protocol_handler_;
     55 };
     56 
     57 namespace {
     58 
     59 class SimpleProxyConfigService : public ProxyConfigService {
     60  public:
     61   SimpleProxyConfigService() {
     62     // Any FTP requests that ever go through HTTP paths are proxied requests.
     63     config_.proxy_rules().ParseFromString("ftp=localhost");
     64   }
     65 
     66   virtual void AddObserver(Observer* observer) OVERRIDE {
     67     observer_ = observer;
     68   }
     69 
     70   virtual void RemoveObserver(Observer* observer) OVERRIDE {
     71     if (observer_ == observer) {
     72       observer_ = NULL;
     73     }
     74   }
     75 
     76   virtual ConfigAvailability GetLatestProxyConfig(
     77       ProxyConfig* config) OVERRIDE {
     78     *config = config_;
     79     return CONFIG_VALID;
     80   }
     81 
     82   void IncrementConfigId() {
     83     config_.set_id(config_.id() + 1);
     84     observer_->OnProxyConfigChanged(config_, ProxyConfigService::CONFIG_VALID);
     85   }
     86 
     87  private:
     88   ProxyConfig config_;
     89   Observer* observer_;
     90 };
     91 
     92 // Inherit from URLRequestFtpJob to expose the priority and some
     93 // other hidden functions.
     94 class TestURLRequestFtpJob : public URLRequestFtpJob {
     95  public:
     96   TestURLRequestFtpJob(URLRequest* request,
     97                        FtpTransactionFactory* ftp_factory,
     98                        FtpAuthCache* ftp_auth_cache)
     99       : URLRequestFtpJob(request, NULL, ftp_factory, ftp_auth_cache) {}
    100 
    101   using URLRequestFtpJob::SetPriority;
    102   using URLRequestFtpJob::Start;
    103   using URLRequestFtpJob::Kill;
    104   using URLRequestFtpJob::priority;
    105 
    106  protected:
    107   virtual ~TestURLRequestFtpJob() {}
    108 };
    109 
    110 class MockFtpTransactionFactory : public FtpTransactionFactory {
    111  public:
    112   virtual FtpTransaction* CreateTransaction() OVERRIDE {
    113     return NULL;
    114   }
    115 
    116   virtual void Suspend(bool suspend) OVERRIDE {}
    117 };
    118 
    119 // Fixture for priority-related tests. Priority matters when there is
    120 // an HTTP proxy.
    121 class URLRequestFtpJobPriorityTest : public testing::Test {
    122  protected:
    123   URLRequestFtpJobPriorityTest()
    124       : proxy_service_(new SimpleProxyConfigService, NULL, NULL),
    125         req_(GURL("ftp://ftp.example.com"),
    126              DEFAULT_PRIORITY,
    127              &delegate_,
    128              &context_) {
    129     context_.set_proxy_service(&proxy_service_);
    130     context_.set_http_transaction_factory(&network_layer_);
    131   }
    132 
    133   ProxyService proxy_service_;
    134   MockNetworkLayer network_layer_;
    135   MockFtpTransactionFactory ftp_factory_;
    136   FtpAuthCache ftp_auth_cache_;
    137   TestURLRequestContext context_;
    138   TestDelegate delegate_;
    139   TestURLRequest req_;
    140 };
    141 
    142 // Make sure that SetPriority actually sets the URLRequestFtpJob's
    143 // priority, both before and after start.
    144 TEST_F(URLRequestFtpJobPriorityTest, SetPriorityBasic) {
    145   scoped_refptr<TestURLRequestFtpJob> job(new TestURLRequestFtpJob(
    146       &req_, &ftp_factory_, &ftp_auth_cache_));
    147   EXPECT_EQ(DEFAULT_PRIORITY, job->priority());
    148 
    149   job->SetPriority(LOWEST);
    150   EXPECT_EQ(LOWEST, job->priority());
    151 
    152   job->SetPriority(LOW);
    153   EXPECT_EQ(LOW, job->priority());
    154 
    155   job->Start();
    156   EXPECT_EQ(LOW, job->priority());
    157 
    158   job->SetPriority(MEDIUM);
    159   EXPECT_EQ(MEDIUM, job->priority());
    160 }
    161 
    162 // Make sure that URLRequestFtpJob passes on its priority to its
    163 // transaction on start.
    164 TEST_F(URLRequestFtpJobPriorityTest, SetTransactionPriorityOnStart) {
    165   scoped_refptr<TestURLRequestFtpJob> job(new TestURLRequestFtpJob(
    166       &req_, &ftp_factory_, &ftp_auth_cache_));
    167   job->SetPriority(LOW);
    168 
    169   EXPECT_FALSE(network_layer_.last_transaction());
    170 
    171   job->Start();
    172 
    173   ASSERT_TRUE(network_layer_.last_transaction());
    174   EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
    175 }
    176 
    177 // Make sure that URLRequestFtpJob passes on its priority updates to
    178 // its transaction.
    179 TEST_F(URLRequestFtpJobPriorityTest, SetTransactionPriority) {
    180   scoped_refptr<TestURLRequestFtpJob> job(new TestURLRequestFtpJob(
    181       &req_, &ftp_factory_, &ftp_auth_cache_));
    182   job->SetPriority(LOW);
    183   job->Start();
    184   ASSERT_TRUE(network_layer_.last_transaction());
    185   EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
    186 
    187   job->SetPriority(HIGHEST);
    188   EXPECT_EQ(HIGHEST, network_layer_.last_transaction()->priority());
    189 }
    190 
    191 // Make sure that URLRequestFtpJob passes on its priority updates to
    192 // newly-created transactions after the first one.
    193 TEST_F(URLRequestFtpJobPriorityTest, SetSubsequentTransactionPriority) {
    194   scoped_refptr<TestURLRequestFtpJob> job(new TestURLRequestFtpJob(
    195       &req_, &ftp_factory_, &ftp_auth_cache_));
    196   job->Start();
    197 
    198   job->SetPriority(LOW);
    199   ASSERT_TRUE(network_layer_.last_transaction());
    200   EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
    201 
    202   job->Kill();
    203   network_layer_.ClearLastTransaction();
    204 
    205   // Creates a second transaction.
    206   job->Start();
    207   ASSERT_TRUE(network_layer_.last_transaction());
    208   EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
    209 }
    210 
    211 class URLRequestFtpJobTest : public testing::Test {
    212  public:
    213   URLRequestFtpJobTest()
    214       : request_context_(&socket_factory_,
    215                          new ProxyService(
    216                              new SimpleProxyConfigService, NULL, NULL),
    217                          &network_delegate_,
    218                          &ftp_transaction_factory_) {
    219   }
    220 
    221   virtual ~URLRequestFtpJobTest() {
    222     // Clean up any remaining tasks that mess up unrelated tests.
    223     base::RunLoop run_loop;
    224     run_loop.RunUntilIdle();
    225   }
    226 
    227   void AddSocket(MockRead* reads, size_t reads_size,
    228                  MockWrite* writes, size_t writes_size) {
    229     DeterministicSocketData* socket_data = new DeterministicSocketData(
    230         reads, reads_size, writes, writes_size);
    231     socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
    232     socket_data->StopAfter(reads_size + writes_size - 1);
    233     socket_factory_.AddSocketDataProvider(socket_data);
    234 
    235     socket_data_.push_back(socket_data);
    236   }
    237 
    238   FtpTestURLRequestContext* request_context() { return &request_context_; }
    239   TestNetworkDelegate* network_delegate() { return &network_delegate_; }
    240   DeterministicSocketData* socket_data(size_t index) {
    241     return socket_data_[index];
    242   }
    243 
    244  private:
    245   ScopedVector<DeterministicSocketData> socket_data_;
    246   DeterministicMockClientSocketFactory socket_factory_;
    247   TestNetworkDelegate network_delegate_;
    248   MockFtpTransactionFactory ftp_transaction_factory_;
    249 
    250   FtpTestURLRequestContext request_context_;
    251 };
    252 
    253 TEST_F(URLRequestFtpJobTest, FtpProxyRequest) {
    254   MockWrite writes[] = {
    255     MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
    256               "Host: ftp.example.com\r\n"
    257               "Proxy-Connection: keep-alive\r\n\r\n"),
    258   };
    259   MockRead reads[] = {
    260     MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"),
    261     MockRead(ASYNC, 2, "Content-Length: 9\r\n\r\n"),
    262     MockRead(ASYNC, 3, "test.html"),
    263   };
    264 
    265   AddSocket(reads, arraysize(reads), writes, arraysize(writes));
    266 
    267   TestDelegate request_delegate;
    268   URLRequest url_request(GURL("ftp://ftp.example.com/"),
    269                          DEFAULT_PRIORITY,
    270                          &request_delegate,
    271                          request_context());
    272   url_request.Start();
    273   ASSERT_TRUE(url_request.is_pending());
    274   socket_data(0)->RunFor(4);
    275 
    276   EXPECT_TRUE(url_request.status().is_success());
    277   EXPECT_EQ(1, network_delegate()->completed_requests());
    278   EXPECT_EQ(0, network_delegate()->error_count());
    279   EXPECT_FALSE(request_delegate.auth_required_called());
    280   EXPECT_EQ("test.html", request_delegate.data_received());
    281 }
    282 
    283 // Regression test for http://crbug.com/237526 .
    284 TEST_F(URLRequestFtpJobTest, FtpProxyRequestOrphanJob) {
    285   // Use a PAC URL so that URLRequestFtpJob's |pac_request_| field is non-NULL.
    286   request_context()->set_proxy_service(
    287       new ProxyService(
    288           new ProxyConfigServiceFixed(
    289               ProxyConfig::CreateFromCustomPacURL(GURL("http://foo"))),
    290           new MockAsyncProxyResolver, NULL));
    291 
    292   TestDelegate request_delegate;
    293   URLRequest url_request(GURL("ftp://ftp.example.com/"),
    294                          DEFAULT_PRIORITY,
    295                          &request_delegate,
    296                          request_context());
    297   url_request.Start();
    298 
    299   // Now |url_request| will be deleted before its completion,
    300   // resulting in it being orphaned. It should not crash.
    301 }
    302 
    303 TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedProxyAuthNoCredentials) {
    304   MockWrite writes[] = {
    305     MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
    306               "Host: ftp.example.com\r\n"
    307               "Proxy-Connection: keep-alive\r\n\r\n"),
    308   };
    309   MockRead reads[] = {
    310     // No credentials.
    311     MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
    312     MockRead(ASYNC, 2, "Proxy-Authenticate: Basic "
    313              "realm=\"MyRealm1\"\r\n"),
    314     MockRead(ASYNC, 3, "Content-Length: 9\r\n\r\n"),
    315     MockRead(ASYNC, 4, "test.html"),
    316   };
    317 
    318   AddSocket(reads, arraysize(reads), writes, arraysize(writes));
    319 
    320   TestDelegate request_delegate;
    321   URLRequest url_request(GURL("ftp://ftp.example.com/"),
    322                          DEFAULT_PRIORITY,
    323                          &request_delegate,
    324                          request_context());
    325   url_request.Start();
    326   ASSERT_TRUE(url_request.is_pending());
    327   socket_data(0)->RunFor(5);
    328 
    329   EXPECT_TRUE(url_request.status().is_success());
    330   EXPECT_EQ(1, network_delegate()->completed_requests());
    331   EXPECT_EQ(0, network_delegate()->error_count());
    332   EXPECT_TRUE(request_delegate.auth_required_called());
    333   EXPECT_EQ("test.html", request_delegate.data_received());
    334 }
    335 
    336 TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedProxyAuthWithCredentials) {
    337   MockWrite writes[] = {
    338     MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
    339               "Host: ftp.example.com\r\n"
    340               "Proxy-Connection: keep-alive\r\n\r\n"),
    341     MockWrite(ASYNC, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
    342               "Host: ftp.example.com\r\n"
    343               "Proxy-Connection: keep-alive\r\n"
    344               "Proxy-Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
    345   };
    346   MockRead reads[] = {
    347     // No credentials.
    348     MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
    349     MockRead(ASYNC, 2, "Proxy-Authenticate: Basic "
    350              "realm=\"MyRealm1\"\r\n"),
    351     MockRead(ASYNC, 3, "Content-Length: 9\r\n\r\n"),
    352     MockRead(ASYNC, 4, "test.html"),
    353 
    354     // Second response.
    355     MockRead(ASYNC, 6, "HTTP/1.1 200 OK\r\n"),
    356     MockRead(ASYNC, 7, "Content-Length: 10\r\n\r\n"),
    357     MockRead(ASYNC, 8, "test2.html"),
    358   };
    359 
    360   AddSocket(reads, arraysize(reads), writes, arraysize(writes));
    361 
    362   TestDelegate request_delegate;
    363   request_delegate.set_credentials(
    364       AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
    365   URLRequest url_request(GURL("ftp://ftp.example.com/"),
    366                          DEFAULT_PRIORITY,
    367                          &request_delegate,
    368                          request_context());
    369   url_request.Start();
    370   ASSERT_TRUE(url_request.is_pending());
    371   socket_data(0)->RunFor(9);
    372 
    373   EXPECT_TRUE(url_request.status().is_success());
    374   EXPECT_EQ(1, network_delegate()->completed_requests());
    375   EXPECT_EQ(0, network_delegate()->error_count());
    376   EXPECT_TRUE(request_delegate.auth_required_called());
    377   EXPECT_EQ("test2.html", request_delegate.data_received());
    378 }
    379 
    380 TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedServerAuthNoCredentials) {
    381   MockWrite writes[] = {
    382     MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
    383               "Host: ftp.example.com\r\n"
    384               "Proxy-Connection: keep-alive\r\n\r\n"),
    385   };
    386   MockRead reads[] = {
    387     // No credentials.
    388     MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
    389     MockRead(ASYNC, 2, "WWW-Authenticate: Basic "
    390              "realm=\"MyRealm1\"\r\n"),
    391     MockRead(ASYNC, 3, "Content-Length: 9\r\n\r\n"),
    392     MockRead(ASYNC, 4, "test.html"),
    393   };
    394 
    395   AddSocket(reads, arraysize(reads), writes, arraysize(writes));
    396 
    397   TestDelegate request_delegate;
    398   URLRequest url_request(GURL("ftp://ftp.example.com/"),
    399                          DEFAULT_PRIORITY,
    400                          &request_delegate,
    401                          request_context());
    402   url_request.Start();
    403   ASSERT_TRUE(url_request.is_pending());
    404   socket_data(0)->RunFor(5);
    405 
    406   EXPECT_TRUE(url_request.status().is_success());
    407   EXPECT_EQ(1, network_delegate()->completed_requests());
    408   EXPECT_EQ(0, network_delegate()->error_count());
    409   EXPECT_TRUE(request_delegate.auth_required_called());
    410   EXPECT_EQ("test.html", request_delegate.data_received());
    411 }
    412 
    413 TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedServerAuthWithCredentials) {
    414   MockWrite writes[] = {
    415     MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
    416               "Host: ftp.example.com\r\n"
    417               "Proxy-Connection: keep-alive\r\n\r\n"),
    418     MockWrite(ASYNC, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
    419               "Host: ftp.example.com\r\n"
    420               "Proxy-Connection: keep-alive\r\n"
    421               "Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
    422   };
    423   MockRead reads[] = {
    424     // No credentials.
    425     MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
    426     MockRead(ASYNC, 2, "WWW-Authenticate: Basic "
    427              "realm=\"MyRealm1\"\r\n"),
    428     MockRead(ASYNC, 3, "Content-Length: 9\r\n\r\n"),
    429     MockRead(ASYNC, 4, "test.html"),
    430 
    431     // Second response.
    432     MockRead(ASYNC, 6, "HTTP/1.1 200 OK\r\n"),
    433     MockRead(ASYNC, 7, "Content-Length: 10\r\n\r\n"),
    434     MockRead(ASYNC, 8, "test2.html"),
    435   };
    436 
    437   AddSocket(reads, arraysize(reads), writes, arraysize(writes));
    438 
    439   TestDelegate request_delegate;
    440   request_delegate.set_credentials(
    441       AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
    442   URLRequest url_request(GURL("ftp://ftp.example.com/"),
    443                          DEFAULT_PRIORITY,
    444                          &request_delegate,
    445                          request_context());
    446   url_request.Start();
    447   ASSERT_TRUE(url_request.is_pending());
    448   socket_data(0)->RunFor(9);
    449 
    450   EXPECT_TRUE(url_request.status().is_success());
    451   EXPECT_EQ(1, network_delegate()->completed_requests());
    452   EXPECT_EQ(0, network_delegate()->error_count());
    453   EXPECT_TRUE(request_delegate.auth_required_called());
    454   EXPECT_EQ("test2.html", request_delegate.data_received());
    455 }
    456 
    457 TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedProxyAndServerAuth) {
    458   MockWrite writes[] = {
    459     MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
    460               "Host: ftp.example.com\r\n"
    461               "Proxy-Connection: keep-alive\r\n\r\n"),
    462     MockWrite(ASYNC, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
    463               "Host: ftp.example.com\r\n"
    464               "Proxy-Connection: keep-alive\r\n"
    465               "Proxy-Authorization: Basic "
    466               "cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n"),
    467     MockWrite(ASYNC, 10, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
    468               "Host: ftp.example.com\r\n"
    469               "Proxy-Connection: keep-alive\r\n"
    470               "Proxy-Authorization: Basic "
    471               "cHJveHl1c2VyOnByb3h5cGFzcw==\r\n"
    472               "Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
    473   };
    474   MockRead reads[] = {
    475     // No credentials.
    476     MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
    477     MockRead(ASYNC, 2, "Proxy-Authenticate: Basic "
    478              "realm=\"MyRealm1\"\r\n"),
    479     MockRead(ASYNC, 3, "Content-Length: 9\r\n\r\n"),
    480     MockRead(ASYNC, 4, "test.html"),
    481 
    482     // Second response.
    483     MockRead(ASYNC, 6, "HTTP/1.1 401 Unauthorized\r\n"),
    484     MockRead(ASYNC, 7, "WWW-Authenticate: Basic "
    485              "realm=\"MyRealm1\"\r\n"),
    486     MockRead(ASYNC, 8, "Content-Length: 9\r\n\r\n"),
    487     MockRead(ASYNC, 9, "test.html"),
    488 
    489     // Third response.
    490     MockRead(ASYNC, 11, "HTTP/1.1 200 OK\r\n"),
    491     MockRead(ASYNC, 12, "Content-Length: 10\r\n\r\n"),
    492     MockRead(ASYNC, 13, "test2.html"),
    493   };
    494 
    495   AddSocket(reads, arraysize(reads), writes, arraysize(writes));
    496 
    497   GURL url("ftp://ftp.example.com");
    498 
    499   // Make sure cached FTP credentials are not used for proxy authentication.
    500   request_context()->GetFtpAuthCache()->Add(
    501       url.GetOrigin(),
    502       AuthCredentials(ASCIIToUTF16("userdonotuse"),
    503                       ASCIIToUTF16("passworddonotuse")));
    504 
    505   TestDelegate request_delegate;
    506   request_delegate.set_credentials(
    507       AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")));
    508   URLRequest url_request(
    509       url, DEFAULT_PRIORITY, &request_delegate, request_context());
    510   url_request.Start();
    511   ASSERT_TRUE(url_request.is_pending());
    512   socket_data(0)->RunFor(5);
    513 
    514   request_delegate.set_credentials(
    515       AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
    516   socket_data(0)->RunFor(9);
    517 
    518   EXPECT_TRUE(url_request.status().is_success());
    519   EXPECT_EQ(1, network_delegate()->completed_requests());
    520   EXPECT_EQ(0, network_delegate()->error_count());
    521   EXPECT_TRUE(request_delegate.auth_required_called());
    522   EXPECT_EQ("test2.html", request_delegate.data_received());
    523 }
    524 
    525 TEST_F(URLRequestFtpJobTest, FtpProxyRequestDoNotSaveCookies) {
    526   MockWrite writes[] = {
    527     MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
    528               "Host: ftp.example.com\r\n"
    529               "Proxy-Connection: keep-alive\r\n\r\n"),
    530   };
    531   MockRead reads[] = {
    532     MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"),
    533     MockRead(ASYNC, 2, "Content-Length: 9\r\n"),
    534     MockRead(ASYNC, 3, "Set-Cookie: name=value\r\n\r\n"),
    535     MockRead(ASYNC, 4, "test.html"),
    536   };
    537 
    538   AddSocket(reads, arraysize(reads), writes, arraysize(writes));
    539 
    540   TestDelegate request_delegate;
    541   URLRequest url_request(GURL("ftp://ftp.example.com/"),
    542                          DEFAULT_PRIORITY,
    543                          &request_delegate,
    544                          request_context());
    545   url_request.Start();
    546   ASSERT_TRUE(url_request.is_pending());
    547 
    548   socket_data(0)->RunFor(5);
    549 
    550   EXPECT_TRUE(url_request.status().is_success());
    551   EXPECT_EQ(1, network_delegate()->completed_requests());
    552   EXPECT_EQ(0, network_delegate()->error_count());
    553 
    554   // Make sure we do not accept cookies.
    555   EXPECT_EQ(0, network_delegate()->set_cookie_count());
    556 
    557   EXPECT_FALSE(request_delegate.auth_required_called());
    558   EXPECT_EQ("test.html", request_delegate.data_received());
    559 }
    560 
    561 TEST_F(URLRequestFtpJobTest, FtpProxyRequestDoNotFollowRedirects) {
    562   MockWrite writes[] = {
    563     MockWrite(SYNCHRONOUS, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
    564               "Host: ftp.example.com\r\n"
    565               "Proxy-Connection: keep-alive\r\n\r\n"),
    566   };
    567   MockRead reads[] = {
    568     MockRead(SYNCHRONOUS, 1, "HTTP/1.1 302 Found\r\n"),
    569     MockRead(ASYNC, 2, "Location: http://other.example.com/\r\n\r\n"),
    570   };
    571 
    572   AddSocket(reads, arraysize(reads), writes, arraysize(writes));
    573 
    574   TestDelegate request_delegate;
    575   URLRequest url_request(GURL("ftp://ftp.example.com/"),
    576                          DEFAULT_PRIORITY,
    577                          &request_delegate,
    578                          request_context());
    579   url_request.Start();
    580   EXPECT_TRUE(url_request.is_pending());
    581 
    582   base::MessageLoop::current()->RunUntilIdle();
    583 
    584   EXPECT_TRUE(url_request.is_pending());
    585   EXPECT_EQ(0, request_delegate.response_started_count());
    586   EXPECT_EQ(0, network_delegate()->error_count());
    587   ASSERT_TRUE(url_request.status().is_success());
    588 
    589   socket_data(0)->RunFor(1);
    590 
    591   EXPECT_EQ(1, network_delegate()->completed_requests());
    592   EXPECT_EQ(1, network_delegate()->error_count());
    593   EXPECT_FALSE(url_request.status().is_success());
    594   EXPECT_EQ(ERR_UNSAFE_REDIRECT, url_request.status().error());
    595 }
    596 
    597 // We should re-use socket for requests using the same scheme, host, and port.
    598 TEST_F(URLRequestFtpJobTest, FtpProxyRequestReuseSocket) {
    599   MockWrite writes[] = {
    600     MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/first HTTP/1.1\r\n"
    601               "Host: ftp.example.com\r\n"
    602               "Proxy-Connection: keep-alive\r\n\r\n"),
    603     MockWrite(ASYNC, 4, "GET ftp://ftp.example.com/second HTTP/1.1\r\n"
    604               "Host: ftp.example.com\r\n"
    605               "Proxy-Connection: keep-alive\r\n\r\n"),
    606   };
    607   MockRead reads[] = {
    608     MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"),
    609     MockRead(ASYNC, 2, "Content-Length: 10\r\n\r\n"),
    610     MockRead(ASYNC, 3, "test1.html"),
    611     MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\n"),
    612     MockRead(ASYNC, 6, "Content-Length: 10\r\n\r\n"),
    613     MockRead(ASYNC, 7, "test2.html"),
    614   };
    615 
    616   AddSocket(reads, arraysize(reads), writes, arraysize(writes));
    617 
    618   TestDelegate request_delegate1;
    619   URLRequest url_request1(GURL("ftp://ftp.example.com/first"),
    620                           DEFAULT_PRIORITY,
    621                           &request_delegate1,
    622                           request_context());
    623   url_request1.Start();
    624   ASSERT_TRUE(url_request1.is_pending());
    625   socket_data(0)->RunFor(4);
    626 
    627   EXPECT_TRUE(url_request1.status().is_success());
    628   EXPECT_EQ(1, network_delegate()->completed_requests());
    629   EXPECT_EQ(0, network_delegate()->error_count());
    630   EXPECT_FALSE(request_delegate1.auth_required_called());
    631   EXPECT_EQ("test1.html", request_delegate1.data_received());
    632 
    633   TestDelegate request_delegate2;
    634   URLRequest url_request2(GURL("ftp://ftp.example.com/second"),
    635                           DEFAULT_PRIORITY,
    636                           &request_delegate2,
    637                           request_context());
    638   url_request2.Start();
    639   ASSERT_TRUE(url_request2.is_pending());
    640   socket_data(0)->RunFor(4);
    641 
    642   EXPECT_TRUE(url_request2.status().is_success());
    643   EXPECT_EQ(2, network_delegate()->completed_requests());
    644   EXPECT_EQ(0, network_delegate()->error_count());
    645   EXPECT_FALSE(request_delegate2.auth_required_called());
    646   EXPECT_EQ("test2.html", request_delegate2.data_received());
    647 }
    648 
    649 // We should not re-use socket when there are two requests to the same host,
    650 // but one is FTP and the other is HTTP.
    651 TEST_F(URLRequestFtpJobTest, FtpProxyRequestDoNotReuseSocket) {
    652   MockWrite writes1[] = {
    653     MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/first HTTP/1.1\r\n"
    654               "Host: ftp.example.com\r\n"
    655               "Proxy-Connection: keep-alive\r\n\r\n"),
    656   };
    657   MockWrite writes2[] = {
    658     MockWrite(ASYNC, 0, "GET /second HTTP/1.1\r\n"
    659               "Host: ftp.example.com\r\n"
    660               "Connection: keep-alive\r\n"
    661               "User-Agent:\r\n"
    662               "Accept-Encoding: gzip,deflate\r\n"
    663               "Accept-Language: en-us,fr\r\n\r\n"),
    664   };
    665   MockRead reads1[] = {
    666     MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"),
    667     MockRead(ASYNC, 2, "Content-Length: 10\r\n\r\n"),
    668     MockRead(ASYNC, 3, "test1.html"),
    669   };
    670   MockRead reads2[] = {
    671     MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"),
    672     MockRead(ASYNC, 2, "Content-Length: 10\r\n\r\n"),
    673     MockRead(ASYNC, 3, "test2.html"),
    674   };
    675 
    676   AddSocket(reads1, arraysize(reads1), writes1, arraysize(writes1));
    677   AddSocket(reads2, arraysize(reads2), writes2, arraysize(writes2));
    678 
    679   TestDelegate request_delegate1;
    680   URLRequest url_request1(GURL("ftp://ftp.example.com/first"),
    681                           DEFAULT_PRIORITY,
    682                           &request_delegate1,
    683                           request_context());
    684   url_request1.Start();
    685   ASSERT_TRUE(url_request1.is_pending());
    686   socket_data(0)->RunFor(4);
    687 
    688   EXPECT_TRUE(url_request1.status().is_success());
    689   EXPECT_EQ(1, network_delegate()->completed_requests());
    690   EXPECT_EQ(0, network_delegate()->error_count());
    691   EXPECT_FALSE(request_delegate1.auth_required_called());
    692   EXPECT_EQ("test1.html", request_delegate1.data_received());
    693 
    694   TestDelegate request_delegate2;
    695   URLRequest url_request2(GURL("http://ftp.example.com/second"),
    696                           DEFAULT_PRIORITY,
    697                           &request_delegate2,
    698                           request_context());
    699   url_request2.Start();
    700   ASSERT_TRUE(url_request2.is_pending());
    701   socket_data(1)->RunFor(4);
    702 
    703   EXPECT_TRUE(url_request2.status().is_success());
    704   EXPECT_EQ(2, network_delegate()->completed_requests());
    705   EXPECT_EQ(0, network_delegate()->error_count());
    706   EXPECT_FALSE(request_delegate2.auth_required_called());
    707   EXPECT_EQ("test2.html", request_delegate2.data_received());
    708 }
    709 
    710 }  // namespace
    711 
    712 }  // namespace net
    713