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