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.
5 #include "net/url_request/url_request_ftp_job.h"
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"
28 using base::ASCIIToUTF16
;
32 class FtpTestURLRequestContext
: public TestURLRequestContext
{
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
);
49 FtpAuthCache
* GetFtpAuthCache() {
50 return ftp_protocol_handler_
->ftp_auth_cache_
.get();
53 void set_proxy_service(ProxyService
* proxy_service
) {
54 context_storage_
.set_proxy_service(proxy_service
);
58 FtpProtocolHandler
* ftp_protocol_handler_
;
63 class SimpleProxyConfigService
: public ProxyConfigService
{
65 SimpleProxyConfigService() {
66 // Any FTP requests that ever go through HTTP paths are proxied requests.
67 config_
.proxy_rules().ParseFromString("ftp=localhost");
70 void AddObserver(Observer
* observer
) override
{ observer_
= observer
; }
72 void RemoveObserver(Observer
* observer
) override
{
73 if (observer_
== observer
) {
78 ConfigAvailability
GetLatestProxyConfig(ProxyConfig
* config
) override
{
83 void IncrementConfigId() {
84 config_
.set_id(config_
.id() + 1);
85 observer_
->OnProxyConfigChanged(config_
, ProxyConfigService::CONFIG_VALID
);
93 // Inherit from URLRequestFtpJob to expose the priority and some
94 // other hidden functions.
95 class TestURLRequestFtpJob
: public URLRequestFtpJob
{
97 TestURLRequestFtpJob(URLRequest
* request
,
98 FtpTransactionFactory
* ftp_factory
,
99 FtpAuthCache
* ftp_auth_cache
)
100 : URLRequestFtpJob(request
, NULL
, ftp_factory
, ftp_auth_cache
) {}
102 using URLRequestFtpJob::SetPriority
;
103 using URLRequestFtpJob::Start
;
104 using URLRequestFtpJob::Kill
;
105 using URLRequestFtpJob::priority
;
108 ~TestURLRequestFtpJob() override
{}
111 class MockFtpTransactionFactory
: public FtpTransactionFactory
{
113 FtpTransaction
* CreateTransaction() override
{ return NULL
; }
115 void Suspend(bool suspend
) override
{}
118 // Fixture for priority-related tests. Priority matters when there is
120 class URLRequestFtpJobPriorityTest
: public testing::Test
{
122 URLRequestFtpJobPriorityTest()
123 : proxy_service_(new SimpleProxyConfigService
, NULL
, NULL
),
124 req_(context_
.CreateRequest(GURL("ftp://ftp.example.com"),
128 context_
.set_proxy_service(&proxy_service_
);
129 context_
.set_http_transaction_factory(&network_layer_
);
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_
;
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());
148 job
->SetPriority(LOWEST
);
149 EXPECT_EQ(LOWEST
, job
->priority());
151 job
->SetPriority(LOW
);
152 EXPECT_EQ(LOW
, job
->priority());
155 EXPECT_EQ(LOW
, job
->priority());
157 job
->SetPriority(MEDIUM
);
158 EXPECT_EQ(MEDIUM
, job
->priority());
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
);
168 EXPECT_FALSE(network_layer_
.last_transaction());
172 ASSERT_TRUE(network_layer_
.last_transaction());
173 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
176 // Make sure that URLRequestFtpJob passes on its priority updates to
178 TEST_F(URLRequestFtpJobPriorityTest
, SetTransactionPriority
) {
179 scoped_refptr
<TestURLRequestFtpJob
> job(new TestURLRequestFtpJob(
180 req_
.get(), &ftp_factory_
, &ftp_auth_cache_
));
181 job
->SetPriority(LOW
);
183 ASSERT_TRUE(network_layer_
.last_transaction());
184 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
186 job
->SetPriority(HIGHEST
);
187 EXPECT_EQ(HIGHEST
, network_layer_
.last_transaction()->priority());
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_
));
197 job
->SetPriority(LOW
);
198 ASSERT_TRUE(network_layer_
.last_transaction());
199 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
202 network_layer_
.ClearLastTransaction();
204 // Creates a second transaction.
206 ASSERT_TRUE(network_layer_
.last_transaction());
207 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
210 class URLRequestFtpJobTest
: public testing::Test
{
212 URLRequestFtpJobTest()
213 : request_context_(&socket_factory_
,
215 new SimpleProxyConfigService
, NULL
, NULL
),
217 &ftp_transaction_factory_
) {
220 ~URLRequestFtpJobTest() override
{
221 // Clean up any remaining tasks that mess up unrelated tests.
222 base::RunLoop run_loop
;
223 run_loop
.RunUntilIdle();
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
);
234 socket_data_
.push_back(socket_data
);
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
];
244 ScopedVector
<DeterministicSocketData
> socket_data_
;
245 DeterministicMockClientSocketFactory socket_factory_
;
246 TestNetworkDelegate network_delegate_
;
247 MockFtpTransactionFactory ftp_transaction_factory_
;
249 FtpTestURLRequestContext request_context_
;
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"),
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"),
264 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
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);
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());
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(
288 new ProxyConfigServiceFixed(
289 ProxyConfig::CreateFromCustomPacURL(GURL("http://foo"))),
290 new MockAsyncProxyResolver
, NULL
));
292 TestDelegate request_delegate
;
293 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
294 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
,
296 url_request
->Start();
298 // Now |url_request| will be deleted before its completion,
299 // resulting in it being orphaned. It should not crash.
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"),
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"),
317 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
319 TestDelegate request_delegate
;
320 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
321 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
,
323 url_request
->Start();
324 ASSERT_TRUE(url_request
->is_pending());
325 socket_data(0)->RunFor(5);
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());
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"),
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"),
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"),
360 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
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
,
368 url_request
->Start();
369 ASSERT_TRUE(url_request
->is_pending());
370 socket_data(0)->RunFor(9);
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());
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"),
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"),
394 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
396 TestDelegate request_delegate
;
397 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
398 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
,
400 url_request
->Start();
401 ASSERT_TRUE(url_request
->is_pending());
402 socket_data(0)->RunFor(5);
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());
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"),
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"),
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"),
435 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
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
,
443 url_request
->Start();
444 ASSERT_TRUE(url_request
->is_pending());
445 socket_data(0)->RunFor(9);
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());
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"),
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"),
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"),
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"),
492 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
494 GURL
url("ftp://ftp.example.com");
496 // Make sure cached FTP credentials are not used for proxy authentication.
497 request_context()->GetFtpAuthCache()->Add(
499 AuthCredentials(ASCIIToUTF16("userdonotuse"),
500 ASCIIToUTF16("passworddonotuse")));
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);
511 request_delegate
.set_credentials(
512 AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
513 socket_data(0)->RunFor(9);
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());
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"),
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"),
535 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
537 TestDelegate request_delegate
;
538 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
539 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
,
541 url_request
->Start();
542 ASSERT_TRUE(url_request
->is_pending());
544 socket_data(0)->RunFor(5);
546 EXPECT_TRUE(url_request
->status().is_success());
547 EXPECT_EQ(1, network_delegate()->completed_requests());
548 EXPECT_EQ(0, network_delegate()->error_count());
550 // Make sure we do not accept cookies.
551 EXPECT_EQ(0, network_delegate()->set_cookie_count());
553 EXPECT_FALSE(request_delegate
.auth_required_called());
554 EXPECT_EQ("test.html", request_delegate
.data_received());
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"),
564 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 302 Found\r\n"),
565 MockRead(ASYNC
, 2, "Location: http://other.example.com/\r\n\r\n"),
568 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
570 TestDelegate request_delegate
;
571 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
572 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
,
574 url_request
->Start();
575 EXPECT_TRUE(url_request
->is_pending());
577 base::MessageLoop::current()->RunUntilIdle();
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());
584 socket_data(0)->RunFor(1);
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());
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"),
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"),
611 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
613 TestDelegate request_delegate1
;
615 scoped_ptr
<URLRequest
> url_request1(request_context()->CreateRequest(
616 GURL("ftp://ftp.example.com/first"), DEFAULT_PRIORITY
, &request_delegate1
,
618 url_request1
->Start();
619 ASSERT_TRUE(url_request1
->is_pending());
620 socket_data(0)->RunFor(4);
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());
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);
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());
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"),
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"
658 "Accept-Encoding: gzip, deflate\r\n"
659 "Accept-Language: en-us,fr\r\n\r\n"),
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"),
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"),
672 AddSocket(reads1
, arraysize(reads1
), writes1
, arraysize(writes1
));
673 AddSocket(reads2
, arraysize(reads2
), writes2
, arraysize(writes2
));
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);
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());
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);
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());