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 scoped_ptr
<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
.Pass());
58 set_network_delegate(network_delegate
);
59 scoped_ptr
<URLRequestJobFactoryImpl
> job_factory
=
60 make_scoped_ptr(new URLRequestJobFactoryImpl
);
61 job_factory
->SetProtocolHandler("ftp",
62 make_scoped_ptr(ftp_protocol_handler_
));
63 context_storage_
.set_job_factory(job_factory
.Pass());
67 FtpAuthCache
* GetFtpAuthCache() {
68 return ftp_protocol_handler_
->ftp_auth_cache_
.get();
71 void set_proxy_service(scoped_ptr
<ProxyService
> proxy_service
) {
72 context_storage_
.set_proxy_service(proxy_service
.Pass());
76 FtpProtocolHandler
* ftp_protocol_handler_
;
81 class SimpleProxyConfigService
: public ProxyConfigService
{
83 SimpleProxyConfigService() {
84 // Any FTP requests that ever go through HTTP paths are proxied requests.
85 config_
.proxy_rules().ParseFromString("ftp=localhost");
88 void AddObserver(Observer
* observer
) override
{ observer_
= observer
; }
90 void RemoveObserver(Observer
* observer
) override
{
91 if (observer_
== observer
) {
96 ConfigAvailability
GetLatestProxyConfig(ProxyConfig
* config
) override
{
101 void IncrementConfigId() {
102 config_
.set_id(config_
.id() + 1);
103 observer_
->OnProxyConfigChanged(config_
, ProxyConfigService::CONFIG_VALID
);
111 // Inherit from URLRequestFtpJob to expose the priority and some
112 // other hidden functions.
113 class TestURLRequestFtpJob
: public URLRequestFtpJob
{
115 TestURLRequestFtpJob(URLRequest
* request
,
116 FtpTransactionFactory
* ftp_factory
,
117 FtpAuthCache
* ftp_auth_cache
)
118 : URLRequestFtpJob(request
, NULL
, ftp_factory
, ftp_auth_cache
) {}
120 using URLRequestFtpJob::SetPriority
;
121 using URLRequestFtpJob::Start
;
122 using URLRequestFtpJob::Kill
;
123 using URLRequestFtpJob::priority
;
126 ~TestURLRequestFtpJob() override
{}
129 class MockFtpTransactionFactory
: public FtpTransactionFactory
{
131 FtpTransaction
* CreateTransaction() override
{ return NULL
; }
133 void Suspend(bool suspend
) override
{}
136 // Fixture for priority-related tests. Priority matters when there is
138 class URLRequestFtpJobPriorityTest
: public testing::Test
{
140 URLRequestFtpJobPriorityTest()
141 : proxy_service_(new SimpleProxyConfigService
, NULL
, NULL
),
142 req_(context_
.CreateRequest(GURL("ftp://ftp.example.com"),
145 context_
.set_proxy_service(&proxy_service_
);
146 context_
.set_http_transaction_factory(&network_layer_
);
149 ProxyService proxy_service_
;
150 MockNetworkLayer network_layer_
;
151 MockFtpTransactionFactory ftp_factory_
;
152 FtpAuthCache ftp_auth_cache_
;
153 TestURLRequestContext context_
;
154 TestDelegate delegate_
;
155 scoped_ptr
<URLRequest
> req_
;
158 // Make sure that SetPriority actually sets the URLRequestFtpJob's
159 // priority, both before and after start.
160 TEST_F(URLRequestFtpJobPriorityTest
, SetPriorityBasic
) {
161 scoped_refptr
<TestURLRequestFtpJob
> job(new TestURLRequestFtpJob(
162 req_
.get(), &ftp_factory_
, &ftp_auth_cache_
));
163 EXPECT_EQ(DEFAULT_PRIORITY
, job
->priority());
165 job
->SetPriority(LOWEST
);
166 EXPECT_EQ(LOWEST
, job
->priority());
168 job
->SetPriority(LOW
);
169 EXPECT_EQ(LOW
, job
->priority());
172 EXPECT_EQ(LOW
, job
->priority());
174 job
->SetPriority(MEDIUM
);
175 EXPECT_EQ(MEDIUM
, job
->priority());
178 // Make sure that URLRequestFtpJob passes on its priority to its
179 // transaction on start.
180 TEST_F(URLRequestFtpJobPriorityTest
, SetTransactionPriorityOnStart
) {
181 scoped_refptr
<TestURLRequestFtpJob
> job(new TestURLRequestFtpJob(
182 req_
.get(), &ftp_factory_
, &ftp_auth_cache_
));
183 job
->SetPriority(LOW
);
185 EXPECT_FALSE(network_layer_
.last_transaction());
189 ASSERT_TRUE(network_layer_
.last_transaction());
190 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
193 // Make sure that URLRequestFtpJob passes on its priority updates to
195 TEST_F(URLRequestFtpJobPriorityTest
, SetTransactionPriority
) {
196 scoped_refptr
<TestURLRequestFtpJob
> job(new TestURLRequestFtpJob(
197 req_
.get(), &ftp_factory_
, &ftp_auth_cache_
));
198 job
->SetPriority(LOW
);
200 ASSERT_TRUE(network_layer_
.last_transaction());
201 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
203 job
->SetPriority(HIGHEST
);
204 EXPECT_EQ(HIGHEST
, network_layer_
.last_transaction()->priority());
207 // Make sure that URLRequestFtpJob passes on its priority updates to
208 // newly-created transactions after the first one.
209 TEST_F(URLRequestFtpJobPriorityTest
, SetSubsequentTransactionPriority
) {
210 scoped_refptr
<TestURLRequestFtpJob
> job(new TestURLRequestFtpJob(
211 req_
.get(), &ftp_factory_
, &ftp_auth_cache_
));
214 job
->SetPriority(LOW
);
215 ASSERT_TRUE(network_layer_
.last_transaction());
216 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
219 network_layer_
.ClearLastTransaction();
221 // Creates a second transaction.
223 ASSERT_TRUE(network_layer_
.last_transaction());
224 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
227 class URLRequestFtpJobTest
: public testing::Test
{
229 URLRequestFtpJobTest()
233 new ProxyService(new SimpleProxyConfigService
, NULL
, NULL
)),
235 &ftp_transaction_factory_
) {}
237 ~URLRequestFtpJobTest() override
{
238 // Clean up any remaining tasks that mess up unrelated tests.
239 base::RunLoop().RunUntilIdle();
242 void AddSocket(MockRead
* reads
, size_t reads_size
,
243 MockWrite
* writes
, size_t writes_size
) {
244 SequencedSocketData
* socket_data
=
245 new SequencedSocketData(reads
, reads_size
, writes
, writes_size
);
246 socket_data
->set_connect_data(MockConnect(SYNCHRONOUS
, OK
));
247 socket_factory_
.AddSocketDataProvider(socket_data
);
249 socket_data_
.push_back(socket_data
);
252 FtpTestURLRequestContext
* request_context() { return &request_context_
; }
253 TestNetworkDelegate
* network_delegate() { return &network_delegate_
; }
256 ScopedVector
<SequencedSocketData
> socket_data_
;
257 MockClientSocketFactory socket_factory_
;
258 TestNetworkDelegate network_delegate_
;
259 MockFtpTransactionFactory ftp_transaction_factory_
;
261 FtpTestURLRequestContext request_context_
;
264 TEST_F(URLRequestFtpJobTest
, FtpProxyRequest
) {
265 MockWrite writes
[] = {
266 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
267 "Host: ftp.example.com\r\n"
268 "Proxy-Connection: keep-alive\r\n\r\n"),
271 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
272 MockRead(ASYNC
, 2, "Content-Length: 9\r\n\r\n"),
273 MockRead(ASYNC
, 3, "test.html"),
276 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
278 TestDelegate request_delegate
;
279 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
280 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
281 url_request
->Start();
282 ASSERT_TRUE(url_request
->is_pending());
284 // The TestDelegate will by default quit the message loop on completion.
285 base::RunLoop().Run();
287 EXPECT_TRUE(url_request
->status().is_success());
288 EXPECT_TRUE(url_request
->proxy_server().Equals(
289 HostPortPair::FromString("localhost:80")));
290 EXPECT_EQ(1, network_delegate()->completed_requests());
291 EXPECT_EQ(0, network_delegate()->error_count());
292 EXPECT_FALSE(request_delegate
.auth_required_called());
293 EXPECT_EQ("test.html", request_delegate
.data_received());
296 // Regression test for http://crbug.com/237526 .
297 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestOrphanJob
) {
298 // Use a PAC URL so that URLRequestFtpJob's |pac_request_| field is non-NULL.
299 request_context()->set_proxy_service(make_scoped_ptr(new ProxyService(
300 new ProxyConfigServiceFixed(
301 ProxyConfig::CreateFromCustomPacURL(GURL("http://foo"))),
302 make_scoped_ptr(new MockProxyResolverFactory
), NULL
)));
304 TestDelegate request_delegate
;
305 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
306 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
307 url_request
->Start();
309 // Now |url_request| will be deleted before its completion,
310 // resulting in it being orphaned. It should not crash.
313 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestNeedProxyAuthNoCredentials
) {
314 MockWrite writes
[] = {
315 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
316 "Host: ftp.example.com\r\n"
317 "Proxy-Connection: keep-alive\r\n\r\n"),
321 MockRead(ASYNC
, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
322 MockRead(ASYNC
, 2, "Proxy-Authenticate: Basic "
323 "realm=\"MyRealm1\"\r\n"),
324 MockRead(ASYNC
, 3, "Content-Length: 9\r\n\r\n"),
325 MockRead(ASYNC
, 4, "test.html"),
328 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
330 TestDelegate request_delegate
;
331 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
332 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
333 url_request
->Start();
334 ASSERT_TRUE(url_request
->is_pending());
336 // The TestDelegate will by default quit the message loop on completion.
337 base::RunLoop().Run();
339 EXPECT_TRUE(url_request
->status().is_success());
340 EXPECT_TRUE(url_request
->proxy_server().Equals(
341 HostPortPair::FromString("localhost:80")));
342 EXPECT_EQ(1, network_delegate()->completed_requests());
343 EXPECT_EQ(0, network_delegate()->error_count());
344 EXPECT_TRUE(request_delegate
.auth_required_called());
345 EXPECT_EQ("test.html", request_delegate
.data_received());
348 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestNeedProxyAuthWithCredentials
) {
349 MockWrite writes
[] = {
350 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
351 "Host: ftp.example.com\r\n"
352 "Proxy-Connection: keep-alive\r\n\r\n"),
353 MockWrite(ASYNC
, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
354 "Host: ftp.example.com\r\n"
355 "Proxy-Connection: keep-alive\r\n"
356 "Proxy-Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
360 MockRead(ASYNC
, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
361 MockRead(ASYNC
, 2, "Proxy-Authenticate: Basic "
362 "realm=\"MyRealm1\"\r\n"),
363 MockRead(ASYNC
, 3, "Content-Length: 9\r\n\r\n"),
364 MockRead(ASYNC
, 4, "test.html"),
367 MockRead(ASYNC
, 6, "HTTP/1.1 200 OK\r\n"),
368 MockRead(ASYNC
, 7, "Content-Length: 10\r\n\r\n"),
369 MockRead(ASYNC
, 8, "test2.html"),
372 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
374 TestDelegate request_delegate
;
375 request_delegate
.set_credentials(
376 AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
377 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
378 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
379 url_request
->Start();
380 ASSERT_TRUE(url_request
->is_pending());
382 // The TestDelegate will by default quit the message loop on completion.
383 base::RunLoop().Run();
385 EXPECT_TRUE(url_request
->status().is_success());
386 EXPECT_EQ(1, network_delegate()->completed_requests());
387 EXPECT_EQ(0, network_delegate()->error_count());
388 EXPECT_TRUE(request_delegate
.auth_required_called());
389 EXPECT_EQ("test2.html", request_delegate
.data_received());
392 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestNeedServerAuthNoCredentials
) {
393 MockWrite writes
[] = {
394 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
395 "Host: ftp.example.com\r\n"
396 "Proxy-Connection: keep-alive\r\n\r\n"),
400 MockRead(ASYNC
, 1, "HTTP/1.1 401 Unauthorized\r\n"),
401 MockRead(ASYNC
, 2, "WWW-Authenticate: Basic "
402 "realm=\"MyRealm1\"\r\n"),
403 MockRead(ASYNC
, 3, "Content-Length: 9\r\n\r\n"),
404 MockRead(ASYNC
, 4, "test.html"),
407 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
409 TestDelegate request_delegate
;
410 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
411 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
412 url_request
->Start();
413 ASSERT_TRUE(url_request
->is_pending());
415 // The TestDelegate will by default quit the message loop on completion.
416 base::RunLoop().Run();
418 EXPECT_TRUE(url_request
->status().is_success());
419 EXPECT_EQ(1, network_delegate()->completed_requests());
420 EXPECT_EQ(0, network_delegate()->error_count());
421 EXPECT_TRUE(request_delegate
.auth_required_called());
422 EXPECT_EQ("test.html", request_delegate
.data_received());
425 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestNeedServerAuthWithCredentials
) {
426 MockWrite writes
[] = {
427 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
428 "Host: ftp.example.com\r\n"
429 "Proxy-Connection: keep-alive\r\n\r\n"),
430 MockWrite(ASYNC
, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
431 "Host: ftp.example.com\r\n"
432 "Proxy-Connection: keep-alive\r\n"
433 "Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
437 MockRead(ASYNC
, 1, "HTTP/1.1 401 Unauthorized\r\n"),
438 MockRead(ASYNC
, 2, "WWW-Authenticate: Basic "
439 "realm=\"MyRealm1\"\r\n"),
440 MockRead(ASYNC
, 3, "Content-Length: 9\r\n\r\n"),
441 MockRead(ASYNC
, 4, "test.html"),
444 MockRead(ASYNC
, 6, "HTTP/1.1 200 OK\r\n"),
445 MockRead(ASYNC
, 7, "Content-Length: 10\r\n\r\n"),
446 MockRead(ASYNC
, 8, "test2.html"),
449 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
451 TestDelegate request_delegate
;
452 request_delegate
.set_credentials(
453 AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
454 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
455 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
456 url_request
->Start();
457 ASSERT_TRUE(url_request
->is_pending());
459 // The TestDelegate will by default quit the message loop on completion.
460 base::RunLoop().Run();
462 EXPECT_TRUE(url_request
->status().is_success());
463 EXPECT_EQ(1, network_delegate()->completed_requests());
464 EXPECT_EQ(0, network_delegate()->error_count());
465 EXPECT_TRUE(request_delegate
.auth_required_called());
466 EXPECT_EQ("test2.html", request_delegate
.data_received());
469 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestNeedProxyAndServerAuth
) {
470 MockWrite writes
[] = {
471 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
472 "Host: ftp.example.com\r\n"
473 "Proxy-Connection: keep-alive\r\n\r\n"),
474 MockWrite(ASYNC
, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
475 "Host: ftp.example.com\r\n"
476 "Proxy-Connection: keep-alive\r\n"
477 "Proxy-Authorization: Basic "
478 "cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n"),
479 MockWrite(ASYNC
, 10, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
480 "Host: ftp.example.com\r\n"
481 "Proxy-Connection: keep-alive\r\n"
482 "Proxy-Authorization: Basic "
483 "cHJveHl1c2VyOnByb3h5cGFzcw==\r\n"
484 "Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
488 MockRead(ASYNC
, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
489 MockRead(ASYNC
, 2, "Proxy-Authenticate: Basic "
490 "realm=\"MyRealm1\"\r\n"),
491 MockRead(ASYNC
, 3, "Content-Length: 9\r\n\r\n"),
492 MockRead(ASYNC
, 4, "test.html"),
495 MockRead(ASYNC
, 6, "HTTP/1.1 401 Unauthorized\r\n"),
496 MockRead(ASYNC
, 7, "WWW-Authenticate: Basic "
497 "realm=\"MyRealm1\"\r\n"),
498 MockRead(ASYNC
, 8, "Content-Length: 9\r\n\r\n"),
499 MockRead(ASYNC
, 9, "test.html"),
502 MockRead(ASYNC
, 11, "HTTP/1.1 200 OK\r\n"),
503 MockRead(ASYNC
, 12, "Content-Length: 10\r\n\r\n"),
504 MockRead(ASYNC
, 13, "test2.html"),
507 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
509 GURL
url("ftp://ftp.example.com");
511 // Make sure cached FTP credentials are not used for proxy authentication.
512 request_context()->GetFtpAuthCache()->Add(
514 AuthCredentials(ASCIIToUTF16("userdonotuse"),
515 ASCIIToUTF16("passworddonotuse")));
517 TestDelegate request_delegate
;
518 request_delegate
.set_quit_on_auth_required(true);
519 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
520 url
, DEFAULT_PRIORITY
, &request_delegate
));
521 url_request
->Start();
522 ASSERT_TRUE(url_request
->is_pending());
524 // Run until proxy auth is requested.
525 base::RunLoop().Run();
527 ASSERT_TRUE(request_delegate
.auth_required_called());
528 EXPECT_EQ(0, network_delegate()->completed_requests());
529 EXPECT_EQ(0, network_delegate()->error_count());
530 url_request
->SetAuth(
531 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")));
533 // Run until server auth is requested.
534 base::RunLoop().Run();
536 EXPECT_TRUE(url_request
->status().is_success());
537 EXPECT_EQ(0, network_delegate()->completed_requests());
538 EXPECT_EQ(0, network_delegate()->error_count());
539 url_request
->SetAuth(
540 AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
542 // The TestDelegate will by default quit the message loop on completion.
543 base::RunLoop().Run();
545 EXPECT_TRUE(url_request
->status().is_success());
546 EXPECT_EQ(1, network_delegate()->completed_requests());
547 EXPECT_EQ(0, network_delegate()->error_count());
548 EXPECT_TRUE(request_delegate
.auth_required_called());
549 EXPECT_EQ("test2.html", request_delegate
.data_received());
552 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestDoNotSaveCookies
) {
553 MockWrite writes
[] = {
554 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
555 "Host: ftp.example.com\r\n"
556 "Proxy-Connection: keep-alive\r\n\r\n"),
559 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
560 MockRead(ASYNC
, 2, "Content-Length: 9\r\n"),
561 MockRead(ASYNC
, 3, "Set-Cookie: name=value\r\n\r\n"),
562 MockRead(ASYNC
, 4, "test.html"),
565 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
567 TestDelegate request_delegate
;
568 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
569 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
570 url_request
->Start();
571 ASSERT_TRUE(url_request
->is_pending());
573 // The TestDelegate will by default quit the message loop on completion.
574 base::RunLoop().Run();
576 EXPECT_TRUE(url_request
->status().is_success());
577 EXPECT_EQ(1, network_delegate()->completed_requests());
578 EXPECT_EQ(0, network_delegate()->error_count());
580 // Make sure we do not accept cookies.
581 EXPECT_EQ(0, network_delegate()->set_cookie_count());
583 EXPECT_FALSE(request_delegate
.auth_required_called());
584 EXPECT_EQ("test.html", request_delegate
.data_received());
587 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestDoNotFollowRedirects
) {
588 MockWrite writes
[] = {
589 MockWrite(SYNCHRONOUS
, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
590 "Host: ftp.example.com\r\n"
591 "Proxy-Connection: keep-alive\r\n\r\n"),
594 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 302 Found\r\n"),
595 MockRead(ASYNC
, 2, "Location: http://other.example.com/\r\n\r\n"),
598 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
600 TestDelegate request_delegate
;
601 scoped_ptr
<URLRequest
> url_request(request_context()->CreateRequest(
602 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY
, &request_delegate
));
603 url_request
->Start();
604 EXPECT_TRUE(url_request
->is_pending());
606 // The TestDelegate will by default quit the message loop on completion.
607 base::RunLoop().Run();
609 EXPECT_EQ(1, network_delegate()->completed_requests());
610 EXPECT_EQ(1, network_delegate()->error_count());
611 EXPECT_FALSE(url_request
->status().is_success());
612 EXPECT_EQ(ERR_UNSAFE_REDIRECT
, url_request
->status().error());
615 // We should re-use socket for requests using the same scheme, host, and port.
616 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestReuseSocket
) {
617 MockWrite writes
[] = {
618 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/first HTTP/1.1\r\n"
619 "Host: ftp.example.com\r\n"
620 "Proxy-Connection: keep-alive\r\n\r\n"),
621 MockWrite(ASYNC
, 4, "GET ftp://ftp.example.com/second HTTP/1.1\r\n"
622 "Host: ftp.example.com\r\n"
623 "Proxy-Connection: keep-alive\r\n\r\n"),
626 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
627 MockRead(ASYNC
, 2, "Content-Length: 10\r\n\r\n"),
628 MockRead(ASYNC
, 3, "test1.html"),
629 MockRead(ASYNC
, 5, "HTTP/1.1 200 OK\r\n"),
630 MockRead(ASYNC
, 6, "Content-Length: 10\r\n\r\n"),
631 MockRead(ASYNC
, 7, "test2.html"),
634 AddSocket(reads
, arraysize(reads
), writes
, arraysize(writes
));
636 TestDelegate request_delegate1
;
638 scoped_ptr
<URLRequest
> url_request1(
639 request_context()->CreateRequest(GURL("ftp://ftp.example.com/first"),
640 DEFAULT_PRIORITY
, &request_delegate1
));
641 url_request1
->Start();
642 ASSERT_TRUE(url_request1
->is_pending());
644 // The TestDelegate will by default quit the message loop on completion.
645 base::RunLoop().Run();
647 EXPECT_TRUE(url_request1
->status().is_success());
648 EXPECT_TRUE(url_request1
->proxy_server().Equals(
649 HostPortPair::FromString("localhost:80")));
650 EXPECT_EQ(1, network_delegate()->completed_requests());
651 EXPECT_EQ(0, network_delegate()->error_count());
652 EXPECT_FALSE(request_delegate1
.auth_required_called());
653 EXPECT_EQ("test1.html", request_delegate1
.data_received());
655 TestDelegate request_delegate2
;
656 scoped_ptr
<URLRequest
> url_request2(
657 request_context()->CreateRequest(GURL("ftp://ftp.example.com/second"),
658 DEFAULT_PRIORITY
, &request_delegate2
));
659 url_request2
->Start();
660 ASSERT_TRUE(url_request2
->is_pending());
662 // The TestDelegate will by default quit the message loop on completion.
663 base::RunLoop().Run();
665 EXPECT_TRUE(url_request2
->status().is_success());
666 EXPECT_EQ(2, network_delegate()->completed_requests());
667 EXPECT_EQ(0, network_delegate()->error_count());
668 EXPECT_FALSE(request_delegate2
.auth_required_called());
669 EXPECT_EQ("test2.html", request_delegate2
.data_received());
672 // We should not re-use socket when there are two requests to the same host,
673 // but one is FTP and the other is HTTP.
674 TEST_F(URLRequestFtpJobTest
, FtpProxyRequestDoNotReuseSocket
) {
675 MockWrite writes1
[] = {
676 MockWrite(ASYNC
, 0, "GET ftp://ftp.example.com/first HTTP/1.1\r\n"
677 "Host: ftp.example.com\r\n"
678 "Proxy-Connection: keep-alive\r\n\r\n"),
680 MockWrite writes2
[] = {
681 MockWrite(ASYNC
, 0, "GET /second HTTP/1.1\r\n"
682 "Host: ftp.example.com\r\n"
683 "Connection: keep-alive\r\n"
685 "Accept-Encoding: gzip, deflate\r\n"
686 "Accept-Language: en-us,fr\r\n\r\n"),
688 MockRead reads1
[] = {
689 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
690 MockRead(ASYNC
, 2, "Content-Length: 10\r\n\r\n"),
691 MockRead(ASYNC
, 3, "test1.html"),
693 MockRead reads2
[] = {
694 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
695 MockRead(ASYNC
, 2, "Content-Length: 10\r\n\r\n"),
696 MockRead(ASYNC
, 3, "test2.html"),
699 AddSocket(reads1
, arraysize(reads1
), writes1
, arraysize(writes1
));
700 AddSocket(reads2
, arraysize(reads2
), writes2
, arraysize(writes2
));
702 TestDelegate request_delegate1
;
703 scoped_ptr
<URLRequest
> url_request1(
704 request_context()->CreateRequest(GURL("ftp://ftp.example.com/first"),
705 DEFAULT_PRIORITY
, &request_delegate1
));
706 url_request1
->Start();
707 ASSERT_TRUE(url_request1
->is_pending());
709 // The TestDelegate will by default quit the message loop on completion.
710 base::RunLoop().Run();
712 EXPECT_TRUE(url_request1
->status().is_success());
713 EXPECT_EQ(1, network_delegate()->completed_requests());
714 EXPECT_EQ(0, network_delegate()->error_count());
715 EXPECT_FALSE(request_delegate1
.auth_required_called());
716 EXPECT_EQ("test1.html", request_delegate1
.data_received());
718 TestDelegate request_delegate2
;
719 scoped_ptr
<URLRequest
> url_request2(
720 request_context()->CreateRequest(GURL("http://ftp.example.com/second"),
721 DEFAULT_PRIORITY
, &request_delegate2
));
722 url_request2
->Start();
723 ASSERT_TRUE(url_request2
->is_pending());
725 // The TestDelegate will by default quit the message loop on completion.
726 base::RunLoop().Run();
728 EXPECT_TRUE(url_request2
->status().is_success());
729 EXPECT_EQ(2, network_delegate()->completed_requests());
730 EXPECT_EQ(0, network_delegate()->error_count());
731 EXPECT_FALSE(request_delegate2
.auth_required_called());
732 EXPECT_EQ("test2.html", request_delegate2
.data_received());