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
;
33 class MockProxyResolverFactory
: public ProxyResolverFactory
{
35 MockProxyResolverFactory() : ProxyResolverFactory(false) {}
36 int CreateProxyResolver(
37 const scoped_refptr
<ProxyResolverScriptData
>& pac_script
,
38 scoped_ptr
<ProxyResolver
>* resolver
,
39 const CompletionCallback
& callback
,
40 scoped_ptr
<Request
>* request
) override
{
41 resolver
->reset(new MockAsyncProxyResolver());
48 class FtpTestURLRequestContext
: public TestURLRequestContext
{
50 FtpTestURLRequestContext(ClientSocketFactory
* socket_factory
,
51 ProxyService
* proxy_service
,
52 NetworkDelegate
* network_delegate
,
53 FtpTransactionFactory
* ftp_transaction_factory
)
54 : TestURLRequestContext(true),
55 ftp_protocol_handler_(new FtpProtocolHandler(ftp_transaction_factory
)) {
56 set_client_socket_factory(socket_factory
);
57 context_storage_
.set_proxy_service(proxy_service
);
58 set_network_delegate(network_delegate
);
59 URLRequestJobFactoryImpl
* job_factory
= new URLRequestJobFactoryImpl
;
60 job_factory
->SetProtocolHandler("ftp",
61 make_scoped_ptr(ftp_protocol_handler_
));
62 context_storage_
.set_job_factory(job_factory
);
66 FtpAuthCache
* GetFtpAuthCache() {
67 return ftp_protocol_handler_
->ftp_auth_cache_
.get();
70 void set_proxy_service(ProxyService
* proxy_service
) {
71 context_storage_
.set_proxy_service(proxy_service
);
75 FtpProtocolHandler
* ftp_protocol_handler_
;
80 class SimpleProxyConfigService
: public ProxyConfigService
{
82 SimpleProxyConfigService() {
83 // Any FTP requests that ever go through HTTP paths are proxied requests.
84 config_
.proxy_rules().ParseFromString("ftp=localhost");
87 void AddObserver(Observer
* observer
) override
{ observer_
= observer
; }
89 void RemoveObserver(Observer
* observer
) override
{
90 if (observer_
== observer
) {
95 ConfigAvailability
GetLatestProxyConfig(ProxyConfig
* config
) override
{
100 void IncrementConfigId() {
101 config_
.set_id(config_
.id() + 1);
102 observer_
->OnProxyConfigChanged(config_
, ProxyConfigService::CONFIG_VALID
);
110 // Inherit from URLRequestFtpJob to expose the priority and some
111 // other hidden functions.
112 class TestURLRequestFtpJob
: public URLRequestFtpJob
{
114 TestURLRequestFtpJob(URLRequest
* request
,
115 FtpTransactionFactory
* ftp_factory
,
116 FtpAuthCache
* ftp_auth_cache
)
117 : URLRequestFtpJob(request
, NULL
, ftp_factory
, ftp_auth_cache
) {}
119 using URLRequestFtpJob::SetPriority
;
120 using URLRequestFtpJob::Start
;
121 using URLRequestFtpJob::Kill
;
122 using URLRequestFtpJob::priority
;
125 ~TestURLRequestFtpJob() override
{}
128 class MockFtpTransactionFactory
: public FtpTransactionFactory
{
130 FtpTransaction
* CreateTransaction() override
{ return NULL
; }
132 void Suspend(bool suspend
) override
{}
135 // Fixture for priority-related tests. Priority matters when there is
137 class URLRequestFtpJobPriorityTest
: public testing::Test
{
139 URLRequestFtpJobPriorityTest()
140 : proxy_service_(new SimpleProxyConfigService
, NULL
, NULL
),
141 req_(context_
.CreateRequest(GURL("ftp://ftp.example.com"),
144 context_
.set_proxy_service(&proxy_service_
);
145 context_
.set_http_transaction_factory(&network_layer_
);
148 ProxyService proxy_service_
;
149 MockNetworkLayer network_layer_
;
150 MockFtpTransactionFactory ftp_factory_
;
151 FtpAuthCache ftp_auth_cache_
;
152 TestURLRequestContext context_
;
153 TestDelegate delegate_
;
154 scoped_ptr
<URLRequest
> req_
;
157 // Make sure that SetPriority actually sets the URLRequestFtpJob's
158 // priority, both before and after start.
159 TEST_F(URLRequestFtpJobPriorityTest
, SetPriorityBasic
) {
160 scoped_refptr
<TestURLRequestFtpJob
> job(new TestURLRequestFtpJob(
161 req_
.get(), &ftp_factory_
, &ftp_auth_cache_
));
162 EXPECT_EQ(DEFAULT_PRIORITY
, job
->priority());
164 job
->SetPriority(LOWEST
);
165 EXPECT_EQ(LOWEST
, job
->priority());
167 job
->SetPriority(LOW
);
168 EXPECT_EQ(LOW
, job
->priority());
171 EXPECT_EQ(LOW
, job
->priority());
173 job
->SetPriority(MEDIUM
);
174 EXPECT_EQ(MEDIUM
, job
->priority());
177 // Make sure that URLRequestFtpJob passes on its priority to its
178 // transaction on start.
179 TEST_F(URLRequestFtpJobPriorityTest
, SetTransactionPriorityOnStart
) {
180 scoped_refptr
<TestURLRequestFtpJob
> job(new TestURLRequestFtpJob(
181 req_
.get(), &ftp_factory_
, &ftp_auth_cache_
));
182 job
->SetPriority(LOW
);
184 EXPECT_FALSE(network_layer_
.last_transaction());
188 ASSERT_TRUE(network_layer_
.last_transaction());
189 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
192 // Make sure that URLRequestFtpJob passes on its priority updates to
194 TEST_F(URLRequestFtpJobPriorityTest
, SetTransactionPriority
) {
195 scoped_refptr
<TestURLRequestFtpJob
> job(new TestURLRequestFtpJob(
196 req_
.get(), &ftp_factory_
, &ftp_auth_cache_
));
197 job
->SetPriority(LOW
);
199 ASSERT_TRUE(network_layer_
.last_transaction());
200 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
202 job
->SetPriority(HIGHEST
);
203 EXPECT_EQ(HIGHEST
, network_layer_
.last_transaction()->priority());
206 // Make sure that URLRequestFtpJob passes on its priority updates to
207 // newly-created transactions after the first one.
208 TEST_F(URLRequestFtpJobPriorityTest
, SetSubsequentTransactionPriority
) {
209 scoped_refptr
<TestURLRequestFtpJob
> job(new TestURLRequestFtpJob(
210 req_
.get(), &ftp_factory_
, &ftp_auth_cache_
));
213 job
->SetPriority(LOW
);
214 ASSERT_TRUE(network_layer_
.last_transaction());
215 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
218 network_layer_
.ClearLastTransaction();
220 // Creates a second transaction.
222 ASSERT_TRUE(network_layer_
.last_transaction());
223 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
226 class URLRequestFtpJobTest
: public testing::Test
{
228 URLRequestFtpJobTest()
229 : request_context_(&socket_factory_
,
231 new SimpleProxyConfigService
, NULL
, NULL
),
233 &ftp_transaction_factory_
) {
236 ~URLRequestFtpJobTest() override
{
237 // Clean up any remaining tasks that mess up unrelated tests.
238 base::RunLoop().RunUntilIdle();
241 void AddSocket(MockRead
* reads
, size_t reads_size
,
242 MockWrite
* writes
, size_t writes_size
) {
243 SequencedSocketData
* socket_data
=
244 new SequencedSocketData(reads
, reads_size
, writes
, writes_size
);
245 socket_data
->set_connect_data(MockConnect(SYNCHRONOUS
, OK
));
246 socket_factory_
.AddSocketDataProvider(socket_data
);
248 socket_data_
.push_back(socket_data
);
251 FtpTestURLRequestContext
* request_context() { return &request_context_
; }
252 TestNetworkDelegate
* network_delegate() { return &network_delegate_
; }
255 ScopedVector
<SequencedSocketData
> socket_data_
;
256 MockClientSocketFactory socket_factory_
;
257 TestNetworkDelegate network_delegate_
;
258 MockFtpTransactionFactory ftp_transaction_factory_
;
260 FtpTestURLRequestContext request_context_
;
263 TEST_F(URLRequestFtpJobTest
, FtpProxyRequest
) {
264 MockWrite writes
[] = {
265 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
266 "Host: ftp.example.com\r\n"
267 "Proxy-Connection: keep-alive\r\n\r\n"),
270 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
271 MockRead(ASYNC
, 2, "Content-Length: 9\r\n\r\n"),
272 MockRead(ASYNC
, 3, "test.html"),
275 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
277 TestDelegate request_delegate
;
278 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
279 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
280 url_request
->Start();
281 ASSERT_TRUE(url_request
->is_pending());
283 // The TestDelegate will by default quit the message loop on completion.
284 base::RunLoop().Run();
286 EXPECT_TRUE(url_request
->status().is_success());
287 EXPECT_TRUE(url_request
->proxy_server().Equals(
288 HostPortPair::FromString("localhost:80")));
289 EXPECT_EQ(1, network_delegate()->completed_requests());
290 EXPECT_EQ(0, network_delegate()->error_count());
291 EXPECT_FALSE(request_delegate
.auth_required_called());
292 EXPECT_EQ("test.html", request_delegate
.data_received());
295 // Regression test for http://crbug.com/237526 .
296 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestOrphanJob
) {
297 // Use a PAC URL so that URLRequestFtpJob's |pac_request_| field is non-NULL.
298 request_context()->set_proxy_service(new ProxyService(
299 new ProxyConfigServiceFixed(
300 ProxyConfig::CreateFromCustomPacURL(GURL("http://foo"))),
301 make_scoped_ptr(new MockProxyResolverFactory
), NULL
));
303 TestDelegate request_delegate
;
304 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
305 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
306 url_request
->Start();
308 // Now |url_request| will be deleted before its completion,
309 // resulting in it being orphaned. It should not crash.
312 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestNeedProxyAuthNoCredentials
) {
313 MockWrite writes
[] = {
314 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
315 "Host: ftp.example.com\r\n"
316 "Proxy-Connection: keep-alive\r\n\r\n"),
320 MockRead(ASYNC
, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
321 MockRead(ASYNC
, 2, "Proxy-Authenticate: Basic "
322 "realm=\"MyRealm1\"\r\n"),
323 MockRead(ASYNC
, 3, "Content-Length: 9\r\n\r\n"),
324 MockRead(ASYNC
, 4, "test.html"),
327 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
329 TestDelegate request_delegate
;
330 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
331 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
332 url_request
->Start();
333 ASSERT_TRUE(url_request
->is_pending());
335 // The TestDelegate will by default quit the message loop on completion.
336 base::RunLoop().Run();
338 EXPECT_TRUE(url_request
->status().is_success());
339 EXPECT_TRUE(url_request
->proxy_server().Equals(
340 HostPortPair::FromString("localhost:80")));
341 EXPECT_EQ(1, network_delegate()->completed_requests());
342 EXPECT_EQ(0, network_delegate()->error_count());
343 EXPECT_TRUE(request_delegate
.auth_required_called());
344 EXPECT_EQ("test.html", request_delegate
.data_received());
347 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestNeedProxyAuthWithCredentials
) {
348 MockWrite writes
[] = {
349 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
350 "Host: ftp.example.com\r\n"
351 "Proxy-Connection: keep-alive\r\n\r\n"),
352 MockWrite(ASYNC
, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
353 "Host: ftp.example.com\r\n"
354 "Proxy-Connection: keep-alive\r\n"
355 "Proxy-Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
359 MockRead(ASYNC
, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
360 MockRead(ASYNC
, 2, "Proxy-Authenticate: Basic "
361 "realm=\"MyRealm1\"\r\n"),
362 MockRead(ASYNC
, 3, "Content-Length: 9\r\n\r\n"),
363 MockRead(ASYNC
, 4, "test.html"),
366 MockRead(ASYNC
, 6, "HTTP/1.1 200 OK\r\n"),
367 MockRead(ASYNC
, 7, "Content-Length: 10\r\n\r\n"),
368 MockRead(ASYNC
, 8, "test2.html"),
371 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
373 TestDelegate request_delegate
;
374 request_delegate
.set_credentials(
375 AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
376 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
377 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
378 url_request
->Start();
379 ASSERT_TRUE(url_request
->is_pending());
381 // The TestDelegate will by default quit the message loop on completion.
382 base::RunLoop().Run();
384 EXPECT_TRUE(url_request
->status().is_success());
385 EXPECT_EQ(1, network_delegate()->completed_requests());
386 EXPECT_EQ(0, network_delegate()->error_count());
387 EXPECT_TRUE(request_delegate
.auth_required_called());
388 EXPECT_EQ("test2.html", request_delegate
.data_received());
391 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestNeedServerAuthNoCredentials
) {
392 MockWrite writes
[] = {
393 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
394 "Host: ftp.example.com\r\n"
395 "Proxy-Connection: keep-alive\r\n\r\n"),
399 MockRead(ASYNC
, 1, "HTTP/1.1 401 Unauthorized\r\n"),
400 MockRead(ASYNC
, 2, "WWW-Authenticate: Basic "
401 "realm=\"MyRealm1\"\r\n"),
402 MockRead(ASYNC
, 3, "Content-Length: 9\r\n\r\n"),
403 MockRead(ASYNC
, 4, "test.html"),
406 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
408 TestDelegate request_delegate
;
409 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
410 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
411 url_request
->Start();
412 ASSERT_TRUE(url_request
->is_pending());
414 // The TestDelegate will by default quit the message loop on completion.
415 base::RunLoop().Run();
417 EXPECT_TRUE(url_request
->status().is_success());
418 EXPECT_EQ(1, network_delegate()->completed_requests());
419 EXPECT_EQ(0, network_delegate()->error_count());
420 EXPECT_TRUE(request_delegate
.auth_required_called());
421 EXPECT_EQ("test.html", request_delegate
.data_received());
424 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestNeedServerAuthWithCredentials
) {
425 MockWrite writes
[] = {
426 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
427 "Host: ftp.example.com\r\n"
428 "Proxy-Connection: keep-alive\r\n\r\n"),
429 MockWrite(ASYNC
, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
430 "Host: ftp.example.com\r\n"
431 "Proxy-Connection: keep-alive\r\n"
432 "Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
436 MockRead(ASYNC
, 1, "HTTP/1.1 401 Unauthorized\r\n"),
437 MockRead(ASYNC
, 2, "WWW-Authenticate: Basic "
438 "realm=\"MyRealm1\"\r\n"),
439 MockRead(ASYNC
, 3, "Content-Length: 9\r\n\r\n"),
440 MockRead(ASYNC
, 4, "test.html"),
443 MockRead(ASYNC
, 6, "HTTP/1.1 200 OK\r\n"),
444 MockRead(ASYNC
, 7, "Content-Length: 10\r\n\r\n"),
445 MockRead(ASYNC
, 8, "test2.html"),
448 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
450 TestDelegate request_delegate
;
451 request_delegate
.set_credentials(
452 AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
453 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
454 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
455 url_request
->Start();
456 ASSERT_TRUE(url_request
->is_pending());
458 // The TestDelegate will by default quit the message loop on completion.
459 base::RunLoop().Run();
461 EXPECT_TRUE(url_request
->status().is_success());
462 EXPECT_EQ(1, network_delegate()->completed_requests());
463 EXPECT_EQ(0, network_delegate()->error_count());
464 EXPECT_TRUE(request_delegate
.auth_required_called());
465 EXPECT_EQ("test2.html", request_delegate
.data_received());
468 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestNeedProxyAndServerAuth
) {
469 MockWrite writes
[] = {
470 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
471 "Host: ftp.example.com\r\n"
472 "Proxy-Connection: keep-alive\r\n\r\n"),
473 MockWrite(ASYNC
, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
474 "Host: ftp.example.com\r\n"
475 "Proxy-Connection: keep-alive\r\n"
476 "Proxy-Authorization: Basic "
477 "cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n"),
478 MockWrite(ASYNC
, 10, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
479 "Host: ftp.example.com\r\n"
480 "Proxy-Connection: keep-alive\r\n"
481 "Proxy-Authorization: Basic "
482 "cHJveHl1c2VyOnByb3h5cGFzcw==\r\n"
483 "Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
487 MockRead(ASYNC
, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
488 MockRead(ASYNC
, 2, "Proxy-Authenticate: Basic "
489 "realm=\"MyRealm1\"\r\n"),
490 MockRead(ASYNC
, 3, "Content-Length: 9\r\n\r\n"),
491 MockRead(ASYNC
, 4, "test.html"),
494 MockRead(ASYNC
, 6, "HTTP/1.1 401 Unauthorized\r\n"),
495 MockRead(ASYNC
, 7, "WWW-Authenticate: Basic "
496 "realm=\"MyRealm1\"\r\n"),
497 MockRead(ASYNC
, 8, "Content-Length: 9\r\n\r\n"),
498 MockRead(ASYNC
, 9, "test.html"),
501 MockRead(ASYNC
, 11, "HTTP/1.1 200 OK\r\n"),
502 MockRead(ASYNC
, 12, "Content-Length: 10\r\n\r\n"),
503 MockRead(ASYNC
, 13, "test2.html"),
506 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
508 GURL
url("ftp://ftp.example.com");
510 // Make sure cached FTP credentials are not used for proxy authentication.
511 request_context()->GetFtpAuthCache()->Add(
513 AuthCredentials(ASCIIToUTF16("userdonotuse"),
514 ASCIIToUTF16("passworddonotuse")));
516 TestDelegate request_delegate
;
517 request_delegate
.set_quit_on_auth_required(true);
518 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
519 url
, DEFAULT_PRIORITY
, &request_delegate
));
520 url_request
->Start();
521 ASSERT_TRUE(url_request
->is_pending());
523 // Run until proxy auth is requested.
524 base::RunLoop().Run();
526 ASSERT_TRUE(request_delegate
.auth_required_called());
527 EXPECT_EQ(0, network_delegate()->completed_requests());
528 EXPECT_EQ(0, network_delegate()->error_count());
529 url_request
->SetAuth(
530 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")));
532 // Run until server auth is requested.
533 base::RunLoop().Run();
535 EXPECT_TRUE(url_request
->status().is_success());
536 EXPECT_EQ(0, network_delegate()->completed_requests());
537 EXPECT_EQ(0, network_delegate()->error_count());
538 url_request
->SetAuth(
539 AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
541 // The TestDelegate will by default quit the message loop on completion.
542 base::RunLoop().Run();
544 EXPECT_TRUE(url_request
->status().is_success());
545 EXPECT_EQ(1, network_delegate()->completed_requests());
546 EXPECT_EQ(0, network_delegate()->error_count());
547 EXPECT_TRUE(request_delegate
.auth_required_called());
548 EXPECT_EQ("test2.html", request_delegate
.data_received());
551 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestDoNotSaveCookies
) {
552 MockWrite writes
[] = {
553 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
554 "Host: ftp.example.com\r\n"
555 "Proxy-Connection: keep-alive\r\n\r\n"),
558 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
559 MockRead(ASYNC
, 2, "Content-Length: 9\r\n"),
560 MockRead(ASYNC
, 3, "Set-Cookie: name=value\r\n\r\n"),
561 MockRead(ASYNC
, 4, "test.html"),
564 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
566 TestDelegate request_delegate
;
567 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
568 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
569 url_request
->Start();
570 ASSERT_TRUE(url_request
->is_pending());
572 // The TestDelegate will by default quit the message loop on completion.
573 base::RunLoop().Run();
575 EXPECT_TRUE(url_request
->status().is_success());
576 EXPECT_EQ(1, network_delegate()->completed_requests());
577 EXPECT_EQ(0, network_delegate()->error_count());
579 // Make sure we do not accept cookies.
580 EXPECT_EQ(0, network_delegate()->set_cookie_count());
582 EXPECT_FALSE(request_delegate
.auth_required_called());
583 EXPECT_EQ("test.html", request_delegate
.data_received());
586 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestDoNotFollowRedirects
) {
587 MockWrite writes
[] = {
588 MockWrite(SYNCHRONOUS
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
589 "Host: ftp.example.com\r\n"
590 "Proxy-Connection: keep-alive\r\n\r\n"),
593 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 302 Found\r\n"),
594 MockRead(ASYNC
, 2, "Location: http://other.example.com/\r\n\r\n"),
597 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
599 TestDelegate request_delegate
;
600 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
601 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
602 url_request
->Start();
603 EXPECT_TRUE(url_request
->is_pending());
605 // The TestDelegate will by default quit the message loop on completion.
606 base::RunLoop().Run();
608 EXPECT_EQ(1, network_delegate()->completed_requests());
609 EXPECT_EQ(1, network_delegate()->error_count());
610 EXPECT_FALSE(url_request
->status().is_success());
611 EXPECT_EQ(ERR_UNSAFE_REDIRECT
, url_request
->status().error());
614 // We should re-use socket for requests using the same scheme, host, and port.
615 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestReuseSocket
) {
616 MockWrite writes
[] = {
617 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/first HTTP/1.1\r\n"
618 "Host: ftp.example.com\r\n"
619 "Proxy-Connection: keep-alive\r\n\r\n"),
620 MockWrite(ASYNC
, 4, "GET ftp://ftp.example.com/second HTTP/1.1\r\n"
621 "Host: ftp.example.com\r\n"
622 "Proxy-Connection: keep-alive\r\n\r\n"),
625 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
626 MockRead(ASYNC
, 2, "Content-Length: 10\r\n\r\n"),
627 MockRead(ASYNC
, 3, "test1.html"),
628 MockRead(ASYNC
, 5, "HTTP/1.1 200 OK\r\n"),
629 MockRead(ASYNC
, 6, "Content-Length: 10\r\n\r\n"),
630 MockRead(ASYNC
, 7, "test2.html"),
633 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
635 TestDelegate request_delegate1
;
637 scoped_ptr
<URLRequest
> url_request1(
638 request_context()->CreateRequest(GURL("ftp://ftp.example.com/first"),
639 DEFAULT_PRIORITY
, &request_delegate1
));
640 url_request1
->Start();
641 ASSERT_TRUE(url_request1
->is_pending());
643 // The TestDelegate will by default quit the message loop on completion.
644 base::RunLoop().Run();
646 EXPECT_TRUE(url_request1
->status().is_success());
647 EXPECT_TRUE(url_request1
->proxy_server().Equals(
648 HostPortPair::FromString("localhost:80")));
649 EXPECT_EQ(1, network_delegate()->completed_requests());
650 EXPECT_EQ(0, network_delegate()->error_count());
651 EXPECT_FALSE(request_delegate1
.auth_required_called());
652 EXPECT_EQ("test1.html", request_delegate1
.data_received());
654 TestDelegate request_delegate2
;
655 scoped_ptr
<URLRequest
> url_request2(
656 request_context()->CreateRequest(GURL("ftp://ftp.example.com/second"),
657 DEFAULT_PRIORITY
, &request_delegate2
));
658 url_request2
->Start();
659 ASSERT_TRUE(url_request2
->is_pending());
661 // The TestDelegate will by default quit the message loop on completion.
662 base::RunLoop().Run();
664 EXPECT_TRUE(url_request2
->status().is_success());
665 EXPECT_EQ(2, network_delegate()->completed_requests());
666 EXPECT_EQ(0, network_delegate()->error_count());
667 EXPECT_FALSE(request_delegate2
.auth_required_called());
668 EXPECT_EQ("test2.html", request_delegate2
.data_received());
671 // We should not re-use socket when there are two requests to the same host,
672 // but one is FTP and the other is HTTP.
673 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestDoNotReuseSocket
) {
674 MockWrite writes1
[] = {
675 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/first HTTP/1.1\r\n"
676 "Host: ftp.example.com\r\n"
677 "Proxy-Connection: keep-alive\r\n\r\n"),
679 MockWrite writes2
[] = {
680 MockWrite(ASYNC
, 0, "GET /second HTTP/1.1\r\n"
681 "Host: ftp.example.com\r\n"
682 "Connection: keep-alive\r\n"
684 "Accept-Encoding: gzip, deflate\r\n"
685 "Accept-Language: en-us,fr\r\n\r\n"),
687 MockRead reads1
[] = {
688 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
689 MockRead(ASYNC
, 2, "Content-Length: 10\r\n\r\n"),
690 MockRead(ASYNC
, 3, "test1.html"),
692 MockRead reads2
[] = {
693 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
694 MockRead(ASYNC
, 2, "Content-Length: 10\r\n\r\n"),
695 MockRead(ASYNC
, 3, "test2.html"),
698 AddSocket(reads1
, arraysize(reads1
), writes1
, arraysize(writes1
));
699 AddSocket(reads2
, arraysize(reads2
), writes2
, arraysize(writes2
));
701 TestDelegate request_delegate1
;
702 scoped_ptr
<URLRequest
> url_request1(
703 request_context()->CreateRequest(GURL("ftp://ftp.example.com/first"),
704 DEFAULT_PRIORITY
, &request_delegate1
));
705 url_request1
->Start();
706 ASSERT_TRUE(url_request1
->is_pending());
708 // The TestDelegate will by default quit the message loop on completion.
709 base::RunLoop().Run();
711 EXPECT_TRUE(url_request1
->status().is_success());
712 EXPECT_EQ(1, network_delegate()->completed_requests());
713 EXPECT_EQ(0, network_delegate()->error_count());
714 EXPECT_FALSE(request_delegate1
.auth_required_called());
715 EXPECT_EQ("test1.html", request_delegate1
.data_received());
717 TestDelegate request_delegate2
;
718 scoped_ptr
<URLRequest
> url_request2(
719 request_context()->CreateRequest(GURL("http://ftp.example.com/second"),
720 DEFAULT_PRIORITY
, &request_delegate2
));
721 url_request2
->Start();
722 ASSERT_TRUE(url_request2
->is_pending());
724 // The TestDelegate will by default quit the message loop on completion.
725 base::RunLoop().Run();
727 EXPECT_TRUE(url_request2
->status().is_success());
728 EXPECT_EQ(2, network_delegate()->completed_requests());
729 EXPECT_EQ(0, network_delegate()->error_count());
730 EXPECT_FALSE(request_delegate2
.auth_required_called());
731 EXPECT_EQ("test2.html", request_delegate2
.data_received());