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