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", ftp_protocol_handler_
);
61 context_storage_
.set_job_factory(job_factory
);
65 FtpAuthCache
* GetFtpAuthCache() {
66 return ftp_protocol_handler_
->ftp_auth_cache_
.get();
69 void set_proxy_service(ProxyService
* proxy_service
) {
70 context_storage_
.set_proxy_service(proxy_service
);
74 FtpProtocolHandler
* ftp_protocol_handler_
;
79 class SimpleProxyConfigService
: public ProxyConfigService
{
81 SimpleProxyConfigService() {
82 // Any FTP requests that ever go through HTTP paths are proxied requests.
83 config_
.proxy_rules().ParseFromString("ftp=localhost");
86 void AddObserver(Observer
* observer
) override
{ observer_
= observer
; }
88 void RemoveObserver(Observer
* observer
) override
{
89 if (observer_
== observer
) {
94 ConfigAvailability
GetLatestProxyConfig(ProxyConfig
* config
) override
{
99 void IncrementConfigId() {
100 config_
.set_id(config_
.id() + 1);
101 observer_
->OnProxyConfigChanged(config_
, ProxyConfigService::CONFIG_VALID
);
109 // Inherit from URLRequestFtpJob to expose the priority and some
110 // other hidden functions.
111 class TestURLRequestFtpJob
: public URLRequestFtpJob
{
113 TestURLRequestFtpJob(URLRequest
* request
,
114 FtpTransactionFactory
* ftp_factory
,
115 FtpAuthCache
* ftp_auth_cache
)
116 : URLRequestFtpJob(request
, NULL
, ftp_factory
, ftp_auth_cache
) {}
118 using URLRequestFtpJob::SetPriority
;
119 using URLRequestFtpJob::Start
;
120 using URLRequestFtpJob::Kill
;
121 using URLRequestFtpJob::priority
;
124 ~TestURLRequestFtpJob() override
{}
127 class MockFtpTransactionFactory
: public FtpTransactionFactory
{
129 FtpTransaction
* CreateTransaction() override
{ return NULL
; }
131 void Suspend(bool suspend
) override
{}
134 // Fixture for priority-related tests. Priority matters when there is
136 class URLRequestFtpJobPriorityTest
: public testing::Test
{
138 URLRequestFtpJobPriorityTest()
139 : proxy_service_(new SimpleProxyConfigService
, NULL
, NULL
),
140 req_(context_
.CreateRequest(GURL("ftp://ftp.example.com"),
143 context_
.set_proxy_service(&proxy_service_
);
144 context_
.set_http_transaction_factory(&network_layer_
);
147 ProxyService proxy_service_
;
148 MockNetworkLayer network_layer_
;
149 MockFtpTransactionFactory ftp_factory_
;
150 FtpAuthCache ftp_auth_cache_
;
151 TestURLRequestContext context_
;
152 TestDelegate delegate_
;
153 scoped_ptr
<URLRequest
> req_
;
156 // Make sure that SetPriority actually sets the URLRequestFtpJob's
157 // priority, both before and after start.
158 TEST_F(URLRequestFtpJobPriorityTest
, SetPriorityBasic
) {
159 scoped_refptr
<TestURLRequestFtpJob
> job(new TestURLRequestFtpJob(
160 req_
.get(), &ftp_factory_
, &ftp_auth_cache_
));
161 EXPECT_EQ(DEFAULT_PRIORITY
, job
->priority());
163 job
->SetPriority(LOWEST
);
164 EXPECT_EQ(LOWEST
, job
->priority());
166 job
->SetPriority(LOW
);
167 EXPECT_EQ(LOW
, job
->priority());
170 EXPECT_EQ(LOW
, job
->priority());
172 job
->SetPriority(MEDIUM
);
173 EXPECT_EQ(MEDIUM
, job
->priority());
176 // Make sure that URLRequestFtpJob passes on its priority to its
177 // transaction on start.
178 TEST_F(URLRequestFtpJobPriorityTest
, SetTransactionPriorityOnStart
) {
179 scoped_refptr
<TestURLRequestFtpJob
> job(new TestURLRequestFtpJob(
180 req_
.get(), &ftp_factory_
, &ftp_auth_cache_
));
181 job
->SetPriority(LOW
);
183 EXPECT_FALSE(network_layer_
.last_transaction());
187 ASSERT_TRUE(network_layer_
.last_transaction());
188 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
191 // Make sure that URLRequestFtpJob passes on its priority updates to
193 TEST_F(URLRequestFtpJobPriorityTest
, SetTransactionPriority
) {
194 scoped_refptr
<TestURLRequestFtpJob
> job(new TestURLRequestFtpJob(
195 req_
.get(), &ftp_factory_
, &ftp_auth_cache_
));
196 job
->SetPriority(LOW
);
198 ASSERT_TRUE(network_layer_
.last_transaction());
199 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
201 job
->SetPriority(HIGHEST
);
202 EXPECT_EQ(HIGHEST
, network_layer_
.last_transaction()->priority());
205 // Make sure that URLRequestFtpJob passes on its priority updates to
206 // newly-created transactions after the first one.
207 TEST_F(URLRequestFtpJobPriorityTest
, SetSubsequentTransactionPriority
) {
208 scoped_refptr
<TestURLRequestFtpJob
> job(new TestURLRequestFtpJob(
209 req_
.get(), &ftp_factory_
, &ftp_auth_cache_
));
212 job
->SetPriority(LOW
);
213 ASSERT_TRUE(network_layer_
.last_transaction());
214 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
217 network_layer_
.ClearLastTransaction();
219 // Creates a second transaction.
221 ASSERT_TRUE(network_layer_
.last_transaction());
222 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
225 class URLRequestFtpJobTest
: public testing::Test
{
227 URLRequestFtpJobTest()
228 : request_context_(&socket_factory_
,
230 new SimpleProxyConfigService
, NULL
, NULL
),
232 &ftp_transaction_factory_
) {
235 ~URLRequestFtpJobTest() override
{
236 // Clean up any remaining tasks that mess up unrelated tests.
237 base::RunLoop().RunUntilIdle();
240 void AddSocket(MockRead
* reads
, size_t reads_size
,
241 MockWrite
* writes
, size_t writes_size
) {
242 SequencedSocketData
* socket_data
=
243 new SequencedSocketData(reads
, reads_size
, writes
, writes_size
);
244 socket_data
->set_connect_data(MockConnect(SYNCHRONOUS
, OK
));
245 socket_factory_
.AddSocketDataProvider(socket_data
);
247 socket_data_
.push_back(socket_data
);
250 FtpTestURLRequestContext
* request_context() { return &request_context_
; }
251 TestNetworkDelegate
* network_delegate() { return &network_delegate_
; }
254 ScopedVector
<SequencedSocketData
> socket_data_
;
255 MockClientSocketFactory socket_factory_
;
256 TestNetworkDelegate network_delegate_
;
257 MockFtpTransactionFactory ftp_transaction_factory_
;
259 FtpTestURLRequestContext request_context_
;
262 TEST_F(URLRequestFtpJobTest
, FtpProxyRequest
) {
263 MockWrite writes
[] = {
264 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
265 "Host: ftp.example.com\r\n"
266 "Proxy-Connection: keep-alive\r\n\r\n"),
269 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
270 MockRead(ASYNC
, 2, "Content-Length: 9\r\n\r\n"),
271 MockRead(ASYNC
, 3, "test.html"),
274 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
276 TestDelegate request_delegate
;
277 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
278 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
279 url_request
->Start();
280 ASSERT_TRUE(url_request
->is_pending());
282 // The TestDelegate will by default quit the message loop on completion.
283 base::RunLoop().Run();
285 EXPECT_TRUE(url_request
->status().is_success());
286 EXPECT_TRUE(url_request
->proxy_server().Equals(
287 HostPortPair::FromString("localhost:80")));
288 EXPECT_EQ(1, network_delegate()->completed_requests());
289 EXPECT_EQ(0, network_delegate()->error_count());
290 EXPECT_FALSE(request_delegate
.auth_required_called());
291 EXPECT_EQ("test.html", request_delegate
.data_received());
294 // Regression test for http://crbug.com/237526 .
295 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestOrphanJob
) {
296 // Use a PAC URL so that URLRequestFtpJob's |pac_request_| field is non-NULL.
297 request_context()->set_proxy_service(new ProxyService(
298 new ProxyConfigServiceFixed(
299 ProxyConfig::CreateFromCustomPacURL(GURL("http://foo"))),
300 make_scoped_ptr(new MockProxyResolverFactory
), NULL
));
302 TestDelegate request_delegate
;
303 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
304 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
305 url_request
->Start();
307 // Now |url_request| will be deleted before its completion,
308 // resulting in it being orphaned. It should not crash.
311 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestNeedProxyAuthNoCredentials
) {
312 MockWrite writes
[] = {
313 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
314 "Host: ftp.example.com\r\n"
315 "Proxy-Connection: keep-alive\r\n\r\n"),
319 MockRead(ASYNC
, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
320 MockRead(ASYNC
, 2, "Proxy-Authenticate: Basic "
321 "realm=\"MyRealm1\"\r\n"),
322 MockRead(ASYNC
, 3, "Content-Length: 9\r\n\r\n"),
323 MockRead(ASYNC
, 4, "test.html"),
326 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
328 TestDelegate request_delegate
;
329 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
330 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
331 url_request
->Start();
332 ASSERT_TRUE(url_request
->is_pending());
334 // The TestDelegate will by default quit the message loop on completion.
335 base::RunLoop().Run();
337 EXPECT_TRUE(url_request
->status().is_success());
338 EXPECT_TRUE(url_request
->proxy_server().Equals(
339 HostPortPair::FromString("localhost:80")));
340 EXPECT_EQ(1, network_delegate()->completed_requests());
341 EXPECT_EQ(0, network_delegate()->error_count());
342 EXPECT_TRUE(request_delegate
.auth_required_called());
343 EXPECT_EQ("test.html", request_delegate
.data_received());
346 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestNeedProxyAuthWithCredentials
) {
347 MockWrite writes
[] = {
348 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
349 "Host: ftp.example.com\r\n"
350 "Proxy-Connection: keep-alive\r\n\r\n"),
351 MockWrite(ASYNC
, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
352 "Host: ftp.example.com\r\n"
353 "Proxy-Connection: keep-alive\r\n"
354 "Proxy-Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
358 MockRead(ASYNC
, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
359 MockRead(ASYNC
, 2, "Proxy-Authenticate: Basic "
360 "realm=\"MyRealm1\"\r\n"),
361 MockRead(ASYNC
, 3, "Content-Length: 9\r\n\r\n"),
362 MockRead(ASYNC
, 4, "test.html"),
365 MockRead(ASYNC
, 6, "HTTP/1.1 200 OK\r\n"),
366 MockRead(ASYNC
, 7, "Content-Length: 10\r\n\r\n"),
367 MockRead(ASYNC
, 8, "test2.html"),
370 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
372 TestDelegate request_delegate
;
373 request_delegate
.set_credentials(
374 AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
375 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
376 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
377 url_request
->Start();
378 ASSERT_TRUE(url_request
->is_pending());
380 // The TestDelegate will by default quit the message loop on completion.
381 base::RunLoop().Run();
383 EXPECT_TRUE(url_request
->status().is_success());
384 EXPECT_EQ(1, network_delegate()->completed_requests());
385 EXPECT_EQ(0, network_delegate()->error_count());
386 EXPECT_TRUE(request_delegate
.auth_required_called());
387 EXPECT_EQ("test2.html", request_delegate
.data_received());
390 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestNeedServerAuthNoCredentials
) {
391 MockWrite writes
[] = {
392 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
393 "Host: ftp.example.com\r\n"
394 "Proxy-Connection: keep-alive\r\n\r\n"),
398 MockRead(ASYNC
, 1, "HTTP/1.1 401 Unauthorized\r\n"),
399 MockRead(ASYNC
, 2, "WWW-Authenticate: Basic "
400 "realm=\"MyRealm1\"\r\n"),
401 MockRead(ASYNC
, 3, "Content-Length: 9\r\n\r\n"),
402 MockRead(ASYNC
, 4, "test.html"),
405 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
407 TestDelegate request_delegate
;
408 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
409 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
410 url_request
->Start();
411 ASSERT_TRUE(url_request
->is_pending());
413 // The TestDelegate will by default quit the message loop on completion.
414 base::RunLoop().Run();
416 EXPECT_TRUE(url_request
->status().is_success());
417 EXPECT_EQ(1, network_delegate()->completed_requests());
418 EXPECT_EQ(0, network_delegate()->error_count());
419 EXPECT_TRUE(request_delegate
.auth_required_called());
420 EXPECT_EQ("test.html", request_delegate
.data_received());
423 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestNeedServerAuthWithCredentials
) {
424 MockWrite writes
[] = {
425 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
426 "Host: ftp.example.com\r\n"
427 "Proxy-Connection: keep-alive\r\n\r\n"),
428 MockWrite(ASYNC
, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
429 "Host: ftp.example.com\r\n"
430 "Proxy-Connection: keep-alive\r\n"
431 "Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
435 MockRead(ASYNC
, 1, "HTTP/1.1 401 Unauthorized\r\n"),
436 MockRead(ASYNC
, 2, "WWW-Authenticate: Basic "
437 "realm=\"MyRealm1\"\r\n"),
438 MockRead(ASYNC
, 3, "Content-Length: 9\r\n\r\n"),
439 MockRead(ASYNC
, 4, "test.html"),
442 MockRead(ASYNC
, 6, "HTTP/1.1 200 OK\r\n"),
443 MockRead(ASYNC
, 7, "Content-Length: 10\r\n\r\n"),
444 MockRead(ASYNC
, 8, "test2.html"),
447 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
449 TestDelegate request_delegate
;
450 request_delegate
.set_credentials(
451 AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
452 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
453 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
454 url_request
->Start();
455 ASSERT_TRUE(url_request
->is_pending());
457 // The TestDelegate will by default quit the message loop on completion.
458 base::RunLoop().Run();
460 EXPECT_TRUE(url_request
->status().is_success());
461 EXPECT_EQ(1, network_delegate()->completed_requests());
462 EXPECT_EQ(0, network_delegate()->error_count());
463 EXPECT_TRUE(request_delegate
.auth_required_called());
464 EXPECT_EQ("test2.html", request_delegate
.data_received());
467 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestNeedProxyAndServerAuth
) {
468 MockWrite writes
[] = {
469 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
470 "Host: ftp.example.com\r\n"
471 "Proxy-Connection: keep-alive\r\n\r\n"),
472 MockWrite(ASYNC
, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
473 "Host: ftp.example.com\r\n"
474 "Proxy-Connection: keep-alive\r\n"
475 "Proxy-Authorization: Basic "
476 "cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n"),
477 MockWrite(ASYNC
, 10, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
478 "Host: ftp.example.com\r\n"
479 "Proxy-Connection: keep-alive\r\n"
480 "Proxy-Authorization: Basic "
481 "cHJveHl1c2VyOnByb3h5cGFzcw==\r\n"
482 "Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
486 MockRead(ASYNC
, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
487 MockRead(ASYNC
, 2, "Proxy-Authenticate: Basic "
488 "realm=\"MyRealm1\"\r\n"),
489 MockRead(ASYNC
, 3, "Content-Length: 9\r\n\r\n"),
490 MockRead(ASYNC
, 4, "test.html"),
493 MockRead(ASYNC
, 6, "HTTP/1.1 401 Unauthorized\r\n"),
494 MockRead(ASYNC
, 7, "WWW-Authenticate: Basic "
495 "realm=\"MyRealm1\"\r\n"),
496 MockRead(ASYNC
, 8, "Content-Length: 9\r\n\r\n"),
497 MockRead(ASYNC
, 9, "test.html"),
500 MockRead(ASYNC
, 11, "HTTP/1.1 200 OK\r\n"),
501 MockRead(ASYNC
, 12, "Content-Length: 10\r\n\r\n"),
502 MockRead(ASYNC
, 13, "test2.html"),
505 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
507 GURL
url("ftp://ftp.example.com");
509 // Make sure cached FTP credentials are not used for proxy authentication.
510 request_context()->GetFtpAuthCache()->Add(
512 AuthCredentials(ASCIIToUTF16("userdonotuse"),
513 ASCIIToUTF16("passworddonotuse")));
515 TestDelegate request_delegate
;
516 request_delegate
.set_quit_on_auth_required(true);
517 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
518 url
, DEFAULT_PRIORITY
, &request_delegate
));
519 url_request
->Start();
520 ASSERT_TRUE(url_request
->is_pending());
522 // Run until proxy auth is requested.
523 base::RunLoop().Run();
525 ASSERT_TRUE(request_delegate
.auth_required_called());
526 EXPECT_EQ(0, network_delegate()->completed_requests());
527 EXPECT_EQ(0, network_delegate()->error_count());
528 url_request
->SetAuth(
529 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")));
531 // Run until server auth is requested.
532 base::RunLoop().Run();
534 EXPECT_TRUE(url_request
->status().is_success());
535 EXPECT_EQ(0, network_delegate()->completed_requests());
536 EXPECT_EQ(0, network_delegate()->error_count());
537 url_request
->SetAuth(
538 AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
540 // The TestDelegate will by default quit the message loop on completion.
541 base::RunLoop().Run();
543 EXPECT_TRUE(url_request
->status().is_success());
544 EXPECT_EQ(1, network_delegate()->completed_requests());
545 EXPECT_EQ(0, network_delegate()->error_count());
546 EXPECT_TRUE(request_delegate
.auth_required_called());
547 EXPECT_EQ("test2.html", request_delegate
.data_received());
550 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestDoNotSaveCookies
) {
551 MockWrite writes
[] = {
552 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
553 "Host: ftp.example.com\r\n"
554 "Proxy-Connection: keep-alive\r\n\r\n"),
557 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
558 MockRead(ASYNC
, 2, "Content-Length: 9\r\n"),
559 MockRead(ASYNC
, 3, "Set-Cookie: name=value\r\n\r\n"),
560 MockRead(ASYNC
, 4, "test.html"),
563 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
565 TestDelegate request_delegate
;
566 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
567 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
568 url_request
->Start();
569 ASSERT_TRUE(url_request
->is_pending());
571 // The TestDelegate will by default quit the message loop on completion.
572 base::RunLoop().Run();
574 EXPECT_TRUE(url_request
->status().is_success());
575 EXPECT_EQ(1, network_delegate()->completed_requests());
576 EXPECT_EQ(0, network_delegate()->error_count());
578 // Make sure we do not accept cookies.
579 EXPECT_EQ(0, network_delegate()->set_cookie_count());
581 EXPECT_FALSE(request_delegate
.auth_required_called());
582 EXPECT_EQ("test.html", request_delegate
.data_received());
585 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestDoNotFollowRedirects
) {
586 MockWrite writes
[] = {
587 MockWrite(SYNCHRONOUS
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
588 "Host: ftp.example.com\r\n"
589 "Proxy-Connection: keep-alive\r\n\r\n"),
592 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 302 Found\r\n"),
593 MockRead(ASYNC
, 2, "Location: http://other.example.com/\r\n\r\n"),
596 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
598 TestDelegate request_delegate
;
599 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
600 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
601 url_request
->Start();
602 EXPECT_TRUE(url_request
->is_pending());
604 // The TestDelegate will by default quit the message loop on completion.
605 base::RunLoop().Run();
607 EXPECT_EQ(1, network_delegate()->completed_requests());
608 EXPECT_EQ(1, network_delegate()->error_count());
609 EXPECT_FALSE(url_request
->status().is_success());
610 EXPECT_EQ(ERR_UNSAFE_REDIRECT
, url_request
->status().error());
613 // We should re-use socket for requests using the same scheme, host, and port.
614 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestReuseSocket
) {
615 MockWrite writes
[] = {
616 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/first HTTP/1.1\r\n"
617 "Host: ftp.example.com\r\n"
618 "Proxy-Connection: keep-alive\r\n\r\n"),
619 MockWrite(ASYNC
, 4, "GET ftp://ftp.example.com/second HTTP/1.1\r\n"
620 "Host: ftp.example.com\r\n"
621 "Proxy-Connection: keep-alive\r\n\r\n"),
624 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
625 MockRead(ASYNC
, 2, "Content-Length: 10\r\n\r\n"),
626 MockRead(ASYNC
, 3, "test1.html"),
627 MockRead(ASYNC
, 5, "HTTP/1.1 200 OK\r\n"),
628 MockRead(ASYNC
, 6, "Content-Length: 10\r\n\r\n"),
629 MockRead(ASYNC
, 7, "test2.html"),
632 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
634 TestDelegate request_delegate1
;
636 scoped_ptr
<URLRequest
> url_request1(
637 request_context()->CreateRequest(GURL("ftp://ftp.example.com/first"),
638 DEFAULT_PRIORITY
, &request_delegate1
));
639 url_request1
->Start();
640 ASSERT_TRUE(url_request1
->is_pending());
642 // The TestDelegate will by default quit the message loop on completion.
643 base::RunLoop().Run();
645 EXPECT_TRUE(url_request1
->status().is_success());
646 EXPECT_TRUE(url_request1
->proxy_server().Equals(
647 HostPortPair::FromString("localhost:80")));
648 EXPECT_EQ(1, network_delegate()->completed_requests());
649 EXPECT_EQ(0, network_delegate()->error_count());
650 EXPECT_FALSE(request_delegate1
.auth_required_called());
651 EXPECT_EQ("test1.html", request_delegate1
.data_received());
653 TestDelegate request_delegate2
;
654 scoped_ptr
<URLRequest
> url_request2(
655 request_context()->CreateRequest(GURL("ftp://ftp.example.com/second"),
656 DEFAULT_PRIORITY
, &request_delegate2
));
657 url_request2
->Start();
658 ASSERT_TRUE(url_request2
->is_pending());
660 // The TestDelegate will by default quit the message loop on completion.
661 base::RunLoop().Run();
663 EXPECT_TRUE(url_request2
->status().is_success());
664 EXPECT_EQ(2, network_delegate()->completed_requests());
665 EXPECT_EQ(0, network_delegate()->error_count());
666 EXPECT_FALSE(request_delegate2
.auth_required_called());
667 EXPECT_EQ("test2.html", request_delegate2
.data_received());
670 // We should not re-use socket when there are two requests to the same host,
671 // but one is FTP and the other is HTTP.
672 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestDoNotReuseSocket
) {
673 MockWrite writes1
[] = {
674 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/first HTTP/1.1\r\n"
675 "Host: ftp.example.com\r\n"
676 "Proxy-Connection: keep-alive\r\n\r\n"),
678 MockWrite writes2
[] = {
679 MockWrite(ASYNC
, 0, "GET /second HTTP/1.1\r\n"
680 "Host: ftp.example.com\r\n"
681 "Connection: keep-alive\r\n"
683 "Accept-Encoding: gzip, deflate\r\n"
684 "Accept-Language: en-us,fr\r\n\r\n"),
686 MockRead reads1
[] = {
687 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
688 MockRead(ASYNC
, 2, "Content-Length: 10\r\n\r\n"),
689 MockRead(ASYNC
, 3, "test1.html"),
691 MockRead reads2
[] = {
692 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
693 MockRead(ASYNC
, 2, "Content-Length: 10\r\n\r\n"),
694 MockRead(ASYNC
, 3, "test2.html"),
697 AddSocket(reads1
, arraysize(reads1
), writes1
, arraysize(writes1
));
698 AddSocket(reads2
, arraysize(reads2
), writes2
, arraysize(writes2
));
700 TestDelegate request_delegate1
;
701 scoped_ptr
<URLRequest
> url_request1(
702 request_context()->CreateRequest(GURL("ftp://ftp.example.com/first"),
703 DEFAULT_PRIORITY
, &request_delegate1
));
704 url_request1
->Start();
705 ASSERT_TRUE(url_request1
->is_pending());
707 // The TestDelegate will by default quit the message loop on completion.
708 base::RunLoop().Run();
710 EXPECT_TRUE(url_request1
->status().is_success());
711 EXPECT_EQ(1, network_delegate()->completed_requests());
712 EXPECT_EQ(0, network_delegate()->error_count());
713 EXPECT_FALSE(request_delegate1
.auth_required_called());
714 EXPECT_EQ("test1.html", request_delegate1
.data_received());
716 TestDelegate request_delegate2
;
717 scoped_ptr
<URLRequest
> url_request2(
718 request_context()->CreateRequest(GURL("http://ftp.example.com/second"),
719 DEFAULT_PRIORITY
, &request_delegate2
));
720 url_request2
->Start();
721 ASSERT_TRUE(url_request2
->is_pending());
723 // The TestDelegate will by default quit the message loop on completion.
724 base::RunLoop().Run();
726 EXPECT_TRUE(url_request2
->status().is_success());
727 EXPECT_EQ(2, network_delegate()->completed_requests());
728 EXPECT_EQ(0, network_delegate()->error_count());
729 EXPECT_FALSE(request_delegate2
.auth_required_called());
730 EXPECT_EQ("test2.html", request_delegate2
.data_received());