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