url_request_ftp_job_unittest.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
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. 4 5#include "net/url_request/url_request_ftp_job.h" 6 7#include "base/memory/ref_counted.h" 8#include "base/memory/scoped_vector.h" 9#include "base/run_loop.h" 10#include "net/base/host_port_pair.h" 11#include "net/base/request_priority.h" 12#include "net/ftp/ftp_auth_cache.h" 13#include "net/http/http_transaction_test_util.h" 14#include "net/proxy/mock_proxy_resolver.h" 15#include "net/proxy/proxy_config_service.h" 16#include "net/proxy/proxy_config_service_fixed.h" 17#include "net/socket/socket_test_util.h" 18#include "net/url_request/ftp_protocol_handler.h" 19#include "net/url_request/url_request.h" 20#include "net/url_request/url_request_context.h" 21#include "net/url_request/url_request_job_factory_impl.h" 22#include "net/url_request/url_request_status.h" 23#include "net/url_request/url_request_test_util.h" 24#include "testing/gtest/include/gtest/gtest.h" 25#include "url/gurl.h" 26 27using base::ASCIIToUTF16; 28 29namespace net { 30 31class FtpTestURLRequestContext : public TestURLRequestContext { 32 public: 33 FtpTestURLRequestContext(ClientSocketFactory* socket_factory, 34 ProxyService* proxy_service, 35 NetworkDelegate* network_delegate, 36 FtpTransactionFactory* ftp_transaction_factory) 37 : TestURLRequestContext(true), 38 ftp_protocol_handler_(new FtpProtocolHandler(ftp_transaction_factory)) { 39 set_client_socket_factory(socket_factory); 40 context_storage_.set_proxy_service(proxy_service); 41 set_network_delegate(network_delegate); 42 URLRequestJobFactoryImpl* job_factory = new URLRequestJobFactoryImpl; 43 job_factory->SetProtocolHandler("ftp", ftp_protocol_handler_); 44 context_storage_.set_job_factory(job_factory); 45 Init(); 46 } 47 48 FtpAuthCache* GetFtpAuthCache() { 49 return ftp_protocol_handler_->ftp_auth_cache_.get(); 50 } 51 52 void set_proxy_service(ProxyService* proxy_service) { 53 context_storage_.set_proxy_service(proxy_service); 54 } 55 56 private: 57 FtpProtocolHandler* ftp_protocol_handler_; 58}; 59 60namespace { 61 62class SimpleProxyConfigService : public ProxyConfigService { 63 public: 64 SimpleProxyConfigService() { 65 // Any FTP requests that ever go through HTTP paths are proxied requests. 66 config_.proxy_rules().ParseFromString("ftp=localhost"); 67 } 68 69 virtual void AddObserver(Observer* observer) OVERRIDE { 70 observer_ = observer; 71 } 72 73 virtual void RemoveObserver(Observer* observer) OVERRIDE { 74 if (observer_ == observer) { 75 observer_ = NULL; 76 } 77 } 78 79 virtual ConfigAvailability GetLatestProxyConfig( 80 ProxyConfig* config) OVERRIDE { 81 *config = config_; 82 return CONFIG_VALID; 83 } 84 85 void IncrementConfigId() { 86 config_.set_id(config_.id() + 1); 87 observer_->OnProxyConfigChanged(config_, ProxyConfigService::CONFIG_VALID); 88 } 89 90 private: 91 ProxyConfig config_; 92 Observer* observer_; 93}; 94 95// Inherit from URLRequestFtpJob to expose the priority and some 96// other hidden functions. 97class TestURLRequestFtpJob : public URLRequestFtpJob { 98 public: 99 TestURLRequestFtpJob(URLRequest* request, 100 FtpTransactionFactory* ftp_factory, 101 FtpAuthCache* ftp_auth_cache) 102 : URLRequestFtpJob(request, NULL, ftp_factory, ftp_auth_cache) {} 103 104 using URLRequestFtpJob::SetPriority; 105 using URLRequestFtpJob::Start; 106 using URLRequestFtpJob::Kill; 107 using URLRequestFtpJob::priority; 108 109 protected: 110 virtual ~TestURLRequestFtpJob() {} 111}; 112 113class MockFtpTransactionFactory : public FtpTransactionFactory { 114 public: 115 virtual FtpTransaction* CreateTransaction() OVERRIDE { 116 return NULL; 117 } 118 119 virtual void Suspend(bool suspend) OVERRIDE {} 120}; 121 122// Fixture for priority-related tests. Priority matters when there is 123// an HTTP proxy. 124class URLRequestFtpJobPriorityTest : public testing::Test { 125 protected: 126 URLRequestFtpJobPriorityTest() 127 : proxy_service_(new SimpleProxyConfigService, NULL, NULL), 128 req_(GURL("ftp://ftp.example.com"), 129 DEFAULT_PRIORITY, 130 &delegate_, 131 &context_) { 132 context_.set_proxy_service(&proxy_service_); 133 context_.set_http_transaction_factory(&network_layer_); 134 } 135 136 ProxyService proxy_service_; 137 MockNetworkLayer network_layer_; 138 MockFtpTransactionFactory ftp_factory_; 139 FtpAuthCache ftp_auth_cache_; 140 TestURLRequestContext context_; 141 TestDelegate delegate_; 142 TestURLRequest req_; 143}; 144 145// Make sure that SetPriority actually sets the URLRequestFtpJob's 146// priority, both before and after start. 147TEST_F(URLRequestFtpJobPriorityTest, SetPriorityBasic) { 148 scoped_refptr<TestURLRequestFtpJob> job(new TestURLRequestFtpJob( 149 &req_, &ftp_factory_, &ftp_auth_cache_)); 150 EXPECT_EQ(DEFAULT_PRIORITY, job->priority()); 151 152 job->SetPriority(LOWEST); 153 EXPECT_EQ(LOWEST, job->priority()); 154 155 job->SetPriority(LOW); 156 EXPECT_EQ(LOW, job->priority()); 157 158 job->Start(); 159 EXPECT_EQ(LOW, job->priority()); 160 161 job->SetPriority(MEDIUM); 162 EXPECT_EQ(MEDIUM, job->priority()); 163} 164 165// Make sure that URLRequestFtpJob passes on its priority to its 166// transaction on start. 167TEST_F(URLRequestFtpJobPriorityTest, SetTransactionPriorityOnStart) { 168 scoped_refptr<TestURLRequestFtpJob> job(new TestURLRequestFtpJob( 169 &req_, &ftp_factory_, &ftp_auth_cache_)); 170 job->SetPriority(LOW); 171 172 EXPECT_FALSE(network_layer_.last_transaction()); 173 174 job->Start(); 175 176 ASSERT_TRUE(network_layer_.last_transaction()); 177 EXPECT_EQ(LOW, network_layer_.last_transaction()->priority()); 178} 179 180// Make sure that URLRequestFtpJob passes on its priority updates to 181// its transaction. 182TEST_F(URLRequestFtpJobPriorityTest, SetTransactionPriority) { 183 scoped_refptr<TestURLRequestFtpJob> job(new TestURLRequestFtpJob( 184 &req_, &ftp_factory_, &ftp_auth_cache_)); 185 job->SetPriority(LOW); 186 job->Start(); 187 ASSERT_TRUE(network_layer_.last_transaction()); 188 EXPECT_EQ(LOW, network_layer_.last_transaction()->priority()); 189 190 job->SetPriority(HIGHEST); 191 EXPECT_EQ(HIGHEST, network_layer_.last_transaction()->priority()); 192} 193 194// Make sure that URLRequestFtpJob passes on its priority updates to 195// newly-created transactions after the first one. 196TEST_F(URLRequestFtpJobPriorityTest, SetSubsequentTransactionPriority) { 197 scoped_refptr<TestURLRequestFtpJob> job(new TestURLRequestFtpJob( 198 &req_, &ftp_factory_, &ftp_auth_cache_)); 199 job->Start(); 200 201 job->SetPriority(LOW); 202 ASSERT_TRUE(network_layer_.last_transaction()); 203 EXPECT_EQ(LOW, network_layer_.last_transaction()->priority()); 204 205 job->Kill(); 206 network_layer_.ClearLastTransaction(); 207 208 // Creates a second transaction. 209 job->Start(); 210 ASSERT_TRUE(network_layer_.last_transaction()); 211 EXPECT_EQ(LOW, network_layer_.last_transaction()->priority()); 212} 213 214class URLRequestFtpJobTest : public testing::Test { 215 public: 216 URLRequestFtpJobTest() 217 : request_context_(&socket_factory_, 218 new ProxyService( 219 new SimpleProxyConfigService, NULL, NULL), 220 &network_delegate_, 221 &ftp_transaction_factory_) { 222 } 223 224 virtual ~URLRequestFtpJobTest() { 225 // Clean up any remaining tasks that mess up unrelated tests. 226 base::RunLoop run_loop; 227 run_loop.RunUntilIdle(); 228 } 229 230 void AddSocket(MockRead* reads, size_t reads_size, 231 MockWrite* writes, size_t writes_size) { 232 DeterministicSocketData* socket_data = new DeterministicSocketData( 233 reads, reads_size, writes, writes_size); 234 socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); 235 socket_data->StopAfter(reads_size + writes_size - 1); 236 socket_factory_.AddSocketDataProvider(socket_data); 237 238 socket_data_.push_back(socket_data); 239 } 240 241 FtpTestURLRequestContext* request_context() { return &request_context_; } 242 TestNetworkDelegate* network_delegate() { return &network_delegate_; } 243 DeterministicSocketData* socket_data(size_t index) { 244 return socket_data_[index]; 245 } 246 247 private: 248 ScopedVector<DeterministicSocketData> socket_data_; 249 DeterministicMockClientSocketFactory socket_factory_; 250 TestNetworkDelegate network_delegate_; 251 MockFtpTransactionFactory ftp_transaction_factory_; 252 253 FtpTestURLRequestContext request_context_; 254}; 255 256TEST_F(URLRequestFtpJobTest, FtpProxyRequest) { 257 MockWrite writes[] = { 258 MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n" 259 "Host: ftp.example.com\r\n" 260 "Proxy-Connection: keep-alive\r\n\r\n"), 261 }; 262 MockRead reads[] = { 263 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"), 264 MockRead(ASYNC, 2, "Content-Length: 9\r\n\r\n"), 265 MockRead(ASYNC, 3, "test.html"), 266 }; 267 268 AddSocket(reads, arraysize(reads), writes, arraysize(writes)); 269 270 TestDelegate request_delegate; 271 scoped_ptr<URLRequest> url_request(request_context()->CreateRequest( 272 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY, 273 &request_delegate, NULL)); 274 url_request->Start(); 275 ASSERT_TRUE(url_request->is_pending()); 276 socket_data(0)->RunFor(4); 277 278 EXPECT_TRUE(url_request->status().is_success()); 279 EXPECT_TRUE(url_request->proxy_server().Equals( 280 net::HostPortPair::FromString("localhost:80"))); 281 EXPECT_EQ(1, network_delegate()->completed_requests()); 282 EXPECT_EQ(0, network_delegate()->error_count()); 283 EXPECT_FALSE(request_delegate.auth_required_called()); 284 EXPECT_EQ("test.html", request_delegate.data_received()); 285} 286 287// Regression test for http://crbug.com/237526 . 288TEST_F(URLRequestFtpJobTest, FtpProxyRequestOrphanJob) { 289 // Use a PAC URL so that URLRequestFtpJob's |pac_request_| field is non-NULL. 290 request_context()->set_proxy_service( 291 new ProxyService( 292 new ProxyConfigServiceFixed( 293 ProxyConfig::CreateFromCustomPacURL(GURL("http://foo"))), 294 new MockAsyncProxyResolver, NULL)); 295 296 TestDelegate request_delegate; 297 scoped_ptr<URLRequest> url_request(request_context()->CreateRequest( 298 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY, &request_delegate, 299 NULL)); 300 url_request->Start(); 301 302 // Now |url_request| will be deleted before its completion, 303 // resulting in it being orphaned. It should not crash. 304} 305 306TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedProxyAuthNoCredentials) { 307 MockWrite writes[] = { 308 MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n" 309 "Host: ftp.example.com\r\n" 310 "Proxy-Connection: keep-alive\r\n\r\n"), 311 }; 312 MockRead reads[] = { 313 // No credentials. 314 MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"), 315 MockRead(ASYNC, 2, "Proxy-Authenticate: Basic " 316 "realm=\"MyRealm1\"\r\n"), 317 MockRead(ASYNC, 3, "Content-Length: 9\r\n\r\n"), 318 MockRead(ASYNC, 4, "test.html"), 319 }; 320 321 AddSocket(reads, arraysize(reads), writes, arraysize(writes)); 322 323 TestDelegate request_delegate; 324 scoped_ptr<URLRequest> url_request(request_context()->CreateRequest( 325 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY, &request_delegate, 326 NULL)); 327 url_request->Start(); 328 ASSERT_TRUE(url_request->is_pending()); 329 socket_data(0)->RunFor(5); 330 331 EXPECT_TRUE(url_request->status().is_success()); 332 EXPECT_TRUE(url_request->proxy_server().Equals( 333 net::HostPortPair::FromString("localhost:80"))); 334 EXPECT_EQ(1, network_delegate()->completed_requests()); 335 EXPECT_EQ(0, network_delegate()->error_count()); 336 EXPECT_TRUE(request_delegate.auth_required_called()); 337 EXPECT_EQ("test.html", request_delegate.data_received()); 338} 339 340TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedProxyAuthWithCredentials) { 341 MockWrite writes[] = { 342 MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n" 343 "Host: ftp.example.com\r\n" 344 "Proxy-Connection: keep-alive\r\n\r\n"), 345 MockWrite(ASYNC, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n" 346 "Host: ftp.example.com\r\n" 347 "Proxy-Connection: keep-alive\r\n" 348 "Proxy-Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"), 349 }; 350 MockRead reads[] = { 351 // No credentials. 352 MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"), 353 MockRead(ASYNC, 2, "Proxy-Authenticate: Basic " 354 "realm=\"MyRealm1\"\r\n"), 355 MockRead(ASYNC, 3, "Content-Length: 9\r\n\r\n"), 356 MockRead(ASYNC, 4, "test.html"), 357 358 // Second response. 359 MockRead(ASYNC, 6, "HTTP/1.1 200 OK\r\n"), 360 MockRead(ASYNC, 7, "Content-Length: 10\r\n\r\n"), 361 MockRead(ASYNC, 8, "test2.html"), 362 }; 363 364 AddSocket(reads, arraysize(reads), writes, arraysize(writes)); 365 366 TestDelegate request_delegate; 367 request_delegate.set_credentials( 368 AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass"))); 369 scoped_ptr<URLRequest> url_request(request_context()->CreateRequest( 370 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY, &request_delegate, 371 NULL)); 372 url_request->Start(); 373 ASSERT_TRUE(url_request->is_pending()); 374 socket_data(0)->RunFor(9); 375 376 EXPECT_TRUE(url_request->status().is_success()); 377 EXPECT_EQ(1, network_delegate()->completed_requests()); 378 EXPECT_EQ(0, network_delegate()->error_count()); 379 EXPECT_TRUE(request_delegate.auth_required_called()); 380 EXPECT_EQ("test2.html", request_delegate.data_received()); 381} 382 383TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedServerAuthNoCredentials) { 384 MockWrite writes[] = { 385 MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n" 386 "Host: ftp.example.com\r\n" 387 "Proxy-Connection: keep-alive\r\n\r\n"), 388 }; 389 MockRead reads[] = { 390 // No credentials. 391 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"), 392 MockRead(ASYNC, 2, "WWW-Authenticate: Basic " 393 "realm=\"MyRealm1\"\r\n"), 394 MockRead(ASYNC, 3, "Content-Length: 9\r\n\r\n"), 395 MockRead(ASYNC, 4, "test.html"), 396 }; 397 398 AddSocket(reads, arraysize(reads), writes, arraysize(writes)); 399 400 TestDelegate request_delegate; 401 scoped_ptr<URLRequest> url_request(request_context()->CreateRequest( 402 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY, &request_delegate, 403 NULL)); 404 url_request->Start(); 405 ASSERT_TRUE(url_request->is_pending()); 406 socket_data(0)->RunFor(5); 407 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()); 413} 414 415TEST_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"), 424 }; 425 MockRead reads[] = { 426 // No credentials. 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"), 432 433 // Second response. 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"), 437 }; 438 439 AddSocket(reads, arraysize(reads), writes, arraysize(writes)); 440 441 TestDelegate request_delegate; 442 request_delegate.set_credentials( 443 AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass"))); 444 scoped_ptr<URLRequest> url_request(request_context()->CreateRequest( 445 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY, &request_delegate, 446 NULL)); 447 url_request->Start(); 448 ASSERT_TRUE(url_request->is_pending()); 449 socket_data(0)->RunFor(9); 450 451 EXPECT_TRUE(url_request->status().is_success()); 452 EXPECT_EQ(1, network_delegate()->completed_requests()); 453 EXPECT_EQ(0, network_delegate()->error_count()); 454 EXPECT_TRUE(request_delegate.auth_required_called()); 455 EXPECT_EQ("test2.html", request_delegate.data_received()); 456} 457 458TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedProxyAndServerAuth) { 459 MockWrite writes[] = { 460 MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n" 461 "Host: ftp.example.com\r\n" 462 "Proxy-Connection: keep-alive\r\n\r\n"), 463 MockWrite(ASYNC, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n" 464 "Host: ftp.example.com\r\n" 465 "Proxy-Connection: keep-alive\r\n" 466 "Proxy-Authorization: Basic " 467 "cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n"), 468 MockWrite(ASYNC, 10, "GET ftp://ftp.example.com/ HTTP/1.1\r\n" 469 "Host: ftp.example.com\r\n" 470 "Proxy-Connection: keep-alive\r\n" 471 "Proxy-Authorization: Basic " 472 "cHJveHl1c2VyOnByb3h5cGFzcw==\r\n" 473 "Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"), 474 }; 475 MockRead reads[] = { 476 // No credentials. 477 MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"), 478 MockRead(ASYNC, 2, "Proxy-Authenticate: Basic " 479 "realm=\"MyRealm1\"\r\n"), 480 MockRead(ASYNC, 3, "Content-Length: 9\r\n\r\n"), 481 MockRead(ASYNC, 4, "test.html"), 482 483 // Second response. 484 MockRead(ASYNC, 6, "HTTP/1.1 401 Unauthorized\r\n"), 485 MockRead(ASYNC, 7, "WWW-Authenticate: Basic " 486 "realm=\"MyRealm1\"\r\n"), 487 MockRead(ASYNC, 8, "Content-Length: 9\r\n\r\n"), 488 MockRead(ASYNC, 9, "test.html"), 489 490 // Third response. 491 MockRead(ASYNC, 11, "HTTP/1.1 200 OK\r\n"), 492 MockRead(ASYNC, 12, "Content-Length: 10\r\n\r\n"), 493 MockRead(ASYNC, 13, "test2.html"), 494 }; 495 496 AddSocket(reads, arraysize(reads), writes, arraysize(writes)); 497 498 GURL url("ftp://ftp.example.com"); 499 500 // Make sure cached FTP credentials are not used for proxy authentication. 501 request_context()->GetFtpAuthCache()->Add( 502 url.GetOrigin(), 503 AuthCredentials(ASCIIToUTF16("userdonotuse"), 504 ASCIIToUTF16("passworddonotuse"))); 505 506 TestDelegate request_delegate; 507 request_delegate.set_credentials( 508 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass"))); 509 scoped_ptr<URLRequest> url_request(request_context()->CreateRequest( 510 url, DEFAULT_PRIORITY, &request_delegate, NULL)); 511 url_request->Start(); 512 ASSERT_TRUE(url_request->is_pending()); 513 socket_data(0)->RunFor(5); 514 515 request_delegate.set_credentials( 516 AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass"))); 517 socket_data(0)->RunFor(9); 518 519 EXPECT_TRUE(url_request->status().is_success()); 520 EXPECT_EQ(1, network_delegate()->completed_requests()); 521 EXPECT_EQ(0, network_delegate()->error_count()); 522 EXPECT_TRUE(request_delegate.auth_required_called()); 523 EXPECT_EQ("test2.html", request_delegate.data_received()); 524} 525 526TEST_F(URLRequestFtpJobTest, FtpProxyRequestDoNotSaveCookies) { 527 MockWrite writes[] = { 528 MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n" 529 "Host: ftp.example.com\r\n" 530 "Proxy-Connection: keep-alive\r\n\r\n"), 531 }; 532 MockRead reads[] = { 533 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"), 534 MockRead(ASYNC, 2, "Content-Length: 9\r\n"), 535 MockRead(ASYNC, 3, "Set-Cookie: name=value\r\n\r\n"), 536 MockRead(ASYNC, 4, "test.html"), 537 }; 538 539 AddSocket(reads, arraysize(reads), writes, arraysize(writes)); 540 541 TestDelegate request_delegate; 542 scoped_ptr<URLRequest> url_request(request_context()->CreateRequest( 543 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY, &request_delegate, 544 NULL)); 545 url_request->Start(); 546 ASSERT_TRUE(url_request->is_pending()); 547 548 socket_data(0)->RunFor(5); 549 550 EXPECT_TRUE(url_request->status().is_success()); 551 EXPECT_EQ(1, network_delegate()->completed_requests()); 552 EXPECT_EQ(0, network_delegate()->error_count()); 553 554 // Make sure we do not accept cookies. 555 EXPECT_EQ(0, network_delegate()->set_cookie_count()); 556 557 EXPECT_FALSE(request_delegate.auth_required_called()); 558 EXPECT_EQ("test.html", request_delegate.data_received()); 559} 560 561TEST_F(URLRequestFtpJobTest, FtpProxyRequestDoNotFollowRedirects) { 562 MockWrite writes[] = { 563 MockWrite(SYNCHRONOUS, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n" 564 "Host: ftp.example.com\r\n" 565 "Proxy-Connection: keep-alive\r\n\r\n"), 566 }; 567 MockRead reads[] = { 568 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 302 Found\r\n"), 569 MockRead(ASYNC, 2, "Location: http://other.example.com/\r\n\r\n"), 570 }; 571 572 AddSocket(reads, arraysize(reads), writes, arraysize(writes)); 573 574 TestDelegate request_delegate; 575 scoped_ptr<URLRequest> url_request(request_context()->CreateRequest( 576 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY, &request_delegate, 577 NULL)); 578 url_request->Start(); 579 EXPECT_TRUE(url_request->is_pending()); 580 581 base::MessageLoop::current()->RunUntilIdle(); 582 583 EXPECT_TRUE(url_request->is_pending()); 584 EXPECT_EQ(0, request_delegate.response_started_count()); 585 EXPECT_EQ(0, network_delegate()->error_count()); 586 ASSERT_TRUE(url_request->status().is_success()); 587 588 socket_data(0)->RunFor(1); 589 590 EXPECT_EQ(1, network_delegate()->completed_requests()); 591 EXPECT_EQ(1, network_delegate()->error_count()); 592 EXPECT_FALSE(url_request->status().is_success()); 593 EXPECT_EQ(ERR_UNSAFE_REDIRECT, url_request->status().error()); 594} 595 596// We should re-use socket for requests using the same scheme, host, and port. 597TEST_F(URLRequestFtpJobTest, FtpProxyRequestReuseSocket) { 598 MockWrite writes[] = { 599 MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/first HTTP/1.1\r\n" 600 "Host: ftp.example.com\r\n" 601 "Proxy-Connection: keep-alive\r\n\r\n"), 602 MockWrite(ASYNC, 4, "GET ftp://ftp.example.com/second HTTP/1.1\r\n" 603 "Host: ftp.example.com\r\n" 604 "Proxy-Connection: keep-alive\r\n\r\n"), 605 }; 606 MockRead reads[] = { 607 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"), 608 MockRead(ASYNC, 2, "Content-Length: 10\r\n\r\n"), 609 MockRead(ASYNC, 3, "test1.html"), 610 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\n"), 611 MockRead(ASYNC, 6, "Content-Length: 10\r\n\r\n"), 612 MockRead(ASYNC, 7, "test2.html"), 613 }; 614 615 AddSocket(reads, arraysize(reads), writes, arraysize(writes)); 616 617 TestDelegate request_delegate1; 618 619 scoped_ptr<URLRequest> url_request1(request_context()->CreateRequest( 620 GURL("ftp://ftp.example.com/first"), DEFAULT_PRIORITY, &request_delegate1, 621 NULL)); 622 url_request1->Start(); 623 ASSERT_TRUE(url_request1->is_pending()); 624 socket_data(0)->RunFor(4); 625 626 EXPECT_TRUE(url_request1->status().is_success()); 627 EXPECT_TRUE(url_request1->proxy_server().Equals( 628 net::HostPortPair::FromString("localhost:80"))); 629 EXPECT_EQ(1, network_delegate()->completed_requests()); 630 EXPECT_EQ(0, network_delegate()->error_count()); 631 EXPECT_FALSE(request_delegate1.auth_required_called()); 632 EXPECT_EQ("test1.html", request_delegate1.data_received()); 633 634 TestDelegate request_delegate2; 635 scoped_ptr<URLRequest> url_request2(request_context()->CreateRequest( 636 GURL("ftp://ftp.example.com/second"), DEFAULT_PRIORITY, 637 &request_delegate2, NULL)); 638 url_request2->Start(); 639 ASSERT_TRUE(url_request2->is_pending()); 640 socket_data(0)->RunFor(4); 641 642 EXPECT_TRUE(url_request2->status().is_success()); 643 EXPECT_EQ(2, network_delegate()->completed_requests()); 644 EXPECT_EQ(0, network_delegate()->error_count()); 645 EXPECT_FALSE(request_delegate2.auth_required_called()); 646 EXPECT_EQ("test2.html", request_delegate2.data_received()); 647} 648 649// We should not re-use socket when there are two requests to the same host, 650// but one is FTP and the other is HTTP. 651TEST_F(URLRequestFtpJobTest, FtpProxyRequestDoNotReuseSocket) { 652 MockWrite writes1[] = { 653 MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/first HTTP/1.1\r\n" 654 "Host: ftp.example.com\r\n" 655 "Proxy-Connection: keep-alive\r\n\r\n"), 656 }; 657 MockWrite writes2[] = { 658 MockWrite(ASYNC, 0, "GET /second HTTP/1.1\r\n" 659 "Host: ftp.example.com\r\n" 660 "Connection: keep-alive\r\n" 661 "User-Agent:\r\n" 662 "Accept-Encoding: gzip,deflate\r\n" 663 "Accept-Language: en-us,fr\r\n\r\n"), 664 }; 665 MockRead reads1[] = { 666 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"), 667 MockRead(ASYNC, 2, "Content-Length: 10\r\n\r\n"), 668 MockRead(ASYNC, 3, "test1.html"), 669 }; 670 MockRead reads2[] = { 671 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"), 672 MockRead(ASYNC, 2, "Content-Length: 10\r\n\r\n"), 673 MockRead(ASYNC, 3, "test2.html"), 674 }; 675 676 AddSocket(reads1, arraysize(reads1), writes1, arraysize(writes1)); 677 AddSocket(reads2, arraysize(reads2), writes2, arraysize(writes2)); 678 679 TestDelegate request_delegate1; 680 scoped_ptr<URLRequest> url_request1(request_context()->CreateRequest( 681 GURL("ftp://ftp.example.com/first"), DEFAULT_PRIORITY, 682 &request_delegate1, NULL)); 683 url_request1->Start(); 684 ASSERT_TRUE(url_request1->is_pending()); 685 socket_data(0)->RunFor(4); 686 687 EXPECT_TRUE(url_request1->status().is_success()); 688 EXPECT_EQ(1, network_delegate()->completed_requests()); 689 EXPECT_EQ(0, network_delegate()->error_count()); 690 EXPECT_FALSE(request_delegate1.auth_required_called()); 691 EXPECT_EQ("test1.html", request_delegate1.data_received()); 692 693 TestDelegate request_delegate2; 694 scoped_ptr<URLRequest> url_request2(request_context()->CreateRequest( 695 GURL("http://ftp.example.com/second"), DEFAULT_PRIORITY, 696 &request_delegate2, NULL)); 697 url_request2->Start(); 698 ASSERT_TRUE(url_request2->is_pending()); 699 socket_data(1)->RunFor(4); 700 701 EXPECT_TRUE(url_request2->status().is_success()); 702 EXPECT_EQ(2, network_delegate()->completed_requests()); 703 EXPECT_EQ(0, network_delegate()->error_count()); 704 EXPECT_FALSE(request_delegate2.auth_required_called()); 705 EXPECT_EQ("test2.html", request_delegate2.data_received()); 706} 707 708} // namespace 709 710} // namespace net 711