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_vector.h"
9 #include "base/run_loop.h"
10 #include "net/base/request_priority.h"
11 #include "net/ftp/ftp_auth_cache.h"
12 #include "net/http/http_transaction_unittest.h"
13 #include "net/proxy/mock_proxy_resolver.h"
14 #include "net/proxy/proxy_config_service.h"
15 #include "net/proxy/proxy_config_service_fixed.h"
16 #include "net/socket/socket_test_util.h"
17 #include "net/url_request/ftp_protocol_handler.h"
18 #include "net/url_request/url_request.h"
19 #include "net/url_request/url_request_context.h"
20 #include "net/url_request/url_request_job_factory_impl.h"
21 #include "net/url_request/url_request_status.h"
22 #include "net/url_request/url_request_test_util.h"
23 #include "testing/gtest/include/gtest/gtest.h"
26 using base::ASCIIToUTF16
;
30 class FtpTestURLRequestContext
: public TestURLRequestContext
{
32 FtpTestURLRequestContext(ClientSocketFactory
* socket_factory
,
33 ProxyService
* proxy_service
,
34 NetworkDelegate
* network_delegate
,
35 FtpTransactionFactory
* ftp_transaction_factory
)
36 : TestURLRequestContext(true),
37 ftp_protocol_handler_(new FtpProtocolHandler(ftp_transaction_factory
)) {
38 set_client_socket_factory(socket_factory
);
39 context_storage_
.set_proxy_service(proxy_service
);
40 set_network_delegate(network_delegate
);
41 URLRequestJobFactoryImpl
* job_factory
= new URLRequestJobFactoryImpl
;
42 job_factory
->SetProtocolHandler("ftp", ftp_protocol_handler_
);
43 context_storage_
.set_job_factory(job_factory
);
47 FtpAuthCache
* GetFtpAuthCache() {
48 return ftp_protocol_handler_
->ftp_auth_cache_
.get();
51 void set_proxy_service(ProxyService
* proxy_service
) {
52 context_storage_
.set_proxy_service(proxy_service
);
56 FtpProtocolHandler
* ftp_protocol_handler_
;
61 class SimpleProxyConfigService
: public ProxyConfigService
{
63 SimpleProxyConfigService() {
64 // Any FTP requests that ever go through HTTP paths are proxied requests.
65 config_
.proxy_rules().ParseFromString("ftp=localhost");
68 virtual void AddObserver(Observer
* observer
) OVERRIDE
{
72 virtual void RemoveObserver(Observer
* observer
) OVERRIDE
{
73 if (observer_
== observer
) {
78 virtual ConfigAvailability
GetLatestProxyConfig(
79 ProxyConfig
* config
) OVERRIDE
{
84 void IncrementConfigId() {
85 config_
.set_id(config_
.id() + 1);
86 observer_
->OnProxyConfigChanged(config_
, ProxyConfigService::CONFIG_VALID
);
94 // Inherit from URLRequestFtpJob to expose the priority and some
95 // other hidden functions.
96 class TestURLRequestFtpJob
: public URLRequestFtpJob
{
98 TestURLRequestFtpJob(URLRequest
* request
,
99 FtpTransactionFactory
* ftp_factory
,
100 FtpAuthCache
* ftp_auth_cache
)
101 : URLRequestFtpJob(request
, NULL
, ftp_factory
, ftp_auth_cache
) {}
103 using URLRequestFtpJob::SetPriority
;
104 using URLRequestFtpJob::Start
;
105 using URLRequestFtpJob::Kill
;
106 using URLRequestFtpJob::priority
;
109 virtual ~TestURLRequestFtpJob() {}
112 class MockFtpTransactionFactory
: public FtpTransactionFactory
{
114 virtual FtpTransaction
* CreateTransaction() OVERRIDE
{
118 virtual void Suspend(bool suspend
) OVERRIDE
{}
121 // Fixture for priority-related tests. Priority matters when there is
123 class URLRequestFtpJobPriorityTest
: public testing::Test
{
125 URLRequestFtpJobPriorityTest()
126 : proxy_service_(new SimpleProxyConfigService
, NULL
, NULL
),
127 req_(GURL("ftp://ftp.example.com"),
131 context_
.set_proxy_service(&proxy_service_
);
132 context_
.set_http_transaction_factory(&network_layer_
);
135 ProxyService proxy_service_
;
136 MockNetworkLayer network_layer_
;
137 MockFtpTransactionFactory ftp_factory_
;
138 FtpAuthCache ftp_auth_cache_
;
139 TestURLRequestContext context_
;
140 TestDelegate delegate_
;
144 // Make sure that SetPriority actually sets the URLRequestFtpJob's
145 // priority, both before and after start.
146 TEST_F(URLRequestFtpJobPriorityTest
, SetPriorityBasic
) {
147 scoped_refptr
<TestURLRequestFtpJob
> job(new TestURLRequestFtpJob(
148 &req_
, &ftp_factory_
, &ftp_auth_cache_
));
149 EXPECT_EQ(DEFAULT_PRIORITY
, job
->priority());
151 job
->SetPriority(LOWEST
);
152 EXPECT_EQ(LOWEST
, job
->priority());
154 job
->SetPriority(LOW
);
155 EXPECT_EQ(LOW
, job
->priority());
158 EXPECT_EQ(LOW
, job
->priority());
160 job
->SetPriority(MEDIUM
);
161 EXPECT_EQ(MEDIUM
, job
->priority());
164 // Make sure that URLRequestFtpJob passes on its priority to its
165 // transaction on start.
166 TEST_F(URLRequestFtpJobPriorityTest
, SetTransactionPriorityOnStart
) {
167 scoped_refptr
<TestURLRequestFtpJob
> job(new TestURLRequestFtpJob(
168 &req_
, &ftp_factory_
, &ftp_auth_cache_
));
169 job
->SetPriority(LOW
);
171 EXPECT_FALSE(network_layer_
.last_transaction());
175 ASSERT_TRUE(network_layer_
.last_transaction());
176 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
179 // Make sure that URLRequestFtpJob passes on its priority updates to
181 TEST_F(URLRequestFtpJobPriorityTest
, SetTransactionPriority
) {
182 scoped_refptr
<TestURLRequestFtpJob
> job(new TestURLRequestFtpJob(
183 &req_
, &ftp_factory_
, &ftp_auth_cache_
));
184 job
->SetPriority(LOW
);
186 ASSERT_TRUE(network_layer_
.last_transaction());
187 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
189 job
->SetPriority(HIGHEST
);
190 EXPECT_EQ(HIGHEST
, network_layer_
.last_transaction()->priority());
193 // Make sure that URLRequestFtpJob passes on its priority updates to
194 // newly-created transactions after the first one.
195 TEST_F(URLRequestFtpJobPriorityTest
, SetSubsequentTransactionPriority
) {
196 scoped_refptr
<TestURLRequestFtpJob
> job(new TestURLRequestFtpJob(
197 &req_
, &ftp_factory_
, &ftp_auth_cache_
));
200 job
->SetPriority(LOW
);
201 ASSERT_TRUE(network_layer_
.last_transaction());
202 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
205 network_layer_
.ClearLastTransaction();
207 // Creates a second transaction.
209 ASSERT_TRUE(network_layer_
.last_transaction());
210 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
213 class URLRequestFtpJobTest
: public testing::Test
{
215 URLRequestFtpJobTest()
216 : request_context_(&socket_factory_
,
218 new SimpleProxyConfigService
, NULL
, NULL
),
220 &ftp_transaction_factory_
) {
223 virtual ~URLRequestFtpJobTest() {
224 // Clean up any remaining tasks that mess up unrelated tests.
225 base::RunLoop run_loop
;
226 run_loop
.RunUntilIdle();
229 void AddSocket(MockRead
* reads
, size_t reads_size
,
230 MockWrite
* writes
, size_t writes_size
) {
231 DeterministicSocketData
* socket_data
= new DeterministicSocketData(
232 reads
, reads_size
, writes
, writes_size
);
233 socket_data
->set_connect_data(MockConnect(SYNCHRONOUS
, OK
));
234 socket_data
->StopAfter(reads_size
+ writes_size
- 1);
235 socket_factory_
.AddSocketDataProvider(socket_data
);
237 socket_data_
.push_back(socket_data
);
240 FtpTestURLRequestContext
* request_context() { return &request_context_
; }
241 TestNetworkDelegate
* network_delegate() { return &network_delegate_
; }
242 DeterministicSocketData
* socket_data(size_t index
) {
243 return socket_data_
[index
];
247 ScopedVector
<DeterministicSocketData
> socket_data_
;
248 DeterministicMockClientSocketFactory socket_factory_
;
249 TestNetworkDelegate network_delegate_
;
250 MockFtpTransactionFactory ftp_transaction_factory_
;
252 FtpTestURLRequestContext request_context_
;
255 TEST_F(URLRequestFtpJobTest
, FtpProxyRequest
) {
256 MockWrite writes
[] = {
257 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
258 "Host: ftp.example.com\r\n"
259 "Proxy-Connection: keep-alive\r\n\r\n"),
262 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
263 MockRead(ASYNC
, 2, "Content-Length: 9\r\n\r\n"),
264 MockRead(ASYNC
, 3, "test.html"),
267 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
269 TestDelegate request_delegate
;
270 URLRequest
url_request(GURL("ftp://ftp.example.com/"),
275 ASSERT_TRUE(url_request
.is_pending());
276 socket_data(0)->RunFor(4);
278 EXPECT_TRUE(url_request
.status().is_success());
279 EXPECT_EQ(1, network_delegate()->completed_requests());
280 EXPECT_EQ(0, network_delegate()->error_count());
281 EXPECT_FALSE(request_delegate
.auth_required_called());
282 EXPECT_EQ("test.html", request_delegate
.data_received());
285 // Regression test for http://crbug.com/237526 .
286 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestOrphanJob
) {
287 // Use a PAC URL so that URLRequestFtpJob's |pac_request_| field is non-NULL.
288 request_context()->set_proxy_service(
290 new ProxyConfigServiceFixed(
291 ProxyConfig::CreateFromCustomPacURL(GURL("http://foo"))),
292 new MockAsyncProxyResolver
, NULL
));
294 TestDelegate request_delegate
;
295 URLRequest
url_request(GURL("ftp://ftp.example.com/"),
301 // Now |url_request| will be deleted before its completion,
302 // resulting in it being orphaned. It should not crash.
305 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestNeedProxyAuthNoCredentials
) {
306 MockWrite writes
[] = {
307 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
308 "Host: ftp.example.com\r\n"
309 "Proxy-Connection: keep-alive\r\n\r\n"),
313 MockRead(ASYNC
, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
314 MockRead(ASYNC
, 2, "Proxy-Authenticate: Basic "
315 "realm=\"MyRealm1\"\r\n"),
316 MockRead(ASYNC
, 3, "Content-Length: 9\r\n\r\n"),
317 MockRead(ASYNC
, 4, "test.html"),
320 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
322 TestDelegate request_delegate
;
323 URLRequest
url_request(GURL("ftp://ftp.example.com/"),
328 ASSERT_TRUE(url_request
.is_pending());
329 socket_data(0)->RunFor(5);
331 EXPECT_TRUE(url_request
.status().is_success());
332 EXPECT_EQ(1, network_delegate()->completed_requests());
333 EXPECT_EQ(0, network_delegate()->error_count());
334 EXPECT_TRUE(request_delegate
.auth_required_called());
335 EXPECT_EQ("test.html", request_delegate
.data_received());
338 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestNeedProxyAuthWithCredentials
) {
339 MockWrite writes
[] = {
340 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
341 "Host: ftp.example.com\r\n"
342 "Proxy-Connection: keep-alive\r\n\r\n"),
343 MockWrite(ASYNC
, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
344 "Host: ftp.example.com\r\n"
345 "Proxy-Connection: keep-alive\r\n"
346 "Proxy-Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
350 MockRead(ASYNC
, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
351 MockRead(ASYNC
, 2, "Proxy-Authenticate: Basic "
352 "realm=\"MyRealm1\"\r\n"),
353 MockRead(ASYNC
, 3, "Content-Length: 9\r\n\r\n"),
354 MockRead(ASYNC
, 4, "test.html"),
357 MockRead(ASYNC
, 6, "HTTP/1.1 200 OK\r\n"),
358 MockRead(ASYNC
, 7, "Content-Length: 10\r\n\r\n"),
359 MockRead(ASYNC
, 8, "test2.html"),
362 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
364 TestDelegate request_delegate
;
365 request_delegate
.set_credentials(
366 AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
367 URLRequest
url_request(GURL("ftp://ftp.example.com/"),
372 ASSERT_TRUE(url_request
.is_pending());
373 socket_data(0)->RunFor(9);
375 EXPECT_TRUE(url_request
.status().is_success());
376 EXPECT_EQ(1, network_delegate()->completed_requests());
377 EXPECT_EQ(0, network_delegate()->error_count());
378 EXPECT_TRUE(request_delegate
.auth_required_called());
379 EXPECT_EQ("test2.html", request_delegate
.data_received());
382 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestNeedServerAuthNoCredentials
) {
383 MockWrite writes
[] = {
384 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
385 "Host: ftp.example.com\r\n"
386 "Proxy-Connection: keep-alive\r\n\r\n"),
390 MockRead(ASYNC
, 1, "HTTP/1.1 401 Unauthorized\r\n"),
391 MockRead(ASYNC
, 2, "WWW-Authenticate: Basic "
392 "realm=\"MyRealm1\"\r\n"),
393 MockRead(ASYNC
, 3, "Content-Length: 9\r\n\r\n"),
394 MockRead(ASYNC
, 4, "test.html"),
397 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
399 TestDelegate request_delegate
;
400 URLRequest
url_request(GURL("ftp://ftp.example.com/"),
405 ASSERT_TRUE(url_request
.is_pending());
406 socket_data(0)->RunFor(5);
408 EXPECT_TRUE(url_request
.status().is_success());
409 EXPECT_EQ(1, network_delegate()->completed_requests());
410 EXPECT_EQ(0, network_delegate()->error_count());
411 EXPECT_TRUE(request_delegate
.auth_required_called());
412 EXPECT_EQ("test.html", request_delegate
.data_received());
415 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestNeedServerAuthWithCredentials
) {
416 MockWrite writes
[] = {
417 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
418 "Host: ftp.example.com\r\n"
419 "Proxy-Connection: keep-alive\r\n\r\n"),
420 MockWrite(ASYNC
, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
421 "Host: ftp.example.com\r\n"
422 "Proxy-Connection: keep-alive\r\n"
423 "Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
427 MockRead(ASYNC
, 1, "HTTP/1.1 401 Unauthorized\r\n"),
428 MockRead(ASYNC
, 2, "WWW-Authenticate: Basic "
429 "realm=\"MyRealm1\"\r\n"),
430 MockRead(ASYNC
, 3, "Content-Length: 9\r\n\r\n"),
431 MockRead(ASYNC
, 4, "test.html"),
434 MockRead(ASYNC
, 6, "HTTP/1.1 200 OK\r\n"),
435 MockRead(ASYNC
, 7, "Content-Length: 10\r\n\r\n"),
436 MockRead(ASYNC
, 8, "test2.html"),
439 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
441 TestDelegate request_delegate
;
442 request_delegate
.set_credentials(
443 AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
444 URLRequest
url_request(GURL("ftp://ftp.example.com/"),
449 ASSERT_TRUE(url_request
.is_pending());
450 socket_data(0)->RunFor(9);
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());
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"),
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"),
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"),
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"),
497 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
499 GURL
url("ftp://ftp.example.com");
501 // Make sure cached FTP credentials are not used for proxy authentication.
502 request_context()->GetFtpAuthCache()->Add(
504 AuthCredentials(ASCIIToUTF16("userdonotuse"),
505 ASCIIToUTF16("passworddonotuse")));
507 TestDelegate request_delegate
;
508 request_delegate
.set_credentials(
509 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")));
510 URLRequest
url_request(
511 url
, DEFAULT_PRIORITY
, &request_delegate
, request_context());
513 ASSERT_TRUE(url_request
.is_pending());
514 socket_data(0)->RunFor(5);
516 request_delegate
.set_credentials(
517 AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
518 socket_data(0)->RunFor(9);
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());
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"),
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"),
540 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
542 TestDelegate request_delegate
;
543 URLRequest
url_request(GURL("ftp://ftp.example.com/"),
548 ASSERT_TRUE(url_request
.is_pending());
550 socket_data(0)->RunFor(5);
552 EXPECT_TRUE(url_request
.status().is_success());
553 EXPECT_EQ(1, network_delegate()->completed_requests());
554 EXPECT_EQ(0, network_delegate()->error_count());
556 // Make sure we do not accept cookies.
557 EXPECT_EQ(0, network_delegate()->set_cookie_count());
559 EXPECT_FALSE(request_delegate
.auth_required_called());
560 EXPECT_EQ("test.html", request_delegate
.data_received());
563 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestDoNotFollowRedirects
) {
564 MockWrite writes
[] = {
565 MockWrite(SYNCHRONOUS
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
566 "Host: ftp.example.com\r\n"
567 "Proxy-Connection: keep-alive\r\n\r\n"),
570 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 302 Found\r\n"),
571 MockRead(ASYNC
, 2, "Location: http://other.example.com/\r\n\r\n"),
574 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
576 TestDelegate request_delegate
;
577 URLRequest
url_request(GURL("ftp://ftp.example.com/"),
582 EXPECT_TRUE(url_request
.is_pending());
584 base::MessageLoop::current()->RunUntilIdle();
586 EXPECT_TRUE(url_request
.is_pending());
587 EXPECT_EQ(0, request_delegate
.response_started_count());
588 EXPECT_EQ(0, network_delegate()->error_count());
589 ASSERT_TRUE(url_request
.status().is_success());
591 socket_data(0)->RunFor(1);
593 EXPECT_EQ(1, network_delegate()->completed_requests());
594 EXPECT_EQ(1, network_delegate()->error_count());
595 EXPECT_FALSE(url_request
.status().is_success());
596 EXPECT_EQ(ERR_UNSAFE_REDIRECT
, url_request
.status().error());
599 // We should re-use socket for requests using the same scheme, host, and port.
600 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestReuseSocket
) {
601 MockWrite writes
[] = {
602 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/first HTTP/1.1\r\n"
603 "Host: ftp.example.com\r\n"
604 "Proxy-Connection: keep-alive\r\n\r\n"),
605 MockWrite(ASYNC
, 4, "GET ftp://ftp.example.com/second HTTP/1.1\r\n"
606 "Host: ftp.example.com\r\n"
607 "Proxy-Connection: keep-alive\r\n\r\n"),
610 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
611 MockRead(ASYNC
, 2, "Content-Length: 10\r\n\r\n"),
612 MockRead(ASYNC
, 3, "test1.html"),
613 MockRead(ASYNC
, 5, "HTTP/1.1 200 OK\r\n"),
614 MockRead(ASYNC
, 6, "Content-Length: 10\r\n\r\n"),
615 MockRead(ASYNC
, 7, "test2.html"),
618 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
620 TestDelegate request_delegate1
;
621 URLRequest
url_request1(GURL("ftp://ftp.example.com/first"),
625 url_request1
.Start();
626 ASSERT_TRUE(url_request1
.is_pending());
627 socket_data(0)->RunFor(4);
629 EXPECT_TRUE(url_request1
.status().is_success());
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());
635 TestDelegate request_delegate2
;
636 URLRequest
url_request2(GURL("ftp://ftp.example.com/second"),
640 url_request2
.Start();
641 ASSERT_TRUE(url_request2
.is_pending());
642 socket_data(0)->RunFor(4);
644 EXPECT_TRUE(url_request2
.status().is_success());
645 EXPECT_EQ(2, network_delegate()->completed_requests());
646 EXPECT_EQ(0, network_delegate()->error_count());
647 EXPECT_FALSE(request_delegate2
.auth_required_called());
648 EXPECT_EQ("test2.html", request_delegate2
.data_received());
651 // We should not re-use socket when there are two requests to the same host,
652 // but one is FTP and the other is HTTP.
653 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestDoNotReuseSocket
) {
654 MockWrite writes1
[] = {
655 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/first HTTP/1.1\r\n"
656 "Host: ftp.example.com\r\n"
657 "Proxy-Connection: keep-alive\r\n\r\n"),
659 MockWrite writes2
[] = {
660 MockWrite(ASYNC
, 0, "GET /second HTTP/1.1\r\n"
661 "Host: ftp.example.com\r\n"
662 "Connection: keep-alive\r\n"
664 "Accept-Encoding: gzip,deflate\r\n"
665 "Accept-Language: en-us,fr\r\n\r\n"),
667 MockRead reads1
[] = {
668 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
669 MockRead(ASYNC
, 2, "Content-Length: 10\r\n\r\n"),
670 MockRead(ASYNC
, 3, "test1.html"),
672 MockRead reads2
[] = {
673 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
674 MockRead(ASYNC
, 2, "Content-Length: 10\r\n\r\n"),
675 MockRead(ASYNC
, 3, "test2.html"),
678 AddSocket(reads1
, arraysize(reads1
), writes1
, arraysize(writes1
));
679 AddSocket(reads2
, arraysize(reads2
), writes2
, arraysize(writes2
));
681 TestDelegate request_delegate1
;
682 URLRequest
url_request1(GURL("ftp://ftp.example.com/first"),
686 url_request1
.Start();
687 ASSERT_TRUE(url_request1
.is_pending());
688 socket_data(0)->RunFor(4);
690 EXPECT_TRUE(url_request1
.status().is_success());
691 EXPECT_EQ(1, network_delegate()->completed_requests());
692 EXPECT_EQ(0, network_delegate()->error_count());
693 EXPECT_FALSE(request_delegate1
.auth_required_called());
694 EXPECT_EQ("test1.html", request_delegate1
.data_received());
696 TestDelegate request_delegate2
;
697 URLRequest
url_request2(GURL("http://ftp.example.com/second"),
701 url_request2
.Start();
702 ASSERT_TRUE(url_request2
.is_pending());
703 socket_data(1)->RunFor(4);
705 EXPECT_TRUE(url_request2
.status().is_success());
706 EXPECT_EQ(2, network_delegate()->completed_requests());
707 EXPECT_EQ(0, network_delegate()->error_count());
708 EXPECT_FALSE(request_delegate2
.auth_required_called());
709 EXPECT_EQ("test2.html", request_delegate2
.data_received());