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